hi-secure 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hi-secure",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -1,3 +1,6 @@
1
+ /* The `HiSecure` class is a security library in TypeScript that provides various security features
2
+ such as hashing, rate limiting, validation, sanitization, and authentication through a fluent API
3
+ and global middleware setup. */
1
4
  // // // src/core/HiSecure.ts
2
5
 
3
6
  // // import { HiSecureConfig } from "./types/HiSecureConfig.js";
@@ -238,7 +241,7 @@
238
241
 
239
242
 
240
243
 
241
- // // src/core/HiSecure.ts - COMPLETE FIXED
244
+ // src/core/HiSecure.ts - COMPLETE FIXED
242
245
  // import { HiSecureConfig } from "./types/HiSecureConfig.js";
243
246
  // import { defaultConfig } from "./config.js";
244
247
  // import { LIB_NAME, LIB_VERSION } from "./constants.js";
@@ -595,9 +598,376 @@
595
598
  // }
596
599
 
597
600
 
601
+
598
602
  // =================
599
603
 
600
- // // src/core/HiSecure.ts - COMPLETELY FIXED
604
+ // src/core/HiSecure.ts - COMPLETELY FIXED
605
+ import { HiSecureConfig } from "./types/HiSecureConfig.js";
606
+ import { defaultConfig } from "./config.js";
607
+ import { LIB_NAME, LIB_VERSION } from "./constants.js";
608
+ import { deepMerge } from "../utils/deepMerge.js";
609
+ import { deepFreeze } from "../utils/deepFreeze.js";
610
+ import { logger } from "../logging/index.js";
611
+
612
+ // Adapters
613
+ import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
614
+ import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
615
+ import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
616
+ import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
617
+ import { ZodAdapter } from "../adapters/ZodAdapter.js";
618
+ import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
619
+ import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
620
+ import { XSSAdapter } from "../adapters/XSSAdapter.js";
621
+
622
+ // Managers
623
+ import { HashManager } from "../managers/HashManager.js";
624
+ import { RateLimitManager } from "../managers/RateLimitManager.js";
625
+ import { ValidatorManager } from "../managers/ValidatorManager.js";
626
+ import { SanitizerManager } from "../managers/SanitizerManager.js";
627
+ import { JsonManager } from "../managers/JsonManager.js";
628
+ import { CorsManager } from "../managers/CorsManager.js";
629
+ import { AuthManager } from "../managers/AuthManager.js";
630
+
631
+ // Middlewares
632
+ import helmet from "helmet";
633
+ import hpp from "hpp";
634
+ import compression from "compression";
635
+ import { errorHandler } from "../middlewares/errorHandler.js";
636
+
637
+ // Types
638
+ import { SecureOptions, ValidationSchema, RateLimitOptions } from "./types/SecureOptions.js";
639
+
640
+ export class HiSecure {
641
+ private static instance: HiSecure | null = null;
642
+ private config: HiSecureConfig;
643
+ private initialized = false;
644
+
645
+ // Managers
646
+ public hashManager!: HashManager;
647
+ public rateLimitManager!: RateLimitManager;
648
+ public validatorManager!: ValidatorManager;
649
+ public sanitizerManager!: SanitizerManager;
650
+ public jsonManager!: JsonManager;
651
+ public corsManager!: CorsManager;
652
+ public authManager?: AuthManager;
653
+
654
+ // Internal adapters
655
+ private hashingPrimary: any;
656
+ private hashingFallback: any;
657
+ private rateLimiterPrimary: any;
658
+ private rateLimiterFallback: any;
659
+ private validatorPrimary: any;
660
+ private validatorFallback: any;
661
+ private sanitizerPrimary: any;
662
+ private sanitizerFallback: any;
663
+
664
+ // Private constructor for singleton
665
+ private constructor(userConfig: Partial<HiSecureConfig> = {}) {
666
+ this.config = deepMerge(defaultConfig, userConfig);
667
+ }
668
+
669
+ // =====================================================
670
+ // SINGLETON & INITIALIZATION
671
+ // =====================================================
672
+
673
+ static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
674
+ if (!HiSecure.instance) {
675
+ HiSecure.instance = new HiSecure(config);
676
+ HiSecure.instance.init();
677
+ }
678
+ return HiSecure.instance;
679
+ }
680
+
681
+ static resetInstance(): void {
682
+ HiSecure.instance = null;
683
+ }
684
+
685
+ init(): void {
686
+ if (this.initialized) {
687
+ logger.warn("⚠ HiSecure already initialized");
688
+ return;
689
+ }
690
+
691
+ logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initializing...`);
692
+
693
+ this.setupAdapters();
694
+ this.setupManagers();
695
+ this.setupDynamicManagers();
696
+
697
+ // Make everything immutable
698
+ deepFreeze(this.config);
699
+ // deepFreeze(this.hashManager);
700
+ // deepFreeze(this.rateLimitManager);
701
+ // deepFreeze(this.validatorManager);
702
+ // deepFreeze(this.sanitizerManager);
703
+ // deepFreeze(this.jsonManager);
704
+ // deepFreeze(this.corsManager);
705
+ // if (this.authManager) deepFreeze(this.authManager);
706
+
707
+ this.initialized = true;
708
+ logger.info("✅ HiSecure initialized successfully");
709
+ }
710
+
711
+ isInitialized(): boolean {
712
+ return this.initialized;
713
+ }
714
+
715
+ // =====================================================
716
+ // FLUENT API METHODS (Route-level security)
717
+ // =====================================================
718
+
719
+ static auth(options?: { required?: boolean; roles?: string[] }) {
720
+ const instance = this.getInstance();
721
+ if (!instance.authManager) {
722
+ throw new Error("Auth not enabled. Set auth.enabled=true in config.");
723
+ }
724
+ return instance.authManager.protect(options);
725
+ }
726
+
727
+ static validate(schema: ValidationSchema) {
728
+ return this.getInstance().validatorManager.validate(schema);
729
+ }
730
+
731
+ static sanitize(options?: any) {
732
+ return this.getInstance().sanitizerManager.middleware(options);
733
+ }
734
+
735
+ static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
736
+ const instance = this.getInstance();
737
+
738
+ if (typeof preset === "string") {
739
+ const presets: Record<string, { mode?: "strict" | "relaxed" | "api"; options?: any }> = {
740
+ strict: { mode: "strict" },
741
+ relaxed: { mode: "relaxed" },
742
+ api: { mode: "api", options: { max: 100, windowMs: 60000 } }
743
+ };
744
+ return instance.rateLimitManager.middleware(presets[preset] || {});
745
+ }
746
+
747
+ return instance.rateLimitManager.middleware({ options: preset });
748
+ }
749
+
750
+ static cors(options?: any) {
751
+ return this.getInstance().corsManager.middleware(options);
752
+ }
753
+
754
+ static json(options?: any) {
755
+ const instance = this.getInstance();
756
+ const chain = [];
757
+ chain.push(instance.jsonManager.middleware(options));
758
+ chain.push(instance.jsonManager.urlencoded());
759
+ return chain;
760
+ }
761
+
762
+ // =====================================================
763
+ // UTILITY METHODS (Direct usage)
764
+ // =====================================================
765
+
766
+ static async hash(password: string): Promise<string> {
767
+ const instance = this.getInstance();
768
+ const result = await instance.hashManager.hash(password, { allowFallback: true });
769
+ return result.hash;
770
+ }
771
+
772
+ static async verify(password: string, hash: string): Promise<boolean> {
773
+ return this.getInstance().hashManager.verify(password, hash);
774
+ }
775
+
776
+ static jwt = {
777
+ sign: (payload: object, options?: any) => {
778
+ const instance = HiSecure.getInstance();
779
+ if (!instance.authManager) {
780
+ throw new Error("Auth not enabled");
781
+ }
782
+ return instance.authManager.sign(payload, options);
783
+ },
784
+
785
+ verify: (token: string) => {
786
+ const instance = HiSecure.getInstance();
787
+ if (!instance.authManager) {
788
+ throw new Error("Auth not enabled");
789
+ }
790
+ return instance.authManager.verify(token);
791
+ },
792
+
793
+ google: {
794
+ verifyIdToken: (idToken: string) => {
795
+ const instance = HiSecure.getInstance();
796
+ if (!instance.authManager) {
797
+ throw new Error("Auth not enabled");
798
+ }
799
+ return instance.authManager.verifyGoogleIdToken(idToken);
800
+ }
801
+ }
802
+ };
803
+
804
+ // =====================================================
805
+ // GLOBAL MIDDLEWARE (app.use())
806
+ // =====================================================
807
+
808
+ static middleware(options?: SecureOptions | "api" | "strict" | "public") {
809
+ const instance = this.getInstance();
810
+
811
+ // Handle preset strings
812
+ if (typeof options === "string") {
813
+ const presets: Record<string, SecureOptions> = {
814
+ api: { cors: true, rateLimit: "relaxed" as any, sanitize: true },
815
+ strict: { cors: true, rateLimit: "strict" as any, sanitize: true, auth: true },
816
+ public: { cors: true, rateLimit: true as any, sanitize: false }
817
+ };
818
+ const presetOptions = presets[options];
819
+ if (presetOptions) {
820
+ return instance.createMiddlewareChain(presetOptions);
821
+ }
822
+ return instance.createMiddlewareChain({});
823
+ }
824
+
825
+ return instance.createMiddlewareChain(options || {});
826
+ }
827
+
828
+ // =====================================================
829
+ // INTERNAL METHODS
830
+ // =====================================================
831
+
832
+ private setupAdapters(): void {
833
+ logger.info("🧩 Setting up adapters...");
834
+
835
+ // Hashing
836
+ this.hashingPrimary = this.config.hashing.primary === "argon2"
837
+ ? new ArgonAdapter()
838
+ : new BcryptAdapter(this.config.hashing.saltRounds);
839
+
840
+ this.hashingFallback = this.config.hashing.fallback === "bcrypt"
841
+ ? new BcryptAdapter(this.config.hashing.saltRounds)
842
+ : null;
843
+
844
+ // Rate limiting
845
+ this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
846
+ ? new RLFlexibleAdapter()
847
+ : new ExpressRLAdapter();
848
+ this.rateLimiterFallback = new ExpressRLAdapter();
849
+
850
+ // Validation
851
+ this.validatorPrimary = this.config.validation.mode === "zod"
852
+ ? new ZodAdapter()
853
+ : new ExpressValidatorAdapter();
854
+ this.validatorFallback = this.config.validation.fallback === "express-validator"
855
+ ? new ExpressValidatorAdapter()
856
+ : null;
857
+
858
+ // Sanitization
859
+ this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
860
+ this.sanitizerFallback = new XSSAdapter(this.config.sanitizer);
861
+
862
+ logger.info("✅ Adapters ready");
863
+ }
864
+
865
+ private setupManagers(): void {
866
+ this.hashManager = new HashManager(
867
+ this.config.hashing,
868
+ this.hashingPrimary,
869
+ this.hashingFallback
870
+ );
871
+
872
+ this.rateLimitManager = new RateLimitManager(
873
+ this.config.rateLimiter,
874
+ this.rateLimiterPrimary,
875
+ this.rateLimiterFallback
876
+ );
877
+
878
+ this.validatorManager = new ValidatorManager(
879
+ // this.config.validation,
880
+ // this.validatorPrimary,
881
+ // this.validatorFallback
882
+ new ZodAdapter(),
883
+ new ExpressValidatorAdapter()
884
+ );
885
+
886
+ this.sanitizerManager = new SanitizerManager(
887
+ this.sanitizerPrimary,
888
+ this.sanitizerFallback
889
+ );
890
+ }
891
+
892
+ private setupDynamicManagers(): void {
893
+ this.jsonManager = new JsonManager();
894
+ this.corsManager = new CorsManager();
895
+
896
+ // Auth manager (only if enabled)
897
+ if (this.config.auth.enabled) {
898
+ const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
899
+ if (!jwtSecret) {
900
+ throw new Error("JWT_SECRET environment variable or jwtSecret in config is required when auth.enabled=true");
901
+ }
902
+
903
+ this.authManager = new AuthManager({
904
+ jwtSecret,
905
+ jwtExpiresIn: this.config.auth.jwtExpiresIn,
906
+ googleClientId: process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
907
+ // Removed algorithm - handled in AuthManager
908
+ });
909
+ }
910
+ }
911
+
912
+ private createMiddlewareChain(options: SecureOptions): any[] {
913
+ const chain: any[] = [];
914
+
915
+ // JSON parsing
916
+ chain.push(this.jsonManager.middleware(this.config.json));
917
+ chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
918
+
919
+ // Security headers
920
+ if (this.config.enableHelmet) chain.push(helmet());
921
+ if (this.config.enableHPP) chain.push(hpp());
922
+
923
+ // Compression (check if compression config exists)
924
+ if (this.config.enableCompression && this.config.compression) {
925
+ chain.push(compression(this.config.compression));
926
+ } else if (this.config.enableCompression) {
927
+ chain.push(compression()); // Use defaults
928
+ }
929
+
930
+ // CORS
931
+ if (this.config.enableCORS || options.cors) {
932
+ const corsOptions = options.cors === true ? this.config.cors :
933
+ (typeof options.cors === 'object' ? options.cors : this.config.cors);
934
+ chain.push(this.corsManager.middleware(corsOptions));
935
+ }
936
+
937
+ // Sanitization
938
+ if (this.config.enableSanitizer || options.sanitize) {
939
+ const sanitizeOptions = options.sanitize === true ? undefined :
940
+ (typeof options.sanitize === 'object' ? options.sanitize : undefined);
941
+ chain.push(this.sanitizerManager.middleware(sanitizeOptions));
942
+ }
943
+
944
+ // Rate limiting
945
+ if (this.config.enableRateLimiter || options.rateLimit) {
946
+ const rateLimitOpts = typeof options.rateLimit === 'object' ?
947
+ { options: options.rateLimit } : {};
948
+ chain.push(this.rateLimitManager.middleware(rateLimitOpts));
949
+ }
950
+
951
+ // Authentication
952
+ if (options.auth && this.authManager) {
953
+ const authOpts = options.auth === true ? undefined :
954
+ (typeof options.auth === 'object' ? options.auth : undefined);
955
+ chain.push(this.authManager.protect(authOpts));
956
+ }
957
+
958
+ // Error handler (always last)
959
+ chain.push(errorHandler);
960
+
961
+ return chain;
962
+ }
963
+ }
964
+
965
+
966
+ // ===================
967
+
968
+
969
+
970
+ // // src/core/HiSecure.ts - FINAL VERSION
601
971
  // import { HiSecureConfig } from "./types/HiSecureConfig.js";
602
972
  // import { defaultConfig } from "./config.js";
603
973
  // import { LIB_NAME, LIB_VERSION } from "./constants.js";
@@ -631,7 +1001,7 @@
631
1001
  // import { errorHandler } from "../middlewares/errorHandler.js";
632
1002
 
633
1003
  // // Types
634
- // import { SecureOptions, ValidationSchema, RateLimitOptions } from "./types/SecureOptions.js";
1004
+ // import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
635
1005
 
636
1006
  // export class HiSecure {
637
1007
  // private static instance: HiSecure | null = null;
@@ -652,20 +1022,14 @@
652
1022
  // private hashingFallback: any;
653
1023
  // private rateLimiterPrimary: any;
654
1024
  // private rateLimiterFallback: any;
655
- // private validatorPrimary: any;
656
- // private validatorFallback: any;
657
- // private sanitizerPrimary: any;
658
- // private sanitizerFallback: any;
659
1025
 
660
- // // Private constructor for singleton
661
1026
  // private constructor(userConfig: Partial<HiSecureConfig> = {}) {
662
1027
  // this.config = deepMerge(defaultConfig, userConfig);
663
1028
  // }
664
1029
 
665
1030
  // // =====================================================
666
- // // SINGLETON & INITIALIZATION
1031
+ // // SINGLETON
667
1032
  // // =====================================================
668
-
669
1033
  // static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
670
1034
  // if (!HiSecure.instance) {
671
1035
  // HiSecure.instance = new HiSecure(config);
@@ -679,10 +1043,7 @@
679
1043
  // }
680
1044
 
681
1045
  // init(): void {
682
- // if (this.initialized) {
683
- // logger.warn("⚠ HiSecure already initialized");
684
- // return;
685
- // }
1046
+ // if (this.initialized) return;
686
1047
 
687
1048
  // logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initializing...`);
