@boo-labs/server 0.0.0-stage → 1.0.0

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 (114) hide show
  1. package/README.md +229 -2
  2. package/index.mjs +23 -0
  3. package/package.json +71 -4
  4. package/source/application/Kernel/index.mjs +1137 -0
  5. package/source/application/Server/index.mjs +1201 -0
  6. package/source/application/configurations/Http2CleartextServerConfiguration/index.mjs +168 -0
  7. package/source/application/configurations/Http2SecureServerConfiguration/index.mjs +172 -0
  8. package/source/application/configurations/HttpServerConfiguration/index.mjs +169 -0
  9. package/source/application/configurations/HttpsServerConfiguration/index.mjs +172 -0
  10. package/source/application/configurations/ServerConfiguration/Options/CORSOptions/CORSOptionsValue.mjs +158 -0
  11. package/source/application/configurations/ServerConfiguration/Options/CORSOptions/index.mjs +87 -0
  12. package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/CSRFOptionsValue.mjs +178 -0
  13. package/source/application/configurations/ServerConfiguration/Options/CSRFOptions/index.mjs +80 -0
  14. package/source/application/configurations/ServerConfiguration/Options/CompressOptions/CompressOptionsValue.mjs +126 -0
  15. package/source/application/configurations/ServerConfiguration/Options/CompressOptions/index.mjs +81 -0
  16. package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/CookieParserOptionsValue.mjs +107 -0
  17. package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/index.mjs +82 -0
  18. package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/CookieSessionOptionsValue.mjs +182 -0
  19. package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/index.mjs +86 -0
  20. package/source/application/configurations/ServerConfiguration/Options/ListenOptions/ListenOptionsValue.mjs +95 -0
  21. package/source/application/configurations/ServerConfiguration/Options/ListenOptions/index.mjs +47 -0
  22. package/source/application/configurations/ServerConfiguration/Options/MiddlewareOption.mjs +102 -0
  23. package/source/application/configurations/ServerConfiguration/Options/Options.mjs +105 -0
  24. package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/RateLimitOptionsValue.mjs +164 -0
  25. package/source/application/configurations/ServerConfiguration/Options/RateLimitOptions/index.mjs +84 -0
  26. package/source/application/configurations/ServerConfiguration/Options/RequestOptions/RequestOptionsValue.mjs +108 -0
  27. package/source/application/configurations/ServerConfiguration/Options/RequestOptions/index.mjs +47 -0
  28. package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/ResponseOptionsValue.mjs +101 -0
  29. package/source/application/configurations/ServerConfiguration/Options/ResponseOptions/index.mjs +47 -0
  30. package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/SecurityHeadersOptionsValue.mjs +272 -0
  31. package/source/application/configurations/ServerConfiguration/Options/SecurityHeadersOptions/index.mjs +85 -0
  32. package/source/application/configurations/ServerConfiguration/Options/ServerOption.mjs +50 -0
  33. package/source/application/configurations/ServerConfiguration/Options/StaticOptions/StaticOptionsValue.mjs +164 -0
  34. package/source/application/configurations/ServerConfiguration/Options/StaticOptions/index.mjs +89 -0
  35. package/source/application/configurations/ServerConfiguration/index.mjs +781 -0
  36. package/source/application/resolvers/TransportResolver/index.mjs +119 -0
  37. package/source/application/use-cases/CloseServer/index.mjs +85 -0
  38. package/source/application/use-cases/ListenServer/index.mjs +98 -0
  39. package/source/core/EventSystem/index.mjs +110 -0
  40. package/source/core/Exchange/ExchangeContext.mjs +291 -0
  41. package/source/core/Exchange/Telemetry.mjs +193 -0
  42. package/source/core/Exchange/index.mjs +604 -0
  43. package/source/core/ExchangeLayerBuilder/index.mjs +133 -0
  44. package/source/core/IPCMain/IPCMain.mjs +507 -0
  45. package/source/core/IPCMain/IPCProtocol.mjs +441 -0
  46. package/source/core/IPCMain/IPCServerChannel.mjs +331 -0
  47. package/source/core/IPCMain/WebSocketAdapter.mjs +189 -0
  48. package/source/core/Request/BodyParser/BodyParser.mjs +197 -0
  49. package/source/core/Request/BodyParser/JSONParser.mjs +70 -0
  50. package/source/core/Request/BodyParser/MultipartParser.mjs +612 -0
  51. package/source/core/Request/BodyParser/URLEncodedParser.mjs +71 -0
  52. package/source/core/Request/RequestHeaders.mjs +177 -0
  53. package/source/core/Request/index.mjs +805 -0
  54. package/source/core/Response/ResponseHeaders.mjs +402 -0
  55. package/source/core/Response/index.mjs +1370 -0
  56. package/source/core/middlewares/CORSMiddleware/index.mjs +289 -0
  57. package/source/core/middlewares/CSRFMiddleware/index.mjs +284 -0
  58. package/source/core/middlewares/CompressMiddleware/index.mjs +460 -0
  59. package/source/core/middlewares/CookieParserMiddleware/index.mjs +194 -0
  60. package/source/core/middlewares/CookieSessionMiddleware/index.mjs +460 -0
  61. package/source/core/middlewares/RateLimitMiddleware/index.mjs +245 -0
  62. package/source/core/middlewares/SecurityHeadersMiddleware/index.mjs +151 -0
  63. package/source/core/middlewares/StaticMiddleware/index.mjs +628 -0
  64. package/source/core/routing/ExchangeLayer/ExchangeMatcher.mjs +127 -0
  65. package/source/core/routing/ExchangeLayer/index.mjs +254 -0
  66. package/source/core/routing/Pipeline/index.mjs +157 -0
  67. package/source/core/routing/Router/Route.mjs +184 -0
  68. package/source/core/routing/Router/index.mjs +523 -0
  69. package/source/core/routing/RouterRegister/OptionsMiddleware.mjs +147 -0
  70. package/source/core/routing/RouterRegister/index.mjs +150 -0
  71. package/source/core/routing/RouterSystem/index.mjs +225 -0
  72. package/source/core/value-objects/Address/index.mjs +281 -0
  73. package/source/core/value-objects/Endpoint/index.mjs +293 -0
  74. package/source/index.mjs +62 -0
  75. package/source/infrastructure/adapters/Http2Adapter/index.mjs +144 -0
  76. package/source/infrastructure/adapters/Http2CleartextAdapter/index.mjs +147 -0
  77. package/source/infrastructure/adapters/HttpAdapter/index.mjs +124 -0
  78. package/source/infrastructure/adapters/HttpsAdapter/index.mjs +124 -0
  79. package/source/infrastructure/adapters/TransportAdapter/createWebSocketOpenRequest.mjs +843 -0
  80. package/source/infrastructure/adapters/TransportAdapter/index.mjs +555 -0
  81. package/source/shared/Identifier/index.mjs +671 -0
  82. package/source/shared/constants/symbols/brands/index.mjs +45 -0
  83. package/source/shared/domain/UUIDV7/index.mjs +346 -0
  84. package/source/shared/errors/BaseError/index.mjs +157 -0
  85. package/source/shared/errors/IPCError/index.mjs +97 -0
  86. package/source/shared/errors/MiddlewareError/index.mjs +106 -0
  87. package/source/shared/errors/PathnamePatternError/index.mjs +103 -0
  88. package/source/shared/errors/RequestError/index.mjs +116 -0
  89. package/source/shared/errors/ResponseError/index.mjs +140 -0
  90. package/source/shared/errors/RouterError/index.mjs +90 -0
  91. package/source/shared/errors/ServerConfigurationError/index.mjs +551 -0
  92. package/source/shared/errors/ServerError/index.mjs +127 -0
  93. package/source/shared/errors/WebSocketError/index.mjs +58 -0
  94. package/source/shared/outcome/ErrorSchema.mjs +361 -0
  95. package/source/shared/outcome/Result/index.mjs +239 -0
  96. package/source/shared/outcome/Validation/index.mjs +208 -0
  97. package/source/shared/validations/Middleware/index.mjs +160 -0
  98. package/source/shared/validations/PathnamePattern/index.mjs +256 -0
  99. package/source/shared/validations/Server/NotFoundHandler/index.mjs +94 -0
  100. package/source/shared/validations/Server/Router/index.mjs +68 -0
  101. package/source/shared/validations/Server/ServerConfiguration/index.mjs +68 -0
  102. package/source/shared/validations/Server/SystemErrorHandler/index.mjs +94 -0
  103. package/source/shared/validations/ServerConfiguration/CORSOptions/index.mjs +310 -0
  104. package/source/shared/validations/ServerConfiguration/CSRFOptions/index.mjs +299 -0
  105. package/source/shared/validations/ServerConfiguration/CompressOptions/index.mjs +204 -0
  106. package/source/shared/validations/ServerConfiguration/CookieParserOptions/index.mjs +102 -0
  107. package/source/shared/validations/ServerConfiguration/CookieSessionOptions/index.mjs +332 -0
  108. package/source/shared/validations/ServerConfiguration/ListenOptions/index.mjs +178 -0
  109. package/source/shared/validations/ServerConfiguration/RateLimitOptions/index.mjs +229 -0
  110. package/source/shared/validations/ServerConfiguration/RequestOptions/index.mjs +132 -0
  111. package/source/shared/validations/ServerConfiguration/ResponseOptions/index.mjs +122 -0
  112. package/source/shared/validations/ServerConfiguration/SecurityHeadersOptions/index.mjs +137 -0
  113. package/source/shared/validations/ServerConfiguration/StaticOptions/index.mjs +248 -0
  114. package/types/index.d.ts +719 -0
