@nest-boot/hash 7.0.2 → 7.2.0

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.
@@ -10,13 +10,17 @@ import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE } from "./has
10
10
  * @Module({
11
11
  * imports: [
12
12
  * HashModule.register({
13
- * secret: 'your-secret-key',
14
- * isGlobal: true,
13
+ * secret: process.env.HASH_SECRET
15
14
  * }),
16
15
  * ],
17
16
  * })
18
17
  * export class AppModule {}
19
18
  * ```
19
+ *
20
+ * Generate a secure secret:
21
+ * ```bash
22
+ * node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
23
+ * ```
20
24
  */
21
25
  export declare class HashModule extends ConfigurableModuleClass {
22
26
  /**
@@ -10,6 +10,7 @@ exports.HashModule = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
11
  const hash_module_definition_1 = require("./hash.module-definition");
12
12
  const hash_service_1 = require("./hash.service");
13
+ const estimate_entropy_1 = require("./utils/estimate-entropy");
13
14
  /**
14
15
  * Module that provides password hashing services using Argon2.
15
16
  *
@@ -20,13 +21,17 @@ const hash_service_1 = require("./hash.service");
20
21
  * @Module({
21
22
  * imports: [
22
23
  * HashModule.register({
23
- * secret: 'your-secret-key',
24
- * isGlobal: true,
24
+ * secret: process.env.HASH_SECRET
25
25
  * }),
26
26
  * ],
27
27
  * })
28
28
  * export class AppModule {}
29
29
  * ```
30
+ *
31
+ * Generate a secure secret:
32
+ * ```bash
33
+ * node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
34
+ * ```
30
35
  */
