@boo-labs/server 1.0.1 → 1.0.2
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/package.json +1 -1
- package/source/core/IPCMain/IPCProtocol.mjs +80 -75
- package/source/shared/domain/UUIDV7/index.mjs +31 -39
- package/source/shared/errors/ServerError/index.mjs +48 -2
- package/source/shared/outcome/Result/index.mjs +77 -130
- package/source/shared/outcome/Validation/index.mjs +56 -114
- package/source/shared/validations/Middleware/index.mjs +32 -23
- package/source/shared/validations/PathnamePattern/index.mjs +38 -39
- package/source/shared/validations/Server/NotFoundHandler/index.mjs +25 -15
- package/source/shared/validations/Server/Router/index.mjs +24 -14
- package/source/shared/validations/Server/ServerConfiguration/index.mjs +24 -14
- package/source/shared/validations/Server/SystemErrorHandler/index.mjs +25 -15
- package/source/shared/validations/ServerConfiguration/CORSOptions/index.mjs +95 -91
- package/source/shared/validations/ServerConfiguration/CSRFOptions/index.mjs +96 -96
- package/source/shared/validations/ServerConfiguration/CompressOptions/index.mjs +55 -43
- package/source/shared/validations/ServerConfiguration/CookieParserOptions/index.mjs +28 -13
- package/source/shared/validations/ServerConfiguration/CookieSessionOptions/index.mjs +101 -111
- package/source/shared/validations/ServerConfiguration/ListenOptions/index.mjs +55 -43
- package/source/shared/validations/ServerConfiguration/RateLimitOptions/index.mjs +71 -61
- package/source/shared/validations/ServerConfiguration/RequestOptions/index.mjs +44 -31
- package/source/shared/validations/ServerConfiguration/ResponseOptions/index.mjs +39 -25
- package/source/shared/validations/ServerConfiguration/SecurityHeadersOptions/index.mjs +27 -14
- package/source/shared/validations/ServerConfiguration/StaticOptions/index.mjs +85 -84
- package/source/shared/outcome/ErrorSchema.mjs +0 -361
|
@@ -14,11 +14,24 @@
|
|
|
14
14
|
import Validation from '#shared/outcome/Validation';
|
|
15
15
|
import PathnamePatternError from '#shared/errors/PathnamePatternError';
|
|
16
16
|
|
|
17
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
18
|
+
/**
|
|
19
|
+
* A successful {@link Validation} instance.
|
|
20
|
+
*
|
|
21
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A failed {@link Validation} instance.
|
|
26
|
+
*
|
|
27
|
+
* @template {Error} E
|
|
28
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
29
|
+
*/
|
|
30
|
+
|
|
17
31
|
// ━━ CONSTANTS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
18
32
|
/**
|
|
19
33
|
* Maximum number of characters allowed in a pathname pattern.
|
|
20
34
|
*
|
|
21
|
-
* @private
|
|
22
35
|
* @type {number}
|
|
23
36
|
*/
|
|
24
37
|
const MAX_PATTERN_LENGTH = 512;
|
|
@@ -29,7 +42,6 @@ const MAX_PATTERN_LENGTH = 512;
|
|
|
29
42
|
* Parameter names must begin with a letter or underscore and may contain
|
|
30
43
|
* letters, digits, and underscores.
|
|
31
44
|
*
|
|
32
|
-
* @private
|
|
33
45
|
* @type {string}
|
|
34
46
|
*/
|
|
35
47
|
const PARAM_NAME = String.raw`[A-Za-z_][A-Za-z0-9_]*`;
|
|
@@ -38,7 +50,6 @@ const PARAM_NAME = String.raw`[A-Za-z_][A-Za-z0-9_]*`;
|
|
|
38
50
|
* Regular expression source for a literal character allowed inside a pathname
|
|
39
51
|
* segment.
|
|
40
52
|
*
|
|
41
|
-
* @private
|
|
42
53
|
* @type {string}
|
|
43
54
|
*/
|
|
44
55
|
const LITERAL_CHAR = String.raw`[A-Za-z0-9._~!$&'()+,;=@-]`;
|
|
@@ -49,7 +60,6 @@ const LITERAL_CHAR = String.raw`[A-Za-z0-9._~!$&'()+,;=@-]`;
|
|
|
49
60
|
*
|
|
50
61
|
* Supported forms are `:name` and `{name}`.
|
|
51
62
|
*
|
|
52
|
-
* @private
|
|
53
63
|
* @type {string}
|
|
54
64
|
*/
|
|
55
65
|
const PARAM_SEGMENT = String.raw`(?::${PARAM_NAME}|\{${PARAM_NAME}\})`;
|
|
@@ -111,7 +121,8 @@ const PARAMETER_PATTERN_REGEXP = /:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0
|
|
|
111
121
|
*
|
|
112
122
|
* @private
|
|
113
123
|
* @param {string} pathnamePattern - Pathname pattern to validate.
|
|
114
|
-
* @returns {
|
|
124
|
+
* @returns {SuccessValidation|FailureValidation<PathnamePatternError>} Validation result.
|
|
125
|
+
*
|
|
115
126
|
* @example
|
|
116
127
|
* ```js
|
|
117
128
|
* const validation = validateUniqueParamNames('/users/:id/posts/{postId}');
|
|
@@ -119,6 +130,7 @@ const PARAMETER_PATTERN_REGEXP = /:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0
|
|
|
119
130
|
* console.log(validation.ok);
|
|
120
131
|
* // => true
|
|
121
132
|
* ```
|
|
133
|
+
*
|
|
122
134
|
* @example
|
|
123
135
|
* ```js
|
|
124
136
|
* const validation = validateUniqueParamNames('/users/:id/posts/{id}');
|
|
@@ -134,15 +146,12 @@ function validateUniqueParamNames(pathnamePattern) {
|
|
|
134
146
|
const name = match[1] ?? match[2];
|
|
135
147
|
|
|
136
148
|
if (names.has(name)) {
|
|
137
|
-
return Validation.failure(
|
|
138
|
-
|
|
139
|
-
code: 'DUPLICATE_PARAMETER_NAME',
|
|
140
|
-
custom: true,
|
|
141
|
-
options: {
|
|
149
|
+
return Validation.failure(
|
|
150
|
+
new PathnamePatternError('DUPLICATE_PARAMETER_NAME', {
|
|
142
151
|
values: { name },
|
|
143
152
|
details: { pathnamePattern },
|
|
144
|
-
},
|
|
145
|
-
|
|
153
|
+
}),
|
|
154
|
+
);
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
names.add(name);
|
|
@@ -165,7 +174,8 @@ function validateUniqueParamNames(pathnamePattern) {
|
|
|
165
174
|
* 5. Parameter names must be unique.
|
|
166
175
|
*
|
|
167
176
|
* @param {unknown} pathnamePattern - Pathname pattern to validate.
|
|
168
|
-
* @returns {
|
|
177
|
+
* @returns {SuccessValidation|FailureValidation<PathnamePatternError>} Validation result.
|
|
178
|
+
*
|
|
169
179
|
* @example
|
|
170
180
|
* ```js
|
|
171
181
|
* const validation = validatePathnamePattern('/users/:id');
|
|
@@ -184,45 +194,32 @@ function validateUniqueParamNames(pathnamePattern) {
|
|
|
184
194
|
*/
|
|
185
195
|
export function validatePathnamePattern(pathnamePattern) {
|
|
186
196
|
if (typeof pathnamePattern !== 'string') {
|
|
187
|
-
return Validation.failure(
|
|
188
|
-
|
|
189
|
-
code: 'INVALID_PATTERN_TYPE',
|
|
190
|
-
custom: true,
|
|
191
|
-
options: {
|
|
197
|
+
return Validation.failure(
|
|
198
|
+
new PathnamePatternError('INVALID_PATTERN_TYPE', {
|
|
192
199
|
values: { expected: 'string', received: typeof pathnamePattern },
|
|
193
|
-
},
|
|
194
|
-
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
195
202
|
}
|
|
196
203
|
|
|
197
204
|
if (pathnamePattern.length === 0) {
|
|
198
|
-
return Validation.failure(
|
|
199
|
-
error: PathnamePatternError,
|
|
200
|
-
code: 'EMPTY_PATTERN',
|
|
201
|
-
custom: true,
|
|
202
|
-
});
|
|
205
|
+
return Validation.failure(new PathnamePatternError('EMPTY_PATTERN'));
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
if (pathnamePattern.length > MAX_PATTERN_LENGTH) {
|
|
206
|
-
return Validation.failure(
|
|
207
|
-
|
|
208
|
-
code: 'PATTERN_TOO_LONG',
|
|
209
|
-
custom: true,
|
|
210
|
-
options: {
|
|
209
|
+
return Validation.failure(
|
|
210
|
+
new PathnamePatternError('PATTERN_TOO_LONG', {
|
|
211
211
|
values: { maxLength: MAX_PATTERN_LENGTH, actualLength: pathnamePattern.length },
|
|
212
|
-
},
|
|
213
|
-
|
|
212
|
+
}),
|
|
213
|
+
);
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
if (!PATHNAME_PATTERN_REGEXP.test(pathnamePattern)) {
|
|
217
|
-
return Validation.failure(
|
|
218
|
-
|
|
219
|
-
code: 'INVALID_PATHNAME_PATTERN',
|
|
220
|
-
custom: true,
|
|
221
|
-
options: {
|
|
217
|
+
return Validation.failure(
|
|
218
|
+
new PathnamePatternError('INVALID_PATHNAME_PATTERN', {
|
|
222
219
|
values: { pathnamePattern },
|
|
223
220
|
details: { constraint: 'Must be * or start with / and contain valid segments' },
|
|
224
|
-
},
|
|
225
|
-
|
|
221
|
+
}),
|
|
222
|
+
);
|
|
226
223
|
}
|
|
227
224
|
|
|
228
225
|
return validateUniqueParamNames(pathnamePattern);
|
|
@@ -237,6 +234,7 @@ export function validatePathnamePattern(pathnamePattern) {
|
|
|
237
234
|
* @throws {PathnamePatternError} If the pathname pattern exceeds the maximum length.
|
|
238
235
|
* @throws {PathnamePatternError} If the pathname pattern syntax is invalid.
|
|
239
236
|
* @throws {PathnamePatternError} If the pathname pattern has duplicate parameter names.
|
|
237
|
+
*
|
|
240
238
|
* @example
|
|
241
239
|
* ```js
|
|
242
240
|
* assertPathnamePattern('/users/:id');
|
|
@@ -250,6 +248,7 @@ export function validatePathnamePattern(pathnamePattern) {
|
|
|
250
248
|
*/
|
|
251
249
|
export function assertPathnamePattern(pathnamePattern) {
|
|
252
250
|
const validation = validatePathnamePattern(pathnamePattern);
|
|
251
|
+
|
|
253
252
|
if (!validation.ok) {
|
|
254
253
|
throw validation.error;
|
|
255
254
|
}
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
import Validation from '#shared/outcome/Validation';
|
|
14
14
|
import ServerError from '#shared/errors/ServerError';
|
|
15
15
|
|
|
16
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
|
+
/**
|
|
18
|
+
* A successful {@link Validation} instance.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A failed {@link Validation} instance.
|
|
25
|
+
*
|
|
26
|
+
* @template {Error} E
|
|
27
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
28
|
+
*/
|
|
29
|
+
|
|
16
30
|
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
31
|
/**
|
|
18
32
|
* Validates a not-found handler.
|
|
@@ -21,7 +35,8 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
21
35
|
* `exchange`.
|
|
22
36
|
*
|
|
23
37
|
* @param {unknown} handler - Handler function to validate.
|
|
24
|
-
* @returns {
|
|
38
|
+
* @returns {SuccessValidation|FailureValidation<ServerError>} Validation result.
|
|
39
|
+
*
|
|
25
40
|
* @example
|
|
26
41
|
* ```js
|
|
27
42
|
* const validation = validateNotFoundHandler((exchange) => {
|
|
@@ -42,31 +57,25 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
42
57
|
*/
|
|
43
58
|
export function validateNotFoundHandler(handler) {
|
|
44
59
|
if (typeof handler !== 'function') {
|
|
45
|
-
return Validation.failure(
|
|
46
|
-
|
|
47
|
-
code: 'INVALID_NOT_FOUND_HANDLER_TYPE',
|
|
48
|
-
custom: true,
|
|
49
|
-
options: {
|
|
60
|
+
return Validation.failure(
|
|
61
|
+
new ServerError('INVALID_NOT_FOUND_HANDLER_TYPE', {
|
|
50
62
|
values: {
|
|
51
63
|
expected: 'function',
|
|
52
64
|
received: typeof handler,
|
|
53
65
|
},
|
|
54
|
-
},
|
|
55
|
-
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
if (handler.length !== 1) {
|
|
59
|
-
return Validation.failure(
|
|
60
|
-
|
|
61
|
-
code: 'INVALID_NOT_FOUND_HANDLER_ARITY',
|
|
62
|
-
custom: true,
|
|
63
|
-
options: {
|
|
71
|
+
return Validation.failure(
|
|
72
|
+
new ServerError('INVALID_NOT_FOUND_HANDLER_ARITY', {
|
|
64
73
|
values: {
|
|
65
74
|
expected: 1,
|
|
66
75
|
received: handler.length,
|
|
67
76
|
},
|
|
68
|
-
},
|
|
69
|
-
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
return Validation.success();
|
|
@@ -78,6 +87,7 @@ export function validateNotFoundHandler(handler) {
|
|
|
78
87
|
* @param {unknown} handler - Handler function to validate.
|
|
79
88
|
* @throws {ServerError} If the handler is not a function.
|
|
80
89
|
* @throws {ServerError} If the handler does not declare exactly one parameter.
|
|
90
|
+
*
|
|
81
91
|
* @example
|
|
82
92
|
* ```js
|
|
83
93
|
* assertNotFoundHandler((exchange) => {
|
|
@@ -13,12 +13,27 @@ import { ROUTER_BRAND } from '#shared/constants/symbols/brands';
|
|
|
13
13
|
import Validation from '#shared/outcome/Validation';
|
|
14
14
|
import ServerError from '#shared/errors/ServerError';
|
|
15
15
|
|
|
16
|
-
// ━━
|
|
16
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
|
+
/**
|
|
18
|
+
* A successful {@link Validation} instance.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A failed {@link Validation} instance.
|
|
25
|
+
*
|
|
26
|
+
* @template {Error} E
|
|
27
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
31
|
/**
|
|
18
32
|
* Validates that a value implements the Router contract.
|
|
19
33
|
*
|
|
20
34
|
* @param {unknown} value - Value to validate.
|
|
21
|
-
* @returns {
|
|
35
|
+
* @returns {SuccessValidation|FailureValidation<ServerError>} Validation result.
|
|
36
|
+
*
|
|
22
37
|
* @example
|
|
23
38
|
* ```js
|
|
24
39
|
* const validation = validateRouter(router);
|
|
@@ -29,21 +44,15 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
29
44
|
*/
|
|
30
45
|
export function validateRouter(value) {
|
|
31
46
|
if (value === null || typeof value !== 'object') {
|
|
32
|
-
return Validation.failure(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
47
|
+
return Validation.failure(
|
|
48
|
+
new ServerError('INVALID_ROUTER_TYPE', {
|
|
49
|
+
values: { received: value === null ? 'null' : typeof value },
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
if (Reflect.get(value, ROUTER_BRAND) !== true) {
|
|
41
|
-
return Validation.failure(
|
|
42
|
-
error: ServerError,
|
|
43
|
-
message: 'Expected a Router instance.',
|
|
44
|
-
code: 'INVALID_ROUTER_INSTANCE',
|
|
45
|
-
custom: true,
|
|
46
|
-
});
|
|
55
|
+
return Validation.failure(new ServerError('INVALID_ROUTER_INSTANCE'));
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
return Validation.success();
|
|
@@ -54,6 +63,7 @@ export function validateRouter(value) {
|
|
|
54
63
|
*
|
|
55
64
|
* @param {unknown} value - Value to assert.
|
|
56
65
|
* @throws {ServerError} If the value does not implement the Router contract.
|
|
66
|
+
*
|
|
57
67
|
* @example
|
|
58
68
|
* ```js
|
|
59
69
|
* assertRouter(router);
|
|
@@ -13,12 +13,27 @@ import { SERVER_CONFIGURATION_BRAND } from '#shared/constants/symbols/brands';
|
|
|
13
13
|
import Validation from '#shared/outcome/Validation';
|
|
14
14
|
import ServerError from '#shared/errors/ServerError';
|
|
15
15
|
|
|
16
|
-
// ━━
|
|
16
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
|
+
/**
|
|
18
|
+
* A successful {@link Validation} instance.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A failed {@link Validation} instance.
|
|
25
|
+
*
|
|
26
|
+
* @template {Error} E
|
|
27
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
31
|
/**
|
|
18
32
|
* Validates that a value implements the ServerConfiguration contract.
|
|
19
33
|
*
|
|
20
34
|
* @param {unknown} value - Value to validate.
|
|
21
|
-
* @returns {
|
|
35
|
+
* @returns {SuccessValidation|FailureValidation<ServerError>} Validation result.
|
|
36
|
+
*
|
|
22
37
|
* @example
|
|
23
38
|
* ```js
|
|
24
39
|
* const validation = validateServerConfiguration(configuration);
|
|
@@ -29,21 +44,15 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
29
44
|
*/
|
|
30
45
|
export function validateServerConfiguration(value) {
|
|
31
46
|
if (value === null || typeof value !== 'object') {
|
|
32
|
-
return Validation.failure(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
47
|
+
return Validation.failure(
|
|
48
|
+
new ServerError('INVALID_SERVER_CONFIGURATION_TYPE', {
|
|
49
|
+
values: { received: value === null ? 'null' : typeof value },
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
if (Reflect.get(value, SERVER_CONFIGURATION_BRAND) !== true) {
|
|
41
|
-
return Validation.failure(
|
|
42
|
-
error: ServerError,
|
|
43
|
-
message: 'Expected a ServerConfiguration instance.',
|
|
44
|
-
code: 'INVALID_SERVER_CONFIGURATION_INSTANCE',
|
|
45
|
-
custom: true,
|
|
46
|
-
});
|
|
55
|
+
return Validation.failure(new ServerError('INVALID_SERVER_CONFIGURATION_INSTANCE'));
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
return Validation.success();
|
|
@@ -54,6 +63,7 @@ export function validateServerConfiguration(value) {
|
|
|
54
63
|
*
|
|
55
64
|
* @param {unknown} value - Value to assert.
|
|
56
65
|
* @throws {ServerError} If the value does not implement the ServerConfiguration contract.
|
|
66
|
+
*
|
|
57
67
|
* @example
|
|
58
68
|
* ```js
|
|
59
69
|
* assertServerConfiguration(configuration);
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
import Validation from '#shared/outcome/Validation';
|
|
14
14
|
import ServerError from '#shared/errors/ServerError';
|
|
15
15
|
|
|
16
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
|
+
/**
|
|
18
|
+
* A successful {@link Validation} instance.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A failed {@link Validation} instance.
|
|
25
|
+
*
|
|
26
|
+
* @template {Error} E
|
|
27
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
28
|
+
*/
|
|
29
|
+
|
|
16
30
|
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
31
|
/**
|
|
18
32
|
* Validates a system error handler.
|
|
@@ -21,7 +35,8 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
21
35
|
* parameters: `error` and `exchange`.
|
|
22
36
|
*
|
|
23
37
|
* @param {unknown} handler - Handler function to validate.
|
|
24
|
-
* @returns {
|
|
38
|
+
* @returns {SuccessValidation|FailureValidation<ServerError>} Validation result.
|
|
39
|
+
*
|
|
25
40
|
* @example
|
|
26
41
|
* ```js
|
|
27
42
|
* const validation = validateSystemErrorHandler((error, exchange) => {
|
|
@@ -42,31 +57,25 @@ import ServerError from '#shared/errors/ServerError';
|
|
|
42
57
|
*/
|
|
43
58
|
export function validateSystemErrorHandler(handler) {
|
|
44
59
|
if (typeof handler !== 'function') {
|
|
45
|
-
return Validation.failure(
|
|
46
|
-
|
|
47
|
-
code: 'INVALID_SYSTEM_ERROR_HANDLER_TYPE',
|
|
48
|
-
custom: true,
|
|
49
|
-
options: {
|
|
60
|
+
return Validation.failure(
|
|
61
|
+
new ServerError('INVALID_SYSTEM_ERROR_HANDLER_TYPE', {
|
|
50
62
|
values: {
|
|
51
63
|
expected: 'function',
|
|
52
64
|
received: typeof handler,
|
|
53
65
|
},
|
|
54
|
-
},
|
|
55
|
-
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
if (handler.length !== 2) {
|
|
59
|
-
return Validation.failure(
|
|
60
|
-
|
|
61
|
-
code: 'INVALID_SYSTEM_ERROR_HANDLER_ARITY',
|
|
62
|
-
custom: true,
|
|
63
|
-
options: {
|
|
71
|
+
return Validation.failure(
|
|
72
|
+
new ServerError('INVALID_SYSTEM_ERROR_HANDLER_ARITY', {
|
|
64
73
|
values: {
|
|
65
74
|
expected: 2,
|
|
66
75
|
received: handler.length,
|
|
67
76
|
},
|
|
68
|
-
},
|
|
69
|
-
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
return Validation.success();
|
|
@@ -78,6 +87,7 @@ export function validateSystemErrorHandler(handler) {
|
|
|
78
87
|
* @param {unknown} handler - Handler function to validate.
|
|
79
88
|
* @throws {ServerError} If the handler is not a function.
|
|
80
89
|
* @throws {ServerError} If the handler does not declare exactly two parameters.
|
|
90
|
+
*
|
|
81
91
|
* @example
|
|
82
92
|
* ```js
|
|
83
93
|
* assertSystemErrorHandler((error, exchange) => {
|