hi-secure 1.0.6 → 1.0.10
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/dist/adapters/ArgonAdapter.js +1 -1
- package/dist/adapters/ArgonAdapter.js.map +1 -1
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressRLAdapter.js +1 -2
- package/dist/adapters/ExpressRLAdapter.js.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.js +1 -39
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
- package/dist/adapters/GoogleAdapter.js +0 -101
- package/dist/adapters/GoogleAdapter.js.map +1 -1
- package/dist/adapters/JWTAdapter.d.ts.map +1 -1
- package/dist/adapters/JWTAdapter.js +3 -210
- package/dist/adapters/JWTAdapter.js.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.js +0 -52
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.d.ts +0 -3
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.js +2 -71
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
- package/dist/adapters/XSSAdapter.d.ts +0 -10
- package/dist/adapters/XSSAdapter.d.ts.map +1 -1
- package/dist/adapters/XSSAdapter.js +2 -19
- package/dist/adapters/XSSAdapter.js.map +1 -1
- package/dist/adapters/ZodAdapter.d.ts.map +1 -1
- package/dist/adapters/ZodAdapter.js +2 -6
- package/dist/adapters/ZodAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts +15 -2
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +130 -37
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/core/useSecure.d.ts +4 -0
- package/dist/core/useSecure.d.ts.map +1 -1
- package/dist/core/useSecure.js +19 -114
- package/dist/core/useSecure.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -19
- package/dist/index.js.map +1 -1
- package/dist/managers/AuthManager.d.ts.map +1 -1
- package/dist/managers/AuthManager.js +1 -89
- package/dist/managers/AuthManager.js.map +1 -1
- package/dist/managers/CorsManager.d.ts.map +1 -1
- package/dist/managers/CorsManager.js +1 -19
- package/dist/managers/CorsManager.js.map +1 -1
- package/dist/managers/HashManager.d.ts.map +1 -1
- package/dist/managers/HashManager.js +0 -243
- package/dist/managers/HashManager.js.map +1 -1
- package/dist/managers/JsonManager.d.ts.map +1 -1
- package/dist/managers/JsonManager.js +1 -77
- package/dist/managers/JsonManager.js.map +1 -1
- package/dist/managers/RateLimitManager.d.ts.map +1 -1
- package/dist/managers/RateLimitManager.js +3 -17
- package/dist/managers/RateLimitManager.js.map +1 -1
- package/dist/managers/SanitizerManager.d.ts +0 -6
- package/dist/managers/SanitizerManager.d.ts.map +1 -1
- package/dist/managers/SanitizerManager.js +1 -213
- package/dist/managers/SanitizerManager.js.map +1 -1
- package/dist/managers/ValidatorManager.d.ts.map +1 -1
- package/dist/managers/ValidatorManager.js +1 -109
- package/dist/managers/ValidatorManager.js.map +1 -1
- package/dist/middlewares/errorHandler.d.ts.map +1 -1
- package/dist/middlewares/errorHandler.js +0 -19
- package/dist/middlewares/errorHandler.js.map +1 -1
- package/dist/utils/deepFreeze.d.ts.map +1 -1
- package/dist/utils/deepFreeze.js +0 -25
- package/dist/utils/deepFreeze.js.map +1 -1
- package/dist/utils/deepMerge.d.ts.map +1 -1
- package/dist/utils/deepMerge.js +0 -26
- package/dist/utils/deepMerge.js.map +1 -1
- package/dist/utils/normalizeOptions.d.ts +1 -3
- package/dist/utils/normalizeOptions.d.ts.map +1 -1
- package/dist/utils/normalizeOptions.js +0 -1
- package/dist/utils/normalizeOptions.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/ArgonAdapter.ts +1 -1
- package/src/adapters/ExpressRLAdapter.ts +1 -2
- package/src/adapters/ExpressValidatorAdapter.ts +1 -54
- package/src/adapters/GoogleAdapter.ts +0 -129
- package/src/adapters/JWTAdapter.ts +5 -259
- package/src/adapters/RLFlexibleAdapter.ts +2 -65
- package/src/adapters/SanitizeHtmlAdapter.ts +3 -87
- package/src/adapters/XSSAdapter.ts +11 -19
- package/src/adapters/ZodAdapter.ts +2 -51
- package/src/core/HiSecure.ts +25 -36
- package/src/core/useSecure.ts +5 -7
- package/src/index.ts +4 -5
- package/src/managers/AuthManager.ts +5 -109
- package/src/managers/CorsManager.ts +1 -25
- package/src/managers/HashManager.ts +0 -286
- package/src/managers/JsonManager.ts +1 -91
- package/src/managers/RateLimitManager.ts +3 -262
- package/src/managers/SanitizerManager.ts +4 -263
- package/src/managers/ValidatorManager.ts +53 -187
- package/src/middlewares/errorHandler.ts +1 -176
- package/src/utils/deepFreeze.ts +0 -32
- package/src/utils/deepMerge.ts +0 -35
- package/src/utils/normalizeOptions.ts +16 -133
- package/src/examples/e1.ts +0 -1
- package/src/test/t1.ts +0 -1
|
@@ -1,254 +1,3 @@
|
|
|
1
|
-
// // // import { SanitizerError } from "../core/errors/SanitizerError";
|
|
2
|
-
// // // import { logger } from "../logging";
|
|
3
|
-
|
|
4
|
-
// // // interface SanitizerAdapter {
|
|
5
|
-
// // // sanitize: (value: string) => string;
|
|
6
|
-
// // // middleware?: () => any;
|
|
7
|
-
// // // }
|
|
8
|
-
|
|
9
|
-
// // // export class SanitizerManager {
|
|
10
|
-
// // // private primary: SanitizerAdapter;
|
|
11
|
-
// // // private fallback: SanitizerAdapter | null;
|
|
12
|
-
|
|
13
|
-
// // // constructor(primary: SanitizerAdapter, fallback: SanitizerAdapter | null = null) {
|
|
14
|
-
// // // this.primary = primary;
|
|
15
|
-
// // // this.fallback = fallback;
|
|
16
|
-
// // // }
|
|
17
|
-
|
|
18
|
-
// // // sanitize(value: string): string {
|
|
19
|
-
// // // try {
|
|
20
|
-
// // // return this.primary.sanitize(value);
|
|
21
|
-
// // // } catch (err: any) {
|
|
22
|
-
// // // logger.warn("⚠ Sanitizer primary adapter failed", { error: err?.message });
|
|
23
|
-
|
|
24
|
-
// // // if (!this.fallback) {
|
|
25
|
-
// // // throw new SanitizerError("Primary sanitizer failed, no fallback available.");
|
|
26
|
-
// // // }
|
|
27
|
-
|
|
28
|
-
// // // try {
|
|
29
|
-
// // // logger.info("📌 Using fallback sanitizer");
|
|
30
|
-
// // // return this.fallback.sanitize(value);
|
|
31
|
-
// // // } catch (fallbackErr: any) {
|
|
32
|
-
// // // logger.error("❌ Fallback sanitizer failed", {
|
|
33
|
-
// // // error: fallbackErr?.message
|
|
34
|
-
// // // });
|
|
35
|
-
// // // throw new SanitizerError("Both primary and fallback sanitizers failed.");
|
|
36
|
-
// // // }
|
|
37
|
-
// // // }
|
|
38
|
-
// // // }
|
|
39
|
-
|
|
40
|
-
// // // middleware() {
|
|
41
|
-
// // // return (req: any, _res: any, next: any) => {
|
|
42
|
-
// // // try {
|
|
43
|
-
// // // if (req.body && typeof req.body === "object") {
|
|
44
|
-
// // // for (const key of Object.keys(req.body)) {
|
|
45
|
-
// // // const value = req.body[key];
|
|
46
|
-
|
|
47
|
-
// // // if (typeof value === "string") {
|
|
48
|
-
// // // const clean = this.sanitize(value);
|
|
49
|
-
|
|
50
|
-
// // // logger.debug("🧼 Sanitized field", {
|
|
51
|
-
// // // field: key,
|
|
52
|
-
// // // before: value.slice(0, 80),
|
|
53
|
-
// // // after: clean.slice(0, 80),
|
|
54
|
-
// // // });
|
|
55
|
-
|
|
56
|
-
// // // req.body[key] = clean;
|
|
57
|
-
// // // }
|
|
58
|
-
// // // }
|
|
59
|
-
// // // }
|
|
60
|
-
|
|
61
|
-
// // // next();
|
|
62
|
-
// // // } catch (err: any) {
|
|
63
|
-
// // // logger.error("❌ Sanitizer middleware failed", { error: err?.message });
|
|
64
|
-
// // // next(new SanitizerError("Sanitizer middleware failure"));
|
|
65
|
-
// // // }
|
|
66
|
-
// // // };
|
|
67
|
-
// // // }
|
|
68
|
-
// // // }
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// // // src/managers/SanitizerManager.ts
|
|
73
|
-
// // import { SanitizerError } from "../core/errors/SanitizerError.js";
|
|
74
|
-
// // import { logger } from "../logging";
|
|
75
|
-
|
|
76
|
-
// // interface SanitizerAdapter {
|
|
77
|
-
// // sanitize: (value: string, options?: any) => string;
|
|
78
|
-
// // }
|
|
79
|
-
|
|
80
|
-
// // export class SanitizerManager {
|
|
81
|
-
// // private primary: SanitizerAdapter;
|
|
82
|
-
// // private fallback: SanitizerAdapter | null;
|
|
83
|
-
|
|
84
|
-
// // constructor(primary: SanitizerAdapter, fallback: SanitizerAdapter | null = null) {
|
|
85
|
-
// // this.primary = primary;
|
|
86
|
-
// // this.fallback = fallback;
|
|
87
|
-
// // }
|
|
88
|
-
|
|
89
|
-
// // /**
|
|
90
|
-
// // * Sanitize a single value with optional dynamic options.
|
|
91
|
-
// // */
|
|
92
|
-
// // sanitize(value: string, options?: any): string {
|
|
93
|
-
// // try {
|
|
94
|
-
// // return this.primary.sanitize(value, options);
|
|
95
|
-
|
|
96
|
-
// // } catch (err: any) {
|
|
97
|
-
// // logger.warn("⚠ Primary sanitizer failed", { error: err?.message });
|
|
98
|
-
|
|
99
|
-
// // if (!this.fallback) {
|
|
100
|
-
// // throw new SanitizerError("Primary sanitizer failed and no fallback available.");
|
|
101
|
-
// // }
|
|
102
|
-
|
|
103
|
-
// // try {
|
|
104
|
-
// // logger.info("📌 Using fallback sanitizer");
|
|
105
|
-
// // return this.fallback.sanitize(value, options);
|
|
106
|
-
|
|
107
|
-
// // } catch (fallbackErr: any) {
|
|
108
|
-
// // logger.error("❌ Fallback sanitizer failed", {
|
|
109
|
-
// // error: fallbackErr?.message
|
|
110
|
-
// // });
|
|
111
|
-
|
|
112
|
-
// // throw new SanitizerError("Both primary and fallback sanitizers failed.");
|
|
113
|
-
// // }
|
|
114
|
-
// // }
|
|
115
|
-
// // }
|
|
116
|
-
|
|
117
|
-
// // /**
|
|
118
|
-
// // * Dynamic express middleware for sanitizing body.
|
|
119
|
-
// // * Options can override global config on each route.
|
|
120
|
-
// // */
|
|
121
|
-
// // middleware(options?: any) {
|
|
122
|
-
// // return (req: any, _res: any, next: any) => {
|
|
123
|
-
// // try {
|
|
124
|
-
// // if (req.body && typeof req.body === "object") {
|
|
125
|
-
// // for (const key of Object.keys(req.body)) {
|
|
126
|
-
// // const original = req.body[key];
|
|
127
|
-
|
|
128
|
-
// // if (typeof original === "string") {
|
|
129
|
-
// // const sanitized = this.sanitize(original, options);
|
|
130
|
-
|
|
131
|
-
// // logger.debug("🧼 Sanitized field", {
|
|
132
|
-
// // field: key,
|
|
133
|
-
// // before: original.slice(0, 80),
|
|
134
|
-
// // after: sanitized.slice(0, 80)
|
|
135
|
-
// // });
|
|
136
|
-
|
|
137
|
-
// // req.body[key] = sanitized;
|
|
138
|
-
// // }
|
|
139
|
-
// // }
|
|
140
|
-
// // }
|
|
141
|
-
|
|
142
|
-
// // next();
|
|
143
|
-
|
|
144
|
-
// // } catch (err: any) {
|
|
145
|
-
// // logger.error("❌ Sanitizer middleware failed", {
|
|
146
|
-
// // error: err?.message
|
|
147
|
-
// // });
|
|
148
|
-
|
|
149
|
-
// // next(new SanitizerError("Sanitizer middleware failure"));
|
|
150
|
-
// // }
|
|
151
|
-
// // };
|
|
152
|
-
// // }
|
|
153
|
-
// // }
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// // src/managers/SanitizerManager.ts - FIXED
|
|
158
|
-
// import { SanitizerError } from "../core/errors/SanitizerError.js";
|
|
159
|
-
// import { logger } from "../logging";
|
|
160
|
-
|
|
161
|
-
// interface SanitizerAdapter {
|
|
162
|
-
// sanitize: (value: string, options?: any) => string;
|
|
163
|
-
// }
|
|
164
|
-
|
|
165
|
-
// export class SanitizerManager {
|
|
166
|
-
// private primary: SanitizerAdapter;
|
|
167
|
-
// private fallback: SanitizerAdapter | null;
|
|
168
|
-
// private useFallbackOnly: boolean = false;
|
|
169
|
-
|
|
170
|
-
// constructor(primary: SanitizerAdapter, fallback: SanitizerAdapter | null = null) {
|
|
171
|
-
// this.primary = primary;
|
|
172
|
-
// this.fallback = fallback;
|
|
173
|
-
// }
|
|
174
|
-
|
|
175
|
-
// /**
|
|
176
|
-
// * Sanitize a single value
|
|
177
|
-
// */
|
|
178
|
-
// sanitize(value: string, options?: any): string {
|
|
179
|
-
// // Don't process non-strings
|
|
180
|
-
// if (typeof value !== 'string') {
|
|
181
|
-
// return value;
|
|
182
|
-
// }
|
|
183
|
-
|
|
184
|
-
// // Use only one sanitizer, not both
|
|
185
|
-
// if (this.useFallbackOnly && this.fallback) {
|
|
186
|
-
// return this.fallback.sanitize(value, options);
|
|
187
|
-
// }
|
|
188
|
-
|
|
189
|
-
// try {
|
|
190
|
-
// return this.primary.sanitize(value, options);
|
|
191
|
-
// } catch (err: any) {
|
|
192
|
-
// logger.warn("⚠ Primary sanitizer failed", { error: err?.message });
|
|
193
|
-
|
|
194
|
-
// if (!this.fallback) {
|
|
195
|
-
// throw new SanitizerError("Primary sanitizer failed and no fallback available.");
|
|
196
|
-
// }
|
|
197
|
-
|
|
198
|
-
// logger.info("📌 Using fallback sanitizer");
|
|
199
|
-
// this.useFallbackOnly = true; // Use fallback for subsequent calls
|
|
200
|
-
|
|
201
|
-
// return this.fallback.sanitize(value, options);
|
|
202
|
-
// }
|
|
203
|
-
// }
|
|
204
|
-
|
|
205
|
-
// /**
|
|
206
|
-
// * Middleware that doesn't mutate original request
|
|
207
|
-
// */
|
|
208
|
-
// middleware(options?: any) {
|
|
209
|
-
// return (req: any, _res: any, next: any) => {
|
|
210
|
-
// try {
|
|
211
|
-
// // Create a sanitized copy of body instead of mutating
|
|
212
|
-
// if (req.body && typeof req.body === "object") {
|
|
213
|
-
// const originalBody = req.body;
|
|
214
|
-
// const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};
|
|
215
|
-
|
|
216
|
-
// for (const key of Object.keys(originalBody)) {
|
|
217
|
-
// const value = originalBody[key];
|
|
218
|
-
|
|
219
|
-
// if (typeof value === "string") {
|
|
220
|
-
// sanitizedBody[key] = this.sanitize(value, options);
|
|
221
|
-
// } else if (Array.isArray(value)) {
|
|
222
|
-
// sanitizedBody[key] = value.map(item =>
|
|
223
|
-
// typeof item === "string" ? this.sanitize(item, options) : item
|
|
224
|
-
// );
|
|
225
|
-
// } else {
|
|
226
|
-
// sanitizedBody[key] = value;
|
|
227
|
-
// }
|
|
228
|
-
// }
|
|
229
|
-
|
|
230
|
-
// // Store sanitized version separately
|
|
231
|
-
// req.sanitizedBody = sanitizedBody;
|
|
232
|
-
// logger.debug("🧼 Request body sanitized", {
|
|
233
|
-
// originalKeys: Object.keys(originalBody),
|
|
234
|
-
// sanitizedKeys: Object.keys(sanitizedBody)
|
|
235
|
-
// });
|
|
236
|
-
// }
|
|
237
|
-
|
|
238
|
-
// next();
|
|
239
|
-
// } catch (err: any) {
|
|
240
|
-
// logger.error("❌ Sanitizer middleware failed", {
|
|
241
|
-
// error: err?.message
|
|
242
|
-
// });
|
|
243
|
-
// next(new SanitizerError("Sanitizer middleware failure"));
|
|
244
|
-
// }
|
|
245
|
-
// };
|
|
246
|
-
// }
|
|
247
|
-
// }
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// src/managers/SanitizerManager.ts - COMPLETE FIXED
|
|
252
1
|
import { SanitizerError } from "../core/errors/SanitizerError.js";
|
|
253
2
|
import { logger } from "../logging";
|
|
254
3
|
|
|
@@ -265,11 +14,8 @@ export class SanitizerManager {
|
|
|
265
14
|
this.fallback = fallback;
|
|
266
15
|
}
|
|
267
16
|
|
|
268
|
-
/**
|
|
269
|
-
* Sanitize a single value (public API)
|
|
270
|
-
*/
|
|
271
17
|
sanitize(value: string, options?: any): string {
|
|
272
|
-
|
|
18
|
+
|
|
273
19
|
if (typeof value !== 'string') {
|
|
274
20
|
return value;
|
|
275
21
|
}
|
|
@@ -288,14 +34,11 @@ export class SanitizerManager {
|
|
|
288
34
|
}
|
|
289
35
|
}
|
|
290
36
|
|
|
291
|
-
|
|
292
|
-
* Middleware - Per-request fallback logic
|
|
293
|
-
*/
|
|
37
|
+
|
|
294
38
|
middleware(options?: any) {
|
|
295
39
|
return (req: any, _res: any, next: any) => {
|
|
296
40
|
let fallbackTriggered = false;
|
|
297
41
|
|
|
298
|
-
// Helper function with per-request fallback logic
|
|
299
42
|
const safeSanitize = (value: string): string => {
|
|
300
43
|
if (fallbackTriggered && this.fallback) {
|
|
301
44
|
return this.fallback.sanitize(value, options);
|
|
@@ -315,7 +58,7 @@ export class SanitizerManager {
|
|
|
315
58
|
};
|
|
316
59
|
|
|
317
60
|
try {
|
|
318
|
-
|
|
61
|
+
|
|
319
62
|
if (req.body && typeof req.body === "object") {
|
|
320
63
|
const originalBody = req.body;
|
|
321
64
|
const sanitizedBody: any = Array.isArray(originalBody) ? [] : {};
|
|
@@ -330,14 +73,12 @@ export class SanitizerManager {
|
|
|
330
73
|
typeof item === "string" ? safeSanitize(item) : item
|
|
331
74
|
);
|
|
332
75
|
} else if (value && typeof value === "object") {
|
|
333
|
-
|
|
334
|
-
sanitizedBody[key] = value; // Keep as-is for now
|
|
76
|
+
sanitizedBody[key] = value;
|
|
335
77
|
} else {
|
|
336
78
|
sanitizedBody[key] = value;
|
|
337
79
|
}
|
|
338
80
|
}
|
|
339
81
|
|
|
340
|
-
// Store sanitized version separately
|
|
341
82
|
req.sanitizedBody = sanitizedBody;
|
|
342
83
|
|
|
343
84
|
logger.debug("🧼 Request body sanitized", {
|
|
@@ -1,207 +1,73 @@
|
|
|
1
|
-
// src/managers/ValidatorManager.ts - COMPLETE FIXED
|
|
2
1
|
import { logger } from "../logging";
|
|
3
2
|
import { ValidationError } from "../core/errors/ValidationError.js";
|
|
4
|
-
import { HiSecureConfig } from "../core/types/HiSecureConfig.js"; // ✅ FIXED IMPORT
|
|
5
3
|
|
|
6
4
|
interface ValidatorAdapter {
|
|
7
5
|
validate: (schema?: any) => any;
|
|
8
6
|
}
|
|
9
7
|
|
|
10
8
|
export class ValidatorManager {
|
|
11
|
-
private
|
|
12
|
-
private
|
|
13
|
-
private fallbackAdapter: ValidatorAdapter | null;
|
|
9
|
+
private zodAdapter: ValidatorAdapter;
|
|
10
|
+
private expressAdapter: ValidatorAdapter;
|
|
14
11
|
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
fallbackAdapter: ValidatorAdapter | null
|
|
19
|
-
) {
|
|
20
|
-
this.config = config;
|
|
21
|
-
this.primaryAdapter = primaryAdapter;
|
|
22
|
-
this.fallbackAdapter = fallbackAdapter;
|
|
12
|
+
constructor(zodAdapter: ValidatorAdapter, expressAdapter: ValidatorAdapter) {
|
|
13
|
+
this.zodAdapter = zodAdapter;
|
|
14
|
+
this.expressAdapter = expressAdapter;
|
|
23
15
|
}
|
|
24
16
|
|
|
25
17
|
validate(schema?: any) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
primaryMiddleware(req, res, (err?: any) => {
|
|
32
|
-
if (!err) {
|
|
33
|
-
return next(); // Validation passed
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// If error is a ValidationError, pass it through (don't fallback!)
|
|
37
|
-
if (err instanceof ValidationError) {
|
|
38
|
-
logger.warn("⚠ Validation failed", {
|
|
39
|
-
path: req.path,
|
|
40
|
-
method: req.method,
|
|
41
|
-
error: err.message
|
|
42
|
-
});
|
|
43
|
-
return next(err);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Only use fallback for ADAPTER errors, not validation errors
|
|
47
|
-
logger.warn("⚠ Primary validator adapter failed", {
|
|
48
|
-
error: err?.message,
|
|
49
|
-
path: req.path,
|
|
50
|
-
method: req.method
|
|
51
|
-
});
|
|
18
|
+
const isZod =
|
|
19
|
+
schema &&
|
|
20
|
+
typeof schema === "object" &&
|
|
21
|
+
typeof schema._def === "object" &&
|
|
22
|
+
typeof schema.safeParse === "function";
|
|
52
23
|
|
|
53
|
-
|
|
54
|
-
return next(new ValidationError("Validation system error"));
|
|
55
|
-
}
|
|
24
|
+
const isExpressValidator = Array.isArray(schema);
|
|
56
25
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
26
|
+
return (req: any, res: any, next: any) => {
|
|
27
|
+
let middleware;
|
|
28
|
+
|
|
29
|
+
if (isZod) {
|
|
30
|
+
logger.debug("📌 Using Zod adapter");
|
|
31
|
+
middleware = this.zodAdapter.validate(schema);
|
|
32
|
+
}
|
|
33
|
+
else if (isExpressValidator) {
|
|
34
|
+
logger.debug("📌 Using express-validator adapter");
|
|
35
|
+
middleware = this.expressAdapter.validate(schema);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return next();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// CASE 1 — express-validator returns ARRAY
|
|
42
|
+
if (Array.isArray(middleware)) {
|
|
43
|
+
let idx = 0;
|
|
44
|
+
|
|
45
|
+
const run = (err?: any) => {
|
|
46
|
+
if (err) return next(err);
|
|
47
|
+
|
|
48
|
+
const fn = middleware[idx++];
|
|
49
|
+
if (!fn) return next(); // done
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
fn(req, res, run);
|
|
53
|
+
} catch (error: any) {
|
|
54
|
+
next(new ValidationError(error.message));
|
|
65
55
|
}
|
|
66
|
-
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return run();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// CASE 2 — Zod returns SINGLE MIDDLEWARE
|
|
62
|
+
try {
|
|
63
|
+
middleware(req, res, (err?: any) => {
|
|
64
|
+
if (err) return next(err);
|
|
65
|
+
next();
|
|
67
66
|
});
|
|
68
|
-
})
|
|
67
|
+
} catch (err: any) {
|
|
68
|
+
next(new ValidationError(err.message));
|
|
69
|
+
}
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// // src/managers/ValidatorManager.ts
|
|
77
|
-
// import { logger } from "../logging";
|
|
78
|
-
// import { ValidationError } from "../core/errors/ValidationError.js";
|
|
79
|
-
|
|
80
|
-
// interface ValidatorAdapter {
|
|
81
|
-
// validate: (schema?: any) => any;
|
|
82
|
-
// }
|
|
83
|
-
|
|
84
|
-
// export class ValidatorManager {
|
|
85
|
-
// private primaryAdapter: ValidatorAdapter;
|
|
86
|
-
// private fallbackAdapter: ValidatorAdapter | null;
|
|
87
|
-
|
|
88
|
-
// constructor(primaryAdapter: ValidatorAdapter, fallbackAdapter: ValidatorAdapter | null) {
|
|
89
|
-
// this.primaryAdapter = primaryAdapter;
|
|
90
|
-
// this.fallbackAdapter = fallbackAdapter;
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
// validate(schema?: any) {
|
|
94
|
-
// return (req: any, res: any, next: any) => {
|
|
95
|
-
// const isZod = schema && typeof schema === "object" && typeof schema.safeParse === "function";
|
|
96
|
-
// const isExpressValidator = Array.isArray(schema);
|
|
97
|
-
|
|
98
|
-
// let adapter: ValidatorAdapter;
|
|
99
|
-
|
|
100
|
-
// if (isZod) {
|
|
101
|
-
// adapter = this.primaryAdapter; // ZodAdapter
|
|
102
|
-
// logger.debug("📌 Using Zod adapter for validation");
|
|
103
|
-
// }
|
|
104
|
-
// else if (isExpressValidator) {
|
|
105
|
-
// adapter = this.fallbackAdapter!; // ExpressValidatorAdapter
|
|
106
|
-
// logger.debug("📌 Using express-validator adapter for validation");
|
|
107
|
-
// }
|
|
108
|
-
// else {
|
|
109
|
-
// return next(); // nothing to validate
|
|
110
|
-
// }
|
|
111
|
-
|
|
112
|
-
// const middleware = adapter.validate(schema);
|
|
113
|
-
|
|
114
|
-
// // Execute validation chain
|
|
115
|
-
// middleware(req, res, (err?: any) => {
|
|
116
|
-
// if (err instanceof ValidationError) {
|
|
117
|
-
// return next(err);
|
|
118
|
-
// }
|
|
119
|
-
// if (err) {
|
|
120
|
-
// logger.error("❌ Validator internal error", { error: err.message });
|
|
121
|
-
// return next(new ValidationError("Validation failed internally."));
|
|
122
|
-
// }
|
|
123
|
-
// next();
|
|
124
|
-
// });
|
|
125
|
-
// };
|
|
126
|
-
// }
|
|
127
|
-
// }
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// // // src/managers/ValidatorManager.ts
|
|
134
|
-
// // import { logger } from "../logging";
|
|
135
|
-
// // import { ValidationError } from "../core/errors/ValidationError.js";
|
|
136
|
-
|
|
137
|
-
// // interface ValidatorAdapter {
|
|
138
|
-
// // validate: (schema?: any) => any;
|
|
139
|
-
// // }
|
|
140
|
-
|
|
141
|
-
// // export class ValidatorManager {
|
|
142
|
-
// // private zodAdapter: ValidatorAdapter;
|
|
143
|
-
// // private expressAdapter: ValidatorAdapter;
|
|
144
|
-
|
|
145
|
-
// // constructor(zodAdapter: ValidatorAdapter, expressAdapter: ValidatorAdapter) {
|
|
146
|
-
// // this.zodAdapter = zodAdapter;
|
|
147
|
-
// // this.expressAdapter = expressAdapter;
|
|
148
|
-
// // }
|
|
149
|
-
|
|
150
|
-
// // validate(schema?: any) {
|
|
151
|
-
// // // const isZod = schema && typeof schema.safeParse === "function";
|
|
152
|
-
// // const isZod =
|
|
153
|
-
// // schema &&
|
|
154
|
-
// // typeof schema === "object" &&
|
|
155
|
-
// // typeof schema._def === "object" &&
|
|
156
|
-
// // typeof schema.safeParse === "function";
|
|
157
|
-
|
|
158
|
-
// // const isExpressValidator = Array.isArray(schema);
|
|
159
|
-
|
|
160
|
-
// // return (req: any, res: any, next: any) => {
|
|
161
|
-
// // let middleware;
|
|
162
|
-
|
|
163
|
-
// // if (isZod) {
|
|
164
|
-
// // logger.debug("📌 Using Zod adapter");
|
|
165
|
-
// // middleware = this.zodAdapter.validate(schema);
|
|
166
|
-
// // }
|
|
167
|
-
// // else if (isExpressValidator) {
|
|
168
|
-
// // logger.debug("📌 Using express-validator adapter");
|
|
169
|
-
// // middleware = this.expressAdapter.validate(schema);
|
|
170
|
-
// // }
|
|
171
|
-
// // else {
|
|
172
|
-
// // return next(); // no schema found
|
|
173
|
-
// // }
|
|
174
|
-
|
|
175
|
-
// // // CASE 1 — express-validator returns ARRAY
|
|
176
|
-
// // if (Array.isArray(middleware)) {
|
|
177
|
-
// // let idx = 0;
|
|
178
|
-
|
|
179
|
-
// // const run = (err?: any) => {
|
|
180
|
-
// // if (err) return next(err);
|
|
181
|
-
|
|
182
|
-
// // const fn = middleware[idx++];
|
|
183
|
-
// // if (!fn) return next(); // done
|
|
184
|
-
|
|
185
|
-
// // try {
|
|
186
|
-
// // fn(req, res, run);
|
|
187
|
-
// // } catch (error: any) {
|
|
188
|
-
// // next(new ValidationError(error.message));
|
|
189
|
-
// // }
|
|
190
|
-
// // };
|
|
191
|
-
|
|
192
|
-
// // return run();
|
|
193
|
-
// // }
|
|
194
|
-
|
|
195
|
-
// // // CASE 2 — Zod returns SINGLE MIDDLEWARE
|
|
196
|
-
// // try {
|
|
197
|
-
// // middleware(req, res, (err?: any) => {
|
|
198
|
-
// // if (err) return next(err);
|
|
199
|
-
// // next();
|
|
200
|
-
// // });
|
|
201
|
-
// // } catch (err: any) {
|
|
202
|
-
// // next(new ValidationError(err.message));
|
|
203
|
-
// // }
|
|
204
|
-
// // };
|
|
205
|
-
// // }
|
|
206
|
-
// // }
|
|
207
|
-
|