31
36
  let HashModule = class HashModule extends hash_module_definition_1.ConfigurableModuleClass {
32
37
  /**
@@ -49,6 +54,37 @@ let HashModule = class HashModule extends hash_module_definition_1.ConfigurableM
49
54
  exports.HashModule = HashModule;
50
55
  exports.HashModule = HashModule = __decorate([
51
56
  (0, common_1.Global)(),
52
- (0, common_1.Module)({ providers: [hash_service_1.HashService], exports: [hash_service_1.HashService] })
57
+ (0, common_1.Module)({
58
+ providers: [
59
+ {
60
+ provide: hash_service_1.HashService,
61
+ inject: [{ token: hash_module_definition_1.MODULE_OPTIONS_TOKEN, optional: true }],
62
+ useFactory: (options) => {
63
+ const secret = options.secret ?? process.env.HASH_SECRET ?? process.env.APP_SECRET;
64
+ if (!secret) {
65
+ throw new Error("Hash secret is required.\n" +
66
+ "Set HASH_SECRET or APP_SECRET environment variable, or pass a secret option.\n" +
67
+ "Generate a secure secret with:\n" +
68
+ " node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
69
+ }
70
+ if (secret.length < 32) {
71
+ throw new Error("Hash secret must be at least 32 characters long.\n" +
72
+ "Set HASH_SECRET or APP_SECRET environment variable, or pass a secret option.\n" +
73
+ "Generate a secure secret with:\n" +
74
+ " node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
75
+ }
76
+ if ((0, estimate_entropy_1.estimateEntropy)(secret) < 120) {
77
+ throw new Error("Hash secret appears low-entropy.\n" +
78
+ "Use a randomly generated secret for production.\n" +
79
+ "Generate a secure secret with:\n" +
80
+ " node -e \"console.log(require('crypto').randomBytes(32).toString('base64url'))\"");
81
+ }
82
+ hash_service_1.HashService.init(secret);
83
+ return hash_service_1.HashService.instance;
84
+ },
85
+ },
86
+ ],
87
+ exports: [hash_service_1.HashService],
88
+ })
53
89
  ], HashModule);
54
90
  //# sourceMappingURL=hash.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.module.js","sourceRoot":"","sources":["../src/hash.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoE;AAEpE,qEAIkC;AAClC,iDAA6C;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AAGI,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,gDAAuB;IACrD;;;;OAIG;IACH,MAAM,CAAU,QAAQ,CAAC,OAA4B;QACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAU,aAAa,CAC3B,OAAkC;QAElC,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AApBY,gCAAU;qBAAV,UAAU;IAFtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,SAAS,EAAE,CAAC,0BAAW,CAAC,EAAE,OAAO,EAAE,CAAC,0BAAW,CAAC,EAAE,CAAC;GAChD,UAAU,CAoBtB"}
1
+ {"version":3,"file":"hash.module.js","sourceRoot":"","sources":["../src/hash.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoE;AAEpE,qEAKkC;AAClC,iDAA6C;AAE7C,+DAA2D;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AA8CI,IAAM,UAAU,GAAhB,MAAM,UAAW,SAAQ,gDAAuB;IACrD;;;;OAIG;IACH,MAAM,CAAU,QAAQ,CAAC,OAA4B;QACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAU,aAAa,CAC3B,OAAkC;QAElC,OAAO,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACF,CAAA;AApBY,gCAAU;qBAAV,UAAU;IA7CtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,0BAAW;gBACpB,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,6CAAoB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACzD,UAAU,EAAE,CAAC,OAA0B,EAAE,EAAE;oBACzC,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;oBAEtE,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,MAAM,IAAI,KAAK,CACb,4BAA4B;4BAC1B,gFAAgF;4BAChF,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;wBACvB,MAAM,IAAI,KAAK,CACb,oDAAoD;4BAClD,gFAAgF;4BAChF,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,IAAI,IAAA,kCAAe,EAAC,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;wBAClC,MAAM,IAAI,KAAK,CACb,oCAAoC;4BAClC,mDAAmD;4BACnD,kCAAkC;4BAClC,oFAAoF,CACvF,CAAC;oBACJ,CAAC;oBAED,0BAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAEzB,OAAO,0BAAW,CAAC,QAAQ,CAAC;gBAC9B,CAAC;aACF;SACF;QACD,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAoBtB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const testing_1 = require("@nestjs/testing");
4
+ const _1 = require(".");
5
+ const TEST_SECRET = "myTestSecretThatIsAtLeast32Chars!";
6
+ describe("HashModule", () => {
7
+ const originalEnv = process.env;
8
+ beforeEach(() => {
9
+ // Reset static instance before each test
10
+ _1.HashService._instance = undefined;
11
+ // Reset environment variables
12
+ process.env = { ...originalEnv };
13
+ delete process.env.HASH_SECRET;
14
+ delete process.env.APP_SECRET;
15
+ });
16
+ afterAll(() => {
17
+ process.env = originalEnv;
18
+ });
19
+ describe("register", () => {
20
+ it("should throw error when secret is missing", async () => {
21
+ await expect(testing_1.Test.createTestingModule({
22
+ imports: [_1.HashModule.register({})],
23
+ }).compile()).rejects.toThrow("Hash secret is required.");
24
+ });
25
+ it("should use HASH_SECRET env when no secret provided", async () => {
26
+ process.env.HASH_SECRET = TEST_SECRET;
27
+ const moduleRef = await testing_1.Test.createTestingModule({
28
+ imports: [_1.HashModule.register({})],
29
+ }).compile();
30
+ const hashService = moduleRef.get(_1.HashService);
31
+ expect(hashService).toBeDefined();
32
+ const hashed = await hashService.hash("password");
33
+ expect(hashed).toContain("$argon2");
34
+ });
35
+ it("should use APP_SECRET env when no secret or HASH_SECRET provided", async () => {
36
+ process.env.APP_SECRET = TEST_SECRET;
37
+ const moduleRef = await testing_1.Test.createTestingModule({
38
+ imports: [_1.HashModule.register({})],
39
+ }).compile();
40
+ const hashService = moduleRef.get(_1.HashService);
41
+ expect(hashService).toBeDefined();
42
+ const hashed = await hashService.hash("password");
43
+ expect(hashed).toContain("$argon2");
44
+ });
45
+ it("should throw error when secret is too short", async () => {
46
+ await expect(testing_1.Test.createTestingModule({
47
+ imports: [_1.HashModule.register({ secret: "short" })],
48
+ }).compile()).rejects.toThrow("Hash secret must be at least 32 characters long.");
49
+ });
50
+ it("should throw error when secret has low entropy", async () => {
51
+ // A secret that is 32 chars but low entropy (all same character)
52
+ const lowEntropySecret = "a".repeat(32);
53
+ await expect(testing_1.Test.createTestingModule({
54
+ imports: [_1.HashModule.register({ secret: lowEntropySecret })],
55
+ }).compile()).rejects.toThrow("Hash secret appears low-entropy.");
56
+ });
57
+ });
58
+ describe("registerAsync", () => {
59
+ it("should register module with async factory", async () => {
60
+ const moduleRef = await testing_1.Test.createTestingModule({
61
+ imports: [
62
+ _1.HashModule.registerAsync({
63
+ useFactory: () => ({
64
+ secret: TEST_SECRET,
65
+ }),
66
+ }),
67
+ ],
68
+ }).compile();
69
+ const hashService = moduleRef.get(_1.HashService);
70
+ expect(hashService).toBeDefined();
71
+ const hashed = await hashService.hash("password");
72
+ expect(hashed).toContain("$argon2");
73
+ });
74
+ });
75
+ });
76
+ //# sourceMappingURL=hash.module.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.module.spec.js","sourceRoot":"","sources":["../src/hash.module.spec.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { HashModuleOptions } from "./hash-module-options.interface";
2
1
  /**
3
2
  * Service that provides password hashing and verification using Argon2 algorithm.
4
3
  *
@@ -6,34 +5,97 @@ import { HashModuleOptions } from "./hash-module-options.interface";
6
5
  * ```typescript
7
6
  * import { HashService } from '@nest-boot/hash';
8
7
  *
9
- * @Injectable()
10
- * export class AuthService {
11
- * constructor(private readonly hashService: HashService) {}
8
+ * // Initialize at application startup
9
+ * HashService.init(process.env.HASH_SECRET);
12
10
  *
13
- * async hashPassword(password: string): Promise<string> {
14
- * return this.hashService.create(password);
15
- * }
16
- *
17
- * async verifyPassword(hash: string, password: string): Promise<boolean> {
18
- * return this.hashService.verify(hash, password);
19
- * }
20
- * }
11
+ * // Use static methods
12
+ * const hashed = await HashService.hash(password);
13
+ * const isValid = await HashService.verify(hashed, password);
21
14
  * ```
22
15
  */
23
16
  export declare class HashService {
17
+ private static _instance?;
18
+ /**
19
+ * Gets the static HashService instance.
20
+ * @throws Error if HashService has not been initialized via `init()`
21
+ * @returns The HashService instance
22
+ */
23
+ static get instance(): HashService;
24
+ /**
25
+ * Initializes the static HashService instance with the given secret.
26
+ * Call this method at application startup to configure the default secret.
27
+ *
28
+ * @param secret - The secret key to use for hashing
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // In your application bootstrap
33
+ * HashService.init(process.env.HASH_SECRET);
34
+ * ```
35
+ */
36
+ static init(secret?: string): void;
37
+ /**
38
+ * Creates a hash from the given value using the static instance.
39
+ * @param value - The value to hash (password or other sensitive data)
40
+ * @param secret - Optional secret key to use instead of the default
41
+ * @returns The hashed string
42
+ * @throws Error if HashService has not been initialized via `init()`
43
+ */
44
+ static hash(value: string | Buffer, secret?: string): Promise<string>;
45
+ /**
46
+ * Creates a hash synchronously from the given value using the static instance.
47
+ * @param value - The value to hash (password or other sensitive data)
48
+ * @param secret - Optional secret key to use instead of the default
49
+ * @returns The hashed string
50
+ * @throws Error if HashService has not been initialized via `init()`
51
+ */
52
+ static hashSync(value: string | Buffer, secret?: string): string;
53
+ /**
54
+ * Verifies a value against a hash using the static instance.
55
+ * @param hashed - The hash to verify against
56
+ * @param value - The value to verify
57
+ * @param secret - Optional secret key to use instead of the default
58
+ * @returns True if the value matches the hash, false otherwise
59
+ * @throws Error if HashService has not been initialized via `init()`
60
+ */
61
+ static verify(hashed: string | Buffer, value: string | Buffer, secret?: string): Promise<boolean>;
62
+ /**
63
+ * Verifies a value against a hash synchronously using the static instance.
64
+ * @param hashed - The hash to verify against
65
+ * @param value - The value to verify
66
+ * @param secret - Optional secret key to use instead of the default
67
+ * @returns True if the value matches the hash, false otherwise
68
+ * @throws Error if HashService has not been initialized via `init()`
69
+ */
70
+ static verifySync(hashed: string | Buffer, value: string | Buffer, secret?: string): boolean;
24
71
  private readonly secret?;
25
72
  /**
26
73
  * Creates an instance of HashService.
27
- * @param options - Configuration options for the hash service
74
+ * @param secret - Optional secret key to use for hashing
28
75
  */
29
- constructor(options?: HashModuleOptions);
76
+ constructor(secret?: string);
30
77
  /**
31
78
  * Creates a hash from the given value using Argon2.
32
79
  * @param value - The value to hash (password or other sensitive data)
33
80
  * @param secret - Optional secret key to use instead of the default
34
81
  * @returns The hashed string
82
+ * @deprecated Use `hash` instead
35
83
  */
36
84
  create(value: string | Buffer, secret?: string): Promise<string>;
85
+ /**
86
+ * Creates a hash from the given value using Argon2.
87
+ * @param value - The value to hash (password or other sensitive data)
88
+ * @param secret - Optional secret key to use instead of the default
89
+ * @returns The hashed string
90
+ */
91
+ hash(value: string | Buffer, secret?: string): Promise<string>;
92
+ /**
93
+ * Creates a hash synchronously from the given value using Argon2.
94
+ * @param value - The value to hash (password or other sensitive data)
95
+ * @param secret - Optional secret key to use instead of the default
96
+ * @returns The hashed string
97
+ */
98
+ hashSync(value: string | Buffer, secret?: string): string;
37
99
  /**
38
100
  * Verifies a value against a hash.
39
101
  * @param hashed - The hash to verify against
@@ -42,4 +104,12 @@ export declare class HashService {
42
104
  * @returns True if the value matches the hash, false otherwise
43
105
  */
44
106
  verify(hashed: string | Buffer, value: string | Buffer, secret?: string): Promise<boolean>;
107
+ /**
108
+ * Verifies a value against a hash synchronously.
109
+ * @param hashed - The hash to verify against
110
+ * @param value - The value to verify
111
+ * @param secret - Optional secret key to use instead of the default
112
+ * @returns True if the value matches the hash, false otherwise
113
+ */
114
+ verifySync(hashed: string | Buffer, value: string | Buffer, secret?: string): boolean;
45
115
  }
@@ -1,21 +1,7 @@
1
1
  "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
2
  Object.defineProperty(exports, "__esModule", { value: true });
15
3
  exports.HashService = void 0;
16
- const common_1 = require("@nestjs/common");
17
4
  const argon2_1 = require("@node-rs/argon2");
18
- const hash_module_definition_1 = require("./hash.module-definition");
19
5
  /**
20
6
  * Service that provides password hashing and verification using Argon2 algorithm.
21
7
  *
@@ -23,42 +9,122 @@ const hash_module_definition_1 = require("./hash.module-definition");
23
9
  * ```typescript
24
10
  * import { HashService } from '@nest-boot/hash';
25
11
  *
26
- * @Injectable()
27
- * export class AuthService {
28
- * constructor(private readonly hashService: HashService) {}
12
+ * // Initialize at application startup
13
+ * HashService.init(process.env.HASH_SECRET);
29
14
  *
30
- * async hashPassword(password: string): Promise<string> {
31
- * return this.hashService.create(password);
32
- * }
33
- *
34
- * async verifyPassword(hash: string, password: string): Promise<boolean> {
35
- * return this.hashService.verify(hash, password);
36
- * }
37
- * }
15
+ * // Use static methods
16
+ * const hashed = await HashService.hash(password);
17
+ * const isValid = await HashService.verify(hashed, password);
38
18
  * ```
39
19
  */
40
- let HashService = class HashService {
20
+ class HashService {
41
21
  /**
42
- * Creates an instance of HashService.
43
- * @param options - Configuration options for the hash service
22
+ * Gets the static HashService instance.
23
+ * @throws Error if HashService has not been initialized via `init()`
24
+ * @returns The HashService instance
44
25
  */
45
- constructor(options = {}) {
46
- const secret = options.secret ?? process.env.HASH_SECRET ?? process.env.APP_SECRET;
47
- if (secret) {
48
- this.secret = Buffer.from(secret);
26
+ static get instance() {
27
+ if (!this._instance) {
28
+ throw new Error("HashService not initialized");
49
29
  }
30
+ return this._instance;
31
+ }
32
+ /**
33
+ * Initializes the static HashService instance with the given secret.
34
+ * Call this method at application startup to configure the default secret.
35
+ *
36
+ * @param secret - The secret key to use for hashing
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // In your application bootstrap
41
+ * HashService.init(process.env.HASH_SECRET);
42
+ * ```
43
+ */
44
+ static init(secret) {
45
+ this._instance = new HashService(secret);
46
+ }
47
+ /**
48
+ * Creates a hash from the given value using the static instance.
49
+ * @param value - The value to hash (password or other sensitive data)
50
+ * @param secret - Optional secret key to use instead of the default
51
+ * @returns The hashed string
52
+ * @throws Error if HashService has not been initialized via `init()`
53
+ */
54
+ static hash(value, secret) {
55
+ return this.instance.hash(value, secret);
56
+ }
57
+ /**
58
+ * Creates a hash synchronously from the given value using the static instance.
59
+ * @param value - The value to hash (password or other sensitive data)
60
+ * @param secret - Optional secret key to use instead of the default
61
+ * @returns The hashed string
62
+ * @throws Error if HashService has not been initialized via `init()`
63
+ */
64
+ static hashSync(value, secret) {
65
+ return this.instance.hashSync(value, secret);
66
+ }
67
+ /**
68
+ * Verifies a value against a hash using the static instance.
69
+ * @param hashed - The hash to verify against
70
+ * @param value - The value to verify
71
+ * @param secret - Optional secret key to use instead of the default
72
+ * @returns True if the value matches the hash, false otherwise
73
+ * @throws Error if HashService has not been initialized via `init()`
74
+ */
75
+ static verify(hashed, value, secret) {
76
+ return this.instance.verify(hashed, value, secret);
77
+ }
78
+ /**
79
+ * Verifies a value against a hash synchronously using the static instance.
80
+ * @param hashed - The hash to verify against
81
+ * @param value - The value to verify
82
+ * @param secret - Optional secret key to use instead of the default
83
+ * @returns True if the value matches the hash, false otherwise
84
+ * @throws Error if HashService has not been initialized via `init()`
85
+ */
86
+ static verifySync(hashed, value, secret) {
87
+ return this.instance.verifySync(hashed, value, secret);
88
+ }
89
+ /**
90
+ * Creates an instance of HashService.
91
+ * @param secret - Optional secret key to use for hashing
92
+ */
93
+ constructor(secret) {
94
+ this.secret = secret ? Buffer.from(secret) : undefined;
50
95
  }
51
96
  /**
52
97
  * Creates a hash from the given value using Argon2.
53
98
  * @param value - The value to hash (password or other sensitive data)
54
99
  * @param secret - Optional secret key to use instead of the default
55
100
  * @returns The hashed string
101
+ * @deprecated Use `hash` instead
56
102
  */
57
103
  async create(value, secret) {
104
+ return await this.hash(value, secret);
105
+ }
106
+ /**
107
+ * Creates a hash from the given value using Argon2.
108
+ * @param value - The value to hash (password or other sensitive data)
109
+ * @param secret - Optional secret key to use instead of the default
110
+ * @returns The hashed string
111
+ */
112
+ async hash(value, secret) {
58
113
  return await (0, argon2_1.hash)(value, {
59
114
  secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
60
115
  });
61
116
  }
117
+ /**
118
+ * Creates a hash synchronously from the given value using Argon2.
119
+ * @param value - The value to hash (password or other sensitive data)
120
+ * @param secret - Optional secret key to use instead of the default
121
+ * @returns The hashed string
122
+ */
123
+ hashSync(value, secret) {
124
+ return (0, argon2_1.hashSync)(value, {
125
+ secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
126
+ });
127
+ }
62
128
  /**
63
129
  * Verifies a value against a hash.
64
130
  * @param hashed - The hash to verify against
@@ -71,12 +137,18 @@ let HashService = class HashService {
71
137
  secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
72
138
  });
73
139
  }
74
- };
140
+ /**
141
+ * Verifies a value against a hash synchronously.
142
+ * @param hashed - The hash to verify against
143
+ * @param value - The value to verify
144
+ * @param secret - Optional secret key to use instead of the default
145
+ * @returns True if the value matches the hash, false otherwise
146
+ */
147
+ verifySync(hashed, value, secret) {
148
+ return (0, argon2_1.verifySync)(hashed, value, {
149
+ secret: typeof secret !== "undefined" ? Buffer.from(secret) : this.secret,
150
+ });
151
+ }
152
+ }
75
153
  exports.HashService = HashService;
76
- exports.HashService = HashService = __decorate([
77
- (0, common_1.Injectable)(),
78
- __param(0, (0, common_1.Optional)()),
79
- __param(0, (0, common_1.Inject)(hash_module_definition_1.MODULE_OPTIONS_TOKEN)),
80
- __metadata("design:paramtypes", [Object])
81
- ], HashService);
82
154
  //# sourceMappingURL=hash.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.service.js","sourceRoot":"","sources":["../src/hash.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA8D;AAC9D,4CAA+C;AAE/C,qEAAgE;AAGhE;;;;;;;;;;;;;;;;;;;;GAoBG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAW;IAGtB;;;OAGG;IACH,YAGE,UAA6B,EAAE;QAE/B,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QAEtE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,KAAsB,EAAE,MAAe;QAClD,OAAO,MAAM,IAAA,aAAI,EAAC,KAAK,EAAE;YACvB,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CACV,MAAuB,EACvB,KAAsB,EACtB,MAAe;QAEf,OAAO,MAAM,IAAA,eAAM,EAAC,MAAM,EAAE,KAAK,EAAE;YACjC,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;SAC1E,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAhDY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;IASR,WAAA,IAAA,iBAAQ,GAAE,CAAA;IACV,WAAA,IAAA,eAAM,EAAC,6CAAoB,CAAC,CAAA;;GATpB,WAAW,CAgDvB"}
1
+ {"version":3,"file":"hash.service.js","sourceRoot":"","sources":["../src/hash.service.ts"],"names":[],"mappings":"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"}