688
1049
 
@@ -690,34 +1051,20 @@
690
1051
  // this.setupManagers();
691
1052
  // this.setupDynamicManagers();
692
1053
 
693
- // // Make everything immutable
1054
+ // // DO NOT FREEZE MANAGERS
1055
+ // // ✔ Only freeze config
694
1056
  // deepFreeze(this.config);
695
- // deepFreeze(this.hashManager);
696
- // deepFreeze(this.rateLimitManager);
697
- // deepFreeze(this.validatorManager);
698
- // deepFreeze(this.sanitizerManager);
699
- // deepFreeze(this.jsonManager);
700
- // deepFreeze(this.corsManager);
701
- // if (this.authManager) deepFreeze(this.authManager);
702
1057
 
703
1058
  // this.initialized = true;
704
1059
  // logger.info("✅ HiSecure initialized successfully");
705
1060
  // }
706
1061
 
707
- // isInitialized(): boolean {
708
- // return this.initialized;
709
- // }
710
-
711
1062
  // // =====================================================
712
- // // FLUENT API METHODS (Route-level security)
1063
+ // // FLUENT API (Route-level)
713
1064
  // // =====================================================
714
-
1065
+
715
1066
  // static auth(options?: { required?: boolean; roles?: string[] }) {
716
- // const instance = this.getInstance();
717
- // if (!instance.authManager) {
718
- // throw new Error("Auth not enabled. Set auth.enabled=true in config.");
719
- // }
720
- // return instance.authManager.protect(options);
1067
+ // return this.getInstance().authManager!.protect(options);
721
1068
  // }
