@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
|
@@ -1,203 +1,153 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
|
-
* @file
|
|
3
|
+
* @file Result — Represents successful and failed operation outcomes.
|
|
4
4
|
*
|
|
5
|
-
* @description Provides
|
|
6
|
-
* successful
|
|
7
|
-
*
|
|
5
|
+
* @description Provides a generic Result type that explicitly distinguishes
|
|
6
|
+
* successful operations from failed ones through the `ok` discriminant.
|
|
7
|
+
* The discriminant determines which value is available: `value` on success
|
|
8
|
+
* or `error` on failure. Accessing the property for the opposite state throws.
|
|
8
9
|
*
|
|
9
10
|
* @module Result
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
-
// » IMPORT LOCAL MODULES
|
|
14
|
-
import ErrorSchema from '../ErrorSchema.mjs';
|
|
15
|
-
|
|
16
13
|
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
14
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* @typedef {object} NativeErrorOptions
|
|
21
|
-
* @property {unknown} [cause] - Cause associated with the error.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Represents a native Error schema definition.
|
|
15
|
+
* The value associated with a Result state.
|
|
26
16
|
*
|
|
27
|
-
* @
|
|
28
|
-
* @
|
|
29
|
-
* @
|
|
30
|
-
* @property {NativeErrorOptions} [options] - Options passed to the Error constructor.
|
|
31
|
-
* @property {false} custom - Indicates that the constructor represents a native Error.
|
|
32
|
-
* @property {string} code - Error identifier.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Represents options passed to a custom Error constructor.
|
|
37
|
-
*
|
|
38
|
-
* @typedef {object} CustomErrorOptions
|
|
39
|
-
* @property {Record<string, unknown>} [values] - Values used to resolve message placeholders.
|
|
40
|
-
* @property {Record<string, unknown>} [details] - Additional contextual information about the error.
|
|
41
|
-
* @property {unknown} [cause] - Cause associated with the error.
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Represents a custom Error schema definition.
|
|
46
|
-
*
|
|
47
|
-
* @typedef {object} CustomErrorSchema
|
|
48
|
-
* @property {typeof Error} error - Error constructor used to create the error.
|
|
49
|
-
* @property {string} code - Error code used to resolve the error message and error identifier.
|
|
50
|
-
* @property {string} [message] - Literal error message.
|
|
51
|
-
* @property {CustomErrorOptions} [options] - Options passed to the Error constructor.
|
|
52
|
-
* @property {true} custom - Indicates that the constructor represents a custom Error.
|
|
17
|
+
* @template {boolean} K
|
|
18
|
+
* @template T
|
|
19
|
+
* @typedef {K extends true ? T : undefined } Value
|
|
53
20
|
*/
|
|
54
21
|
|
|
55
22
|
/**
|
|
56
|
-
*
|
|
23
|
+
* The error associated with a Result state.
|
|
57
24
|
*
|
|
58
|
-
* @
|
|
25
|
+
* @template {boolean} K
|
|
26
|
+
* @template E
|
|
27
|
+
* @typedef {K extends false ? E : undefined} ErrorValue
|
|
59
28
|
*/
|
|
60
29
|
|
|
61
30
|
/**
|
|
62
|
-
*
|
|
31
|
+
* A successful {@link Result} instance.
|
|
63
32
|
*
|
|
64
33
|
* @template T
|
|
65
|
-
* @typedef
|
|
66
|
-
* @property {true} ok - Indicates that the operation succeeded.
|
|
67
|
-
* @property {T} value - Successful value produced by the operation.
|
|
68
|
-
* @property {undefined} [error] - Always undefined for a successful result.
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Represents the failed state of a {@link Result} instance.
|
|
73
|
-
*
|
|
74
|
-
* @typedef {object} ResultFailure
|
|
75
|
-
* @property {false} ok - Indicates that the operation failed.
|
|
76
|
-
* @property {undefined} [value] - Always undefined for a failed result.
|
|
77
|
-
* @property {ErrorSchema} error - Error schema describing the operation failure.
|
|
34
|
+
* @typedef {Result<true, T, undefined>} SuccessResult
|
|
78
35
|
*/
|
|
79
36
|
|
|
80
37
|
/**
|
|
81
|
-
*
|
|
38
|
+
* A failed {@link Result} instance.
|
|
82
39
|
*
|
|
83
|
-
* @template
|
|
84
|
-
* @typedef {
|
|
40
|
+
* @template E
|
|
41
|
+
* @typedef {Result<false, undefined, E>} FailureResult
|
|
85
42
|
*/
|
|
86
43
|
|
|
87
44
|
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
45
|
+
|
|
88
46
|
/**
|
|
89
|
-
* Represents the
|
|
90
|
-
*
|
|
47
|
+
* Represents the outcome of an operation.
|
|
48
|
+
*
|
|
49
|
+
* @classdesc `Result` uses the `ok` property as a discriminant to distinguish
|
|
50
|
+
* successful outcomes from failures. A successful result exposes `value`,
|
|
51
|
+
* while a failed result exposes `error`. Accessing the property associated
|
|
52
|
+
* with the opposite state throws an error.
|
|
91
53
|
*
|
|
54
|
+
* @template {boolean} K
|
|
92
55
|
* @template T
|
|
56
|
+
* @template E
|
|
93
57
|
*/
|
|
94
58
|
class Result {
|
|
95
59
|
/**
|
|
96
|
-
*
|
|
60
|
+
* Indicates whether the operation succeeded.
|
|
61
|
+
*
|
|
62
|
+
* @type {K}
|
|
63
|
+
*/
|
|
64
|
+
#ok;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Stores the value associated with a successful operation.
|
|
97
68
|
*
|
|
98
|
-
* @type {
|
|
69
|
+
* @type {Value<K, T>}
|
|
99
70
|
*/
|
|
100
|
-
#
|
|
71
|
+
#value;
|
|
101
72
|
|
|
102
73
|
/**
|
|
103
|
-
*
|
|
74
|
+
* Stores the error associated with a failed operation.
|
|
75
|
+
*
|
|
76
|
+
* @type {ErrorValue<K, E>}
|
|
77
|
+
*/
|
|
78
|
+
#error;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Creates a Result instance with the specified outcome.
|
|
82
|
+
*
|
|
83
|
+
* The `ok` flag determines which argument represents the meaningful
|
|
84
|
+
* result: `value` for success or `error` for failure.
|
|
85
|
+
*
|
|
86
|
+
* @param {K} ok - Whether the operation succeeded.
|
|
87
|
+
* @param {Value<K, T>} value - The successful value, if applicable.
|
|
88
|
+
* @param {ErrorValue<K, E>} error - The failure value, if applicable.
|
|
104
89
|
*
|
|
105
|
-
* @param {boolean} ok - Whether the operation succeeded.
|
|
106
|
-
* @param {T} [value] - The successful value.
|
|
107
|
-
* @param {ErrorSchemaDefinition} [error] - Required when ok is false.
|
|
108
|
-
* @throws {TypeError} If the combination of ok, value, and error is invalid.
|
|
109
90
|
* @example
|
|
110
91
|
* ```js
|
|
111
|
-
* const result = new Result(true, { id: '123' });
|
|
92
|
+
* const result = new Result(true, { id: '123' }, undefined);
|
|
112
93
|
* ```
|
|
113
94
|
*
|
|
114
95
|
* @example
|
|
115
96
|
* ```js
|
|
116
|
-
* const result = new Result(false, undefined,
|
|
117
|
-
* error: RangeError,
|
|
118
|
-
* message: 'Value is out of range.',
|
|
119
|
-
* custom: false,
|
|
120
|
-
* code: 'ERR_RANGE',
|
|
121
|
-
* });
|
|
97
|
+
* const result = new Result(false, undefined, new RangeError('Value is out of range.'));
|
|
122
98
|
* ```
|
|
123
99
|
*/
|
|
124
100
|
constructor(ok, value, error) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (ok === true) {
|
|
130
|
-
if (value === undefined) {
|
|
131
|
-
throw new TypeError('A successful Result must contain a value.');
|
|
132
|
-
}
|
|
133
|
-
if (error !== undefined) {
|
|
134
|
-
throw new TypeError('A successful Result cannot contain an error.');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
this.#result = { ok, value, error };
|
|
138
|
-
} else {
|
|
139
|
-
if (error === undefined) {
|
|
140
|
-
throw new TypeError('A failed Result must contain an error.');
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (value !== undefined) {
|
|
144
|
-
throw new TypeError('A failed Result cannot contain a value.');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
this.#result = {
|
|
148
|
-
ok,
|
|
149
|
-
value: undefined,
|
|
150
|
-
error: new ErrorSchema(error),
|
|
151
|
-
};
|
|
152
|
-
}
|
|
101
|
+
this.#ok = ok;
|
|
102
|
+
this.#value = value;
|
|
103
|
+
this.#error = error;
|
|
153
104
|
}
|
|
154
105
|
|
|
155
106
|
/**
|
|
156
107
|
* Indicates whether the operation succeeded.
|
|
157
108
|
*
|
|
158
109
|
* @readonly
|
|
159
|
-
* @type {
|
|
110
|
+
* @type {K}
|
|
160
111
|
*/
|
|
161
112
|
get ok() {
|
|
162
|
-
return this.#
|
|
113
|
+
return this.#ok;
|
|
163
114
|
}
|
|
164
115
|
|
|
165
116
|
/**
|
|
166
117
|
* The successful value of the operation.
|
|
167
118
|
*
|
|
168
119
|
* @readonly
|
|
169
|
-
* @type {T}
|
|
120
|
+
* @type {Value<K, T>}
|
|
170
121
|
* @throws {Error} If the result is not ok.
|
|
171
122
|
*/
|
|
172
123
|
get value() {
|
|
173
|
-
if (this.#
|
|
124
|
+
if (this.#ok !== true) {
|
|
174
125
|
throw new Error('Cannot access value of a failed Result.');
|
|
175
126
|
}
|
|
176
|
-
|
|
177
|
-
return this.#result.value;
|
|
127
|
+
return this.#value;
|
|
178
128
|
}
|
|
179
129
|
|
|
180
130
|
/**
|
|
181
|
-
* The
|
|
131
|
+
* The error instance of the failed operation.
|
|
182
132
|
*
|
|
183
133
|
* @readonly
|
|
184
|
-
* @type {
|
|
134
|
+
* @type {ErrorValue<K, E>}
|
|
185
135
|
* @throws {Error} If the result is ok.
|
|
186
136
|
*/
|
|
187
137
|
get error() {
|
|
188
|
-
if (this.#
|
|
138
|
+
if (this.#ok !== false) {
|
|
189
139
|
throw new Error('Cannot access error of a successful Result.');
|
|
190
140
|
}
|
|
191
|
-
|
|
192
|
-
return this.#result.error.error;
|
|
141
|
+
return this.#error;
|
|
193
142
|
}
|
|
194
143
|
|
|
195
144
|
/**
|
|
196
145
|
* Creates a successful {@link Result}.
|
|
197
146
|
*
|
|
198
|
-
* @template
|
|
199
|
-
* @param {
|
|
200
|
-
* @returns {
|
|
147
|
+
* @template V
|
|
148
|
+
* @param {V} value - The successful value.
|
|
149
|
+
* @returns {SuccessResult<V>} A successful Result instance.
|
|
150
|
+
*
|
|
201
151
|
* @example
|
|
202
152
|
* ```js
|
|
203
153
|
* const result = Result.success({ id: '123' });
|
|
@@ -208,22 +158,19 @@ class Result {
|
|
|
208
158
|
* ```
|
|
209
159
|
*/
|
|
210
160
|
static success(value) {
|
|
211
|
-
return new Result(true, value);
|
|
161
|
+
return new Result(true, value, undefined);
|
|
212
162
|
}
|
|
213
163
|
|
|
214
164
|
/**
|
|
215
165
|
* Creates a failed {@link Result}.
|
|
216
166
|
*
|
|
217
|
-
* @
|
|
218
|
-
* @
|
|
167
|
+
* @template {Error} E
|
|
168
|
+
* @param {E} error - The error instance describing the failure.
|
|
169
|
+
* @returns {FailureResult<E>} A failed Result instance.
|
|
170
|
+
*
|
|
219
171
|
* @example
|
|
220
172
|
* ```js
|
|
221
|
-
* const result = Result.failure(
|
|
222
|
-
* error: RangeError,
|
|
223
|
-
* message: 'Value is out of range.',
|
|
224
|
-
* custom: false,
|
|
225
|
-
* code: 'ERR_RANGE',
|
|
226
|
-
* });
|
|
173
|
+
* const result = Result.failure(new RangeError('Value is out of range.'));
|
|
227
174
|
*
|
|
228
175
|
* if (!result.ok) {
|
|
229
176
|
* console.log(result.error);
|
|
@@ -231,7 +178,7 @@ class Result {
|
|
|
231
178
|
* ```
|
|
232
179
|
*/
|
|
233
180
|
static failure(error) {
|
|
234
|
-
return
|
|
181
|
+
return new Result(false, undefined, error);
|
|
235
182
|
}
|
|
236
183
|
}
|
|
237
184
|
|
|
@@ -1,173 +1,117 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
|
-
* @file
|
|
3
|
+
* @file Validation — Represents successful and failed validation outcomes.
|
|
4
4
|
*
|
|
5
|
-
* @description Provides
|
|
6
|
-
* successful
|
|
7
|
-
*
|
|
5
|
+
* @description Provides a generic Validation type that explicitly distinguishes
|
|
6
|
+
* successful validations from failed ones through the `ok` discriminant.
|
|
7
|
+
* A successful validation has no payload. A failed validation exposes `error`.
|
|
8
|
+
* Accessing `error` on a successful validation throws.
|
|
8
9
|
*
|
|
9
10
|
* @module Validation
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
// ━━ IMPORT MODULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
-
// » IMPORT LOCAL MODULES
|
|
14
|
-
import ErrorSchema from '../ErrorSchema.mjs';
|
|
15
|
-
|
|
16
13
|
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
14
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* @typedef {new (identifier: string, options?: Record<string, unknown>) => Error} ErrorConstructor
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Represents options passed to a native Error constructor.
|
|
25
|
-
*
|
|
26
|
-
* @typedef {object} NativeErrorOptions
|
|
27
|
-
* @property {unknown} [cause] - Cause associated with the error.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Represents a native Error schema definition.
|
|
32
|
-
*
|
|
33
|
-
* @typedef {object} NativeErrorSchema
|
|
34
|
-
* @property {ErrorConstructor} error - Error constructor used to create the error.
|
|
35
|
-
* @property {string} message - Literal error message.
|
|
36
|
-
* @property {NativeErrorOptions} [options] - Options passed to the Error constructor.
|
|
37
|
-
* @property {false} custom - Indicates that the constructor represents a native Error.
|
|
38
|
-
* @property {string} code - Error identifier.
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Represents options passed to a custom Error constructor.
|
|
43
|
-
*
|
|
44
|
-
* @typedef {object} CustomErrorOptions
|
|
45
|
-
* @property {Record<string, unknown>} [values] - Values used to resolve message placeholders.
|
|
46
|
-
* @property {Record<string, unknown>} [details] - Additional contextual information about the error.
|
|
47
|
-
* @property {unknown} [cause] - Cause associated with the error.
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Represents a custom Error schema definition.
|
|
52
|
-
*
|
|
53
|
-
* @typedef {object} CustomErrorSchema
|
|
54
|
-
* @property {ErrorConstructor} error - Error constructor used to create the error.
|
|
55
|
-
* @property {string} code - Error code used to resolve the error message and error identifier.
|
|
56
|
-
* @property {string} [message] - Literal error message.
|
|
57
|
-
* @property {CustomErrorOptions} [options] - Options passed to the Error constructor.
|
|
58
|
-
* @property {true} custom - Indicates that the constructor represents a custom Error.
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Represents a supported Error schema definition.
|
|
63
|
-
*
|
|
64
|
-
* @typedef {NativeErrorSchema|CustomErrorSchema} ErrorSchemaDefinition
|
|
65
|
-
*/
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Represents the successful state of a {@link Validation} instance.
|
|
15
|
+
* The error associated with a Validation state.
|
|
69
16
|
*
|
|
70
|
-
* @
|
|
71
|
-
* @
|
|
72
|
-
* @
|
|
17
|
+
* @template {boolean} K
|
|
18
|
+
* @template E
|
|
19
|
+
* @typedef {K extends false ? E : undefined} ErrorValue
|
|
73
20
|
*/
|
|
74
21
|
|
|
75
22
|
/**
|
|
76
|
-
*
|
|
23
|
+
* A successful {@link Validation} instance.
|
|
77
24
|
*
|
|
78
|
-
* @typedef
|
|
79
|
-
* @property {false} ok - Indicates that the validation failed.
|
|
80
|
-
* @property {ErrorSchema} error - Error schema describing the validation failure.
|
|
25
|
+
* @typedef {Validation<true, undefined>} SuccessValidation
|
|
81
26
|
*/
|
|
82
27
|
|
|
83
28
|
/**
|
|
84
|
-
*
|
|
29
|
+
* A failed {@link Validation} instance.
|
|
85
30
|
*
|
|
86
|
-
* @
|
|
31
|
+
* @template {Error} E
|
|
32
|
+
* @typedef {Validation<false, E>} FailureValidation
|
|
87
33
|
*/
|
|
88
34
|
|
|
89
35
|
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
90
36
|
/**
|
|
91
|
-
* Represents the
|
|
37
|
+
* Represents the outcome of a validation operation (pass / fail).
|
|
92
38
|
*
|
|
93
|
-
*
|
|
39
|
+
* @classdesc `Validation` uses the `ok` property as a discriminant to
|
|
40
|
+
* distinguish successful validations from failures. A successful validation
|
|
41
|
+
* has no payload; a failed validation exposes `error`. Accessing `error` on
|
|
42
|
+
* a successful validation throws.
|
|
43
|
+
*
|
|
44
|
+
* @template {boolean} K
|
|
45
|
+
* @template E
|
|
94
46
|
*/
|
|
95
47
|
class Validation {
|
|
96
48
|
/**
|
|
97
|
-
*
|
|
49
|
+
* Indicates whether the validation succeeded.
|
|
50
|
+
*
|
|
51
|
+
* @type {K}
|
|
52
|
+
*/
|
|
53
|
+
#ok;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Stores the error associated with a failed validation.
|
|
98
57
|
*
|
|
99
|
-
* @type {
|
|
58
|
+
* @type {ErrorValue<K, E>}
|
|
100
59
|
*/
|
|
101
|
-
#
|
|
60
|
+
#error;
|
|
102
61
|
|
|
103
62
|
/**
|
|
104
63
|
* Creates a Validation instance.
|
|
105
64
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
65
|
+
* The `ok` flag determines whether an error is required: no error on success,
|
|
66
|
+
* a required error instance on failure.
|
|
67
|
+
*
|
|
68
|
+
* @param {K} ok - Whether the validation succeeded.
|
|
69
|
+
* @param {ErrorValue<K, E>} error - The error instance, required when ok is false.
|
|
70
|
+
*
|
|
109
71
|
* @example
|
|
110
72
|
* ```js
|
|
111
|
-
* const validation = new Validation(true);
|
|
73
|
+
* const validation = new Validation(true, undefined);
|
|
112
74
|
* ```
|
|
113
75
|
*
|
|
114
76
|
* @example
|
|
115
77
|
* ```js
|
|
116
|
-
* const validation = new Validation(false,
|
|
117
|
-
* error: TypeError,
|
|
118
|
-
* message: 'Expected a string.',
|
|
119
|
-
* code: 'INVALID_TYPE',
|
|
120
|
-
* });
|
|
78
|
+
* const validation = new Validation(false, new TypeError('Expected a string.'));
|
|
121
79
|
* ```
|
|
122
80
|
*/
|
|
123
81
|
constructor(ok, error) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (ok === true) {
|
|
129
|
-
if (error !== undefined) {
|
|
130
|
-
throw new TypeError('A successful Validation cannot contain an error.');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
this.#validation = { ok, error };
|
|
134
|
-
} else {
|
|
135
|
-
if (error === undefined) {
|
|
136
|
-
throw new TypeError('A failed Validation must contain an error.');
|
|
137
|
-
}
|
|
138
|
-
this.#validation = { ok, error: new ErrorSchema(error) };
|
|
139
|
-
}
|
|
82
|
+
this.#ok = ok;
|
|
83
|
+
this.#error = error;
|
|
140
84
|
}
|
|
141
85
|
|
|
142
86
|
/**
|
|
143
87
|
* Indicates whether the validation succeeded.
|
|
144
88
|
*
|
|
145
89
|
* @readonly
|
|
146
|
-
* @type {
|
|
90
|
+
* @type {K}
|
|
147
91
|
*/
|
|
148
92
|
get ok() {
|
|
149
|
-
return this.#
|
|
93
|
+
return this.#ok;
|
|
150
94
|
}
|
|
151
95
|
|
|
152
96
|
/**
|
|
153
|
-
* The
|
|
97
|
+
* The error instance of the failed validation.
|
|
154
98
|
*
|
|
155
99
|
* @readonly
|
|
156
|
-
* @type {
|
|
100
|
+
* @type {ErrorValue<K, E>}
|
|
157
101
|
* @throws {Error} If the validation succeeded.
|
|
158
102
|
*/
|
|
159
103
|
get error() {
|
|
160
|
-
if (this.#
|
|
104
|
+
if (this.#ok !== false) {
|
|
161
105
|
throw new Error('Cannot access error of a successful Validation.');
|
|
162
106
|
}
|
|
163
|
-
|
|
164
|
-
return this.#validation.error.error;
|
|
107
|
+
return this.#error;
|
|
165
108
|
}
|
|
166
109
|
|
|
167
110
|
/**
|
|
168
111
|
* Creates a successful {@link Validation}.
|
|
169
112
|
*
|
|
170
|
-
* @returns {
|
|
113
|
+
* @returns {SuccessValidation} A successful Validation instance.
|
|
114
|
+
*
|
|
171
115
|
* @example
|
|
172
116
|
* ```js
|
|
173
117
|
* const validation = Validation.success();
|
|
@@ -178,21 +122,19 @@ class Validation {
|
|
|
178
122
|
* ```
|
|
179
123
|
*/
|
|
180
124
|
static success() {
|
|
181
|
-
return new Validation(true);
|
|
125
|
+
return new Validation(true, undefined);
|
|
182
126
|
}
|
|
183
127
|
|
|
184
128
|
/**
|
|
185
129
|
* Creates a failed {@link Validation}.
|
|
186
130
|
*
|
|
187
|
-
* @
|
|
188
|
-
* @
|
|
131
|
+
* @template {Error} E
|
|
132
|
+
* @param {E} error - The error instance describing the failure.
|
|
133
|
+
* @returns {FailureValidation<E>} A failed Validation instance.
|
|
134
|
+
*
|
|
189
135
|
* @example
|
|
190
136
|
* ```js
|
|
191
|
-
* const validation = Validation.failure(
|
|
192
|
-
* error: RangeError,
|
|
193
|
-
* message: 'Value is out of range.',
|
|
194
|
-
* code: 'VALUE_OUT_OF_RANGE',
|
|
195
|
-
* });
|
|
137
|
+
* const validation = Validation.failure(new RangeError('Value is out of range.'));
|
|
196
138
|
*
|
|
197
139
|
* if (!validation.ok) {
|
|
198
140
|
* console.log(validation.error);
|
|
@@ -12,6 +12,20 @@
|
|
|
12
12
|
import Validation from '#shared/outcome/Validation';
|
|
13
13
|
import MiddlewareError from '#shared/errors/MiddlewareError';
|
|
14
14
|
|
|
15
|
+
// ━━ TYPE DEFINITIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
16
|
+
/**
|
|
17
|
+
* A successful {@link Validation} instance.
|
|
18
|
+
*
|
|
19
|
+
* @typedef {import('#shared/outcome/Validation').SuccessValidation} SuccessValidation
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A failed {@link Validation} instance.
|
|
24
|
+
*
|
|
25
|
+
* @template {Error} E
|
|
26
|
+
* @typedef {import('#shared/outcome/Validation').FailureValidation<E>} FailureValidation
|
|
27
|
+
*/
|
|
28
|
+
|
|
15
29
|
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
16
30
|
/**
|
|
17
31
|
* Validates a middleware function.
|
|
@@ -20,7 +34,8 @@ import MiddlewareError from '#shared/errors/MiddlewareError';
|
|
|
20
34
|
* `context` and `next`.
|
|
21
35
|
*
|
|
22
36
|
* @param {unknown} middleware - Middleware function to validate.
|
|
23
|
-
* @returns {
|
|
37
|
+
* @returns {SuccessValidation|FailureValidation<MiddlewareError>} Validation result.
|
|
38
|
+
*
|
|
24
39
|
* @example
|
|
25
40
|
* ```js
|
|
26
41
|
* const validation = validateMiddleware((context, next) => {
|
|
@@ -43,31 +58,25 @@ import MiddlewareError from '#shared/errors/MiddlewareError';
|
|
|
43
58
|
*/
|
|
44
59
|
export function validateMiddleware(middleware) {
|
|
45
60
|
if (typeof middleware !== 'function') {
|
|
46
|
-
return Validation.failure(
|
|
47
|
-
|
|
48
|
-
code: 'INVALID_MIDDLEWARE_TYPE',
|
|
49
|
-
custom: true,
|
|
50
|
-
options: {
|
|
61
|
+
return Validation.failure(
|
|
62
|
+
new MiddlewareError('INVALID_MIDDLEWARE_TYPE', {
|
|
51
63
|
values: {
|
|
52
64
|
expected: 'function',
|
|
53
65
|
received: typeof middleware,
|
|
54
66
|
},
|
|
55
|
-
},
|
|
56
|
-
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
57
69
|
}
|
|
58
70
|
|
|
59
71
|
if (middleware.length !== 2) {
|
|
60
|
-
return Validation.failure(
|
|
61
|
-
|
|
62
|
-
code: 'INVALID_MIDDLEWARE_ARITY',
|
|
63
|
-
custom: true,
|
|
64
|
-
options: {
|
|
72
|
+
return Validation.failure(
|
|
73
|
+
new MiddlewareError('INVALID_MIDDLEWARE_ARITY', {
|
|
65
74
|
values: {
|
|
66
75
|
expected: 2,
|
|
67
76
|
received: middleware.length,
|
|
68
77
|
},
|
|
69
|
-
},
|
|
70
|
-
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
return Validation.success();
|
|
@@ -79,6 +88,7 @@ export function validateMiddleware(middleware) {
|
|
|
79
88
|
* @param {unknown} middleware - Middleware function to validate.
|
|
80
89
|
* @throws {MiddlewareError} If the middleware is not a function.
|
|
81
90
|
* @throws {MiddlewareError} If the middleware does not declare exactly two parameters.
|
|
91
|
+
*
|
|
82
92
|
* @example
|
|
83
93
|
* ```js
|
|
84
94
|
* assertMiddleware((context, next) => {
|
|
@@ -98,7 +108,8 @@ export function assertMiddleware(middleware) {
|
|
|
98
108
|
* Validates an array of middleware functions.
|
|
99
109
|
*
|
|
100
110
|
* @param {unknown} middlewares - Middleware functions to validate.
|
|
101
|
-
* @returns {
|
|
111
|
+
* @returns {SuccessValidation|FailureValidation<MiddlewareError>} Validation result.
|
|
112
|
+
*
|
|
102
113
|
* @example
|
|
103
114
|
* ```js
|
|
104
115
|
* const validation = validateMiddlewares([
|
|
@@ -112,17 +123,14 @@ export function assertMiddleware(middleware) {
|
|
|
112
123
|
*/
|
|
113
124
|
export function validateMiddlewares(middlewares) {
|
|
114
125
|
if (!Array.isArray(middlewares)) {
|
|
115
|
-
return Validation.failure(
|
|
116
|
-
|
|
117
|
-
code: 'INVALID_MIDDLEWARES_TYPE',
|
|
118
|
-
custom: true,
|
|
119
|
-
options: {
|
|
126
|
+
return Validation.failure(
|
|
127
|
+
new MiddlewareError('INVALID_MIDDLEWARES_TYPE', {
|
|
120
128
|
values: {
|
|
121
129
|
expected: 'array',
|
|
122
130
|
received: typeof middlewares,
|
|
123
131
|
},
|
|
124
|
-
},
|
|
125
|
-
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
for (const middleware of middlewares) {
|
|
@@ -143,6 +151,7 @@ export function validateMiddlewares(middlewares) {
|
|
|
143
151
|
* @throws {MiddlewareError} If the middleware collection is not an array.
|
|
144
152
|
* @throws {MiddlewareError} If a middleware is not a function.
|
|
145
153
|
* @throws {MiddlewareError} If a middleware does not declare exactly two parameters.
|
|
154
|
+
*
|
|
146
155
|
* @example
|
|
147
156
|
* ```js
|
|
148
157
|
* assertMiddlewares([
|