hi-secure 1.0.16 → 1.0.18

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 (85) hide show
  1. package/dist/adapters/ArgonAdapter.d.ts.map +1 -1
  2. package/dist/adapters/ArgonAdapter.js +0 -36
  3. package/dist/adapters/ArgonAdapter.js.map +1 -1
  4. package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
  5. package/dist/adapters/BcryptAdapter.js +0 -36
  6. package/dist/adapters/BcryptAdapter.js.map +1 -1
  7. package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
  8. package/dist/adapters/ExpressRLAdapter.js +0 -38
  9. package/dist/adapters/ExpressRLAdapter.js.map +1 -1
  10. package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
  11. package/dist/adapters/ExpressValidatorAdapter.js +0 -36
  12. package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
  13. package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
  14. package/dist/adapters/GoogleAdapter.js +0 -63
  15. package/dist/adapters/GoogleAdapter.js.map +1 -1
  16. package/dist/adapters/JWTAdapter.d.ts.map +1 -1
  17. package/dist/adapters/JWTAdapter.js +0 -79
  18. package/dist/adapters/JWTAdapter.js.map +1 -1
  19. package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
  20. package/dist/adapters/RLFlexibleAdapter.js +0 -64
  21. package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
  22. package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
  23. package/dist/adapters/SanitizeHtmlAdapter.js +0 -64
  24. package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
  25. package/dist/adapters/XSSAdapter.d.ts.map +1 -1
  26. package/dist/adapters/XSSAdapter.js +0 -116
  27. package/dist/adapters/XSSAdapter.js.map +1 -1
  28. package/dist/adapters/ZodAdapter.d.ts.map +1 -1
  29. package/dist/adapters/ZodAdapter.js +0 -3
  30. package/dist/adapters/ZodAdapter.js.map +1 -1
  31. package/dist/core/HiSecure.d.ts.map +1 -1
  32. package/dist/core/HiSecure.js +0 -16
  33. package/dist/core/HiSecure.js.map +1 -1
  34. package/dist/logging/index.d.ts.map +1 -1
  35. package/dist/logging/index.js +0 -2
  36. package/dist/logging/index.js.map +1 -1
  37. package/dist/logging/morganSetup.d.ts.map +1 -1
  38. package/dist/logging/morganSetup.js +0 -14
  39. package/dist/logging/morganSetup.js.map +1 -1
  40. package/dist/logging/winstonSetup.d.ts.map +1 -1
  41. package/dist/logging/winstonSetup.js +2 -46
  42. package/dist/logging/winstonSetup.js.map +1 -1
  43. package/dist/managers/AuthManager.d.ts.map +1 -1
  44. package/dist/managers/AuthManager.js +0 -108
  45. package/dist/managers/AuthManager.js.map +1 -1
  46. package/dist/managers/CorsManager.d.ts.map +1 -1
  47. package/dist/managers/CorsManager.js +0 -28
  48. package/dist/managers/CorsManager.js.map +1 -1
  49. package/dist/managers/HashManager.d.ts.map +1 -1
  50. package/dist/managers/HashManager.js +0 -92
  51. package/dist/managers/HashManager.js.map +1 -1
  52. package/dist/managers/JsonManager.d.ts.map +1 -1
  53. package/dist/managers/JsonManager.js +0 -55
  54. package/dist/managers/JsonManager.js.map +1 -1
  55. package/dist/managers/RateLimitManager.d.ts.map +1 -1
  56. package/dist/managers/RateLimitManager.js +0 -3
  57. package/dist/managers/RateLimitManager.js.map +1 -1
  58. package/dist/managers/SanitizerManager.d.ts.map +1 -1
  59. package/dist/managers/SanitizerManager.js +0 -80
  60. package/dist/managers/SanitizerManager.js.map +1 -1
  61. package/dist/managers/ValidatorManager.d.ts.map +1 -1
  62. package/dist/managers/ValidatorManager.js +0 -59
  63. package/dist/managers/ValidatorManager.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/adapters/ArgonAdapter.ts +0 -45
  66. package/src/adapters/BcryptAdapter.ts +0 -49
  67. package/src/adapters/ExpressRLAdapter.ts +0 -48
  68. package/src/adapters/ExpressValidatorAdapter.ts +0 -50
  69. package/src/adapters/GoogleAdapter.ts +0 -82
  70. package/src/adapters/JWTAdapter.ts +0 -96
  71. package/src/adapters/RLFlexibleAdapter.ts +0 -82
  72. package/src/adapters/SanitizeHtmlAdapter.ts +1 -84
  73. package/src/adapters/XSSAdapter.ts +1 -150
  74. package/src/adapters/ZodAdapter.ts +0 -46
  75. package/src/core/HiSecure.ts +1 -369
  76. package/src/logging/index.ts +0 -6
  77. package/src/logging/morganSetup.ts +0 -25
  78. package/src/logging/winstonSetup.ts +2 -64
  79. package/src/managers/AuthManager.ts +0 -141
  80. package/src/managers/CorsManager.ts +0 -40
  81. package/src/managers/HashManager.ts +0 -108
  82. package/src/managers/JsonManager.ts +0 -62
  83. package/src/managers/RateLimitManager.ts +0 -113
  84. package/src/managers/SanitizerManager.ts +0 -103
  85. package/src/managers/ValidatorManager.ts +0 -75