722
1069
 
723
1070
  // static validate(schema: ValidationSchema) {
@@ -728,107 +1075,39 @@
728
1075
  // return this.getInstance().sanitizerManager.middleware(options);
729
1076
  // }
730
1077
 
1078
+ // static cors(options?: any) {
1079
+ // return this.getInstance().corsManager.middleware(options);
1080
+ // }
1081
+
731
1082
  // static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
732
1083
  // const instance = this.getInstance();
733
-
1084
+
734
1085
  // if (typeof preset === "string") {
735
- // const presets: Record<string, { mode?: "strict" | "relaxed" | "api"; options?: any }> = {
1086
+ // const presets: any = {
736
1087
  // strict: { mode: "strict" },
737
1088
  // relaxed: { mode: "relaxed" },
738
1089
  // api: { mode: "api", options: { max: 100, windowMs: 60000 } }
739
1090
  // };
740
1091
  // return instance.rateLimitManager.middleware(presets[preset] || {});
741
1092
  // }
742
-
743
1093
  // return instance.rateLimitManager.middleware({ options: preset });
744
1094
  // }
745
1095
 
746
- // static cors(options?: any) {
747
- // return this.getInstance().corsManager.middleware(options);
748
- // }
749
-
750
1096
  // static json(options?: any) {
