@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,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
+ }