@@ -1,48 +1,3 @@
1
- // import argon2 from "argon2";
2
- // import { AdapterError } from "../core/errors/AdapterError";
3
- // import { logger } from "../logging";
4
-
5
- // export class ArgonAdapter {
6
- // private options: argon2.Options | undefined;
7
-
8
- // constructor(options?: argon2.Options) {
9
- // if (options) {
10
- // this.options = options;
11
- // }
12
- // }
13
-
14
- // async hash(value: string): Promise<string> {
15
- // try {
16
- // return this.options
17
- // ? await argon2.hash(value, this.options)
18
- // : await argon2.hash(value);
19
- // } catch (err: any) {
20
- // logger.error("Argon2 hashing failed", {
21
- // error: err?.message || err
22
- // });
23
- // throw new AdapterError("Argon2 hashing failed.");
24
- // }
25
- // }
26
-
27
- // async verify(value: string, hashed: string): Promise<boolean> {
28
- // try {
29
- // if (!hashed || typeof hashed !== "string") {
30
- // throw new AdapterError("Invalid hash provided for verification.");
31
- // }
32
-
33
- // return await argon2.verify(hashed, value);
34
- // } catch (err: any) {
35
- // logger.error("Argon2 verify failed", {
36
- // error: err?.message || err
37
- // });
38
- // throw new AdapterError("Argon2 verify failed.");
39
- // }
40
- // }
41
- // }
42
-
43
-
44
-
45
-
46
1
  import argon2 from "argon2";
47
2
  import { AdapterError } from "../core/errors/AdapterError";
48
3
  import { logger } from "../logging";
@@ -1,52 +1,3 @@
1
- // import bcrypt from "bcryptjs";
2
- // import { AdapterError } from "../core/errors/AdapterError";
3
- // import { logger } from "../logging";
4
-
5
- // export class BcryptAdapter {
6
- // constructor(private saltRounds: number = 10) {}
7
-
8
- // async hash(value: string): Promise<string> {
9
- // try {
10
- // if (typeof value !== "string") {
11
- // throw new AdapterError("Value to hash must be a string.");
12
- // }
13
-
14
- // return await bcrypt.hash(value, this.saltRounds);
15
- // } catch (err: any) {
16
- // logger.error("Bcrypt hashing failed", {
17
- // error: err?.message || err,
18
- // saltRounds: this.saltRounds
19
- // });
20
-
21
- // throw new AdapterError("Bcrypt hashing failed.");
22
- // }
23
- // }
24
-
25
- // async verify(value: string, hashed: string): Promise<boolean> {
26
- // try {
27
- // if (typeof value !== "string") {
28
- // throw new AdapterError("Value to verify must be a string.");
29
- // }
30
-
31
- // if (!hashed || typeof hashed !== "string") {
32
- // throw new AdapterError("Invalid hashed string provided.");
33
- // }
34
-
35
- // return await bcrypt.compare(value, hashed);
36
- // } catch (err: any) {
37
- // logger.error("Bcrypt verify failed", {
38
- // error: err?.message || err
39
- // });
40
-
41
- // throw new AdapterError("Bcrypt verify failed.");
42
- // }
43
- // }
44
- // }
45
-
46
-
47
-
48
-
49
-
50
1
  import bcrypt from "bcryptjs";
