hi-secure 1.0.0 → 1.0.3

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.
Files changed (50) hide show
  1. package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
  2. package/dist/adapters/ExpressRLAdapter.js +0 -29
  3. package/dist/adapters/ExpressRLAdapter.js.map +1 -1
  4. package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
  5. package/dist/adapters/GoogleAdapter.js +4 -3
  6. package/dist/adapters/GoogleAdapter.js.map +1 -1
  7. package/dist/adapters/JWTAdapter.d.ts.map +1 -1
  8. package/dist/adapters/JWTAdapter.js +3 -1
  9. package/dist/adapters/JWTAdapter.js.map +1 -1
  10. package/dist/core/HiSecure.d.ts +3 -18
  11. package/dist/core/HiSecure.d.ts.map +1 -1
  12. package/dist/core/HiSecure.js +29 -132
  13. package/dist/core/HiSecure.js.map +1 -1
  14. package/dist/core/errors/HttpError.d.ts +17 -0
  15. package/dist/core/errors/HttpError.d.ts.map +1 -0
  16. package/dist/core/errors/HttpError.js +36 -0
  17. package/dist/core/errors/HttpError.js.map +1 -0
  18. package/dist/core/useSecure.d.ts +0 -7
  19. package/dist/core/useSecure.d.ts.map +1 -1
  20. package/dist/core/useSecure.js +65 -21
  21. package/dist/core/useSecure.js.map +1 -1
  22. package/dist/index.d.ts +3 -6
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +19 -9
  25. package/dist/index.js.map +1 -1
  26. package/dist/managers/AuthManager.d.ts.map +1 -1
  27. package/dist/managers/AuthManager.js +18 -17
  28. package/dist/managers/AuthManager.js.map +1 -1
  29. package/dist/managers/ValidatorManager.d.ts +4 -6
  30. package/dist/managers/ValidatorManager.d.ts.map +1 -1
  31. package/dist/managers/ValidatorManager.js +97 -144
  32. package/dist/managers/ValidatorManager.js.map +1 -1
  33. package/dist/middlewares/errorHandler.js +2 -2
  34. package/dist/middlewares/errorHandler.js.map +1 -1
  35. package/dist/utils/normalizeOptions.d.ts.map +1 -1
  36. package/dist/utils/normalizeOptions.js +14 -4
  37. package/dist/utils/normalizeOptions.js.map +1 -1
  38. package/package.json +2 -2
  39. package/readme.md +195 -0
  40. package/src/adapters/ExpressRLAdapter.ts +0 -38
  41. package/src/adapters/GoogleAdapter.ts +5 -3
  42. package/src/adapters/JWTAdapter.ts +3 -1
  43. package/src/core/HiSecure.ts +414 -175
  44. package/src/core/useSecure.ts +91 -36
  45. package/src/index.ts +28 -12
  46. package/src/managers/AuthManager.ts +15 -13
  47. package/src/managers/ValidatorManager.ts +120 -182
  48. package/src/middlewares/errorHandler.ts +1 -1
  49. package/src/utils/normalizeOptions.ts +24 -9
  50. /package/src/core/errors/{HttpErrror.ts → HttpError.ts} +0 -0
@@ -61,51 +61,106 @@
61
61
  // src/core/useSecure.ts - SIMPLER VERSION
62
62
  // This is now optional since HiSecure class has fluent API
63
63
 