751
1097
  // const instance = this.getInstance();
752
- // const chain = [];
753
- // chain.push(instance.jsonManager.middleware(options));
754
- // chain.push(instance.jsonManager.urlencoded());
755
- // return chain;
1098
+ // return [
1099
+ // instance.jsonManager.middleware(options),
1100
+ // instance.jsonManager.urlencoded()
1101
+ // ];
756
1102
  // }
757
1103
 
758
1104
  // // =====================================================
759
- // // UTILITY METHODS (Direct usage)
1105
+ // // INTERNAL SETUP
760
1106
  // // =====================================================
761
-
762
- // static async hash(password: string): Promise<string> {
763
- // const instance = this.getInstance();
764
- // const result = await instance.hashManager.hash(password, { allowFallback: true });
765
- // return result.hash;
766
- // }
767
1107
 
768
- // static async verify(password: string, hash: string): Promise<boolean> {
769
- // return this.getInstance().hashManager.verify(password, hash);
770
- // }
771
-
772
- // static jwt = {
773
- // sign: (payload: object, options?: any) => {
774
- // const instance = HiSecure.getInstance();
775
- // if (!instance.authManager) {
776
- // throw new Error("Auth not enabled");
777
- // }
778
- // return instance.authManager.sign(payload, options);
779
- // },
780
-
781
- // verify: (token: string) => {
782
- // const instance = HiSecure.getInstance();
783
- // if (!instance.authManager) {
784
- // throw new Error("Auth not enabled");
785
- // }
786
- // return instance.authManager.verify(token);
787
- // },
788
-
789
- // google: {
790
- // verifyIdToken: (idToken: string) => {
791
- // const instance = HiSecure.getInstance();
792
- // if (!instance.authManager) {
793
- // throw new Error("Auth not enabled");
794
- // }
795
- // return instance.authManager.verifyGoogleIdToken(idToken);
796
- // }
797
- // }
798
- // };
799
-
800
- // // =====================================================
801
- // // GLOBAL MIDDLEWARE (app.use())
802
- // // =====================================================
803
-
804
- // static middleware(options?: SecureOptions | "api" | "strict" | "public") {
805
- // const instance = this.getInstance();
806
-
807
- // // Handle preset strings
808
- // if (typeof options === "string") {
809
- // const presets: Record<string, SecureOptions> = {
810
- // api: { cors: true, rateLimit: "relaxed" as any, sanitize: true },
811
- // strict: { cors: true, rateLimit: "strict" as any, sanitize: true, auth: true },
812
- // public: { cors: true, rateLimit: true as any, sanitize: false }
813
- // };
814
- // const presetOptions = presets[options];
815
- // if (presetOptions) {
816
- // return instance.createMiddlewareChain(presetOptions);
817
- // }
818
- // return instance.createMiddlewareChain({});
819
- // }
820
-
821
- // return instance.createMiddlewareChain(options || {});
822
- // }
823
-
824
- // // =====================================================
825
- // // INTERNAL METHODS
826
- // // =====================================================
827
-
828
1108
  // private setupAdapters(): void {