51
2
  import { AdapterError } from "../core/errors/AdapterError";
52
3
  import { logger } from "../logging";
@@ -1,51 +1,3 @@
1
- // import rateLimit from "express-rate-limit";
2
- // import { logger } from "../logging/index.js";
3
- // import { AdapterError } from "../core/errors/AdapterError.js";
4
-
5
- // export interface RateLimitOptions {
6
- // windowMs?: number;
7
- // max?: number;
8
- // message?: any;
9
- // skipFailedRequests?: boolean;
10
- // standardHeaders?: boolean;
11
- // legacyHeaders?: boolean;
12
- // [key: string]: any;
13
- // }
14
-
15
- // export class ExpressRLAdapter {
16
- // getMiddleware(options: RateLimitOptions = {}) {
17
- // try {
18
- // const defaultOptions = {
19
- // windowMs: 15 * 60 * 1000,
20
- // max: 100,
21
- // message: { error: "Too many requests" },
22
- // standardHeaders: true,
23
- // legacyHeaders: false,
24
- // skipFailedRequests: false
25
- // };
26
-
27
- // const finalOptions = { ...defaultOptions, ...options };
28
-
29
- // const limiter = rateLimit(finalOptions);
30
-
31
- // logger.debug("Express rate limiter configured", {
32
- // windowMs: finalOptions.windowMs,
33
- // max: finalOptions.max
34
- // });
35
-
36
- // return limiter;
37
-
38
- // } catch (err: any) {
39
- // logger.error("ExpressRLAdapter: failed to create limiter", {
40
- // error: err?.message || err
41
- // });
42
- // throw new AdapterError("Express rate limiter creation failed.");
43
- // }
44
- // }
45
- // }
46
-
47
-
48
-
49
1
  import rateLimit from "express-rate-limit";
50
2
  import { logger } from "../logging";
51
3
  import { AdapterError } from "../core/errors/AdapterError";
@@ -1,53 +1,3 @@
1
- // import { validationResult } from "express-validator";
2
- // import { ValidationError } from "../core/errors/ValidationError.js";
3
- // import { logger } from "../logging/index.js";
4
-
5
- // export class ExpressValidatorAdapter {
6
- // private globalSchema?: any[];
7
-
8
- // constructor(globalSchema?: any[]) {
9
- // this.globalSchema = globalSchema;
10
- // }
11
-
12
- // validate(dynamicSchema?: any[]) {
13
- // const schema = dynamicSchema || this.globalSchema;
14
-
15
- // if (!schema || !Array.isArray(schema)) {
16
- // return (req: any, res: any, next: any) => next();
17
- // }
18
-
19
- // return [
20
- // ...schema,
21
-
22
- // (req: any, res: any, next: any) => {
23
- // const errors = validationResult(req);
24
-
25
- // if (!errors.isEmpty()) {
26
- // const formatted = errors.array().map(err => ({
27
- // message: err.msg,
28
- // // param: err.param ,
29
- // // location: err.location
30
- // }));
31
-
32
- // logger.warn("express-validator failed", {
33
- // path: req.path,
34
- // method: req.method,
35
- // errors: formatted,
36
- // preview: JSON.stringify(req.body).slice(0, 200)
37
- // });
38
-
39
- // return next(new ValidationError("Validation failed.", formatted as any));
40
- // }
41
-
42
- // next();
43
- // }
44
- // ];
45
- // }
46
- // }
47
-
48
-
49
-
50
-
51
1
  import { validationResult } from "express-validator";
52
2
  import { ValidationError } from "../core/errors/ValidationError";
53
3
  import { logger } from "../logging";
