@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,6 +14,20 @@
|
|
|
14
14
|
import Validation from '#shared/outcome/Validation';
|
|
15
15
|
import ServerConfigurationError from '#shared/errors/ServerConfigurationError';
|
|
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
|
* Minimum valid compression level.
|
|
@@ -70,6 +84,7 @@ function everyNonEmptyString(values) {
|
|
|
70
84
|
return values.every(isNonEmptyString);
|
|
71
85
|
}
|
|
72
86
|
|
|
87
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
73
88
|
/**
|
|
74
89
|
* Validates compression options.
|
|
75
90
|
*
|
|
@@ -82,7 +97,8 @@ function everyNonEmptyString(values) {
|
|
|
82
97
|
* 5. `types`, if present, must be an array of non-empty strings.
|
|
83
98
|
*
|
|
84
99
|
* @param {unknown} options - Compression options to validate.
|
|
85
|
-
* @returns {
|
|
100
|
+
* @returns {SuccessValidation|FailureValidation<ServerConfigurationError>} Validation result.
|
|
101
|
+
*
|
|
86
102
|
* @example
|
|
87
103
|
* ```js
|
|
88
104
|
* const validation = validateCompressOptions({ threshold: 1024, level: 6 });
|
|
@@ -105,33 +121,31 @@ export function validateCompressOptions(options) {
|
|
|
105
121
|
}
|
|
106
122
|
|
|
107
123
|
if (!isPlainObject(options)) {
|
|
108
|
-
return Validation.failure(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
124
|
+
return Validation.failure(
|
|
125
|
+
new ServerConfigurationError('INVALID_COMPRESS_OPTIONS', {
|
|
126
|
+
values: { received: typeof options },
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
if ('threshold' in options) {
|
|
117
132
|
const { threshold } = options;
|
|
118
133
|
|
|
119
134
|
if (typeof threshold !== 'number') {
|
|
120
|
-
return Validation.failure(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
135
|
+
return Validation.failure(
|
|
136
|
+
new ServerConfigurationError('INVALID_COMPRESS_THRESHOLD_TYPE', {
|
|
137
|
+
values: { received: typeof threshold },
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
126
140
|
}
|
|
127
141
|
|
|
128
142
|
if (!Number.isInteger(threshold) || threshold < 0) {
|
|
129
|
-
return Validation.failure(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
143
|
+
return Validation.failure(
|
|
144
|
+
new ServerConfigurationError('INVALID_COMPRESS_THRESHOLD_RANGE', {
|
|
145
|
+
values: { threshold },
|
|
146
|
+
details: { threshold },
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
135
149
|
}
|
|
136
150
|
}
|
|
137
151
|
|
|
@@ -139,21 +153,20 @@ export function validateCompressOptions(options) {
|
|
|
139
153
|
const { level } = options;
|
|
140
154
|
|
|
141
155
|
if (typeof level !== 'number') {
|
|
142
|
-
return Validation.failure(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
156
|
+
return Validation.failure(
|
|
157
|
+
new ServerConfigurationError('INVALID_COMPRESS_LEVEL_TYPE', {
|
|
158
|
+
values: { received: typeof level },
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
148
161
|
}
|
|
149
162
|
|
|
150
163
|
if (!Number.isInteger(level) || level < MIN_LEVEL || level > MAX_LEVEL) {
|
|
151
|
-
return Validation.failure(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
return Validation.failure(
|
|
165
|
+
new ServerConfigurationError('INVALID_COMPRESS_LEVEL_RANGE', {
|
|
166
|
+
values: { level },
|
|
167
|
+
details: { level },
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
157
170
|
}
|
|
158
171
|
}
|
|
159
172
|
|
|
@@ -161,21 +174,19 @@ export function validateCompressOptions(options) {
|
|
|
161
174
|
const { types } = options;
|
|
162
175
|
|
|
163
176
|
if (!Array.isArray(types)) {
|
|
164
|
-
return Validation.failure(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
});
|
|
177
|
+
return Validation.failure(
|
|
178
|
+
new ServerConfigurationError('INVALID_COMPRESS_TYPES_TYPE', {
|
|
179
|
+
values: { received: typeof types },
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
170
182
|
}
|
|
171
183
|
|
|
172
184
|
if (!everyNonEmptyString(types)) {
|
|
173
|
-
return Validation.failure(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
});
|
|
185
|
+
return Validation.failure(
|
|
186
|
+
new ServerConfigurationError('INVALID_COMPRESS_TYPES_ITEM', {
|
|
187
|
+
details: { types },
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
179
190
|
}
|
|
180
191
|
}
|
|
181
192
|
|
|
@@ -190,6 +201,7 @@ export function validateCompressOptions(options) {
|
|
|
190
201
|
* @throws {ServerConfigurationError} If `threshold` is not a non-negative integer.
|
|
191
202
|
* @throws {ServerConfigurationError} If `level` is not an integer between `-1` and `11`.
|
|
192
203
|
* @throws {ServerConfigurationError} If `types` is not an array of non-empty strings.
|
|
204
|
+
*
|
|
193
205
|
* @example
|
|
194
206
|
* ```js
|
|
195
207
|
* assertCompressOptions({ threshold: 1024, level: 6 });
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
import Validation from '#shared/outcome/Validation';
|
|
14
14
|
import ServerConfigurationError from '#shared/errors/ServerConfigurationError';
|
|
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
|
// ━━ FUNCTIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
17
31
|
/**
|
|
18
32
|
* Determines whether a value is a non-null plain object.
|
|
@@ -25,6 +39,7 @@ function isPlainObject(value) {
|
|
|
25
39
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
26
40
|
}
|
|
27
41
|
|
|
42
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
28
43
|
/**
|
|
29
44
|
* Validates cookie parser options.
|
|
30
45
|
*
|
|
@@ -35,7 +50,8 @@ function isPlainObject(value) {
|
|
|
35
50
|
* 3. `decode`, if present, must be a boolean.
|
|
36
51
|
*
|
|
37
52
|
* @param {unknown} options - Cookie parser options to validate.
|
|
38
|
-
* @returns {
|
|
53
|
+
* @returns {SuccessValidation|FailureValidation<ServerConfigurationError>} Validation result.
|
|
54
|
+
*
|
|
39
55
|
* @example
|
|
40
56
|
* ```js
|
|
41
57
|
* const validation = validateCookieParserOptions({ decode: true });
|
|
@@ -58,24 +74,22 @@ export function validateCookieParserOptions(options) {
|
|
|
58
74
|
}
|
|
59
75
|
|
|
60
76
|
if (!isPlainObject(options)) {
|
|
61
|
-
return Validation.failure(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
77
|
+
return Validation.failure(
|
|
78
|
+
new ServerConfigurationError('INVALID_COOKIE_PARSER_OPTIONS', {
|
|
79
|
+
values: { received: typeof options },
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
67
82
|
}
|
|
68
83
|
|
|
69
84
|
if ('decode' in options) {
|
|
70
85
|
const { decode } = options;
|
|
71
86
|
|
|
72
87
|
if (typeof decode !== 'boolean') {
|
|
73
|
-
return Validation.failure(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
88
|
+
return Validation.failure(
|
|
89
|
+
new ServerConfigurationError('INVALID_COOKIE_PARSER_DECODE_TYPE', {
|
|
90
|
+
values: { received: typeof decode },
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
79
93
|
}
|
|
80
94
|
}
|
|
81
95
|
|
|
@@ -88,6 +102,7 @@ export function validateCookieParserOptions(options) {
|
|
|
88
102
|
* @param {unknown} options - Cookie parser options to validate.
|
|
89
103
|
* @throws {ServerConfigurationError} If `options` is not a plain object.
|
|
90
104
|
* @throws {ServerConfigurationError} If `decode` is not a boolean.
|
|
105
|
+
*
|
|
91
106
|
* @example
|
|
92
107
|
* ```js
|
|
93
108
|
* assertCookieParserOptions({ decode: true });
|
|
@@ -14,6 +14,20 @@
|
|
|
14
14
|
import Validation from '#shared/outcome/Validation';
|
|
15
15
|
import ServerConfigurationError from '#shared/errors/ServerConfigurationError';
|
|
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
|
* Valid values for the SameSite cookie attribute.
|
|
@@ -57,6 +71,7 @@ function everyNonEmptyString(values) {
|
|
|
57
71
|
return values.every(isNonEmptyString);
|
|
58
72
|
}
|
|
59
73
|
|
|
74
|
+
// ━━ MODULE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
60
75
|
/**
|
|
61
76
|
* Validates cookie session options.
|
|
62
77
|
*
|
|
@@ -78,7 +93,8 @@ function everyNonEmptyString(values) {
|
|
|
78
93
|
*
|
|
79
94
|
* @param {unknown} options - Cookie session options to validate.
|
|
80
95
|
* @param {boolean} [hasParser] - Whether a cookie parser is configured.
|
|
81
|
-
* @returns {
|
|
96
|
+
* @returns {SuccessValidation|FailureValidation<ServerConfigurationError>} Validation result.
|
|
97
|
+
*
|
|
82
98
|
* @example
|
|
83
99
|
* ```js
|
|
84
100
|
* const validation = validateCookieSessionOptions({ keys: ['secret'] }, true);
|
|
@@ -101,99 +117,83 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
if (!isPlainObject(options)) {
|
|
104
|
-
return Validation.failure(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
120
|
+
return Validation.failure(
|
|
121
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_OPTIONS', {
|
|
122
|
+
values: { received: typeof options },
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
110
125
|
}
|
|
111
126
|
|
|
112
127
|
if (hasParser !== true) {
|
|
113
|
-
return Validation.failure(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
custom: true,
|
|
117
|
-
});
|
|
128
|
+
return Validation.failure(
|
|
129
|
+
new ServerConfigurationError('COOKIE_SESSION_REQUIRES_COOKIE_PARSER'),
|
|
130
|
+
);
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
if ('name' in options) {
|
|
121
134
|
const { name } = options;
|
|
122
135
|
|
|
123
136
|
if (typeof name !== 'string') {
|
|
124
|
-
return Validation.failure(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
137
|
+
return Validation.failure(
|
|
138
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_NAME_TYPE', {
|
|
139
|
+
values: { received: typeof name },
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
if (name.length === 0) {
|
|
133
|
-
return Validation.failure(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
});
|
|
145
|
+
return Validation.failure(
|
|
146
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_NAME_VALUE', {
|
|
147
|
+
details: { name },
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
const { keys } = options;
|
|
143
154
|
|
|
144
155
|
if (keys === undefined) {
|
|
145
|
-
return Validation.failure(
|
|
146
|
-
error: ServerConfigurationError,
|
|
147
|
-
code: 'MISSING_COOKIE_SESSION_KEYS',
|
|
148
|
-
custom: true,
|
|
149
|
-
});
|
|
156
|
+
return Validation.failure(new ServerConfigurationError('MISSING_COOKIE_SESSION_KEYS'));
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
if (!Array.isArray(keys)) {
|
|
153
|
-
return Validation.failure(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
});
|
|
160
|
+
return Validation.failure(
|
|
161
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_KEYS_TYPE', {
|
|
162
|
+
values: { received: typeof keys },
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
159
165
|
}
|
|
160
166
|
|
|
161
167
|
if (keys.length === 0) {
|
|
162
|
-
return Validation.failure(
|
|
163
|
-
error: ServerConfigurationError,
|
|
164
|
-
code: 'MISSING_COOKIE_SESSION_KEYS',
|
|
165
|
-
custom: true,
|
|
166
|
-
});
|
|
168
|
+
return Validation.failure(new ServerConfigurationError('MISSING_COOKIE_SESSION_KEYS'));
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
if (!everyNonEmptyString(keys)) {
|
|
170
|
-
return Validation.failure(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
172
|
+
return Validation.failure(
|
|
173
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_KEYS_ITEM', {
|
|
174
|
+
details: { keys },
|
|
175
|
+
}),
|
|
176
|
+
);
|
|
176
177
|
}
|
|
177
178
|
|
|
178
179
|
if ('maxAge' in options) {
|
|
179
180
|
const { maxAge } = options;
|
|
180
181
|
|
|
181
182
|
if (typeof maxAge !== 'number') {
|
|
182
|
-
return Validation.failure(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
});
|
|
183
|
+
return Validation.failure(
|
|
184
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_MAX_AGE_TYPE', {
|
|
185
|
+
values: { received: typeof maxAge },
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
if (!Number.isInteger(maxAge) || maxAge <= 0) {
|
|
191
|
-
return Validation.failure(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
return Validation.failure(
|
|
192
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_MAX_AGE_RANGE', {
|
|
193
|
+
values: { maxAge },
|
|
194
|
+
details: { maxAge },
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -201,21 +201,19 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
201
201
|
const { path } = options;
|
|
202
202
|
|
|
203
203
|
if (typeof path !== 'string') {
|
|
204
|
-
return Validation.failure(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
});
|
|
204
|
+
return Validation.failure(
|
|
205
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_PATH_TYPE', {
|
|
206
|
+
values: { received: typeof path },
|
|
207
|
+
}),
|
|
208
|
+
);
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
if (path.length === 0) {
|
|
213
|
-
return Validation.failure(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
});
|
|
212
|
+
return Validation.failure(
|
|
213
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_PATH_VALUE', {
|
|
214
|
+
details: { path },
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
219
217
|
}
|
|
220
218
|
}
|
|
221
219
|
|
|
@@ -223,21 +221,19 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
223
221
|
const { domain } = options;
|
|
224
222
|
|
|
225
223
|
if (typeof domain !== 'string') {
|
|
226
|
-
return Validation.failure(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
});
|
|
224
|
+
return Validation.failure(
|
|
225
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_DOMAIN_TYPE', {
|
|
226
|
+
values: { received: typeof domain },
|
|
227
|
+
}),
|
|
228
|
+
);
|
|
232
229
|
}
|
|
233
230
|
|
|
234
231
|
if (domain.length === 0) {
|
|
235
|
-
return Validation.failure(
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
});
|
|
232
|
+
return Validation.failure(
|
|
233
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_DOMAIN_VALUE', {
|
|
234
|
+
details: { domain },
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
241
237
|
}
|
|
242
238
|
}
|
|
243
239
|
|
|
@@ -245,12 +241,11 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
245
241
|
const { secure } = options;
|
|
246
242
|
|
|
247
243
|
if (typeof secure !== 'boolean') {
|
|
248
|
-
return Validation.failure(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
});
|
|
244
|
+
return Validation.failure(
|
|
245
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_SECURE_TYPE', {
|
|
246
|
+
values: { received: typeof secure },
|
|
247
|
+
}),
|
|
248
|
+
);
|
|
254
249
|
}
|
|
255
250
|
}
|
|
256
251
|
|
|
@@ -258,12 +253,11 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
258
253
|
const { httpOnly } = options;
|
|
259
254
|
|
|
260
255
|
if (typeof httpOnly !== 'boolean') {
|
|
261
|
-
return Validation.failure(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
});
|
|
256
|
+
return Validation.failure(
|
|
257
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_HTTP_ONLY_TYPE', {
|
|
258
|
+
values: { received: typeof httpOnly },
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
263
|
|
|
@@ -271,12 +265,12 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
271
265
|
const { sameSite } = options;
|
|
272
266
|
|
|
273
267
|
if (sameSite !== undefined && !SAME_SITE_VALUES.includes(String(sameSite))) {
|
|
274
|
-
return Validation.failure(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
268
|
+
return Validation.failure(
|
|
269
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_SAME_SITE_VALUE', {
|
|
270
|
+
values: { received: sameSite },
|
|
271
|
+
details: { sameSite },
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
280
274
|
}
|
|
281
275
|
}
|
|
282
276
|
|
|
@@ -284,12 +278,11 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
284
278
|
const { overwrite } = options;
|
|
285
279
|
|
|
286
280
|
if (typeof overwrite !== 'boolean') {
|
|
287
|
-
return Validation.failure(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
});
|
|
281
|
+
return Validation.failure(
|
|
282
|
+
new ServerConfigurationError('INVALID_COOKIE_SESSION_OVERWRITE_TYPE', {
|
|
283
|
+
values: { received: typeof overwrite },
|
|
284
|
+
}),
|
|
285
|
+
);
|
|
293
286
|
}
|
|
294
287
|
}
|
|
295
288
|
|
|
@@ -298,11 +291,7 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
298
291
|
const effectiveSecure = options.secure ?? true;
|
|
299
292
|
|
|
300
293
|
if (effectiveSameSite === 'None' && effectiveSecure === false) {
|
|
301
|
-
return Validation.failure(
|
|
302
|
-
error: ServerConfigurationError,
|
|
303
|
-
code: 'COOKIE_SESSION_NONE_REQUIRES_SECURE',
|
|
304
|
-
custom: true,
|
|
305
|
-
});
|
|
294
|
+
return Validation.failure(new ServerConfigurationError('COOKIE_SESSION_NONE_REQUIRES_SECURE'));
|
|
306
295
|
}
|
|
307
296
|
|
|
308
297
|
return Validation.success();
|
|
@@ -318,6 +307,7 @@ export function validateCookieSessionOptions(options, hasParser) {
|
|
|
318
307
|
* @throws {ServerConfigurationError} If `keys` is missing or invalid.
|
|
319
308
|
* @throws {ServerConfigurationError} If any other option is invalid.
|
|
320
309
|
* @throws {ServerConfigurationError} If `sameSite: 'None'` is used without `secure: true`.
|
|
310
|
+
*
|
|
321
311
|
* @example
|
|
322
312
|
* ```js
|
|
323
313
|
* assertCookieSessionOptions({ keys: ['secret'] }, true);
|