@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.
- package/LICENSE +21 -0
- package/README.md +287 -2
- package/index.mjs +23 -0
- package/package.json +71 -4
- package/source/application/Kernel/index.mjs +1137 -0
- package/source/application/Server/index.mjs +1201 -0
- package/source/application/configurations/Http2CleartextServerConfiguration/index.mjs +168 -0
- package/source/application/configurations/Http2SecureServerConfiguration/index.mjs +172 -0
- package/source/application/configurations/HttpServerConfiguration/index.mjs +169 -0
- package/source/application/configurations/HttpsServerConfiguration/index.mjs +172 -0
- package/source/application/configurations/ServerConfiguration/Options/CORSOptions/CORSOptionsValue.mjs +158 -0
- package/source/application/configurations/ServerConfiguration/Options/CORSOptions/index.mjs +87 -0
- package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/CSRFOptionsValue.mjs +178 -0
- package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/index.mjs +80 -0
- package/source/application/configurations/ServerConfiguration/Options/CompressOptions/CompressOptionsValue.mjs +126 -0
- package/source/application/configurations/ServerConfiguration/Options/CompressOptions/index.mjs +81 -0
- package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/CookieParserOptionsValue.mjs +107 -0
- package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/index.mjs +82 -0
- package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/CookieSessionOptionsValue.mjs +182 -0
- package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/index.mjs +86 -0
- package/source/application/configurations/ServerConfiguration/Options/ListenOptions/ListenOptionsValue.mjs +95 -0
- package/source/application/configurations/ServerConfiguration/Options/ListenOptions/index.mjs +47 -0
- package/source/application/configurations/ServerConfiguration/Options/MiddlewareOption.mjs +102 -0
- package/source/application/configurations/ServerConfiguration/Options/Options.mjs +105 -0
- package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/RateLimitOptionsValue.mjs +164 -0
- package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/index.mjs +84 -0
- package/source/application/configurations/ServerConfiguration/Options/RequestOptions/RequestOptionsValue.mjs +108 -0
- package/source/application/configurations/ServerConfiguration/Options/RequestOptions/index.mjs +47 -0
- package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/ResponseOptionsValue.mjs +101 -0
- package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/index.mjs +47 -0
- package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/SecurityHeadersOptionsValue.mjs +272 -0
- package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/index.mjs +85 -0
- package/source/application/configurations/ServerConfiguration/Options/ServerOption.mjs +50 -0
- package/source/application/configurations/ServerConfiguration/Options/StaticOptions/StaticOptionsValue.mjs +164 -0
- package/source/application/configurations/ServerConfiguration/Options/StaticOptions/index.mjs +89 -0
- package/source/application/configurations/ServerConfiguration/index.mjs +781 -0
- package/source/application/resolvers/TransportResolver/index.mjs +119 -0
- package/source/application/use-cases/CloseServer/index.mjs +85 -0
- package/source/application/use-cases/ListenServer/index.mjs +98 -0
- package/source/core/EventSystem/index.mjs +110 -0
- package/source/core/Exchange/ExchangeContext.mjs +291 -0
- package/source/core/Exchange/Telemetry.mjs +193 -0
- package/source/core/Exchange/index.mjs +604 -0
- package/source/core/ExchangeLayerBuilder/index.mjs +133 -0
- package/source/core/IPCMain/IPCMain.mjs +507 -0
- package/source/core/IPCMain/IPCProtocol.mjs +441 -0
- package/source/core/IPCMain/IPCServerChannel.mjs +331 -0
- package/source/core/IPCMain/WebSocketAdapter.mjs +189 -0
- package/source/core/Request/BodyParser/BodyParser.mjs +197 -0
- package/source/core/Request/BodyParser/JSONParser.mjs +70 -0
- package/source/core/Request/BodyParser/MultipartParser.mjs +612 -0
- package/source/core/Request/BodyParser/URLEncodedParser.mjs +71 -0
- package/source/core/Request/RequestHeaders.mjs +177 -0
- package/source/core/Request/index.mjs +805 -0
- package/source/core/Response/ResponseHeaders.mjs +402 -0
- package/source/core/Response/index.mjs +1370 -0
- package/source/core/middlewares/CORSMiddleware/index.mjs +289 -0
- package/source/core/middlewares/CSRFMiddleware/index.mjs +284 -0
- package/source/core/middlewares/CompressMiddleware/index.mjs +460 -0
- package/source/core/middlewares/CookieParserMiddleware/index.mjs +194 -0
- package/source/core/middlewares/CookieSessionMiddleware/index.mjs +460 -0
- package/source/core/middlewares/RateLimitMiddleware/index.mjs +245 -0
- package/source/core/middlewares/SecurityHeadersMiddleware/index.mjs +151 -0
- package/source/core/middlewares/StaticMiddleware/index.mjs +628 -0
- package/source/core/routing/ExchangeLayer/ExchangeMatcher.mjs +127 -0
- package/source/core/routing/ExchangeLayer/index.mjs +254 -0
- package/source/core/routing/Pipeline/index.mjs +157 -0
- package/source/core/routing/Router/Route.mjs +184 -0
- package/source/core/routing/Router/index.mjs +523 -0
- package/source/core/routing/RouterRegister/OptionsMiddleware.mjs +147 -0
- package/source/core/routing/RouterRegister/index.mjs +150 -0
- package/source/core/routing/RouterSystem/index.mjs +225 -0
- package/source/core/value-objects/Address/index.mjs +281 -0
- package/source/core/value-objects/Endpoint/index.mjs +293 -0
- package/source/index.mjs +62 -0
- package/source/infrastructure/adapters/Http2Adapter/index.mjs +144 -0
- package/source/infrastructure/adapters/Http2CleartextAdapter/index.mjs +147 -0
- package/source/infrastructure/adapters/HttpAdapter/index.mjs +124 -0
- package/source/infrastructure/adapters/HttpsAdapter/index.mjs +124 -0
- package/source/infrastructure/adapters/TransportAdapter/createWebSocketOpenRequest.mjs +843 -0
- package/source/infrastructure/adapters/TransportAdapter/index.mjs +555 -0
- package/source/shared/Identifier/index.mjs +671 -0
- package/source/shared/constants/symbols/brands/index.mjs +45 -0
- package/source/shared/domain/UUIDV7/index.mjs +346 -0
- package/source/shared/errors/BaseError/index.mjs +157 -0
- package/source/shared/errors/IPCError/index.mjs +97 -0
- package/source/shared/errors/MiddlewareError/index.mjs +106 -0
- package/source/shared/errors/PathnamePatternError/index.mjs +103 -0
- package/source/shared/errors/RequestError/index.mjs +116 -0
- package/source/shared/errors/ResponseError/index.mjs +140 -0
- package/source/shared/errors/RouterError/index.mjs +90 -0
- package/source/shared/errors/ServerConfigurationError/index.mjs +551 -0
- package/source/shared/errors/ServerError/index.mjs +127 -0
- package/source/shared/errors/WebSocketError/index.mjs +58 -0
- package/source/shared/outcome/ErrorSchema.mjs +361 -0
- package/source/shared/outcome/Result/index.mjs +239 -0
- package/source/shared/outcome/Validation/index.mjs +208 -0
- package/source/shared/validations/Middleware/index.mjs +160 -0
- package/source/shared/validations/PathnamePattern/index.mjs +256 -0
- package/source/shared/validations/Server/NotFoundHandler/index.mjs +94 -0
- package/source/shared/validations/Server/Router/index.mjs +68 -0
- package/source/shared/validations/Server/ServerConfiguration/index.mjs +68 -0
- package/source/shared/validations/Server/SystemErrorHandler/index.mjs +94 -0
- package/source/shared/validations/ServerConfiguration/CORSOptions/index.mjs +310 -0
- package/source/shared/validations/ServerConfiguration/CSRFOptions/index.mjs +299 -0
- package/source/shared/validations/ServerConfiguration/CompressOptions/index.mjs +204 -0
- package/source/shared/validations/ServerConfiguration/CookieParserOptions/index.mjs +102 -0
- package/source/shared/validations/ServerConfiguration/CookieSessionOptions/index.mjs +332 -0
- package/source/shared/validations/ServerConfiguration/ListenOptions/index.mjs +178 -0
- package/source/shared/validations/ServerConfiguration/RateLimitOptions/index.mjs +229 -0
- package/source/shared/validations/ServerConfiguration/RequestOptions/index.mjs +132 -0
- package/source/shared/validations/ServerConfiguration/ResponseOptions/index.mjs +122 -0
- package/source/shared/validations/ServerConfiguration/SecurityHeadersOptions/index.mjs +137 -0
- package/source/shared/validations/ServerConfiguration/StaticOptions/index.mjs +248 -0
- package/types/index.d.ts +719 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @file Defines the Address value object.
|
|
4
|
+
*
|
|
5
|
+
* @module Address
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
9
|
+
// » IMPORT NATIVE NODEJS MODULES
|
|
10
|
+
import { inspect } from 'node:util';
|
|
11
|
+
|
|
12
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
+
/**
|
|
14
|
+
* Options accepted by the Address constructor.
|
|
15
|
+
*
|
|
16
|
+
* @typedef {object} AddressOptions
|
|
17
|
+
* @property {string} address - The network address where the server is listening.
|
|
18
|
+
* @property {number} port - The TCP port where the server is listening.
|
|
19
|
+
* @property {string} family - The IP address family.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Plain object representation of an Address.
|
|
24
|
+
*
|
|
25
|
+
* @typedef {object} AddressInfo
|
|
26
|
+
* @property {string} address - The network address where the server is listening.
|
|
27
|
+
* @property {number} port - The TCP port where the server is listening.
|
|
28
|
+
* @property {string} family - The IP address family reported by Node.js.
|
|
29
|
+
* @property {string} displayHost - The hostname used when displaying the address.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Represents the network address of an HTTP server.
|
|
36
|
+
*
|
|
37
|
+
* @classdesc Immutable value object that encapsulates the network address,
|
|
38
|
+
* port and IP address family of an HTTP server.
|
|
39
|
+
*
|
|
40
|
+
* It provides multiple representations of the same address,
|
|
41
|
+
* including plain objects, JSON serialization and canonical string formatting.
|
|
42
|
+
*
|
|
43
|
+
* IPv6 addresses are automatically enclosed in square brackets when
|
|
44
|
+
* converted to their string representation.
|
|
45
|
+
*/
|
|
46
|
+
class Address {
|
|
47
|
+
/**
|
|
48
|
+
* The server network address.
|
|
49
|
+
*
|
|
50
|
+
* @type {string}
|
|
51
|
+
*/
|
|
52
|
+
#address;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The TCP port where the server is listening.
|
|
56
|
+
*
|
|
57
|
+
* @type {number}
|
|
58
|
+
*/
|
|
59
|
+
#port;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The IP address family.
|
|
63
|
+
*
|
|
64
|
+
* @type {string}
|
|
65
|
+
*/
|
|
66
|
+
#family;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Creates a new Address instance.
|
|
70
|
+
*
|
|
71
|
+
* @param {AddressOptions} options - The server network address.
|
|
72
|
+
* @example
|
|
73
|
+
* ```js
|
|
74
|
+
* const address = new Address({
|
|
75
|
+
* address: '127.0.0.1',
|
|
76
|
+
* port: 3000,
|
|
77
|
+
* family: 'IPv4'
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* console.log(address.toString()); // '127.0.0.1:3000'
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
constructor({ address, port, family }) {
|
|
84
|
+
this.#address = address;
|
|
85
|
+
this.#port = port;
|
|
86
|
+
this.#family = family;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The network address where the server is listening.
|
|
91
|
+
*
|
|
92
|
+
* @readonly
|
|
93
|
+
* @type {string}
|
|
94
|
+
*/
|
|
95
|
+
get address() {
|
|
96
|
+
return this.#address;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The TCP port where the server is listening.
|
|
101
|
+
*
|
|
102
|
+
* @readonly
|
|
103
|
+
* @type {number}
|
|
104
|
+
*/
|
|
105
|
+
get port() {
|
|
106
|
+
return this.#port;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The IP address family.
|
|
111
|
+
*
|
|
112
|
+
* @readonly
|
|
113
|
+
* @type {string}
|
|
114
|
+
*/
|
|
115
|
+
get family() {
|
|
116
|
+
return this.#family;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The hostname used when displaying the network address.
|
|
121
|
+
*
|
|
122
|
+
* IPv4 and IPv6 loopback addresses.
|
|
123
|
+
*
|
|
124
|
+
* @readonly
|
|
125
|
+
* @type {string}
|
|
126
|
+
*/
|
|
127
|
+
get displayHost() {
|
|
128
|
+
if (this.#address === '127.0.0.1' || this.#address === '::1') {
|
|
129
|
+
return 'localhost';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return this.#address;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Custom string tag for better type identification.
|
|
137
|
+
*
|
|
138
|
+
* @readonly
|
|
139
|
+
* @type {string}
|
|
140
|
+
* @example
|
|
141
|
+
* ```js
|
|
142
|
+
* const address = new Address({...});
|
|
143
|
+
* console.log(Object.prototype.toString.call(address)); // '[object Address]'
|
|
144
|
+
* console.log(address[Symbol.toStringTag]); // 'Address'
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
get [Symbol.toStringTag]() {
|
|
148
|
+
return this.constructor.name;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Returns the address as a plain JavaScript object.
|
|
153
|
+
*
|
|
154
|
+
* The returned object includes the real network data and a display-friendly
|
|
155
|
+
* host derived from loopback normalization.
|
|
156
|
+
*
|
|
157
|
+
* @returns {AddressInfo} A plain object representation of this address.
|
|
158
|
+
* @example
|
|
159
|
+
* ```js
|
|
160
|
+
* console.log(address.toObject());
|
|
161
|
+
* // {
|
|
162
|
+
* // address: '::1',
|
|
163
|
+
* // port: 3000,
|
|
164
|
+
* // family: 'IPv6',
|
|
165
|
+
* // displayHost: 'localhost'
|
|
166
|
+
* // }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
toObject() {
|
|
170
|
+
return {
|
|
171
|
+
address: this.#address,
|
|
172
|
+
port: this.#port,
|
|
173
|
+
family: this.#family,
|
|
174
|
+
displayHost: this.displayHost,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Returns a JSON-serializable representation of this address.
|
|
180
|
+
*
|
|
181
|
+
* This method is automatically used by JSON.stringify().
|
|
182
|
+
*
|
|
183
|
+
* @returns {AddressInfo} A JSON representation of this address.
|
|
184
|
+
* @example
|
|
185
|
+
* ```js
|
|
186
|
+
* const json = JSON.stringify(address);
|
|
187
|
+
*
|
|
188
|
+
* console.log(json); // {"address":"::1","port":3000,"family":"IPv6","displayHost":"localhost"}
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
toJSON() {
|
|
192
|
+
return this.toObject();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Returns the canonical string representation of this address.
|
|
197
|
+
*
|
|
198
|
+
* IPv4 addresses are represented as `host:port`.
|
|
199
|
+
* IPv6 addresses are represented as `[host]:port`.
|
|
200
|
+
*
|
|
201
|
+
* @returns {string} The canonical network address.
|
|
202
|
+
* @example
|
|
203
|
+
* ```js
|
|
204
|
+
* const ipv4 = new Address({
|
|
205
|
+
* address: '127.0.0.1',
|
|
206
|
+
* port: 3000,
|
|
207
|
+
* family: 'IPv4'
|
|
208
|
+
* });
|
|
209
|
+
*
|
|
210
|
+
* console.log(ipv4.toString()); // '127.0.0.1:3000'
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```js
|
|
215
|
+
* const ipv6 = new Address({
|
|
216
|
+
* address: '2001:db8::1',
|
|
217
|
+
* port: 3000,
|
|
218
|
+
* family: 'IPv6'
|
|
219
|
+
* });
|
|
220
|
+
*
|
|
221
|
+
* console.log(ipv6.toString()); // '[2001:db8::1]:3000'
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
toString() {
|
|
225
|
+
const host = this.#family === 'IPv6' ? `[${this.#address}]` : this.#address;
|
|
226
|
+
|
|
227
|
+
return `${host}:${this.#port}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Custom inspect implementation for Node.js `util.inspect()`.
|
|
232
|
+
*
|
|
233
|
+
* @returns {string} Custom string representation for debugging.
|
|
234
|
+
* @example
|
|
235
|
+
* ```js
|
|
236
|
+
* const address = new Address({...});
|
|
237
|
+
*
|
|
238
|
+
* console.log(address);
|
|
239
|
+
* // Address {
|
|
240
|
+
* // address: '::1',
|
|
241
|
+
* // port: 5173,
|
|
242
|
+
* // family: 'IPv6',
|
|
243
|
+
* // displayHost: 'localhost'
|
|
244
|
+
* // }
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
[inspect.custom]() {
|
|
248
|
+
return `${this.constructor.name} ${inspect(this.toObject(), { colors: true })}`;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Converts this address to a primitive value.
|
|
253
|
+
*
|
|
254
|
+
* String and default conversions return the canonical address string.
|
|
255
|
+
* Numeric conversion is not supported.
|
|
256
|
+
*
|
|
257
|
+
* @param {'string'|'number'|'default'} hint - The preferred primitive type.
|
|
258
|
+
* @returns {string} The canonical address string.
|
|
259
|
+
* @throws {TypeError} Thrown when a numeric conversion is attempted.
|
|
260
|
+
* @example
|
|
261
|
+
* ```js
|
|
262
|
+
* const address = new Address({
|
|
263
|
+
* address: '127.0.0.1',
|
|
264
|
+
* port: 3000,
|
|
265
|
+
* family: 'IPv4'
|
|
266
|
+
* });
|
|
267
|
+
*
|
|
268
|
+
* console.log(`Server Address: ${address}`); // '127.0.0.1:3000'
|
|
269
|
+
* console.log(String(address)); // '127.0.0.1:3000'
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
[Symbol.toPrimitive](hint) {
|
|
273
|
+
if (hint === 'number') {
|
|
274
|
+
throw new TypeError(`${this.constructor.name} cannot be converted to number.`);
|
|
275
|
+
}
|
|
276
|
+
return this.toString();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
281
|
+
export default Address;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @file Defines the Endpoint value object.
|
|
4
|
+
*
|
|
5
|
+
* @module Endpoint
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
9
|
+
// » IMPORT NATIVE NODEJS MODULES
|
|
10
|
+
import { inspect } from 'node:util';
|
|
11
|
+
|
|
12
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
+
/**
|
|
14
|
+
* Represents the network address of an HTTP server.
|
|
15
|
+
*
|
|
16
|
+
* @typedef {import('#value-objects/Address').default} Address
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Identifies an application-layer communication protocol.
|
|
21
|
+
*
|
|
22
|
+
* @typedef { 'http'|'https'|'ws'|'wss'|'grpc'|'mqtt'|'coap' } Protocol
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Represents network endpoint configuration options.
|
|
27
|
+
*
|
|
28
|
+
* @typedef {object} EndpointOptions
|
|
29
|
+
* @property {Protocol} protocol - The communication protocol.
|
|
30
|
+
* @property {Address} address - The server network address.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Represents the data of a network endpoint.
|
|
35
|
+
*
|
|
36
|
+
* @typedef {object} EndpointData
|
|
37
|
+
* @property {Protocol} protocol - The communication protocol.
|
|
38
|
+
* @property {string} address - The network address where the server is listening.
|
|
39
|
+
* @property {number} port - The TCP port where the server is listening.
|
|
40
|
+
* @property {string} family - The IP address family.
|
|
41
|
+
* @property {string} displayHost - The hostname used when displaying the address.
|
|
42
|
+
* @property {string} displayUrl - The URL used when displaying the endpoint.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
46
|
+
/**
|
|
47
|
+
* Represents a complete network endpoint.
|
|
48
|
+
*
|
|
49
|
+
* @classdesc Immutable value object that combines a communication protocol
|
|
50
|
+
* with a network address.
|
|
51
|
+
*
|
|
52
|
+
* It provides multiple representations of the same endpoint,
|
|
53
|
+
* including plain objects, JSON serialization and URL formatting.
|
|
54
|
+
*/
|
|
55
|
+
class Endpoint {
|
|
56
|
+
/**
|
|
57
|
+
* The communication protocol of the endpoint.
|
|
58
|
+
*
|
|
59
|
+
* @type {Protocol}
|
|
60
|
+
*/
|
|
61
|
+
#protocol;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The server network address.
|
|
65
|
+
*
|
|
66
|
+
* @type {Address}
|
|
67
|
+
*/
|
|
68
|
+
#address;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new Endpoint instance.
|
|
72
|
+
*
|
|
73
|
+
* @param {EndpointOptions} options - The network endpoint configuration.
|
|
74
|
+
* @example
|
|
75
|
+
* ```js
|
|
76
|
+
* const address = new Address({
|
|
77
|
+
* address: '127.0.0.1',
|
|
78
|
+
* port: 3000,
|
|
79
|
+
* family: 'IPv4',
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* const endpoint = new Endpoint({
|
|
83
|
+
* protocol: 'http',
|
|
84
|
+
* address,
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
constructor({ protocol, address }) {
|
|
89
|
+
this.#protocol = protocol;
|
|
90
|
+
this.#address = address;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The communication protocol.
|
|
95
|
+
*
|
|
96
|
+
* @readonly
|
|
97
|
+
* @type {Protocol}
|
|
98
|
+
*/
|
|
99
|
+
get protocol() {
|
|
100
|
+
return this.#protocol;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The network address where the server is listening.
|
|
105
|
+
*
|
|
106
|
+
* @readonly
|
|
107
|
+
* @type {string}
|
|
108
|
+
*/
|
|
109
|
+
get address() {
|
|
110
|
+
return this.#address.address;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The TCP port where the server is listening.
|
|
115
|
+
*
|
|
116
|
+
* @readonly
|
|
117
|
+
* @type {number}
|
|
118
|
+
*/
|
|
119
|
+
get port() {
|
|
120
|
+
return this.#address.port;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The IP address family.
|
|
125
|
+
*
|
|
126
|
+
* @readonly
|
|
127
|
+
* @type {string}
|
|
128
|
+
*/
|
|
129
|
+
get family() {
|
|
130
|
+
return this.#address.family;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The hostname used when displaying the network address.
|
|
135
|
+
*
|
|
136
|
+
* IPv4 and IPv6 loopback addresses.
|
|
137
|
+
*
|
|
138
|
+
* @readonly
|
|
139
|
+
* @type {string}
|
|
140
|
+
*/
|
|
141
|
+
get displayHost() {
|
|
142
|
+
return this.#address.displayHost;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The URL used when displaying the endpoint.
|
|
147
|
+
*
|
|
148
|
+
* Loopback addresses are rendered as `localhost`.
|
|
149
|
+
*
|
|
150
|
+
* @readonly
|
|
151
|
+
* @type {string}
|
|
152
|
+
* @example
|
|
153
|
+
* ```js
|
|
154
|
+
* console.log(endpoint.displayUrl); // 'http://localhost:3000'
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
get displayUrl() {
|
|
158
|
+
const { displayHost, family, port } = this.#address;
|
|
159
|
+
const host =
|
|
160
|
+
family === 'IPv6' && displayHost !== 'localhost' ? `[${displayHost}]` : displayHost;
|
|
161
|
+
|
|
162
|
+
return `${this.#protocol}://${host}:${port}`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Custom string tag for better type identification.
|
|
167
|
+
*
|
|
168
|
+
* @readonly
|
|
169
|
+
* @type {string}
|
|
170
|
+
* @example
|
|
171
|
+
* ```js
|
|
172
|
+
* const endpoint = new Endpoint({...});
|
|
173
|
+
* console.log(Object.prototype.toString.call(endpoint)); // '[object Endpoint]'
|
|
174
|
+
* console.log(endpoint[Symbol.toStringTag]); // 'Endpoint'
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
get [Symbol.toStringTag]() {
|
|
178
|
+
return this.constructor.name;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Returns the endpoint as a plain JavaScript object.
|
|
183
|
+
*
|
|
184
|
+
* @returns {EndpointData} A plain object representation of this endpoint.
|
|
185
|
+
* @example
|
|
186
|
+
* ```js
|
|
187
|
+
* console.log(endpoint.toObject());
|
|
188
|
+
* // {
|
|
189
|
+
* // protocol: 'http',
|
|
190
|
+
* // address: '::1',
|
|
191
|
+
* // port: 3000,
|
|
192
|
+
* // family: 'IPv6',
|
|
193
|
+
* // displayHost: 'localhost',
|
|
194
|
+
* // displayUrl: 'http://localhost:3000',
|
|
195
|
+
* // }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
toObject() {
|
|
199
|
+
return {
|
|
200
|
+
protocol: this.#protocol,
|
|
201
|
+
...this.#address.toObject(),
|
|
202
|
+
displayUrl: this.displayUrl,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns a JSON-serializable representation of this endpoint.
|
|
208
|
+
*
|
|
209
|
+
* This method is automatically used by JSON.stringify().
|
|
210
|
+
*
|
|
211
|
+
* @returns {EndpointData} A JSON representation of this endpoint.
|
|
212
|
+
* @example
|
|
213
|
+
* ```js
|
|
214
|
+
* const json = JSON.stringify(address);
|
|
215
|
+
*
|
|
216
|
+
* console.log(json); // {"protocol":"http","address":"::1","port":3000,"family":"IPv6","displayHost":"localhost","displayUrl":"http://localhost:3000"}
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
toJSON() {
|
|
220
|
+
return this.toObject();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Returns the canonical URL representation of this endpoint.
|
|
225
|
+
*
|
|
226
|
+
* The URL consists of the endpoint protocol followed by the canonical
|
|
227
|
+
* string representation of its server address.
|
|
228
|
+
*
|
|
229
|
+
* @returns {string} The canonical endpoint URL.
|
|
230
|
+
* @example
|
|
231
|
+
* ```js
|
|
232
|
+
* const address = new Address({
|
|
233
|
+
* address: '127.0.0.1',
|
|
234
|
+
* port: 3000,
|
|
235
|
+
* family: 'IPv4',
|
|
236
|
+
* });
|
|
237
|
+
*
|
|
238
|
+
* const endpoint = new Endpoint({
|
|
239
|
+
* protocol: 'http',
|
|
240
|
+
* address,
|
|
241
|
+
* });
|
|
242
|
+
*
|
|
243
|
+
* console.log(endpoint.toString()); // 'http://127.0.0.1:3000'
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
toString() {
|
|
247
|
+
return `${this.#protocol}://${this.#address}`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Custom inspect implementation for Node.js `util.inspect()`.
|
|
252
|
+
*
|
|
253
|
+
* @returns {string} Custom string representation for debugging.
|
|
254
|
+
* @example
|
|
255
|
+
* ```js
|
|
256
|
+
* console.log(endpoint);
|
|
257
|
+
* // Endpoint {
|
|
258
|
+
* // protocol: 'http',
|
|
259
|
+
* // address: '::1',
|
|
260
|
+
* // port: 5173,
|
|
261
|
+
* // family: 'IPv6',
|
|
262
|
+
* // displayHost: 'localhost',
|
|
263
|
+
* // displayUrl: 'http://localhost:5173'
|
|
264
|
+
* // }
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
[inspect.custom]() {
|
|
268
|
+
return `${this.constructor.name} ${inspect(this.toObject(), { colors: true })}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Converts this endpoint to a primitive value.
|
|
273
|
+
*
|
|
274
|
+
* Numeric conversion is not supported.
|
|
275
|
+
*
|
|
276
|
+
* @param {'string'|'number'|'default'} hint - The preferred primitive type.
|
|
277
|
+
* @returns {string} The canonical endpoint URL.
|
|
278
|
+
* @throws {TypeError} Thrown when a numeric conversion is attempted.
|
|
279
|
+
* @example
|
|
280
|
+
* ```js
|
|
281
|
+
* console.log(`${endpoint}`); // 'http://127.0.0.1:3000'
|
|
282
|
+
* ```
|
|
283
|
+
*/
|
|
284
|
+
[Symbol.toPrimitive](hint) {
|
|
285
|
+
if (hint === 'number') {
|
|
286
|
+
throw new TypeError(`${this.constructor.name} cannot be converted to number.`);
|
|
287
|
+
}
|
|
288
|
+
return this.toString();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
293
|
+
export default Endpoint;
|
package/source/index.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @file Public API for the `@boo/server` package.
|
|
4
|
+
*
|
|
5
|
+
* @description Exposes the public classes for configuring, routing, and
|
|
6
|
+
* running zero-dependency HTTP servers in Node.js, following Clean
|
|
7
|
+
* Architecture principles.
|
|
8
|
+
*
|
|
9
|
+
* Exports:
|
|
10
|
+
*
|
|
11
|
+
* - Server (default): The main HTTP server class.
|
|
12
|
+
* - Router: Provides route registration and composition.
|
|
13
|
+
* - HttpServerConfiguration: Configuration for standard HTTP/1.1 servers.
|
|
14
|
+
* - HttpsServerConfiguration: Configuration for secure HTTPS servers.
|
|
15
|
+
* - Http2CleartextServerConfiguration: Configuration for cleartext HTTP/2 (h2c) servers.
|
|
16
|
+
* - Http2SecureServerConfiguration: Configuration for secure HTTP/2 (h2) servers.
|
|
17
|
+
*
|
|
18
|
+
* @module BooServerAPI
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
22
|
+
// » IMPORT LOCAL MODULES
|
|
23
|
+
import Server from '#Server';
|
|
24
|
+
import Router from '#routing/Router';
|
|
25
|
+
import HttpServerConfiguration from '#configurations/HttpServerConfiguration';
|
|
26
|
+
import HttpsServerConfiguration from '#configurations/HttpsServerConfiguration';
|
|
27
|
+
import Http2CleartextServerConfiguration from '#configurations/Http2CleartextServerConfiguration';
|
|
28
|
+
import Http2SecureServerConfiguration from '#configurations/Http2SecureServerConfiguration';
|
|
29
|
+
|
|
30
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
31
|
+
/**
|
|
32
|
+
* Public API namespace for the `@boo/server` package.
|
|
33
|
+
*
|
|
34
|
+
* Describes the classes exposed by the package's public entry point.
|
|
35
|
+
*
|
|
36
|
+
* @typedef {object} BooServerAPI
|
|
37
|
+
* @property {typeof Server} default - Main HTTP server class.
|
|
38
|
+
* @property {typeof Router} Router - Route registration and composition.
|
|
39
|
+
* @property {typeof HttpServerConfiguration} HttpServerConfiguration - HTTP/1.1 server configuration.
|
|
40
|
+
* @property {typeof HttpsServerConfiguration} HttpsServerConfiguration - HTTPS server configuration.
|
|
41
|
+
* @property {typeof Http2CleartextServerConfiguration} Http2CleartextServerConfiguration - Cleartext HTTP/2 (h2c) server configuration.
|
|
42
|
+
* @property {typeof Http2SecureServerConfiguration} Http2SecureServerConfiguration - Secure HTTP/2 (h2) server configuration.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
// ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
46
|
+
/**
|
|
47
|
+
* Default export: The primary class used to create and run an HTTP server.
|
|
48
|
+
*
|
|
49
|
+
* @type {typeof Server}
|
|
50
|
+
*/
|
|
51
|
+
export default Server;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Named exports: The router and the supported server configuration classes.
|
|
55
|
+
*/
|
|
56
|
+
export {
|
|
57
|
+
Router,
|
|
58
|
+
HttpServerConfiguration,
|
|
59
|
+
HttpsServerConfiguration,
|
|
60
|
+
Http2CleartextServerConfiguration,
|
|
61
|
+
Http2SecureServerConfiguration,
|
|
62
|
+
};
|