@@ -1,85 +1,3 @@
1
- // import { OAuth2Client, LoginTicket } from "google-auth-library";
2
- // import { AdapterError } from "../core/errors/AdapterError.js";
3
-
4
- // import {logger} from '../logging';
5
-
6
- // export interface GoogleTokenPayload {
7
- // sub: string;
8
- // email: string;
9
- // email_verified: boolean;
10
- // name?: string;
11
- // picture?: string;
12
- // [key: string]: any;
13
- // }
14
-
15
- // export class GoogleAdapter {
16
- // private client: OAuth2Client;
17
- // private clientId?: string;
18
-
19
- // constructor(clientId?: string) {
20
- // if (clientId && clientId.trim().length === 0) {
21
- // throw new AdapterError("Google clientId cannot be empty string");
22
- // }
23
-
24
- // this.client = new OAuth2Client(clientId);
25
- // this.clientId = clientId;
26
- // }
27
-
28
- // async verifyIdToken(idToken: string): Promise<GoogleTokenPayload> {
29
- // try {
30
- // if (!idToken || typeof idToken !== 'string') {
31
- // throw new AdapterError("Invalid ID token provided");
32
- // }
33
-
34
- // const options: { idToken: string; audience?: string | string[] } = {
35
- // idToken
36
- // };
37
-
38
- // // audience only if clientId is provided and not empty
39
- // if (this.clientId && this.clientId.trim().length > 0) {
40
- // options.audience = this.clientId;
41
- // }
42
-
43
- // const ticket: LoginTicket = await this.client.verifyIdToken(options);
44
- // const payload = ticket.getPayload();
45
-
46
- // if (!payload) {
47
- // logger.warn("GoogleAdapter: Empty payload");
48
- // throw new AdapterError("Invalid Google ID token payload.");
49
- // }
50
-
51
- // // result object
52
- // const result: GoogleTokenPayload = {
53
- // sub: payload.sub,
54
- // email: payload.email || '',
55
- // email_verified: payload.email_verified || false,
56
- // name: payload.name,
57
- // picture: payload.picture
58
- // };
59
-
60
- // // remaining properties from payload
61
- // const { sub, email, email_verified, name, picture, ...rest } = payload;
62
- // Object.assign(result, rest);
63
-
64
- // return result;
65
-
66
- // } catch (err: any) {
67
- // logger.error("GoogleAdapter.verifyIdToken failed", {
68
- // error: err?.message,
69
- // hasClientId: !!this.clientId
70
- // });
71
-
72
- // if (err.message?.includes('audience')) {
73
- // throw new AdapterError("Invalid Google client ID configured.");
74
- // }
75
-
76
- // throw new AdapterError(err?.message || "Google token verification failed");
77
- // }
78
- // }
79
- // }
80
-
81
-
82
-
83
1
  import { OAuth2Client, LoginTicket } from "google-auth-library";
84
2
  import { AdapterError } from "../core/errors/AdapterError";
85
3
  import { logger } from "../logging";
