hi-secure 1.0.15 → 1.0.16

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 (99) hide show
  1. package/dist/adapters/ArgonAdapter.d.ts +1 -1
  2. package/dist/adapters/ArgonAdapter.d.ts.map +1 -1
  3. package/dist/adapters/ArgonAdapter.js +43 -5
  4. package/dist/adapters/ArgonAdapter.js.map +1 -1
  5. package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
  6. package/dist/adapters/BcryptAdapter.js +43 -3
  7. package/dist/adapters/BcryptAdapter.js.map +1 -1
  8. package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
  9. package/dist/adapters/ExpressRLAdapter.js +48 -6
  10. package/dist/adapters/ExpressRLAdapter.js.map +1 -1
  11. package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
  12. package/dist/adapters/ExpressValidatorAdapter.js +50 -10
  13. package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
  14. package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
  15. package/dist/adapters/GoogleAdapter.js +82 -16
  16. package/dist/adapters/GoogleAdapter.js.map +1 -1
  17. package/dist/adapters/JWTAdapter.d.ts.map +1 -1
  18. package/dist/adapters/JWTAdapter.js +104 -15
  19. package/dist/adapters/JWTAdapter.js.map +1 -1
  20. package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
  21. package/dist/adapters/RLFlexibleAdapter.js +87 -12
  22. package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
  23. package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
  24. package/dist/adapters/SanitizeHtmlAdapter.js +81 -13
  25. package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
  26. package/dist/adapters/XSSAdapter.d.ts +1 -1
  27. package/dist/adapters/XSSAdapter.d.ts.map +1 -1
  28. package/dist/adapters/XSSAdapter.js +137 -20
  29. package/dist/adapters/XSSAdapter.js.map +1 -1
  30. package/dist/adapters/ZodAdapter.d.ts +1 -1
  31. package/dist/adapters/ZodAdapter.d.ts.map +1 -1
  32. package/dist/adapters/ZodAdapter.js +13 -8
  33. package/dist/adapters/ZodAdapter.js.map +1 -1
  34. package/dist/core/HiSecure.d.ts +3 -4
  35. package/dist/core/HiSecure.d.ts.map +1 -1
  36. package/dist/core/HiSecure.js +108 -121
  37. package/dist/core/HiSecure.js.map +1 -1
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +8 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/logging/index.d.ts.map +1 -1
  43. package/dist/logging/index.js +2 -0
  44. package/dist/logging/index.js.map +1 -1
  45. package/dist/logging/morganSetup.d.ts.map +1 -1
  46. package/dist/logging/morganSetup.js +22 -1
  47. package/dist/logging/morganSetup.js.map +1 -1
  48. package/dist/logging/winstonSetup.d.ts.map +1 -1
  49. package/dist/logging/winstonSetup.js +61 -3
  50. package/dist/logging/winstonSetup.js.map +1 -1
  51. package/dist/managers/AuthManager.d.ts +2 -2
  52. package/dist/managers/AuthManager.d.ts.map +1 -1
  53. package/dist/managers/AuthManager.js +167 -31
  54. package/dist/managers/AuthManager.js.map +1 -1
  55. package/dist/managers/CorsManager.d.ts.map +1 -1
  56. package/dist/managers/CorsManager.js +46 -11
  57. package/dist/managers/CorsManager.js.map +1 -1
  58. package/dist/managers/HashManager.d.ts +1 -1
  59. package/dist/managers/HashManager.d.ts.map +1 -1
  60. package/dist/managers/HashManager.js +127 -17
  61. package/dist/managers/HashManager.js.map +1 -1
  62. package/dist/managers/JsonManager.d.ts +1 -1
  63. package/dist/managers/JsonManager.d.ts.map +1 -1
  64. package/dist/managers/JsonManager.js +99 -16
  65. package/dist/managers/JsonManager.js.map +1 -1
  66. package/dist/managers/RateLimitManager.d.ts +1 -1
  67. package/dist/managers/RateLimitManager.d.ts.map +1 -1
  68. package/dist/managers/RateLimitManager.js +46 -22
  69. package/dist/managers/RateLimitManager.js.map +1 -1
  70. package/dist/managers/SanitizerManager.d.ts.map +1 -1
  71. package/dist/managers/SanitizerManager.js +112 -15
  72. package/dist/managers/SanitizerManager.js.map +1 -1
  73. package/dist/managers/ValidatorManager.d.ts.map +1 -1
  74. package/dist/managers/ValidatorManager.js +90 -7
  75. package/dist/managers/ValidatorManager.js.map +1 -1
  76. package/package.json +2 -6
  77. package/readme.md +3 -6
  78. package/src/adapters/ArgonAdapter.ts +55 -6
  79. package/src/adapters/BcryptAdapter.ts +56 -8
  80. package/src/adapters/ExpressRLAdapter.ts +62 -9
  81. package/src/adapters/ExpressValidatorAdapter.ts +67 -11
  82. package/src/adapters/GoogleAdapter.ts +106 -21
  83. package/src/adapters/JWTAdapter.ts +129 -21
  84. package/src/adapters/RLFlexibleAdapter.ts +113 -16
  85. package/src/adapters/SanitizeHtmlAdapter.ts +111 -18
  86. package/src/adapters/XSSAdapter.ts +183 -39
  87. package/src/adapters/ZodAdapter.ts +56 -10
  88. package/src/core/HiSecure.ts +496 -162
  89. package/src/index.ts +4 -0
  90. package/src/logging/index.ts +6 -0
  91. package/src/logging/morganSetup.ts +36 -1
  92. package/src/logging/winstonSetup.ts +97 -8
  93. package/src/managers/AuthManager.ts +205 -34
  94. package/src/managers/CorsManager.ts +63 -16
  95. package/src/managers/HashManager.ts +156 -19
  96. package/src/managers/JsonManager.ts +119 -15
  97. package/src/managers/RateLimitManager.ts +174 -29
  98. package/src/managers/SanitizerManager.ts +150 -25
  99. package/src/managers/ValidatorManager.ts +115 -15