829
1109
  // logger.info("🧩 Setting up adapters...");
830
1110
 
831
- // // Hashing
832
1111
  // this.hashingPrimary = this.config.hashing.primary === "argon2"
833
1112
  // ? new ArgonAdapter()
834
1113
  // : new BcryptAdapter(this.config.hashing.saltRounds);
@@ -837,33 +1116,17 @@
837
1116
  // ? new BcryptAdapter(this.config.hashing.saltRounds)
838
1117
  // : null;
839
1118
 
840
- // // Rate limiting
841
1119
  // this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
842
1120
  // ? new RLFlexibleAdapter()
843
1121
  // : new ExpressRLAdapter();
844
- // this.rateLimiterFallback = new ExpressRLAdapter();
845
1122
 
846
- // // Validation
847
- // this.validatorPrimary = this.config.validation.mode === "zod"
848
- // ? new ZodAdapter()
849
- // : new ExpressValidatorAdapter();
850
- // this.validatorFallback = this.config.validation.fallback === "express-validator"
851
- // ? new ExpressValidatorAdapter()
852
- // : null;
853
-
854
- // // Sanitization
855
- // this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
856
- // this.sanitizerFallback = new XSSAdapter(this.config.sanitizer);
1123
+ // this.rateLimiterFallback = new ExpressRLAdapter();
857
1124
 
858
1125
  // logger.info("✅ Adapters ready");
859
1126
  // }
860
1127
 
861
1128
  // private setupManagers(): void {
862
- // this.hashManager = new HashManager(
863
- // this.config.hashing,
864
- // this.hashingPrimary,
865
- // this.hashingFallback
866
- // );
1129
+ // this.hashManager = new HashManager(this.config.hashing, this.hashingPrimary, this.hashingFallback);
867
1130
 
868
1131
  // this.rateLimitManager = new RateLimitManager(
869
1132
  // this.config.rateLimiter,
@@ -871,17 +1134,15 @@
871
1134
  // this.rateLimiterFallback
872
1135
  // );
873
1136
 
1137
+ // // ✔ AUTO-DETECT VALIDATION (ZOD + EXPRESS-VALIDATOR)
874
1138
  // this.validatorManager = new ValidatorManager(
875
- // // this.config.validation,
876
- // // this.validatorPrimary,
877
- // // this.validatorFallback
878
1139
  // new ZodAdapter(),
879
1140
  // new ExpressValidatorAdapter()
880
1141
  // );
881
1142
 
882
1143
  // this.sanitizerManager = new SanitizerManager(
883
- // this.sanitizerPrimary,
884
- // this.sanitizerFallback
1144
+ // new SanitizeHtmlAdapter(this.config.sanitizer),
1145
+ // new XSSAdapter(this.config.sanitizer)
885
1146
  // );
886
1147
  // }
887
1148
 
@@ -889,306 +1150,56 @@
889
1150
  // this.jsonManager = new JsonManager();
890
1151
  // this.corsManager = new CorsManager();
891
1152
 
892
- // // Auth manager (only if enabled)
893
1153
  // if (this.config.auth.enabled) {
894
1154
  // const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
895
- // if (!jwtSecret) {
896
- // throw new Error("JWT_SECRET environment variable or jwtSecret in config is required when auth.enabled=true");
897
- // }
1155
+ // if (!jwtSecret) throw new Error("JWT_SECRET is required when auth.enabled=true");
898
1156
 
899
1157
  // this.authManager = new AuthManager({
900
1158
  // jwtSecret,
901
1159
  // jwtExpiresIn: this.config.auth.jwtExpiresIn,
902
- // googleClientId: process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
903
- // // Removed algorithm - handled in AuthManager
1160
+ // googleClientId: this.config.auth.googleClientId
904
1161
  // });
905
1162
  // }
906
1163
  // }
907
1164
 
908
1165
  // private createMiddlewareChain(options: SecureOptions): any[] {
909
1166
  // const chain: any[] = [];
910
-
911
- // // JSON parsing
1167
+
912
1168
  // chain.push(this.jsonManager.middleware(this.config.json));
913
1169
  // chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
914
-
915
- // // Security headers
1170
+
916
1171
  // if (this.config.enableHelmet) chain.push(helmet());
917
1172
  // if (this.config.enableHPP) chain.push(hpp());
918
-
919
- // // Compression (check if compression config exists)
920
- // if (this.config.enableCompression && this.config.compression) {
921
- // chain.push(compression(this.config.compression));
922
- // } else if (this.config.enableCompression) {
923
- // chain.push(compression()); // Use defaults
924
- // }
925
-
926
- // // CORS
1173
+
1174
+ // if (this.config.enableCompression) chain.push(compression(this.config.compression));
1175
+
927
1176
  // if (this.config.enableCORS || options.cors) {
928
- // const corsOptions = options.cors === true ? this.config.cors :
929
- // (typeof options.cors === 'object' ? options.cors : this.config.cors);
930
- // chain.push(this.corsManager.middleware(corsOptions));
1177
+ // const opts = typeof options.cors === "object" ? options.cors : this.config.cors;
1178
+ // chain.push(this.corsManager.middleware(opts));
931
1179
  // }
932
-
933
- // // Sanitization
1180
+
934
1181
  // if (this.config.enableSanitizer || options.sanitize) {
935
- // const sanitizeOptions = options.sanitize === true ? undefined :
936
- // (typeof options.sanitize === 'object' ? options.sanitize : undefined);
937
- // chain.push(this.sanitizerManager.middleware(sanitizeOptions));
1182
+ // const opts = typeof options.sanitize === "object" ? options.sanitize : undefined;
1183
+ // chain.push(this.sanitizerManager.middleware(opts));
938
1184
  // }