64
+
65
+ // import { HiSecure } from "./HiSecure.js";
66
+ // import { SecureOptions } from "./types/SecureOptions.js";
67
+
68
+ // /**
69
+ // * @deprecated Use HiSecure.middleware() or fluent API instead
70
+ // */
71
+ // export function useSecure(options?: SecureOptions | "api" | "strict" | "public") {
72
+ // console.warn("⚠ useSecure() is deprecated. Use HiSecure.middleware() or fluent API methods.");
73
+ // return HiSecure.middleware(options);
74
+ // }
75
+
76
+ // /**
77
+ // * Legacy support - route-level security
78
+ // */
79
+ // export function secureRoute(options?: SecureOptions) {
80
+ // const chain: any[] = [];
81
+
82
+ // if (options?.cors) {
83
+ // chain.push(HiSecure.cors(
84
+ // typeof options.cors === 'object' ? options.cors : undefined
85
+ // ));
86
+ // }
87
+
88
+ // if (options?.rateLimit) {
89
+ // chain.push(HiSecure.rateLimit(
90
+ // typeof options.rateLimit === 'object' ? options.rateLimit :
91
+ // options.rateLimit === "strict" ? "strict" : "relaxed"
92
+ // ));
93
+ // }
94
+
95
+ // if (options?.sanitize) {
96
+ // chain.push(HiSecure.sanitize(
97
+ // typeof options.sanitize === 'object' ? options.sanitize : undefined
98
+ // ));
99
+ // }
100
+
101
+ // if (options?.validate) {
102
+ // chain.push(HiSecure.validate(options.validate));
103
+ // }
104
+
105
+ // if (options?.auth) {
106
+ // chain.push(HiSecure.auth(
107
+ // typeof options.auth === 'object' ? options.auth : undefined
108
+ // ));
109
+ // }
110
+
111
+ // return chain;
112
+ // }
113
+
114
+
115
+
116
+
64
117
  import { HiSecure } from "./HiSecure.js";
65
118
  import { SecureOptions } from "./types/SecureOptions.js";
66
119
 
