@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,248 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @file Static options validation utilities.
|
|
4
|
+
*
|
|
5
|
+
* @description Validates static middleware options used by ServerConfiguration,
|
|
6
|
+
* including root presence, index array, cache duration, boolean flags,
|
|
7
|
+
* extensions, and dotfile behavior.
|
|
8
|
+
*
|
|
9
|
+
* @module Validation/ServerConfiguration/StaticOptions
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
+
// » IMPORT LOCAL MODULES
|
|
14
|
+
import Validation from '#shared/outcome/Validation';
|
|
15
|
+
import ServerConfigurationError from '#shared/errors/ServerConfigurationError';
|
|
16
|
+
|
|
17
|
+
// ━━ FUNCTIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
18
|
+
/**
|
|
19
|
+
* Determines whether a value is a non-null plain object.
|
|
20
|
+
*
|
|
21
|
+
* @private
|
|
22
|
+
* @param {unknown} value - Value to inspect.
|
|
23
|
+
* @returns {value is Record<string, unknown>} `true` if the value is a plain object.
|
|
24
|
+
*/
|
|
25
|
+
function isPlainObject(value) {
|
|
26
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Validates static middleware options.
|
|
31
|
+
*
|
|
32
|
+
* Validation is performed in the following order:
|
|
33
|
+
*
|
|
34
|
+
* 1. `options` may be `undefined`, in which case validation succeeds.
|
|
35
|
+
* 2. `options` must be a plain object.
|
|
36
|
+
* 3. `root`, when present, must be a non-empty string.
|
|
37
|
+
* 4. `index`, when present, must be an array of non-empty strings.
|
|
38
|
+
* 5. `maxAge`, when present, must be a non-negative integer.
|
|
39
|
+
* 6. `etag`, when present, must be a boolean.
|
|
40
|
+
* 7. `lastModified`, when present, must be a boolean.
|
|
41
|
+
* 8. `fallthrough`, when present, must be a boolean.
|
|
42
|
+
* 9. `extensions`, when present, must be an array of non-empty strings.
|
|
43
|
+
* 10. `dotfiles`, when present, must be a boolean.
|
|
44
|
+
*
|
|
45
|
+
* @param {unknown} options - Static options to validate.
|
|
46
|
+
* @returns {Validation} Validation result.
|
|
47
|
+
* @example
|
|
48
|
+
* ```js
|
|
49
|
+
* const validation = validateStaticOptions({ root: '/var/www/public' });
|
|
50
|
+
*
|
|
51
|
+
* console.log(validation.ok);
|
|
52
|
+
* // => true
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```js
|
|
57
|
+
* const validation = validateStaticOptions({ root: '' });
|
|
58
|
+
*
|
|
59
|
+
* console.log(validation.ok);
|
|
60
|
+
* // => false
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function validateStaticOptions(options) {
|
|
64
|
+
if (options === undefined) {
|
|
65
|
+
return Validation.success();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!isPlainObject(options)) {
|
|
69
|
+
return Validation.failure({
|
|
70
|
+
error: ServerConfigurationError,
|
|
71
|
+
code: 'INVALID_STATIC_OPTIONS',
|
|
72
|
+
custom: true,
|
|
73
|
+
options: { values: { received: typeof options } },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if ('root' in options === false) {
|
|
78
|
+
return Validation.failure({
|
|
79
|
+
error: ServerConfigurationError,
|
|
80
|
+
code: 'MISSING_STATIC_ROOT',
|
|
81
|
+
custom: true,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if ('root' in options) {
|
|
86
|
+
const { root } = options;
|
|
87
|
+
|
|
88
|
+
if (typeof root !== 'string') {
|
|
89
|
+
return Validation.failure({
|
|
90
|
+
error: ServerConfigurationError,
|
|
91
|
+
code: 'INVALID_STATIC_ROOT_TYPE',
|
|
92
|
+
custom: true,
|
|
93
|
+
options: { values: { received: typeof root } },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (root.length === 0) {
|
|
98
|
+
return Validation.failure({
|
|
99
|
+
error: ServerConfigurationError,
|
|
100
|
+
code: 'INVALID_STATIC_ROOT_VALUE',
|
|
101
|
+
custom: true,
|
|
102
|
+
options: { details: { root } },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if ('index' in options) {
|
|
108
|
+
const { index } = options;
|
|
109
|
+
|
|
110
|
+
if (!Array.isArray(index)) {
|
|
111
|
+
return Validation.failure({
|
|
112
|
+
error: ServerConfigurationError,
|
|
113
|
+
code: 'INVALID_STATIC_INDEX_TYPE',
|
|
114
|
+
custom: true,
|
|
115
|
+
options: { values: { received: typeof index } },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (const item of index) {
|
|
120
|
+
if (typeof item !== 'string' || item.length === 0) {
|
|
121
|
+
return Validation.failure({
|
|
122
|
+
error: ServerConfigurationError,
|
|
123
|
+
code: 'INVALID_STATIC_INDEX_ITEM',
|
|
124
|
+
custom: true,
|
|
125
|
+
options: { details: { item } },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if ('maxAge' in options) {
|
|
132
|
+
const { maxAge } = options;
|
|
133
|
+
|
|
134
|
+
if (typeof maxAge !== 'number') {
|
|
135
|
+
return Validation.failure({
|
|
136
|
+
error: ServerConfigurationError,
|
|
137
|
+
code: 'INVALID_STATIC_MAX_AGE_TYPE',
|
|
138
|
+
custom: true,
|
|
139
|
+
options: { values: { received: typeof maxAge } },
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!Number.isInteger(maxAge) || maxAge < 0) {
|
|
144
|
+
return Validation.failure({
|
|
145
|
+
error: ServerConfigurationError,
|
|
146
|
+
code: 'INVALID_STATIC_MAX_AGE_VALUE',
|
|
147
|
+
custom: true,
|
|
148
|
+
options: { details: { maxAge } },
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if ('etag' in options) {
|
|
154
|
+
if (typeof options.etag !== 'boolean') {
|
|
155
|
+
return Validation.failure({
|
|
156
|
+
error: ServerConfigurationError,
|
|
157
|
+
code: 'INVALID_STATIC_ETAG_TYPE',
|
|
158
|
+
custom: true,
|
|
159
|
+
options: { values: { received: typeof options.etag } },
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if ('lastModified' in options) {
|
|
165
|
+
if (typeof options.lastModified !== 'boolean') {
|
|
166
|
+
return Validation.failure({
|
|
167
|
+
error: ServerConfigurationError,
|
|
168
|
+
code: 'INVALID_STATIC_LAST_MODIFIED_TYPE',
|
|
169
|
+
custom: true,
|
|
170
|
+
options: { values: { received: typeof options.lastModified } },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if ('fallthrough' in options) {
|
|
176
|
+
if (typeof options.fallthrough !== 'boolean') {
|
|
177
|
+
return Validation.failure({
|
|
178
|
+
error: ServerConfigurationError,
|
|
179
|
+
code: 'INVALID_STATIC_FALLTHROUGH_TYPE',
|
|
180
|
+
custom: true,
|
|
181
|
+
options: { values: { received: typeof options.fallthrough } },
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if ('extensions' in options) {
|
|
187
|
+
const { extensions } = options;
|
|
188
|
+
|
|
189
|
+
if (!Array.isArray(extensions)) {
|
|
190
|
+
return Validation.failure({
|
|
191
|
+
error: ServerConfigurationError,
|
|
192
|
+
code: 'INVALID_STATIC_EXTENSIONS_TYPE',
|
|
193
|
+
custom: true,
|
|
194
|
+
options: { values: { received: typeof extensions } },
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (const item of extensions) {
|
|
199
|
+
if (typeof item !== 'string' || item.length === 0) {
|
|
200
|
+
return Validation.failure({
|
|
201
|
+
error: ServerConfigurationError,
|
|
202
|
+
code: 'INVALID_STATIC_EXTENSIONS_ITEM',
|
|
203
|
+
custom: true,
|
|
204
|
+
options: { details: { item } },
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if ('dotfiles' in options) {
|
|
211
|
+
if (typeof options.dotfiles !== 'boolean') {
|
|
212
|
+
return Validation.failure({
|
|
213
|
+
error: ServerConfigurationError,
|
|
214
|
+
code: 'INVALID_STATIC_DOTFILES_TYPE',
|
|
215
|
+
custom: true,
|
|
216
|
+
options: { values: { received: typeof options.dotfiles } },
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return Validation.success();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Asserts that static middleware options are valid.
|
|
226
|
+
*
|
|
227
|
+
* @param {unknown} options - Static options to validate.
|
|
228
|
+
* @throws {ServerConfigurationError} If `options` is not a plain object.
|
|
229
|
+
* @throws {ServerConfigurationError} If `root` is not a non-empty string.
|
|
230
|
+
* @throws {ServerConfigurationError} If `index` is not an array of non-empty strings.
|
|
231
|
+
* @throws {ServerConfigurationError} If `maxAge` is not a non-negative integer.
|
|
232
|
+
* @throws {ServerConfigurationError} If `etag` is not a boolean.
|
|
233
|
+
* @throws {ServerConfigurationError} If `lastModified` is not a boolean.
|
|
234
|
+
* @throws {ServerConfigurationError} If `fallthrough` is not a boolean.
|
|
235
|
+
* @throws {ServerConfigurationError} If `extensions` is not an array of non-empty strings.
|
|
236
|
+
* @throws {ServerConfigurationError} If `dotfiles` is not a boolean.
|
|
237
|
+
* @example
|
|
238
|
+
* ```js
|
|
239
|
+
* assertStaticOptions({ root: '/var/www/public' });
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
export function assertStaticOptions(options) {
|
|
243
|
+
const validation = validateStaticOptions(options);
|
|
244
|
+
|
|
245
|
+
if (!validation.ok) {
|
|
246
|
+
throw validation.error;
|
|
247
|
+
}
|
|
248
|
+
}
|