939
-
940
- // // Rate limiting
1185
+
941
1186
  // if (this.config.enableRateLimiter || options.rateLimit) {
942
- // const rateLimitOpts = typeof options.rateLimit === 'object' ?
943
- // { options: options.rateLimit } : {};
944
- // chain.push(this.rateLimitManager.middleware(rateLimitOpts));
1187
+ // const opts = typeof options.rateLimit === "object" ? { options: options.rateLimit } : {};
1188
+ // chain.push(this.rateLimitManager.middleware(opts));
945
1189
  // }
946
-
947
- // // Authentication
1190
+
948
1191
  // if (options.auth && this.authManager) {
949
- // const authOpts = options.auth === true ? undefined :
950
- // (typeof options.auth === 'object' ? options.auth : undefined);
951
- // chain.push(this.authManager.protect(authOpts));
1192
+ // const opts = typeof options.auth === "object" ? options.auth : undefined;
1193
+ // chain.push(this.authManager.protect(opts));
952
1194
  // }
953
-
954
- // // Error handler (always last)
1195
+
955
1196
  // chain.push(errorHandler);
956
-
1197
+
957
1198
  // return chain;
958
1199
  // }
959
1200
  // }
960
1201
 
961
1202
 
962
- // ===================
963
-
964
- // src/core/HiSecure.ts - FINAL VERSION
965
- import { HiSecureConfig } from "./types/HiSecureConfig.js";
966
- import { defaultConfig } from "./config.js";
967
- import { LIB_NAME, LIB_VERSION } from "./constants.js";
968
- import { deepMerge } from "../utils/deepMerge.js";
969
- import { deepFreeze } from "../utils/deepFreeze.js";
970
- import { logger } from "../logging/index.js";
971
-
972
- // Adapters
973
- import { ArgonAdapter } from "../adapters/ArgonAdapter.js";
974
- import { BcryptAdapter } from "../adapters/BcryptAdapter.js";
975
- import { RLFlexibleAdapter } from "../adapters/RLFlexibleAdapter.js";
976
- import { ExpressRLAdapter } from "../adapters/ExpressRLAdapter.js";
977
- import { ZodAdapter } from "../adapters/ZodAdapter.js";
978
- import { ExpressValidatorAdapter } from "../adapters/ExpressValidatorAdapter.js";
979
- import { SanitizeHtmlAdapter } from "../adapters/SanitizeHtmlAdapter.js";
980
- import { XSSAdapter } from "../adapters/XSSAdapter.js";
981
-
982
- // Managers
983
- import { HashManager } from "../managers/HashManager.js";
984
- import { RateLimitManager } from "../managers/RateLimitManager.js";
985
- import { ValidatorManager } from "../managers/ValidatorManager.js";
986
- import { SanitizerManager } from "../managers/SanitizerManager.js";
987
- import { JsonManager } from "../managers/JsonManager.js";
988
- import { CorsManager } from "../managers/CorsManager.js";
989
- import { AuthManager } from "../managers/AuthManager.js";
990
-
991
- // Middlewares
992
- import helmet from "helmet";
993
- import hpp from "hpp";
994
- import compression from "compression";
995
- import { errorHandler } from "../middlewares/errorHandler.js";
996
-
997
- // Types
998
- import { SecureOptions, ValidationSchema } from "./types/SecureOptions.js";
999
-
1000
- export class HiSecure {
1001
- private static instance: HiSecure | null = null;
1002
- private config: HiSecureConfig;
1003
- private initialized = false;
1004
-
1005
- // Managers
1006
- public hashManager!: HashManager;
1007
- public rateLimitManager!: RateLimitManager;
1008
- public validatorManager!: ValidatorManager;
1009
- public sanitizerManager!: SanitizerManager;
1010
- public jsonManager!: JsonManager;
1011
- public corsManager!: CorsManager;
1012
- public authManager?: AuthManager;
1013
1203
 
1014
- // Internal adapters
1015
- private hashingPrimary: any;
1016
- private hashingFallback: any;
1017
- private rateLimiterPrimary: any;
1018
- private rateLimiterFallback: any;
1019
1204
 
1020
- private constructor(userConfig: Partial<HiSecureConfig> = {}) {
1021
- this.config = deepMerge(defaultConfig, userConfig);
1022
- }
1023
1205
 
1024
- // =====================================================
1025
- // SINGLETON
1026
- // =====================================================
1027
- static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
1028
- if (!HiSecure.instance) {
1029
- HiSecure.instance = new HiSecure(config);
1030
- HiSecure.instance.init();
1031
- }
1032
- return HiSecure.instance;
1033
- }
1034
-
1035
- static resetInstance(): void {
1036
- HiSecure.instance = null;
1037
- }
1038
-
1039
- init(): void {
1040
- if (this.initialized) return;
1041
-
1042
- logger.info(`🔐 ${LIB_NAME} v${LIB_VERSION} initializing...`);
1043
-
1044
- this.setupAdapters();
1045
- this.setupManagers();
1046
- this.setupDynamicManagers();
1047
-
1048
- // ❌ DO NOT FREEZE MANAGERS
1049
- // ✔ Only freeze config
1050
- deepFreeze(this.config);
1051
-
1052
- this.initialized = true;
1053
- logger.info("✅ HiSecure initialized successfully");
1054
- }
1055
-
1056
- // =====================================================
1057
- // FLUENT API (Route-level)
1058
- // =====================================================
1059
-
1060
- static auth(options?: { required?: boolean; roles?: string[] }) {
1061
- return this.getInstance().authManager!.protect(options);
1062
- }
1063
-
1064
- static validate(schema: ValidationSchema) {
1065
- return this.getInstance().validatorManager.validate(schema);
1066
- }
1067
-
1068
- static sanitize(options?: any) {
1069
- return this.getInstance().sanitizerManager.middleware(options);
1070
- }
1071
-
1072
- static cors(options?: any) {
1073
- return this.getInstance().corsManager.middleware(options);
1074
- }
1075
-
1076
- static rateLimit(preset: "strict" | "relaxed" | "api" | object) {
1077
- const instance = this.getInstance();
1078
-
1079
- if (typeof preset === "string") {
1080
- const presets: any = {
1081
- strict: { mode: "strict" },
1082
- relaxed: { mode: "relaxed" },
1083
- api: { mode: "api", options: { max: 100, windowMs: 60000 } }
1084
- };
1085
- return instance.rateLimitManager.middleware(presets[preset] || {});
1086
- }
1087
- return instance.rateLimitManager.middleware({ options: preset });
1088
- }
1089
-
1090
- static json(options?: any) {
1091
- const instance = this.getInstance();
1092
- return [
1093
- instance.jsonManager.middleware(options),
1094
- instance.jsonManager.urlencoded()
1095
- ];
1096
- }
1097
-
1098
- // =====================================================
1099
- // INTERNAL SETUP
1100
- // =====================================================
1101
-
1102
- private setupAdapters(): void {
1103
- logger.info("🧩 Setting up adapters...");
1104
-
1105
- this.hashingPrimary = this.config.hashing.primary === "argon2"
1106
- ? new ArgonAdapter()
1107
- : new BcryptAdapter(this.config.hashing.saltRounds);
1108
-
1109
- this.hashingFallback = this.config.hashing.fallback === "bcrypt"
1110
- ? new BcryptAdapter(this.config.hashing.saltRounds)
1111
- : null;
1112
-
1113
- this.rateLimiterPrimary = this.config.rateLimiter.useAdaptiveMode
1114
- ? new RLFlexibleAdapter()
1115
- : new ExpressRLAdapter();
1116
-
1117
- this.rateLimiterFallback = new ExpressRLAdapter();
1118
-
1119
- logger.info("✅ Adapters ready");
1120
- }
1121
-
1122
- private setupManagers(): void {
1123
- this.hashManager = new HashManager(this.config.hashing, this.hashingPrimary, this.hashingFallback);
1124
-
1125
- this.rateLimitManager = new RateLimitManager(
1126
- this.config.rateLimiter,
1127
- this.rateLimiterPrimary,
1128
- this.rateLimiterFallback
1129
- );
1130
-
1131
- // ✔ AUTO-DETECT VALIDATION (ZOD + EXPRESS-VALIDATOR)
1132
- this.validatorManager = new ValidatorManager(
1133
- new ZodAdapter(),
1134
- new ExpressValidatorAdapter()
1135
- );
1136
-
1137
- this.sanitizerManager = new SanitizerManager(
1138
- new SanitizeHtmlAdapter(this.config.sanitizer),
1139
- new XSSAdapter(this.config.sanitizer)
1140
- );
1141
- }
1142
-
1143
- private setupDynamicManagers(): void {
1144
- this.jsonManager = new JsonManager();
1145
- this.corsManager = new CorsManager();
1146
-
1147
- if (this.config.auth.enabled) {
1148
- const jwtSecret = process.env.JWT_SECRET || this.config.auth.jwtSecret;
1149
- if (!jwtSecret) throw new Error("JWT_SECRET is required when auth.enabled=true");
1150
-
1151
- this.authManager = new AuthManager({
1152
- jwtSecret,
1153
- jwtExpiresIn: this.config.auth.jwtExpiresIn,
1154
- googleClientId: this.config.auth.googleClientId
1155
- });
1156
- }
1157
- }
1158
-
1159
- private createMiddlewareChain(options: SecureOptions): any[] {
1160
- const chain: any[] = [];
1161
-
1162
- chain.push(this.jsonManager.middleware(this.config.json));
1163
- chain.push(this.jsonManager.urlencoded(this.config.urlencoded));
1164
-
1165
- if (this.config.enableHelmet) chain.push(helmet());
1166
- if (this.config.enableHPP) chain.push(hpp());
1167
-
1168
- if (this.config.enableCompression) chain.push(compression(this.config.compression));
1169
-
1170
- if (this.config.enableCORS || options.cors) {
1171
- const opts = typeof options.cors === "object" ? options.cors : this.config.cors;
1172
- chain.push(this.corsManager.middleware(opts));
1173
- }
1174
-
1175
- if (this.config.enableSanitizer || options.sanitize) {
1176
- const opts = typeof options.sanitize === "object" ? options.sanitize : undefined;
1177
- chain.push(this.sanitizerManager.middleware(opts));
1178
- }
1179
-
1180
- if (this.config.enableRateLimiter || options.rateLimit) {
1181
- const opts = typeof options.rateLimit === "object" ? { options: options.rateLimit } : {};
1182
- chain.push(this.rateLimitManager.middleware(opts));
1183
- }
1184
-
1185
- if (options.auth && this.authManager) {
1186
- const opts = typeof options.auth === "object" ? options.auth : undefined;
1187
- chain.push(this.authManager.protect(opts));
1188
- }
1189
-
1190
- chain.push(errorHandler);
1191
-
1192
- return chain;
1193
- }
1194
- }
@@ -62,105 +62,105 @@
62
62
  // This is now optional since HiSecure class has fluent API