@@ -0,0 +1,81 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the CompressOptions middleware configuration option.
4
+ *
5
+ * @description CompressOptions wraps a normalized CompressOptionsValue into
6
+ * the middleware configuration option hierarchy.
7
+ *
8
+ * @module CompressOptions
9
+ */
10
+
11
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
12
+ // » IMPORT LOCAL MODULES
13
+ import MiddlewareOption from '../MiddlewareOption.mjs';
14
+ import CompressOptionsValue from './CompressOptionsValue.mjs';
15
+
16
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ /**
18
+ * Represents the compression options accepted by the server configuration.
19
+ *
20
+ * @typedef {import('./CompressOptionsValue.mjs').CompressOptionsInput} CompressOptionsInput
21
+ */
22
+
23
+ /**
24
+ * Represents the normalized compression options.
25
+ *
26
+ * @typedef {import('./CompressOptionsValue.mjs').CompressOptionsData} CompressOptionsData
27
+ */
28
+
29
+ /**
30
+ * Represents one middleware configuration consumed by the exchange layer builder.
31
+ *
32
+ * @typedef {import('../MiddlewareOption.mjs').MiddlewareConfiguration} MiddlewareConfiguration
33
+ */
34
+
35
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
36
+ /**
37
+ * Middleware configuration option wrapping a normalized compression
38
+ * configuration.
39
+ *
40
+ * @augments {MiddlewareOption<CompressOptionsData|undefined>}
41
+ */
42
+ class CompressOptions extends MiddlewareOption {
43
+ /**
44
+ * Creates a new {@link CompressOptions}.
45
+ *
46
+ * @param {CompressOptionsInput} [options] - The compression middleware options.
47
+ * @example
48
+ * ```js
49
+ * const compressOptions = new CompressOptions({ threshold: 1024, level: 6 });
50
+ * ```
51
+ */
52
+ constructor(options) {
53
+ super('compress', new CompressOptionsValue(options));
54
+ }
55
+
56
+ /**
57
+ * Composes the compression middleware configuration consumed by the
58
+ * exchange layer builder.
59
+ *
60
+ * Compression is a cross-cutting concern applied to every response
61
+ * regardless of pathname or method, so both `pathnamePattern` and `method`
62
+ * are `undefined`.
63
+ *
64
+ * @returns {MiddlewareConfiguration} The composed middleware configuration.
65
+ * @example
66
+ * ```js
67
+ * const configuration = compressOptions.compose();
68
+ * ```
69
+ */
70
+ compose() {
71
+ return {
72
+ name: this.name,
73
+ options: this.value,
74
+ pathnamePattern: undefined,
75
+ method: undefined,
76
+ };
77
+ }
78
+ }
79
+
80
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
81
+ export default CompressOptions;
@@ -0,0 +1,107 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the CookieParserOptionsValue value object.
4
+ *
5
+ * @description Normalizes and validates cookie parser middleware
6
+ * configuration used by CookieParserMiddleware. When options are omitted,
7
+ * the value is undefined and the middleware is not registered.
8
+ *
9
+ * @module CookieParserOptionsValue
10
+ */
11
+
12
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
+ // » IMPORT LOCAL MODULES
14
+ import { assertCookieParserOptions } from '#shared/validations/ServerConfiguration/CookieParserOptions';
15
+
16
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ /**
18
+ * Domain error thrown by server configuration validation.
19
+ *
20
+ * @typedef {import('#shared/errors/ServerConfigurationError').default} ServerConfigurationError
21
+ */
22
+
23
+ /**
24
+ * Represents the cookie parser options accepted by the server configuration.
25
+ *
26
+ * @typedef {object} CookieParserOptionsInput
27
+ * @property {boolean} [decode] - Whether cookie values are decoded with `decodeURIComponent`.
28
+ */
29
+
30
+ /**
31
+ * Represents the normalized cookie parser options.
32
+ *
33
+ * @typedef {object} CookieParserOptionsData
34
+ * @property {boolean} decode - Whether cookie values are decoded with `decodeURIComponent`.
35
+ */
36
+
37
+ // ━━ CONSTANTS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
38
+ /**
39
+ * Default URI-decoding behavior for cookie values.
40
+ *
41
+ * @type {boolean}
42
+ */
43
+ const DEFAULT_DECODE = true;
44
+
45
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
46
+ /**
47
+ * Immutable value object representing normalized cookie parser middleware
48
+ * options.
49
+ *
50
+ * @classdesc Validates and normalizes cookie parser middleware options. When
51
+ * options are provided, defaults are applied for any omitted property. When
52
+ * options are omitted, the value is undefined.
53
+ *
54
+ * @example
55
+ * ```js
56
+ * const options = new CookieParserOptionsValue({ decode: false });
57
+ *
58
+ * options.value;
59
+ * // => { decode: false }
60
+ * ```
61
+ *
62
+ * @example
63
+ * ```js
64
+ * const options = new CookieParserOptionsValue();
65
+ *
66
+ * options.value;
67
+ * // => undefined
68
+ * ```
69
+ */
70
+ class CookieParserOptionsValue {
71
+ /**
72
+ * The normalized cookie parser options.
73
+ *
74
+ * @type {Readonly<CookieParserOptionsData>|undefined}
75
+ */
76
+ #value;
77
+
78
+ /**
79
+ * Creates a new {@link CookieParserOptionsValue}.
80
+ *
81
+ * @param {CookieParserOptionsInput} [options] - The cookie parser middleware options.
82
+ * @throws {ServerConfigurationError} If `options` is invalid.
83
+ */
84
+ constructor(options) {
85
+ assertCookieParserOptions(options);
86
+
87
+ this.#value =
88
+ options === undefined
89
+ ? options
90
+ : Object.freeze({
91
+ decode: options.decode ?? DEFAULT_DECODE,
92
+ });
93
+ }
94
+
95
+ /**
96
+ * The normalized cookie parser options.
97
+ *
98
+ * @readonly
99
+ * @type {Readonly<CookieParserOptionsData>|undefined}
100
+ */
101
+ get value() {
102
+ return this.#value;
103
+ }
104
+ }
105
+
106
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
107
+ export default CookieParserOptionsValue;
@@ -0,0 +1,82 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the CookieParserOptions middleware configuration option.
4
+ *
5
+ * @description CookieParserOptions wraps a normalized
6
+ * CookieParserOptionsValue into the middleware configuration option
7
+ * hierarchy.
8
+ *
9
+ * @module CookieParserOptions
10
+ */
11
+
12
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
+ // » IMPORT LOCAL MODULES
14
+ import MiddlewareOption from '../MiddlewareOption.mjs';
15
+ import CookieParserOptionsValue from './CookieParserOptionsValue.mjs';
16
+
17
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18
+ /**
19
+ * Represents the cookie parser options accepted by the server configuration.
20
+ *
21
+ * @typedef {import('./CookieParserOptionsValue.mjs').CookieParserOptionsInput} CookieParserOptionsInput
22
+ */
23
+
24
+ /**
25
+ * Represents the normalized cookie parser options.
26
+ *
27
+ * @typedef {import('./CookieParserOptionsValue.mjs').CookieParserOptionsData} CookieParserOptionsData
28
+ */
29
+
30
+ /**
31
+ * Represents one middleware configuration consumed by the exchange layer builder.
32
+ *
33
+ * @typedef {import('../MiddlewareOption.mjs').MiddlewareConfiguration} MiddlewareConfiguration
34
+ */
35
+
36
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
37
+ /**
38
+ * Middleware configuration option wrapping a normalized cookie parser
39
+ * configuration.
40
+ *
41
+ * @augments {MiddlewareOption<CookieParserOptionsData|undefined>}
42
+ */
43
+ class CookieParserOptions extends MiddlewareOption {
44
+ /**
45
+ * Creates a new {@link CookieParserOptions}.
46
+ *
47
+ * @param {CookieParserOptionsInput} [options] - The cookie parser middleware options.
48
+ * @example
49
+ * ```js
50
+ * const cookieParserOptions = new CookieParserOptions({ decode: true });
51
+ * ```
52
+ */
53
+ constructor(options) {
54
+ super('cookieParser', new CookieParserOptionsValue(options));
55
+ }
56
+
57
+ /**
58
+ * Composes the cookie parser middleware configuration consumed by the
59
+ * exchange layer builder.
60
+ *
61
+ * Cookie parsing is a cross-cutting concern applied to every request
62
+ * regardless of pathname or method, so both `pathnamePattern` and `method`
63
+ * are `undefined`.
64
+ *
65
+ * @returns {MiddlewareConfiguration} The composed middleware configuration.
66
+ * @example
67
+ * ```js
68
+ * const configuration = cookieParserOptions.compose();
69
+ * ```
70
+ */
71
+ compose() {
72
+ return {
73
+ name: this.name,
74
+ options: this.value,
75
+ pathnamePattern: undefined,
76
+ method: undefined,
77
+ };
78
+ }
79
+ }
80
+
81
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
82
+ export default CookieParserOptions;
@@ -0,0 +1,182 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the CookieSessionOptionsValue value object.
4
+ *
5
+ * @description Normalizes and validates cookie session middleware
6
+ * configuration used by CookieSessionMiddleware. When options are omitted,
7
+ * the value is undefined and the middleware is not registered.
8
+ *
9
+ * @module CookieSessionOptionsValue
10
+ */
11
+
12
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
+ // » IMPORT LOCAL MODULES
14
+ import { assertCookieSessionOptions } from '#shared/validations/ServerConfiguration/CookieSessionOptions';
15
+
16
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ /**
18
+ * Domain error thrown by server configuration validation.
19
+ *
20
+ * @typedef {import('#shared/errors/ServerConfigurationError').default} ServerConfigurationError
21
+ */
22
+
23
+ /**
24
+ * Represents the cookie session options accepted by the server configuration.
25
+ *
26
+ * @typedef {object} CookieSessionOptionsInput
27
+ * @property {string} [name] - Name of the session cookie.
28
+ * @property {string[]} keys - Signing keys. Required when options are provided.
29
+ * @property {number} [maxAge] - Cookie max-age in milliseconds. When omitted, the cookie is a session cookie.
30
+ * @property {string} [path] - Cookie path attribute.
31
+ * @property {string} [domain] - Cookie domain attribute.
32
+ * @property {boolean} [secure] - Whether the cookie is marked Secure.
33
+ * @property {boolean} [httpOnly] - Whether the cookie is marked HttpOnly.
34
+ * @property {'Strict'|'Lax'|'None'} [sameSite] - Cookie SameSite attribute.
35
+ * @property {boolean} [overwrite] - Whether an existing Set-Cookie header with the same name should be overwritten.
36
+ */
37
+
38
+ // eslint-disable-next-line jsdoc/check-line-alignment
39
+ /**
40
+ * Represents the normalized cookie session options.
41
+ *
42
+ * @typedef {object} CookieSessionOptionsData
43
+ * @property {string} name - Name of the session cookie.
44
+ * @property {Readonly<string[]>} keys - Signing keys. The first key is used to sign; all keys are tried when verifying.
45
+ * @property {number|undefined} maxAge - Cookie max-age in milliseconds. When `undefined`, the cookie is a session cookie.
46
+ * @property {string} path - Cookie path attribute.
47
+ * @property {string|undefined} domain - Cookie domain attribute.
48
+ * @property {boolean} secure - Whether the cookie is marked Secure.
49
+ * @property {boolean} httpOnly - Whether the cookie is marked HttpOnly.
50
+ * @property {'Strict'|'Lax'|'None'} sameSite - Cookie SameSite attribute.
51
+ * @property {boolean} overwrite - Whether an existing Set-Cookie header with the same name should be overwritten.
52
+ */
53
+
54
+ // ━━ CONSTANTS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
55
+ /**
56
+ * Default session cookie name.
57
+ *
58
+ * @type {string}
59
+ */
60
+ const DEFAULT_NAME = 'session';
61
+
62
+ /**
63
+ * Default cookie path attribute.
64
+ *
65
+ * @type {string}
66
+ */
67
+ const DEFAULT_PATH = '/';
68
+
69
+ /**
70
+ * Default Secure attribute.
71
+ *
72
+ * @type {boolean}
73
+ */
74
+ const DEFAULT_SECURE = true;
75
+
76
+ /**
77
+ * Default HttpOnly attribute.
78
+ *
79
+ * @type {boolean}
80
+ */
81
+ const DEFAULT_HTTP_ONLY = true;
82
+
83
+ /**
84
+ * Default SameSite attribute.
85
+ *
86
+ * @type {'Strict'|'Lax'|'None'}
87
+ */
88
+ const DEFAULT_SAME_SITE = 'Lax';
89
+
90
+ /**
91
+ * Default overwrite behavior.
92
+ *
93
+ * @type {boolean}
94
+ */
95
+ const DEFAULT_OVERWRITE = true;
96
+
97
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
98
+ /**
99
+ * Immutable value object representing normalized cookie session middleware
100
+ * options.
101
+ *
102
+ * @classdesc Validates and normalizes cookie session middleware options.
103
+ * When options are provided, defaults are applied for any omitted property.
104
+ * When options are omitted, the value is undefined.
105
+ *
106
+ * @example
107
+ * ```js
108
+ * const options = new CookieSessionOptionsValue(
109
+ * { keys: ['current-secret', 'previous-secret'] },
110
+ * true,
111
+ * );
112
+ *
113
+ * options.value;
114
+ * // => {
115
+ * // name: 'session',
116
+ * // keys: ['current-secret', 'previous-secret'],
117
+ * // maxAge: undefined,
118
+ * // path: '/',
119
+ * // domain: undefined,
120
+ * // secure: true,
121
+ * // httpOnly: true,
122
+ * // sameSite: 'Lax',
123
+ * // overwrite: true,
124
+ * // }
125
+ * ```
126
+ *
127
+ * @example
128
+ * ```js
129
+ * const options = new CookieSessionOptionsValue(undefined, false);
130
+ *
131
+ * options.value;
132
+ * // => undefined
133
+ * ```
134
+ */
135
+ class CookieSessionOptionsValue {
136
+ /**
137
+ * The normalized cookie session options.
138
+ *
139
+ * @type {Readonly<CookieSessionOptionsData>|undefined}
140
+ */
141
+ #value;
142
+
143
+ /**
144
+ * Creates a new {@link CookieSessionOptionsValue}.
145
+ *
146
+ * @param {CookieSessionOptionsInput} [options] - The cookie session middleware options.
147
+ * @param {boolean} [hasParser] - Whether a cookie parser is configured.
148
+ * @throws {ServerConfigurationError} If `options` is invalid.
149
+ * @throws {ServerConfigurationError} If no cookie parser is configured.
150
+ */
151
+ constructor(options, hasParser) {
152
+ assertCookieSessionOptions(options, hasParser);
153
+
154
+ this.#value =
155
+ options === undefined
156
+ ? options
157
+ : Object.freeze({
158
+ name: options.name ?? DEFAULT_NAME,
159
+ keys: Object.freeze([...options.keys]),
160
+ maxAge: options.maxAge,
161
+ path: options.path ?? DEFAULT_PATH,
162
+ domain: options.domain,
163
+ secure: options.secure ?? DEFAULT_SECURE,
164
+ httpOnly: options.httpOnly ?? DEFAULT_HTTP_ONLY,
165
+ sameSite: options.sameSite ?? DEFAULT_SAME_SITE,
166
+ overwrite: options.overwrite ?? DEFAULT_OVERWRITE,
167
+ });
168
+ }
169
+
170
+ /**
171
+ * The normalized cookie session options.
172
+ *
173
+ * @readonly
174
+ * @type {Readonly<CookieSessionOptionsData>|undefined}
175
+ */
176
+ get value() {
177
+ return this.#value;
178
+ }
179
+ }
180
+
181
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
182
+ export default CookieSessionOptionsValue;
@@ -0,0 +1,86 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the CookieSessionOptions middleware configuration option.
4
+ *
5
+ * @description CookieSessionOptions wraps a normalized
6
+ * CookieSessionOptionsValue into the middleware configuration option
7
+ * hierarchy.
8
+ *
9
+ * @module CookieSessionOptions
10
+ */
11
+
12
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
+ // » IMPORT LOCAL MODULES
14
+ import MiddlewareOption from '../MiddlewareOption.mjs';
15
+ import CookieSessionOptionsValue from './CookieSessionOptionsValue.mjs';
16
+
17
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18
+ /**
19
+ * Represents the cookie session options accepted by the server configuration.
20
+ *
21
+ * @typedef {import('./CookieSessionOptionsValue.mjs').CookieSessionOptionsInput} CookieSessionOptionsInput
22
+ */
23
+
24
+ /**
25
+ * Represents the normalized cookie session options.
26
+ *
27
+ * @typedef {import('./CookieSessionOptionsValue.mjs').CookieSessionOptionsData} CookieSessionOptionsData
28
+ */
29
+
30
+ /**
31
+ * Represents one middleware configuration consumed by the exchange layer builder.
32
+ *
33
+ * @typedef {import('../MiddlewareOption.mjs').MiddlewareConfiguration} MiddlewareConfiguration
34
+ */
35
+
36
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
37
+ /**
38
+ * Middleware configuration option wrapping a normalized cookie session
39
+ * configuration.
40
+ *
41
+ * @augments {MiddlewareOption<CookieSessionOptionsData|undefined>}
42
+ */
43
+ class CookieSessionOptions extends MiddlewareOption {
44
+ /**
45
+ * Creates a new {@link CookieSessionOptions}.
46
+ *
47
+ * @param {CookieSessionOptionsInput} [options] - The cookie session middleware options.
48
+ * @param {boolean} [hasParser] - Whether a cookie parser is configured.
49
+ * @example
50
+ * ```js
51
+ * const cookieSessionOptions = new CookieSessionOptions(
52
+ * { keys: ['current-secret'] },
53
+ * true,
54
+ * );
55
+ * ```
56
+ */
57
+ constructor(options, hasParser) {
58
+ super('cookieSession', new CookieSessionOptionsValue(options, hasParser));
59
+ }
60
+
61
+ /**
62
+ * Composes the cookie session middleware configuration consumed by the
63
+ * exchange layer builder.
64
+ *
65
+ * Cookie session is a cross-cutting concern applied to every request
66
+ * regardless of pathname or method, so both `pathnamePattern` and `method`
67
+ * are `undefined`.
68
+ *
69
+ * @returns {MiddlewareConfiguration} The composed middleware configuration.
70
+ * @example
71
+ * ```js
72
+ * const configuration = cookieSessionOptions.compose();
73
+ * ```
74
+ */
75
+ compose() {
76
+ return {
77
+ name: this.name,
78
+ options: this.value,
79
+ pathnamePattern: undefined,
80
+ method: undefined,
81
+ };
82
+ }
83
+ }
84
+
85
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
86
+ export default CookieSessionOptions;
@@ -0,0 +1,95 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the ListenOptionsValue value object.
4
+ *
5
+ * @description Normalizes and validates listen configuration used by
6
+ * ServerConfiguration. When no options are provided, the value is
7
+ * undefined and Node applies its own defaults.
8
+ *
9
+ * @module ListenOptionsValue
10
+ */
11
+
12
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
+ // » IMPORT LOCAL MODULES
14
+ import { assertListenOptions } from '#shared/validations/ServerConfiguration/ListenOptions';
15
+
16
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ /**
18
+ * Domain error thrown by server configuration validation.
19
+ *
20
+ * @typedef {import('#shared/errors/ServerConfigurationError').default} ServerConfigurationError
21
+ */
22
+
23
+ /**
24
+ * Represents the listen options accepted by the server configuration.
25
+ *
26
+ * @typedef {object} ListenOptionsInput
27
+ * @property {number} [port] - The TCP port on which the server listens.
28
+ * @property {string} [host] - The hostname or IP address on which the server listens.
29
+ * @property {number} [backlog] - The maximum number of pending connections that may be queued.
30
+ */
31
+
32
+ /**
33
+ * Represents the normalized listen options.
34
+ *
35
+ * @typedef {object} ListenOptionsData
36
+ * @property {number|undefined} port - The TCP port on which the server listens.
37
+ * @property {string|undefined} host - The hostname or IP address on which the server listens.
38
+ * @property {number|undefined} backlog - The maximum number of pending connections that may be queued.
39
+ */
40
+
41
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
42
+ /**
43
+ * Immutable value object representing normalized listen options.
44
+ *
45
+ * @classdesc Validates and normalizes listen options for the server.
46
+ * When no options are provided, the value is undefined.
47
+ */
48
+ class ListenOptionsValue {
49
+ /**
50
+ * The normalized listen options.
51
+ *
52
+ * @type {Readonly<ListenOptionsData>|undefined}
53
+ */
54
+ #value;
55
+
56
+ /**
57
+ * Creates a new {@link ListenOptionsValue}.
58
+ *
59
+ * @param {ListenOptionsInput} [options] - The listen options.
60
+ * @throws {ServerConfigurationError} If `options` is invalid.
61
+ *
62
+ * @example
63
+ * ```js
64
+ * const options = new ListenOptionsValue({ port: 3000 });
65
+ *
66
+ * options.value;
67
+ * // => { port: 3000, host: undefined, backlog: undefined }
68
+ * ```
69
+ */
70
+ constructor(options) {
71
+ assertListenOptions(options);
72
+
73
+ this.#value =
74
+ options === undefined
75
+ ? options
76
+ : Object.freeze({
77
+ port: options.port,
78
+ host: options.host,
79
+ backlog: options.backlog,
80
+ });
81
+ }
82
+
83
+ /**
84
+ * The normalized listen options.
85
+ *
86
+ * @readonly
87
+ * @type {Readonly<ListenOptionsData>|undefined}
88
+ */
89
+ get value() {
90
+ return this.#value;
91
+ }
92
+ }
93
+
94
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
95
+ export default ListenOptionsValue;
@@ -0,0 +1,47 @@
1
+ // @ts-check
2
+ /**
3
+ * @file Defines the ListenOptions server configuration option.
4
+ *
5
+ * @description ListenOptions wraps a normalized ListenOptionsValue into the
6
+ * server configuration option hierarchy.
7
+ *
8
+ * @module ListenOptions
9
+ */
10
+
11
+ // ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
12
+ // » IMPORT LOCAL MODULES
13
+ import ServerOption from '../ServerOption.mjs';
14
+ import ListenOptionsValue from './ListenOptionsValue.mjs';
15
+
16
+ // ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
17
+ /**
18
+ * Represents the listen options accepted by the server configuration.
19
+ *
20
+ * @typedef {import('./ListenOptionsValue.mjs').ListenOptionsInput} ListenOptionsInput
21
+ */
22
+
23
+ /**
24
+ * Represents the normalized listen options.
25
+ *
26
+ * @typedef {import('./ListenOptionsValue.mjs').ListenOptionsData} ListenOptionsData
27
+ */
28
+
29
+ // ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
30
+ /**
31
+ * Server configuration option wrapping a normalized listen configuration.
32
+ *
33
+ * @augments {ServerOption<ListenOptionsData|undefined>}
34
+ */
35
+ class ListenOptions extends ServerOption {
36
+ /**
37
+ * Creates a new {@link ListenOptions}.
38
+ *
39
+ * @param {ListenOptionsInput} [options] - The listen options.
40
+ */
41
+ constructor(options) {
42
+ super('listen', new ListenOptionsValue(options));
43
+ }
44
+ }
45
+
46
+ // ━━ EXPORT MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
+ export default ListenOptions;