@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.
- package/README.md +229 -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
package/source/application/configurations/ServerConfiguration/Options/CompressOptions/index.mjs
ADDED
|
@@ -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;
|
package/source/application/configurations/ServerConfiguration/Options/CookieParserOptions/index.mjs
ADDED
|
@@ -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;
|
package/source/application/configurations/ServerConfiguration/Options/CookieSessionOptions/index.mjs
ADDED
|
@@ -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;
|