63
63
 
64
64
 
65
- // import { HiSecure } from "./HiSecure.js";
66
- // import { SecureOptions } from "./types/SecureOptions.js";
65
+ import { HiSecure } from "./HiSecure.js";
66
+ import { SecureOptions } from "./types/SecureOptions.js";
67
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
- // }
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
75
 
76
- // /**
77
- // * Legacy support - route-level security
78
- // */
79
- // export function secureRoute(options?: SecureOptions) {
80
- // const chain: any[] = [];
76
+ /**
77
+ * Legacy support - route-level security
78
+ */
79
+ export function secureRoute(options?: SecureOptions) {
80
+ const chain: any[] = [];
81
81
 
82
- // if (options?.cors) {
83
- // chain.push(HiSecure.cors(
84
- // typeof options.cors === 'object' ? options.cors : undefined
85
- // ));
86
- // }
82
+ if (options?.cors) {
83
+ chain.push(HiSecure.cors(
84
+ typeof options.cors === 'object' ? options.cors : undefined
85
+ ));
86
+ }
87
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
- // }
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
94
 
95
- // if (options?.sanitize) {
96
- // chain.push(HiSecure.sanitize(
97
- // typeof options.sanitize === 'object' ? options.sanitize : undefined
98
- // ));
99
- // }
95
+ if (options?.sanitize) {
96
+ chain.push(HiSecure.sanitize(
97
+ typeof options.sanitize === 'object' ? options.sanitize : undefined
98
+ ));
99
+ }
100
100
 
101
- // if (options?.validate) {
102
- // chain.push(HiSecure.validate(options.validate));
103
- // }
101
+ if (options?.validate) {
102
+ chain.push(HiSecure.validate(options.validate));
103
+ }
104
104
 
105
- // if (options?.auth) {
106
- // chain.push(HiSecure.auth(
107
- // typeof options.auth === 'object' ? options.auth : undefined
108
- // ));
109
- // }
105
+ if (options?.auth) {
106
+ chain.push(HiSecure.auth(
107
+ typeof options.auth === 'object' ? options.auth : undefined
108
+ ));
109
+ }
110
110
 
111
- // return chain;
112
- // }
111
+ return chain;
112
+ }
113
113
 