67
- /**
68
- * @deprecated Use HiSecure.middleware() or fluent API instead
69
- */
70
- export function useSecure(options?: SecureOptions | "api" | "strict" | "public") {
71
- console.warn("⚠ useSecure() is deprecated. Use HiSecure.middleware() or fluent API methods.");
72
- return HiSecure.middleware(options);
73
- }
74
-
75
- /**
76
- * Legacy support - route-level security
77
- */
78
120
  export function secureRoute(options?: SecureOptions) {
121
+ if (!options) return [];
122
+
79
123
  const chain: any[] = [];
80
-
81
- if (options?.cors) {
82
- chain.push(HiSecure.cors(
83
- typeof options.cors === 'object' ? options.cors : undefined
84
- ));
124
+
125
+ // 🔥 1. CORS
126
+ if (options.cors !== undefined) {
127
+ chain.push(
128
+ HiSecure.cors(typeof options.cors === "object" ? options.cors : undefined)
129
+ );
85
130
  }
86
-
87
- if (options?.rateLimit) {
88
- chain.push(HiSecure.rateLimit(
89
- typeof options.rateLimit === 'object' ? options.rateLimit :
90
- options.rateLimit === "strict" ? "strict" : "relaxed"
91
- ));
131
+
132
+ // 🔥 2. Rate Limiting (auto strict / relaxed detection)
133
+ if (options.rateLimit !== undefined) {
134
+ const rl = options.rateLimit;
135
+ if (rl === "strict" || rl === "relaxed") {
136
+ chain.push(HiSecure.rateLimit(rl));
137
+ } else if (typeof rl === "object") {
138
+ chain.push(HiSecure.rateLimit(rl));
139
+ } else {
140
+ chain.push(HiSecure.rateLimit("relaxed"));
141
+ }
92
142
  }
93
-
94
- if (options?.sanitize) {
95
- chain.push(HiSecure.sanitize(
96
- typeof options.sanitize === 'object' ? options.sanitize : undefined
97
- ));
143
+
144
+ // 🔥 3. Sanitization
145
+ if (options.sanitize !== undefined) {
146
+ chain.push(
147
+ HiSecure.sanitize(typeof options.sanitize === "object" ? options.sanitize : undefined)
148
+ );
98
149
  }
99
-
100
- if (options?.validate) {
150
+
151
+ // 🔥 4. Validation — smart auto-detection
152
+ if (options.validate) {
101
153
  chain.push(HiSecure.validate(options.validate));
102
154
  }
103
-
104
- if (options?.auth) {
105
- chain.push(HiSecure.auth(
106
- typeof options.auth === 'object' ? options.auth : undefined
107
- ));
155
+
156
+ // 🔥 5. Auth (roles included)
157
+ if (options.auth) {
158
+ chain.push(
159
+ HiSecure.auth(
160
+ typeof options.auth === "object" ? options.auth : undefined
161
+ )
162
+ );
108
163
  }
109
-
164
+
110
165
  return chain;
111
- }
166
+ }
package/src/index.ts CHANGED
@@ -1,17 +1,33 @@
1
- // src/index.ts - MAIN ENTRY POINT
2
- import { HiSecure } from "./core/HiSecure.js";
3
- import { useSecure, secureRoute } from "./core/useSecure.js";
1
+ // // src/index.ts - MAIN ENTRY POINT
2
+ // import { HiSecure } from "./core/HiSecure.js";
3
+ // import { useSecure, secureRoute } from "./core/useSecure.js";
4
+
5
+ // // Export the singleton instance for quick usage
6
+ // const hiSecure = HiSecure.getInstance();
7
+
8
+ // // Export everything
9
+ // export {
10
+ // HiSecure, // Class for advanced usage
11
+ // hiSecure, // Singleton instance
12
+ // useSecure, // Legacy function (deprecated)
13
+ // secureRoute // Route-level security helper
14
+ // };
15
+
16
+ // // Default export is the singleton instance
17
+ // export default hiSecure;
4
18
 
5
- // Export the singleton instance for quick usage
6
- const hiSecure = HiSecure.getInstance();
7
19
 
8
- // Export everything
20
+
21
+
22
+ // src/index.ts
23
+ import { HiSecure } from "./core/HiSecure.js";
24
+ import { secureRoute } from "./core/useSecure.js"; // Only if kept
25
+
26
+ // DON'T auto-init here
9
27
  export {
10
- HiSecure, // Class for advanced usage
11
- hiSecure, // Singleton instance
12
- useSecure, // Legacy function (deprecated)
13
- secureRoute // Route-level security helper
28
+ HiSecure, // Class
29
+ secureRoute // Optional sugar API
14
30
  };
15
31
 
16
- // Default export is the singleton instance
17
- export default hiSecure;
32
+ // Default export: class itself (NOT instance)
33
+ export default HiSecure;
@@ -105,9 +105,11 @@
105
105
  import { JWTAdapter } from "../adapters/JWTAdapter.js";
106
106
  import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
107
107
  import { AdapterError } from "../core/errors/AdapterError.js";
108
- import { HttpError } from "../core/errors/HttpErrror.js";
108
+ import { HttpError } from "../core/errors/HttpError.js";
109
109
  import { Request, Response, NextFunction } from "express";
110
- import { logError, logWarn, logInfo } from "../logging";
110
+ // import { logError, logWarn, logInfo } from "../logging";
111
+ import { logger } from "../logging";
112
+
111
113
 
112
114
  export interface AuthOptions {
113
115
  jwtSecret: string;
@@ -130,10 +132,10 @@ export class AuthManager {
130
132
  }
131
133
 
132
134
  if (opts.jwtSecret.length < 32) {
133
- logWarn("⚠ JWT secret is less than 32 characters - consider using a stronger secret");
135
+ logger.warn("⚠ JWT secret is less than 32 characters - consider using a stronger secret");
134
136
  }
135
137
 
136
- logInfo("AuthManager initialized");
138
+ logger.info("AuthManager initialized");
137
139
 
138
140
  this.jwtAdapter = new JWTAdapter({
139
141
  secret: opts.jwtSecret,
@@ -142,17 +144,17 @@ export class AuthManager {
142
144
 
143
145
  if (opts.googleClientId) {
144
146
  this.googleAdapter = new GoogleAdapter(opts.googleClientId);
145
- logInfo("GoogleAdapter enabled");
147
+ logger.info("GoogleAdapter enabled");
146
148
  }
147
149
  }
148
150
 
149
151
  sign(payload: object, options?: { expiresIn?: string | number, jti?: string }) {
150
- logInfo("JWT Sign called");
152
+ logger.info("JWT Sign called");
151
153
  return this.jwtAdapter.sign(payload, options);
152
154
  }
153
155
 
154
156
  verify(token: string) {
155
- logInfo("JWT Verify called");
157
+ logger.info("JWT Verify called");
156
158
  return this.jwtAdapter.verify(token);
157
159
  }
158
160
 
@@ -161,12 +163,12 @@ export class AuthManager {
161
163
  throw new AdapterError("GoogleAdapter not configured.");
162
164
  }
163
165
 
164
- logInfo("Google ID Token verify called");
166
+ logger.info("Google ID Token verify called");
165
167
 
166
168
  try {
167
169
  return await this.googleAdapter.verifyIdToken(idToken);
168
170
  } catch (err: any) {
169
- logError("Google ID Token verification failed", { error: err?.message });
171
+ logger.error("Google ID Token verification failed", { error: err?.message });
170
172
  throw HttpError.Unauthorized("Invalid Google ID token");
171
173
  }
172
174
  }
@@ -185,7 +187,7 @@ export class AuthManager {
185
187
 
186
188
  // If auth is required but no header
187
189
  if (!header) {
188
- logWarn("Missing Authorization header", {
190
+ logger.warn("Missing Authorization header", {
189
191
  path: req.path,
190
192
  method: req.method
191
193
  });
@@ -195,7 +197,7 @@ export class AuthManager {
195
197
  // Parse Bearer token
196
198
  const [type, token] = String(header).split(" ");
197
199
  if (type !== "Bearer" || !token) {
198
- logWarn("Invalid Authorization header", {
200
+ logger.warn("Invalid Authorization header", {
199
201
  path: req.path,
200
202
  method: req.method
201
203
  });
@@ -214,7 +216,7 @@ export class AuthManager {
214
216
  if (roles && roles.length > 0) {
215
217
  const userRole = (decoded as any).role || (decoded as any).roles?.[0];
216
218
  if (!userRole || !roles.includes(userRole)) {
217
- logWarn("Insufficient permissions", {
219
+ logger.warn("Insufficient permissions", {
218
220
  path: req.path,
219
221
  requiredRoles: roles,
220
222
  userRole
@@ -225,7 +227,7 @@ export class AuthManager {
225
227
 
226
228
  return next();
227
229
  } catch (err: any) {
228
- logError("JWT verify failed", {
230
+ logger.error("JWT verify failed", {
229
231
  error: err?.message,
230
232
  path: req.path,
231
233
  method: req.method
@@ -1,132 +1,7 @@
1
- // // // import { HiSecureConfig } from "../core/config";
2
- // // // import { logger } from "../logging";
3
- // // // import { ValidationError } from "../core/errors/ValidationError";
4
-
5
- // // // export class ValidatorManager {
6
- // // // private config: HiSecureConfig["validation"];
7
- // // // private primaryAdapter: any;
8
- // // // private fallbackAdapter: any;
9
-
10
- // // // constructor(
11
- // // // config: HiSecureConfig["validation"],
12
- // // // primaryAdapter: any,
13
- // // // fallbackAdapter: any
14
- // // // ) {
15
- // // // this.config = config;
16
- // // // this.primaryAdapter = primaryAdapter;
17
- // // // this.fallbackAdapter = fallbackAdapter;
18
- // // // }
19
-
20
- // // // /**
21
- // // // * Validate request body using primary adapter (Zod/express-validator).
22
- // // // * Fallback is only used if the adapter implementation itself throws.
23
- // // // */
24
- // // // validate(schema: any) {
25
- // // // return (req: any, res: any, next: any) => {
26
- // // // try {
27
- // // // const middleware = this.primaryAdapter.validate(schema);
28
- // // // return middleware(req, res, next);
29
-
30
- // // // } catch (err: any) {
31
- // // // logger.warn("⚠ Primary validator failed", {
32
- // // // error: err?.message,
33
- // // // path: req.path,
34
- // // // method: req.method
35
- // // // });
36
-
37
- // // // if (!this.fallbackAdapter) {
38
- // // // return next(new ValidationError("Validation failed."));
39
- // // // }
40
-
41
- // // // try {
42
- // // // logger.info("📌 Using fallback validator");
43
- // // // const fallbackMiddleware = this.fallbackAdapter.validate(schema);
44
- // // // return fallbackMiddleware(req, res, next);
45
-
46
- // // // } catch (fallbackErr: any) {
47
- // // // logger.error("❌ Fallback validation also failed", {
48
- // // // error: fallbackErr?.message
49
- // // // });
50
-
51
- // // // return next(new ValidationError("Both validators failed."));
52
- // // // }
53
- // // // }
54
- // // // };
55
- // // // }
56
- // // // }
57
-
58
-
59
-
60
- // // import { HiSecureConfig } from "../core/config.js";
61
- // // import { logger } from "../logging";
62
- // // import { ValidationError } from "../core/errors/ValidationError.js";
63
-
64
- // // interface ValidatorAdapter {
65
- // // validate: (schema?: any) => any;
66
- // // }
67
-
68
- // // export class ValidatorManager {
69
- // // private config: HiSecureConfig["validation"];
70
- // // private primaryAdapter: ValidatorAdapter;
71
- // // private fallbackAdapter: ValidatorAdapter | null;
72
-
73
- // // constructor(
74
- // // config: HiSecureConfig["validation"],
75
- // // primaryAdapter: ValidatorAdapter,
76
- // // fallbackAdapter: ValidatorAdapter | null
77
- // // ) {
78
- // // this.config = config;
79
- // // this.primaryAdapter = primaryAdapter;
80
- // // this.fallbackAdapter = fallbackAdapter;
81
- // // }
82
-
83
- // // /**
84
- // // * MAIN DYNAMIC VALIDATOR ENTRY
85
- // // * schema = per-route schema
86
- // // * If schema is undefined → use global schema
87
- // // */
88
- // // validate(schema?: any) {
89
- // // return (req: any, res: any, next: any) => {
90
- // // try {
91
- // // const middleware = this.primaryAdapter.validate(schema);
92
- // // return middleware(req, res, next);
93
-
94
- // // } catch (err: any) {
95
- // // logger.warn("⚠ Primary validator failed", {
96
- // // error: err?.message,
97
- // // path: req.path,
98
- // // method: req.method
99
- // // });
100
-
101
- // // if (!this.fallbackAdapter) {
102
- // // return next(new ValidationError("Validation failed"));
103
- // // }
104
-
105
- // // try {
106
- // // logger.info("📌 Using fallback validator");
107
- // // const fallbackMiddleware = this.fallbackAdapter.validate(schema);
108
- // // return fallbackMiddleware(req, res, next);
109
-
110
- // // } catch (fallbackErr: any) {
111
- // // logger.error("❌ Fallback validator also failed", {
112
- // // error: fallbackErr?.message
113
- // // });
114
-
115
- // // return next(new ValidationError("Both validators failed"));
116
- // // }
117
- // // }
118
- // // };
119
- // // }
120
- // // }
121
-
122
-
123
-
124
-
125
-
126
- // // src/managers/ValidatorManager.ts - FIXED
1
+ // // src/managers/ValidatorManager.ts - COMPLETE FIXED
127
2
  // import { logger } from "../logging";
128
3
  // import { ValidationError } from "../core/errors/ValidationError.js";
129
- // import { HiSecureConfig } from "../core/types/HiSecureConfig";
4
+ // import { HiSecureConfig } from "../core/types/HiSecureConfig.js"; // ✅ FIXED IMPORT
130
5
 
131
6
  // interface ValidatorAdapter {
132
7
  // validate: (schema?: any) => any;
@@ -196,74 +71,137 @@
196
71
  // }
197
72
 
198
73
 
199
- // src/managers/ValidatorManager.ts - COMPLETE FIXED
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
200
134
  import { logger } from "../logging";
201
135
  import { ValidationError } from "../core/errors/ValidationError.js";
202
- import { HiSecureConfig } from "../core/types/HiSecureConfig.js"; // ✅ FIXED IMPORT
203
136
 
204
137
  interface ValidatorAdapter {
205
138
  validate: (schema?: any) => any;
206
139
  }
207
140
 
208
141
  export class ValidatorManager {
209
- private config: HiSecureConfig["validation"];
210
- private primaryAdapter: ValidatorAdapter;
211
- private fallbackAdapter: ValidatorAdapter | null;
212
-
213
- constructor(
214
- config: HiSecureConfig["validation"],
215
- primaryAdapter: ValidatorAdapter,
216
- fallbackAdapter: ValidatorAdapter | null
217
- ) {
218
- this.config = config;
219
- this.primaryAdapter = primaryAdapter;
220
- this.fallbackAdapter = fallbackAdapter;
142
+ private zodAdapter: ValidatorAdapter;
143
+ private expressAdapter: ValidatorAdapter;
144
+
145
+ constructor(zodAdapter: ValidatorAdapter, expressAdapter: ValidatorAdapter) {
146
+ this.zodAdapter = zodAdapter;
147
+ this.expressAdapter = expressAdapter;
221
148
  }
222
149
 
223
150
  validate(schema?: any) {
224
- return (req: any, res: any, next: any) => {
225
- // Execute primary adapter middleware
226
- const primaryMiddleware = this.primaryAdapter.validate(schema);
227
-
228
- // Run middleware and handle errors properly
229
- primaryMiddleware(req, res, (err?: any) => {
230
- if (!err) {
231
- return next(); // Validation passed
232
- }
233
-
234
- // If error is a ValidationError, pass it through (don't fallback!)
235
- if (err instanceof ValidationError) {
236
- logger.warn("⚠ Validation failed", {
237
- path: req.path,
238
- method: req.method,
239
- error: err.message
240
- });
241
- return next(err);
242
- }
243
-
244
- // Only use fallback for ADAPTER errors, not validation errors
245
- logger.warn("⚠ Primary validator adapter failed", {
246
- error: err?.message,
247
- path: req.path,
248
- method: req.method
249
- });
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);
250
159
 
251
- if (!this.fallbackAdapter) {
252
- return next(new ValidationError("Validation system error"));
253
- }
254
-
255
- // Try fallback adapter
256
- const fallbackMiddleware = this.fallbackAdapter.validate(schema);
257
- fallbackMiddleware(req, res, (fallbackErr?: any) => {
258
- if (fallbackErr) {
259
- logger.error(" Fallback validator also failed", {
260
- error: fallbackErr?.message
261
- });
262
- return next(new ValidationError("Validation system unavailable"));
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));
263
189
  }
264
- next(); // Fallback validation passed
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();
265
200
  });
266
- });
201
+ } catch (err: any) {
202
+ next(new ValidationError(err.message));
203
+ }
267
204
  };
268
205
  }
269
- }
206
+ }
207
+
@@ -168,7 +168,7 @@ import { AdapterError } from "../core/errors/AdapterError.js";
168
168
  import { ValidationError } from "../core/errors/ValidationError.js";
169
169
  import { SanitizerError } from "../core/errors/SanitizerError.js";
170
170
  import { SecurityError } from "../core/errors/SecurityError.js";
171
- import { HttpError } from "../core/errors/HttpErrror.js";
171
+ import { HttpError } from "../core/errors/HttpError.js";
172
172
 
173
173
  export function errorHandler(
174
174
  err: any,
@@ -160,10 +160,16 @@ export function normalizeOptions(input?: SecureOptions | false): NormalizedOptio
160
160
  options: typeof opts.sanitize === "object" ? opts.sanitize : undefined
161
161
  },
162
162
 
163
+ // validate: {
164
+ // enabled: !!opts.validate,
165
+ // schema: opts.validate || undefined
166
+ // },
167
+
163
168
  validate: {
164
- enabled: !!opts.validate,
165
- schema: opts.validate || undefined
166
- },
169
+ enabled: opts.validate !== undefined,
170
+ schema: opts.validate
171
+ },
172
+
167
173
 
168
174
  json: {
169
175
  enabled: opts.json === undefined ? true : opts.json !== false,
@@ -212,13 +218,22 @@ function normalizeRateLimit(value: SecureOptions["rateLimit"]): NormalizedOption
212
218
  }
213
219
 
214
220
  function normalizeAuth(value: SecureOptions["auth"]): NormalizedOptions["auth"] {
215
- if (value === false) {
216
- return { enabled: false, required: false };
217
- }
221
+ // if (value === false) {
222
+ // return { enabled: false, required: false };
223
+ // }
218
224
 
219
- if (value === true || value === undefined) {
220
- return { enabled: true, required: true };
221
- }
225
+ // if (value === true || value === undefined) {
226
+ // return { enabled: true, required: true };
227
+ // }
228
+
229
+
230
+ if (value === undefined) {
231
+ return { enabled: false, required: false };
232
+ }
233
+ if (value === true) {
234
+ return { enabled: true, required: true };
235
+ }
236
+
222
237
 
223
238
  const authOptions = value as AuthOptions;
224
239
  const enabled = authOptions.required !== false;