@@ -1,5 +1,113 @@
1
- import { AdapterError } from "../core/errors/AdapterError.js";
2
- import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
1
+ // import { AdapterError } from "../core/errors/AdapterError.js";
2
+ // import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
3
+ // import { logger } from "../logging";
4
+
5
+ // interface HashAdapter {
6
+ // hash(value: string): Promise<string>;
7
+ // verify(value: string, hashed: string): Promise<boolean>;
8
+ // }
9
+
10
+ // export interface HashResult {
11
+ // hash: string;
12
+ // algorithm: string;
13
+ // usedFallback: boolean;
14
+ // }
15
+
16
+ // export class HashManager {
17
+ // private config: HiSecureConfig["hashing"];
18
+ // private primaryAdapter: HashAdapter;
19
+ // private fallbackAdapter: HashAdapter | null;
20
+
21
+ // constructor(
22
+ // config: HiSecureConfig["hashing"],
23
+ // primaryAdapter: HashAdapter,
24
+ // fallbackAdapter: HashAdapter | null
25
+ // ) {
26
+ // this.config = config;
27
+ // this.primaryAdapter = primaryAdapter;
28
+ // this.fallbackAdapter = fallbackAdapter;
29
+ // }
30
+
31
+ // async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
32
+ // try {
33
+ // const hash = await this.primaryAdapter.hash(value);
34
+ // return {
35
+ // hash,
36
+ // algorithm: this.config.primary,
37
+ // usedFallback: false
38
+ // };
39
+ // } catch (err: any) {
40
+ // logger.warn("Primary hashing failed", {
41
+ // error: err.message,
42
+ // algorithm: this.config.primary
43
+ // });
44
+
45
+ // if (!options?.allowFallback || !this.fallbackAdapter) {
46
+ // throw new AdapterError(
47
+ // `Primary hashing (${this.config.primary}) failed. Fallback not allowed.`
48
+ // );
49
+ // }
50
+
51
+ // try {
52
+ // const hash = await this.fallbackAdapter.hash(value);
53
+
54
+ // // Log security downgrade warning
55
+ // logger.warn("SECURITY DOWNGRADE: Using fallback hashing", {
56
+ // from: this.config.primary,
57
+ // to: this.config.fallback
58
+ // });
59
+
60
+ // return {
61
+ // hash,
62
+ // algorithm: this.config.fallback || 'bcrypt',
63
+ // usedFallback: true
64
+ // };
65
+ // } catch (fallbackErr: any) {
66
+ // logger.error("Fallback hashing failed", {
67
+ // error: fallbackErr?.message,
68
+ // });
69
+ // throw new AdapterError(
70
+ // "Both primary and fallback hashing failed."
71
+ // );
72
+ // }
73
+ // }
74
+ // }
75
+
76
+ // async verify(value: string, hashed: string): Promise<boolean> {
77
+ // // primary adapter - first
78
+ // try {
79
+ // return await this.primaryAdapter.verify(value, hashed);
80
+ // } catch (primaryErr: any) {
81
+ // logger.warn("Primary verify failed", {
82
+ // error: primaryErr?.message,
83
+ // });
84
+
85
+ // // fallback exists - try it
86
+ // if (this.fallbackAdapter) {
87
+ // try {
88
+ // return await this.fallbackAdapter.verify(value, hashed);
89
+ // } catch (fallbackErr: any) {
90
+ // logger.error(" Fallback verify failed", {
91
+ // error: fallbackErr?.message,
92
+ // });
93
+ // throw new AdapterError(
94
+ // "Both primary and fallback verify failed."
95
+ // );
96
+ // }
97
+ // }
98
+
99
+ // throw new AdapterError(
100
+ // "Primary verify failed and no fallback adapter configured."
101
+ // );
102
+ // }
103
+ // }
104
+ // }
105
+
106
+
107
+
108
+
109
+ import { AdapterError } from "../core/errors/AdapterError";
110
+ import { HiSecureConfig } from "../core/types/HiSecureConfig";
3
111
  import { logger } from "../logging";