114
114
 
115
115
 
116
116
 
117
- import { HiSecure } from "./HiSecure.js";
118
- import { SecureOptions } from "./types/SecureOptions.js";
117
+ // import { HiSecure } from "./HiSecure.js";
118
+ // import { SecureOptions } from "./types/SecureOptions.js";
119
119
 
120
- export function secureRoute(options?: SecureOptions) {
121
- if (!options) return [];
120
+ // export function secureRoute(options?: SecureOptions) {
121
+ // if (!options) return [];
122
122
 
123
- const chain: any[] = [];
123
+ // const chain: any[] = [];
124
124
 
125
- // 🔥 1. CORS
126
- if (options.cors !== undefined) {
127
- chain.push(
128
- HiSecure.cors(typeof options.cors === "object" ? options.cors : undefined)
129
- );
130
- }
125
+ // // 🔥 1. CORS
126
+ // if (options.cors !== undefined) {
127
+ // chain.push(
128
+ // HiSecure.cors(typeof options.cors === "object" ? options.cors : undefined)
129
+ // );
130
+ // }
131
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
- }
142
- }
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
+ // }
142
+ // }
143
143
 
144
- // 🔥 3. Sanitization
145
- if (options.sanitize !== undefined) {
146
- chain.push(
147
- HiSecure.sanitize(typeof options.sanitize === "object" ? options.sanitize : undefined)
148
- );
149
- }
144
+ // // 🔥 3. Sanitization
145
+ // if (options.sanitize !== undefined) {
146
+ // chain.push(
147
+ // HiSecure.sanitize(typeof options.sanitize === "object" ? options.sanitize : undefined)
148
+ // );
149
+ // }
150
150
 
151
- // 🔥 4. Validation — smart auto-detection
152
- if (options.validate) {
153
- chain.push(HiSecure.validate(options.validate));
154
- }
151
+ // // 🔥 4. Validation — smart auto-detection
152
+ // if (options.validate) {
153
+ // chain.push(HiSecure.validate(options.validate));
154
+ // }
155
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
- );
163
- }
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
+ // );
163
+ // }
164
164
 
165
- return chain;
166
- }
165
+ // return chain;
166
+ // }
package/src/index.ts CHANGED
@@ -1,33 +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
4
 
5
- // // Export the singleton instance for quick usage
6
- // const hiSecure = HiSecure.getInstance();
5
+ // Export the singleton instance for quick usage
6
+ const hiSecure = HiSecure.getInstance();
7
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
- // };
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
15
 
16
- // // Default export is the singleton instance
17
- // export default hiSecure;
16
+ // Default export is the singleton instance
17
+ export default hiSecure;
18
18
 
19
19
 
20
20
 
21
21
 
22
- // src/index.ts
23
- import { HiSecure } from "./core/HiSecure.js";
24
- import { secureRoute } from "./core/useSecure.js"; // Only if kept
22
+ // // src/index.ts
23
+ // import { HiSecure } from "./core/HiSecure.js";
24
+ // import { secureRoute } from "./core/useSecure.js"; // Only if kept
25
25
 
26
- // DON'T auto-init here
27
- export {
28
- HiSecure, // Class
29
- secureRoute // Optional sugar API
30
- };
26
+ // // DON'T auto-init here
27
+ // export {
28
+ // HiSecure, // Class
29
+ // secureRoute // Optional sugar API
30
+ // };
31
31
 
32
- // Default export: class itself (NOT instance)
33
- export default HiSecure;
32
+ // // Default export: class itself (NOT instance)
33
+ // export default HiSecure;