@@ -1,99 +1,3 @@
1
- // import jwt from "jsonwebtoken";
2
- // import { randomUUID } from "crypto";
3
- // import { AdapterError } from "../core/errors/AdapterError.js";
4
- // import { logError } from "../logging/index.js";
5
- // import { logger } from "../logging";
6
-
7
- // export interface JWTAdapterOptions {
8
- // secret: string;
9
- // expiresIn?: string | number;
10
- // algorithm?: jwt.Algorithm;
11
- // issuer?: string;
12
- // audience?: string | string[];
13
- // }
14
-
15
- // export interface SignOptions {
16
- // expiresIn?: string | number;
17
- // jti?: string;
18
- // subject?: string;
19
- // issuer?: string;
20
- // audience?: string | string[];
21
- // }
22
-
23
- // export class JWTAdapter {
24
- // private secret: string;
25
- // private expiresIn?: string | number;
26
- // private algorithm: jwt.Algorithm;
27
- // private issuer?: string;
28
- // private audience?: string | string[];
29
-
30
- // constructor(options: JWTAdapterOptions) {
31
- // if (!options.secret) {
32
- // throw new AdapterError("JWT secret is required");
33
- // }
34
-
35
- // if (options.secret.length < 32) {
36
- // logger.warn("JWT secret shorter than 32 chars. Consider using stronger secret.");
37
- // // logError("JWT secret is too short (minimum 32 characters recommended)");
38
- // }
39
-
40
- // this.secret = options.secret;
41
- // this.expiresIn = options.expiresIn;
42
- // this.algorithm = options.algorithm || 'HS256'; // Default algorithm
43
- // this.issuer = options.issuer;
44
- // this.audience = options.audience;
45
- // }
46
-
47
- // sign(payload: object, options?: SignOptions) {
48
- // try {
49
- // const jwtOptions: jwt.SignOptions = {
50
- // algorithm: this.algorithm,
51
- // issuer: options?.issuer || this.issuer,
52
- // audience: options?.audience || this.audience,
53
- // jwtid: options?.jti || randomUUID(),
54
- // subject: options?.subject
55
- // };
56
-
57
- // if (options?.expiresIn !== undefined) {
58
- // jwtOptions.expiresIn = options.expiresIn as number;
59
- // } else if (this.expiresIn !== undefined) {
60
- // jwtOptions.expiresIn = this.expiresIn as number;
61
- // }
62
-
63
- // return jwt.sign(payload, this.secret, jwtOptions);
64
-
65
- // } catch (err: any) {
66
- // logError("JWTAdapter.sign failed", { error: err?.message });
67
- // throw new AdapterError(err?.message || "JWT sign failed");
68
- // }
69
- // }
70
-
71
- // verify(token: string, options?: { audience?: string | string[] }) {
72
- // try {
73
- // const verifyOptions: jwt.VerifyOptions = {
74
- // algorithms: [this.algorithm],
75
- // issuer: this.issuer,
76
- // audience: options?.audience as string || this.audience as string
77
- // };
78
-
79
- // return jwt.verify(token, this.secret, verifyOptions);
80
- // } catch (err: any) {
81
- // logError("JWTAdapter.verify failed", { error: err?.message });
82
-
83
-
84
- // if (err.name === 'TokenExpiredError') {
85
- // throw new AdapterError("JWT token has expired");
86
- // }
87
- // if (err.name === 'JsonWebTokenError') {
88
- // throw new AdapterError("Invalid JWT token");
89
- // }
90
-
91
- // throw new AdapterError(err?.message || "JWT verification failed");
92
- // }
93
- // }
94
- // }
95
-
96
-
97
1
  import jwt from "jsonwebtoken";
98
2
  import { randomUUID } from "crypto";
99
3
  import { AdapterError } from "../core/errors/AdapterError";
@@ -1,85 +1,3 @@
1
- // import { RateLimiterMemory, RateLimiterRes } from "rate-limiter-flexible";
2
- // import { logger } from "../logging/index.js";
3
- // import { AdapterError } from "../core/errors/AdapterError.js";
4
-
5
- // export interface RLOptions {
6
- // points?: number;
7
- // duration?: number;
8
- // message?: any;
9
- // blockDuration?: number;
10
- // }
11
-
12
- // export class RLFlexibleAdapter {
13
- // getMiddleware(options: RLOptions = {}) {
14
- // try {
15
- // const defaultOptions = {
16
- // points: 100,
17
- // duration: 60,
18
- // message: "Too many requests, slow down.",
19
- // blockDuration: 0
20
- // };
21
-
22
- // const finalOptions = { ...defaultOptions, ...options };
23
-
24
- // const limiter = new RateLimiterMemory({
25
- // points: finalOptions.points,
26
- // duration: finalOptions.duration,
27
- // blockDuration: finalOptions.blockDuration
28
- // });
29
-
30
- // return async (req: any, res: any, next: any) => {
31
-
32
- // const ip = this.extractIP(req);
33
-
34
- // try {
35
- // await limiter.consume(ip);
36
- // next();
37
- // } catch (err: any) {
38
- // const rlErr = err as RateLimiterRes;
39
-
40
- // logger.warn("RLFlexibleAdapter: rate limit exceeded", {
41
- // ip,
42
- // path: req.path,
43
- // method: req.method,
44
- // retryAfter: rlErr.msBeforeNext
45
- // });
46
-
47
- // res.setHeader('Retry-After', Math.ceil(rlErr.msBeforeNext / 1000));
48
-
49
- // return res.status(429).json({
50
- // success: false,
51
- // error: "RATE_LIMIT_EXCEEDED",
52
- // retryAfter: Math.ceil(rlErr.msBeforeNext / 1000),
53
- // message: finalOptions.message
54
- // });
55
- // }
56
- // };
57
-
58
- // } catch (err: any) {
59
- // logger.error("RLFlexibleAdapter: failed to initialize limiter", {
60
- // error: err?.message || err
61
- // });
62
- // throw new AdapterError("RateLimiterFlexible creation failed.");
63
- // }
64
- // }
65
-
66
- // private extractIP(req: any): string {
67
- // return (
68
- // req.headers['x-real-ip'] ||
69
- // req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
70
- // req.ip ||
71
- // req.connection?.remoteAddress ||
72
- // req.socket?.remoteAddress ||
73
- // 'unknown'
74
- // );
75
- // }
76
- // }
77
-
78
-
79
-
80
-
81
-
82
-
83
1
  import { RateLimiterMemory, RateLimiterRes } from "rate-limiter-flexible";