4
112
 
5
113
  interface HashAdapter {
@@ -26,20 +134,33 @@ export class HashManager {
26
134
  this.config = config;
27
135
  this.primaryAdapter = primaryAdapter;
28
136
  this.fallbackAdapter = fallbackAdapter;
137
+
138
+ logger.info("HashManager initialized", {
139
+ layer: "hash-manager",
140
+ primary: config.primary,
141
+ fallbackEnabled: !!fallbackAdapter
142
+ });
29
143
  }
30
144
 
31
- async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
145
+ async hash(
146
+ value: string,
147
+ options?: { allowFallback?: boolean }
148
+ ): Promise<HashResult> {
32
149
  try {
33
150
  const hash = await this.primaryAdapter.hash(value);
151
+
34
152
  return {
35
153
  hash,
36
154
  algorithm: this.config.primary,
37
155
  usedFallback: false
38
156
  };
157
+
39
158
  } catch (err: any) {
40
159
  logger.warn("Primary hashing failed", {
41
- error: err.message,
42
- algorithm: this.config.primary
160
+ layer: "hash-manager",
161
+ operation: "hash",
162
+ algorithm: this.config.primary,
163
+ reason: err?.message
43
164
  });
44
165
 
45
166
  if (!options?.allowFallback || !this.fallbackAdapter) {
@@ -50,22 +171,30 @@ export class HashManager {
50
171
 
51
172
  try {
52
173
  const hash = await this.fallbackAdapter.hash(value);
53
-
54
- // Log security downgrade warning
55
- logger.warn("SECURITY DOWNGRADE: Using fallback hashing", {
174
+
175
+ // ⚠️ security downgrade log (VERY GOOD PRACTICE)
176
+ logger.warn("Hashing fallback used (security downgrade)", {
177
+ layer: "hash-manager",
178
+ operation: "hash",
56
179
  from: this.config.primary,
57
180
  to: this.config.fallback
58
181
  });
59
-
182
+
60
183
  return {
61
184
  hash,
62
- algorithm: this.config.fallback || 'bcrypt',
185
+ algorithm: this.config.fallback || "bcrypt",
63
186
  usedFallback: true
64
187
  };
188
+
65
189
  } catch (fallbackErr: any) {
66
190
  logger.error("Fallback hashing failed", {
67
- error: fallbackErr?.message,
191
+ layer: "hash-manager",
192
+ operation: "hash",
193
+ from: this.config.primary,
194
+ to: this.config.fallback,
195
+ reason: fallbackErr?.message
68
196
  });
197
+
69
198
  throw new AdapterError(
70
199
  "Both primary and fallback hashing failed."
71
200
  );
@@ -74,31 +203,39 @@ export class HashManager {
74
203
  }
75
204
 
76
205
  async verify(value: string, hashed: string): Promise<boolean> {
77
- // primary adapter - first
78
206
  try {
79
207
  return await this.primaryAdapter.verify(value, hashed);
208
+
80
209
  } catch (primaryErr: any) {
81
- logger.warn("Primary verify failed", {
82
- error: primaryErr?.message,
210
+ logger.warn("Primary hash verification failed", {
211
+ layer: "hash-manager",
212
+ operation: "verify",
213
+ algorithm: this.config.primary,
214
+ reason: primaryErr?.message
83
215
  });
84
216
 
85
- // fallback exists - try it
86
217
  if (this.fallbackAdapter) {
87
218
  try {
88
219
  return await this.fallbackAdapter.verify(value, hashed);
220
+
89
221
  } catch (fallbackErr: any) {
90
- logger.error(" Fallback verify failed", {
91
- error: fallbackErr?.message,
222
+ logger.error("Fallback hash verification failed", {
223
+ layer: "hash-manager",
224
+ operation: "verify",
225
+ from: this.config.primary,
226
+ to: this.config.fallback,
227
+ reason: fallbackErr?.message
92
228
  });
229
+
93
230
  throw new AdapterError(
94
231
  "Both primary and fallback verify failed."
95
232
  );
96
233
  }
97
234
  }
98
-
235
+
99
236
  throw new AdapterError(
100
237
  "Primary verify failed and no fallback adapter configured."
101
238
  );
102
239
  }
103
240
  }
104
- }
241
+ }
@@ -1,19 +1,97 @@
1
+ // import express from "express";
2
+ // import qs from "qs";
3
+ // import { logger } from "../logging";
4
+ // import { AdapterError } from "../core/errors/AdapterError.js";
5
+
6
+ // export class JsonManager {
7
+ // middleware(options?: any) {
8
+ // try {
9
+ // const defaultOptions = {
10
+ // limit: '1mb',
11
+ // inflate: true,
12
+ // strict: true
13
+ // };
14
+ // return express.json({ ...defaultOptions, ...(options || {}) });
15
+ // } catch (err: any) {
16
+ // logger.error("JSON Manager: failed to create JSON parser");
17
+ // throw new AdapterError("JSON parser initialization failed.");
18
+ // }
19
+ // }
20
+
21
+ // urlencoded(options?: any) {
22
+ // try {
23
+ // const defaultOptions = {
24
+ // extended: true,
25
+ // limit: '1mb',
26
+ // parameterLimit: 1000
27
+ // };
28
+ // const opts = { ...defaultOptions, ...(options || {}) };
29
+ // return express.urlencoded(opts);
30
+ // } catch (err: any) {
31
+ // logger.error("URL-encoded parser failed");
32
+ // throw new AdapterError("URL-encoded parser initialization failed.");
33
+ // }
34
+ // }
35
+
36
+ // queryParser(options?: any) {
37
+ // return (req: any, res: any, next: any) => {
38
+ // try {
39
+ // if (!req.parsedQuery && req.url.includes('?')) {
40
+ // const queryString = req.url.split("?")[1] || "";
41
+ // const parsed = qs.parse(queryString, {
42
+ // depth: 5,
43
+ // parameterLimit: 100,
44
+ // ...options
45
+ // });
46
+
47
+ // req.parsedQuery = parsed;
48
+ // logger.debug(" Query parsed", {
49
+ // keys: Object.keys(parsed)
50
+ // });
51
+ // }
52
+ // next();
53
+ // } catch (err: any) {
54
+ // logger.error("Failed to parse query", { error: err?.message });
55
+ // next(new AdapterError("Query parsing failed."));
56
+ // }
57
+ // };
58
+ // }
59
+ // }
60
+
61
+
62
+
1
63
  import express from "express";
2
64
  import qs from "qs";
3
65
  import { logger } from "../logging";
4
- import { AdapterError } from "../core/errors/AdapterError.js";
66
+ import { AdapterError } from "../core/errors/AdapterError";
5
67
 
6
68
  export class JsonManager {
7
69
  middleware(options?: any) {
8
70
  try {
9
71
  const defaultOptions = {
10
- limit: '1mb',
72
+ limit: "1mb",
11
73
  inflate: true,
12
74
  strict: true
13
75
  };
14
- return express.json({ ...defaultOptions, ...(options || {}) });
76
+
77
+ const finalOptions = { ...defaultOptions, ...(options || {}) };
78
+
79
+ logger.info("JSON body parser configured", {
80
+ layer: "json-manager",
81
+ operation: "json",
82
+ limit: finalOptions.limit,
83
+ strict: finalOptions.strict
84
+ });
85
+
86
+ return express.json(finalOptions);
87
+
15
88
  } catch (err: any) {
16
- logger.error("JSON Manager: failed to create JSON parser");
89
+ logger.error("JSON body parser initialization failed", {
90
+ layer: "json-manager",
91
+ operation: "json",
92
+ reason: err?.message
93
+ });
94
+
17
95
  throw new AdapterError("JSON parser initialization failed.");
18
96
  }
19
97
  }
@@ -22,38 +100,64 @@ export class JsonManager {
22
100
  try {
23
101
  const defaultOptions = {
24
102
  extended: true,
25
- limit: '1mb',
103
+ limit: "1mb",
26
104
  parameterLimit: 1000
27
105
  };
28
- const opts = { ...defaultOptions, ...(options || {}) };
29
- return express.urlencoded(opts);
106
+
107
+ const finalOptions = { ...defaultOptions, ...(options || {}) };
108
+
109
+ logger.info("URL-encoded parser configured", {
110
+ layer: "json-manager",
111
+ operation: "urlencoded",
112
+ limit: finalOptions.limit,
113
+ parameterLimit: finalOptions.parameterLimit
114
+ });
115
+
116
+ return express.urlencoded(finalOptions);
117
+
30
118
  } catch (err: any) {
31
- logger.error("URL-encoded parser failed");
119
+ logger.error("URL-encoded parser initialization failed", {
120
+ layer: "json-manager",
121
+ operation: "urlencoded",
122
+ reason: err?.message
123
+ });
124
+
32
125
  throw new AdapterError("URL-encoded parser initialization failed.");
33
126
  }
34
127
  }
35
128
 
36
129
  queryParser(options?: any) {
37
- return (req: any, res: any, next: any) => {
130
+ return (req: any, _res: any, next: any) => {
38
131
  try {
39
- if (!req.parsedQuery && req.url.includes('?')) {
132
+ if (!req.parsedQuery && req.url.includes("?")) {
40
133
  const queryString = req.url.split("?")[1] || "";
134
+
41
135
  const parsed = qs.parse(queryString, {
42
136
  depth: 5,
43
137
  parameterLimit: 100,
44
138
  ...options
45
139
  });
46
-
140
+
47
141
  req.parsedQuery = parsed;
48
- logger.debug(" Query parsed", {
49
- keys: Object.keys(parsed)
142
+
143
+ // ✅ visible + safe info
144
+ logger.info("Query parameters parsed", {
145
+ layer: "json-manager",
146
+ operation: "query-parse",
147
+ keyCount: Object.keys(parsed).length
50
148
  });
51
149
  }
150
+
52
151
  next();
53
152
  } catch (err: any) {
54
- logger.error("Failed to parse query", { error: err?.message });
153
+ logger.error("Query parsing failed", {
154
+ layer: "json-manager",
155
+ operation: "query-parse",
156
+ reason: err?.message
157
+ });
158
+
55
159
  next(new AdapterError("Query parsing failed."));
56
160
  }
57
161
  };
58
162
  }
59
- }
163
+ }
@@ -1,5 +1,118 @@
1
- import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
2
- import { AdapterError } from "../core/errors/AdapterError.js";
1
+ // import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
2
+ // import { AdapterError } from "../core/errors/AdapterError.js";
3
+ // import { logger } from "../logging";
4
+
5
+ // interface RateLimiterAdapter {
6
+ // getMiddleware: (options?: any) => any;
7
+ // }
8
+
9
+ // export class RateLimitManager {
10
+ // private config: HiSecureConfig["rateLimiter"];
11
+ // private primaryAdapter: RateLimiterAdapter;
12
+ // private fallbackAdapter: RateLimiterAdapter | null;
13
+
14
+ // constructor(
15
+ // config: HiSecureConfig["rateLimiter"],
16
+ // primaryAdapter: RateLimiterAdapter,
17
+ // fallbackAdapter: RateLimiterAdapter | null
18
+ // ) {
19
+ // this.config = config;
20
+ // this.primaryAdapter = primaryAdapter;
21
+ // this.fallbackAdapter = fallbackAdapter;
22
+ // }
23
+
24
+ // middleware(opts?: { mode?: "strict" | "relaxed" | "api"; options?: any }) {
25
+ // let finalOptions: any = {};
26
+
27
+ // if (opts?.mode === "strict") {
28
+ // finalOptions = {
29
+ // windowMs: 10_000,
30
+ // max: 5,
31
+ // message: "Too many requests, please slow down."
32
+ // };
33
+ // } else if (opts?.mode === "relaxed") {
34
+ // finalOptions = {
35
+ // windowMs: 60_000,
36
+ // max: 100,
37
+ // message: "Rate limit exceeded."
38
+ // };
39
+ // } else if (opts?.mode === "api") {
40
+ // finalOptions = {
41
+ // windowMs: 15 * 60 * 1000,
42
+ // max: 100,
43
+ // message: "API rate limit exceeded."
44
+ // };
45
+ // } else {
46
+ // finalOptions = {
47
+ // windowMs: this.config.windowMs,
48
+ // max: this.config.maxRequests,
49
+ // message: this.config.message,
50
+ // standardHeaders: true,
51
+ // legacyHeaders: false
52
+ // };
53
+ // }
54
+
55
+ // if (opts?.options) {
56
+ // const allowedOverrides = ['message', 'skipFailedRequests', 'standardHeaders', 'legacyHeaders'];
57
+ // for (const key of allowedOverrides) {
58
+ // if (opts.options[key] !== undefined) {
59
+ // finalOptions[key] = opts.options[key];
60
+ // }
61
+ // }
62
+
63
+ // const attemptedOverrides = Object.keys(opts.options).filter(
64
+ // k => !allowedOverrides.includes(k) && k !== 'mode'
65
+ // );
66
+ // if (attemptedOverrides.length > 0) {
67
+ // logger.warn("Rate limit overrides ignored", {
68
+ // preset: opts?.mode || 'default',
69
+ // ignoredOptions: attemptedOverrides
70
+ // });
71
+ // }
72
+ // }
73
+
74
+ // if (finalOptions.standardHeaders === undefined) {
75
+ // finalOptions.standardHeaders = true;
76
+ // }
77
+ // if (finalOptions.legacyHeaders === undefined) {
78
+ // finalOptions.legacyHeaders = false;
79
+ // }
80
+
81
+ // try {
82
+ // logger.info("Applying rate limiting", {
83
+ // mode: opts?.mode || 'default',
84
+ // windowMs: finalOptions.windowMs,
85
+ // max: finalOptions.max
86
+ // });
87
+
88
+ // return this.primaryAdapter.getMiddleware(finalOptions);
89
+ // } catch (err: any) {
90
+ // logger.warn("Primary rate limiter failed → fallback", {
91
+ // error: err?.message
92
+ // });
93
+
94
+ // if (!this.fallbackAdapter) {
95
+ // throw new AdapterError("Rate limiters failed; no fallback adapter.");
96
+ // }
97
+
98
+ // try {
99
+ // logger.info("Using fallback rate limiter");
100
+ // return this.fallbackAdapter.getMiddleware(finalOptions);
101
+ // } catch (fallbackErr: any) {
102
+ // logger.error("Fallback limiter also failed", {
103
+ // error: fallbackErr?.message
104
+ // });
105
+ // throw new AdapterError("Both primary and fallback limiters failed.");
106
+ // }
107
+ // }
108
+ // }
109
+ // }
110
+
111
+
112
+
113
+
114
+ import { HiSecureConfig } from "../core/types/HiSecureConfig";
115
+ import { AdapterError } from "../core/errors/AdapterError";
3
116
  import { logger } from "../logging";
4
117
 
5
118
  interface RateLimiterAdapter {
@@ -19,26 +132,33 @@ export class RateLimitManager {
19
132
  this.config = config;
20
133
  this.primaryAdapter = primaryAdapter;
21
134
  this.fallbackAdapter = fallbackAdapter;
135
+
136
+ logger.info("RateLimitManager initialized", {
137
+ layer: "rate-limit-manager",
138
+ primaryConfigured: true,
139
+ fallbackConfigured: !!fallbackAdapter
140
+ });
22
141
  }
23
142
 
24
143
  middleware(opts?: { mode?: "strict" | "relaxed" | "api"; options?: any }) {
25
144
  let finalOptions: any = {};
145
+ const mode = opts?.mode || "default";
26
146
 
27
- if (opts?.mode === "strict") {
147
+ if (mode === "strict") {
28
148
  finalOptions = {
29
149
  windowMs: 10_000,
30
150
  max: 5,
31
151
  message: "Too many requests, please slow down."
32
152
  };
33
- } else if (opts?.mode === "relaxed") {
153
+ } else if (mode === "relaxed") {
34
154
  finalOptions = {
35
155
  windowMs: 60_000,
36
156
  max: 100,
37
157
  message: "Rate limit exceeded."
38
158
  };
39
- } else if (opts?.mode === "api") {
159
+ } else if (mode === "api") {
40
160
  finalOptions = {
41
- windowMs: 15 * 60 * 1000,
161
+ windowMs: 15 * 60 * 1000,
42
162
  max: 100,
43
163
  message: "API rate limit exceeded."
44
164
  };
@@ -47,63 +167,88 @@ export class RateLimitManager {
47
167
  windowMs: this.config.windowMs,
48
168
  max: this.config.maxRequests,
49
169
  message: this.config.message,
50
- standardHeaders: true,
51
- legacyHeaders: false
170
+ standardHeaders: true,
171
+ legacyHeaders: false
52
172
  };
53
173
  }
54
174
 
55
175
  if (opts?.options) {
56
- const allowedOverrides = ['message', 'skipFailedRequests', 'standardHeaders', 'legacyHeaders'];
176
+ const allowedOverrides = [
177
+ "message",
178
+ "skipFailedRequests",
179
+ "standardHeaders",
180
+ "legacyHeaders"
181
+ ];
182
+
57
183
  for (const key of allowedOverrides) {
58
184
  if (opts.options[key] !== undefined) {
59
185
  finalOptions[key] = opts.options[key];
60
186
  }
61
187
  }
62
-
188
+
63
189
  const attemptedOverrides = Object.keys(opts.options).filter(
64
- k => !allowedOverrides.includes(k) && k !== 'mode'
190
+ k => !allowedOverrides.includes(k) && k !== "mode"
65
191
  );
192
+
66
193
  if (attemptedOverrides.length > 0) {
67
194
  logger.warn("Rate limit overrides ignored", {
68
- preset: opts?.mode || 'default',
195
+ layer: "rate-limit-manager",
196
+ operation: "configure",
197
+ mode,
69
198
  ignoredOptions: attemptedOverrides
70
199
  });
71
200
  }
72
201
  }
73
202
 
74
- if (finalOptions.standardHeaders === undefined) {
75
- finalOptions.standardHeaders = true;
76
- }
77
- if (finalOptions.legacyHeaders === undefined) {
78
- finalOptions.legacyHeaders = false;
79
- }
203
+ finalOptions.standardHeaders ??= true;
204
+ finalOptions.legacyHeaders ??= false;
80
205
 
81
206
  try {
82
- logger.info("Applying rate limiting", {
83
- mode: opts?.mode || 'default',
207
+ logger.info("Rate limiting applied", {
208
+ layer: "rate-limit-manager",
209
+ operation: "apply",
210
+ mode,
84
211
  windowMs: finalOptions.windowMs,
85
212
  max: finalOptions.max
86
213
  });
87
-
214
+
88
215
  return this.primaryAdapter.getMiddleware(finalOptions);
216
+
89
217
  } catch (err: any) {
90
- logger.warn("Primary rate limiter failed → fallback", {
91
- error: err?.message
218
+ logger.warn("Primary rate limiter failed", {
219
+ layer: "rate-limit-manager",
220
+ operation: "apply",
221
+ mode,
222
+ reason: err?.message
92
223
  });
93
224
 
94
225
  if (!this.fallbackAdapter) {
95
- throw new AdapterError("Rate limiters failed; no fallback adapter.");
226
+ throw new AdapterError(
227
+ "Rate limiters failed; no fallback adapter configured."
228
+ );
96
229
  }
97
230
 
98
231
  try {
99
- logger.info("Using fallback rate limiter");
232
+ logger.warn("Using fallback rate limiter", {
233
+ layer: "rate-limit-manager",
234
+ operation: "fallback",
235
+ mode
236
+ });
237
+
100
238
  return this.fallbackAdapter.getMiddleware(finalOptions);
239
+
101
240
  } catch (fallbackErr: any) {
102
- logger.error("Fallback limiter also failed", {
103
- error: fallbackErr?.message
241
+ logger.error("Fallback rate limiter failed", {
242
+ layer: "rate-limit-manager",
243
+ operation: "fallback",
244
+ mode,
245
+ reason: fallbackErr?.message
104
246
  });
105
- throw new AdapterError("Both primary and fallback limiters failed.");
247
+
248
+ throw new AdapterError(
249
+ "Both primary and fallback rate limiters failed."
250
+ );
106
251
  }
107
252
  }
108
253
  }
109
- }
254
+ }