84
2
  import { logger } from "../logging";
85
3
  import { AdapterError } from "../core/errors/AdapterError";
@@ -1,86 +1,3 @@
1
- // import sanitizeHtml from "sanitize-html";
2
- // import { AdapterError } from "../core/errors/AdapterError.js";
3
- // import { logger } from "../logging/index.js";
4
-
5
- // export class SanitizeHtmlAdapter {
6
- // private globalOptions: sanitizeHtml.IOptions;
7
-
8
- // constructor(options: sanitizeHtml.IOptions = {}) {
9
- // this.globalOptions = options;
10
- // }
11
-
12
- // sanitize(input: string, dynamicOptions?: any): string {
13
- // try {
14
- // const opts = { ...this.globalOptions, ...(dynamicOptions || {}) };
15
-
16
- // const clean = sanitizeHtml(input, opts);
17
- // return typeof clean === "string" ? clean : String(clean);
18
-
19
- // } catch (err: any) {
20
- // logger.error("sanitize-html failed", {
21
- // error: err?.message || err,
22
- // preview: typeof input === "string" ? input.slice(0, 100) : undefined
23
- // });
24
-
25
- // throw new AdapterError("sanitize-html adapter failed.");
26
- // }
27
- // }
28
-
29
- // // Deep Sanitization - Recursively
30
- // private deepSanitize(obj: any, dynamicOptions?: any, visited = new WeakSet()): any {
31
-
32
- // if (obj && typeof obj === "object") {
33
- // if (visited.has(obj)) {
34
- // return obj;
35
- // }
36
- // visited.add(obj);
37
- // }
38
-
39
- // if (typeof obj === "string") {
40
- // return this.sanitize(obj, dynamicOptions);
41
- // }
42
-
43
- // if (Array.isArray(obj)) {
44
- // return obj.map((item) => this.deepSanitize(item, dynamicOptions, visited));
45
- // }
46
-
47
- // if (obj && typeof obj === "object") {
48
- // const result: any = {};
49
- // for (const key of Object.keys(obj)) {
50
- // result[key] = this.deepSanitize(obj[key], dynamicOptions, visited);
51
- // }
52
- // return result;
53
- // }
54
-
55
- // return obj;
56
- // }
57
-
58
- // middleware(dynamicOptions?: any) {
59
- // return (req: any, _res: any, next: any) => {
60
- // try {
61
- // if (req.body) {
62
- // req.body = this.deepSanitize(req.body, dynamicOptions);
63
-
64
- // logger.debug("sanitize-html applied", {
65
- // keys: Object.keys(req.body)
66
- // });
67
- // }
68
- // next();
69
-
70
- // } catch (err: any) {
71
- // logger.error("sanitize-html middleware failed", {
72
- // error: err?.message || err
73
- // });
74
- // next(err);
75
- // }
76
- // };
77
- // }
78
- // }
79
-
80
-
81
-
82
-
83
-
84
1
  import sanitizeHtml from "sanitize-html";
85
2
  import { AdapterError } from "../core/errors/AdapterError";
86
3
  import { logger } from "../logging";
@@ -148,7 +65,7 @@ export class SanitizeHtmlAdapter {
148
65
  if (req.body) {
149
66
  req.body = this.deepSanitize(req.body, dynamicOptions);
150
67
 
151
- // ✅ visible + safe info log
68
+
152
69
  logger.info("HTML sanitization applied", {
153
70
  adapter: "sanitize-html",
154
71
  operation: "middleware",