@naman_deep_singh/security 1.4.0 → 1.5.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.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ```bash
2
2
  @naman_deep_singh/security
3
3
 
4
- Version: 1.4.0
4
+ Version: 1.5.0
5
5
 
6
6
  A complete, lightweight security toolkit for Node.js & TypeScript providing:
7
7
 
@@ -38,10 +38,10 @@ class CryptoManager {
38
38
  try {
39
39
  return (0, index_1.encrypt)(plaintext, key);
40
40
  }
41
- catch (err) {
42
- throw new errors_utils_1.InternalServerError(undefined, {
43
- message: 'Encryption failed',
44
- }, err instanceof Error ? err : undefined);
41
+ catch (error) {
42
+ throw new errors_utils_1.CryptoIntegrityError({
43
+ reason: 'Encryption failed',
44
+ }, error instanceof Error ? error : undefined);
45
45
  }
46
46
  }
47
47
  /**
@@ -51,10 +51,10 @@ class CryptoManager {
51
51
  try {
52
52
  return (0, index_1.decrypt)(encryptedData, key);
53
53
  }
54
- catch (err) {
55
- throw new errors_utils_1.InternalServerError(undefined, {
56
- message: 'Decryption failed',
57
- }, err instanceof Error ? err : undefined);
54
+ catch (error) {
55
+ throw new errors_utils_1.CryptoIntegrityError({
56
+ reason: 'Decryption failed',
57
+ }, error instanceof Error ? error : undefined);
58
58
  }
59
59
  }
60
60
  /**
@@ -85,11 +85,11 @@ class CryptoManager {
85
85
  deriveKey(password, salt, iterations = 100000, keyLength = 32) {
86
86
  return new Promise((resolve, reject) => {
87
87
  const crypto = require('crypto');
88
- crypto.pbkdf2(password, salt, iterations, keyLength, 'sha256', (err, derivedKey) => {
89
- if (err) {
90
- reject(new errors_utils_1.InternalServerError(undefined, {
91
- message: 'Key derivation failed',
92
- }, err instanceof Error ? err : undefined));
88
+ crypto.pbkdf2(password, salt, iterations, keyLength, 'sha256', (error, derivedKey) => {
89
+ if (error) {
90
+ reject(new errors_utils_1.CryptoIntegrityError({
91
+ reason: 'Key derivation failed',
92
+ }, error instanceof Error ? error : undefined));
93
93
  }
94
94
  else {
95
95
  resolve(derivedKey.toString('hex'));
@@ -166,10 +166,10 @@ class CryptoManager {
166
166
  const signature = sign.sign(privateKey, 'base64');
167
167
  resolve(signature);
168
168
  }
169
- catch (err) {
170
- reject(new errors_utils_1.InternalServerError(undefined, {
171
- message: 'RSA signing failed',
172
- }, err instanceof Error ? err : undefined));
169
+ catch (error) {
170
+ reject(new errors_utils_1.CryptoIntegrityError({
171
+ reason: 'RSA signing failed',
172
+ }, error instanceof Error ? error : undefined));
173
173
  }
174
174
  });
175
175
  }
@@ -186,10 +186,10 @@ class CryptoManager {
186
186
  const isValid = verify.verify(publicKey, signature, 'base64');
187
187
  resolve(isValid);
188
188
  }
189
- catch (err) {
190
- reject(new errors_utils_1.InternalServerError(undefined, {
191
- message: 'RSA verification failed',
192
- }, err instanceof Error ? err : undefined));
189
+ catch (error) {
190
+ reject(new errors_utils_1.CryptoIntegrityError({
191
+ reason: 'RSA verification failed',
192
+ }, error instanceof Error ? error : undefined));
193
193
  }
194
194
  });
195
195
  }
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.decodeToken = decodeToken;
4
4
  exports.decodeTokenStrict = decodeTokenStrict;
5
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
5
6
  // src/jwt/decodeToken.ts
6
7
  const jsonwebtoken_1 = require("jsonwebtoken");
7
- const errors_utils_1 = require("@naman_deep_singh/errors-utils");
8
8
  /**
9
9
  * Flexible decode
10
10
  * Returns: null | string | JwtPayload
@@ -21,7 +21,7 @@ function decodeTokenStrict(token) {
21
21
  const decoded = (0, jsonwebtoken_1.decode)(token);
22
22
  if (!decoded || typeof decoded === 'string') {
23
23
  throw new errors_utils_1.BadRequestError({
24
- message: 'Invalid JWT payload structure',
24
+ reason: 'Invalid JWT payload structure',
25
25
  });
26
26
  }
27
27
  return decoded;
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateTokens = void 0;
4
4
  exports.rotateRefreshToken = rotateRefreshToken;
5
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
5
6
  const signToken_1 = require("./signToken");
6
7
  const verify_1 = require("./verify");
7
- const errors_utils_1 = require("@naman_deep_singh/errors-utils");
8
8
  // Helper function to create branded tokens
9
9
  /* const createBrandedToken = <T extends string>(token: string, _brand: T): T => {
10
10
  return token as T
@@ -26,7 +26,7 @@ function rotateRefreshToken(oldToken, secret) {
26
26
  const decoded = (0, verify_1.verifyToken)(oldToken, secret);
27
27
  if (typeof decoded === 'string') {
28
28
  throw new errors_utils_1.TokenMalformedError({
29
- message: 'Invalid token payload — expected JWT payload object',
29
+ reason: 'Invalid token payload — expected JWT payload object',
30
30
  });
31
31
  }
32
32
  const payload = { ...decoded };
@@ -31,33 +31,37 @@ class JWTManager {
31
31
  catch (error) {
32
32
  if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError)
33
33
  throw error;
34
- throw new errors_utils_1.BadRequestError({ message: 'Failed to generate tokens' }, error instanceof Error ? error : undefined);
34
+ throw new errors_utils_1.BadRequestError({ reason: 'Failed to generate tokens' }, error instanceof Error ? error : undefined);
35
35
  }
36
36
  }
37
37
  /** Generate access token */
38
38
  async generateAccessToken(payload) {
39
39
  try {
40
40
  this.validatePayload(payload);
41
- const token = (0, signToken_1.signToken)(payload, this.accessSecret, this.accessExpiry, { algorithm: 'HS256' });
41
+ const token = (0, signToken_1.signToken)(payload, this.accessSecret, this.accessExpiry, {
42
+ algorithm: 'HS256',
43
+ });
42
44
  return token;
43
45
  }
44
46
  catch (error) {
45
47
  if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError)
46
48
  throw error;
47
- throw new errors_utils_1.BadRequestError({ message: 'Failed to generate access token' }, error instanceof Error ? error : undefined);
49
+ throw new errors_utils_1.BadRequestError({ reason: 'Failed to generate access token' }, error instanceof Error ? error : undefined);
48
50
  }
49
51
  }
50
52
  /** Generate refresh token */
51
53
  async generateRefreshToken(payload) {
52
54
  try {
53
55
  this.validatePayload(payload);
54
- const token = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry, { algorithm: 'HS256' });
56
+ const token = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry, {
57
+ algorithm: 'HS256',
58
+ });
55
59
  return token;
56
60
  }
57
61
  catch (error) {
58
62
  if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError)
59
63
  throw error;
60
- throw new errors_utils_1.BadRequestError({ message: 'Failed to generate refresh token' }, error instanceof Error ? error : undefined);
64
+ throw new errors_utils_1.BadRequestError({ reason: 'Failed to generate refresh token' }, error instanceof Error ? error : undefined);
61
65
  }
62
66
  }
63
67
  /** Verify access token */
@@ -92,7 +96,9 @@ class JWTManager {
92
96
  /** Rotate refresh token */
93
97
  async rotateRefreshToken(oldToken) {
94
98
  if (!oldToken || typeof oldToken !== 'string') {
95
- throw new errors_utils_1.ValidationError({ message: 'Old refresh token must be a non-empty string' });
99
+ throw new errors_utils_1.ValidationError({
100
+ reason: 'Old refresh token must be a non-empty string',
101
+ });
96
102
  }
97
103
  const decoded = await this.verifyRefreshToken(oldToken);
98
104
  const payload = { ...decoded };
@@ -138,29 +144,42 @@ class JWTManager {
138
144
  /** Private helper methods */
139
145
  validatePayload(payload) {
140
146
  if (!payload || typeof payload !== 'object') {
141
- throw new errors_utils_1.ValidationError({ message: 'Payload must be a non-null object' });
147
+ throw new errors_utils_1.ValidationError({
148
+ reason: 'Payload must be a non-null object',
149
+ });
142
150
  }
143
151
  if (Object.keys(payload).length === 0) {
144
- throw new errors_utils_1.ValidationError({ message: 'Payload cannot be empty' });
152
+ throw new errors_utils_1.ValidationError({ reason: 'Payload cannot be empty' });
145
153
  }
146
154
  }
147
155
  async verifyTokenWithCache(token, secret, type) {
148
156
  if (!token || typeof token !== 'string') {
149
- throw new errors_utils_1.ValidationError({ message: `${type} token must be a non-empty string` });
157
+ throw new errors_utils_1.ValidationError({
158
+ reason: `${type} token must be a non-empty string`,
159
+ });
150
160
  }
151
161
  const cacheKey = `${type}_${token}`;
152
162
  if (this.cache) {
153
163
  const cached = this.cache.get(cacheKey);
154
164
  if (cached && Date.now() - cached.timestamp <= this.cacheTTL) {
155
165
  if (!cached.valid)
156
- throw new errors_utils_1.UnauthorizedError({ message: `${type} token is invalid or expired` });
166
+ throw new errors_utils_1.UnauthorizedError({
167
+ reason: `${type} token is invalid or expired`,
168
+ });
157
169
  return cached.payload;
158
170
  }
159
171
  }
160
172
  const { valid, payload, error } = (0, verify_1.safeVerifyToken)(token, secret);
161
173
  if (!valid || !payload || typeof payload === 'string') {
162
- this.cache?.set(cacheKey, { valid: false, payload: {}, timestamp: Date.now() });
163
- throw new errors_utils_1.UnauthorizedError({ message: `${type} token is invalid or expired`, cause: error });
174
+ this.cache?.set(cacheKey, {
175
+ valid: false,
176
+ payload: {},
177
+ timestamp: Date.now(),
178
+ });
179
+ throw new errors_utils_1.UnauthorizedError({
180
+ reason: `${type} token is invalid or expired`,
181
+ cause: error,
182
+ });
164
183
  }
165
184
  this.cache?.set(cacheKey, { valid: true, payload, timestamp: Date.now() });
166
185
  return payload;
@@ -19,12 +19,12 @@ function parseDuration(input) {
19
19
  const value = Number.parseInt(match[1], 10);
20
20
  const unit = match[2].toLowerCase();
21
21
  if (!TIME_UNITS[unit]) {
22
- throw new errors_utils_1.ValidationError({ message: `Invalid time unit: ${unit}` });
22
+ throw new errors_utils_1.ValidationError({ reason: `Invalid time unit: ${unit}` });
23
23
  }
24
24
  totalSeconds += value * TIME_UNITS[unit];
25
25
  }
26
26
  if (totalSeconds === 0) {
27
- throw new errors_utils_1.ValidationError({ message: `Invalid expiry format: "${input}"` });
27
+ throw new errors_utils_1.ValidationError({ reason: `Invalid expiry format: "${input}"` });
28
28
  }
29
29
  return totalSeconds;
30
30
  }
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.signToken = void 0;
4
+ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
4
5
  const jsonwebtoken_1 = require("jsonwebtoken");
5
6
  const parseDuration_1 = require("./parseDuration");
6
- const errors_utils_1 = require("@naman_deep_singh/errors-utils");
7
7
  function getExpiryTimestamp(seconds) {
8
8
  return Math.floor(Date.now() / 1000) + seconds;
9
9
  }
10
10
  const signToken = (payload, secret, expiresIn = '1h', options = {}) => {
11
11
  const seconds = (0, parseDuration_1.parseDuration)(expiresIn);
12
12
  if (!seconds || seconds < 10) {
13
- throw new errors_utils_1.ValidationError({ message: 'Token expiry too small' });
13
+ throw new errors_utils_1.ValidationError({ reason: 'Token expiry too small' });
14
14
  }
15
15
  const tokenPayload = {
16
16
  ...payload,
@@ -8,24 +8,30 @@ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
8
8
  * Throws ValidationError if validation fails.
9
9
  */
10
10
  function validateTokenPayload(payload, rules = { requiredFields: ['exp', 'iat'] }) {
11
- const { requiredFields = [], forbiddenFields = [], validateTypes = {} } = rules;
11
+ const { requiredFields = [], forbiddenFields = [], validateTypes = {}, } = rules;
12
12
  // 1. Required fields
13
13
  for (const field of requiredFields) {
14
14
  if (!(field in payload)) {
15
- throw new errors_utils_1.ValidationError(`Missing required field: ${field}`);
15
+ throw new errors_utils_1.ValidationError({
16
+ reason: `Missing required field: ${field}`,
17
+ });
16
18
  }
17
19
  }
18
20
  // 2. Forbidden fields
19
21
  for (const field of forbiddenFields) {
20
22
  if (field in payload) {
21
- throw new errors_utils_1.ValidationError(`Forbidden field in token: ${field}`);
23
+ throw new errors_utils_1.ValidationError({
24
+ reason: `Forbidden field in token: ${field}`,
25
+ });
22
26
  }
23
27
  }
24
28
  // 3. Type validation
25
29
  for (const key in validateTypes) {
26
30
  const expectedType = validateTypes[key];
27
31
  if (key in payload && typeof payload[key] !== expectedType) {
28
- throw new errors_utils_1.ValidationError(`Invalid type for ${key}. Expected ${expectedType}, got ${typeof payload[key]}`);
32
+ throw new errors_utils_1.ValidationError({
33
+ reason: `Invalid type for ${key}. Expected ${expectedType}, got ${typeof payload[key]}`,
34
+ });
29
35
  }
30
36
  }
31
37
  }
@@ -1,5 +1,5 @@
1
- import { type JwtPayload, type Secret, VerifyOptions } from 'jsonwebtoken';
2
- import { VerificationResult } from './types';
1
+ import { type JwtPayload, type Secret, type VerifyOptions } from 'jsonwebtoken';
2
+ import type { VerificationResult } from './types';
3
3
  /**
4
4
  * Verify token (throws UnauthorizedError if invalid or expired)
5
5
  */
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.safeVerifyTokenWithOptions = exports.safeVerifyToken = exports.verifyTokenWithOptions = exports.verifyToken = void 0;
4
- const jsonwebtoken_1 = require("jsonwebtoken");
5
4
  const errors_utils_1 = require("@naman_deep_singh/errors-utils");
5
+ const jsonwebtoken_1 = require("jsonwebtoken");
6
6
  /**
7
7
  * Verify token (throws UnauthorizedError if invalid or expired)
8
8
  */
@@ -12,12 +12,12 @@ const verifyToken = (token, secret) => {
12
12
  }
13
13
  catch (error) {
14
14
  if (error.name === 'TokenExpiredError') {
15
- throw new errors_utils_1.UnauthorizedError({ message: 'Token has expired' }, error);
15
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Token has expired' }, error);
16
16
  }
17
17
  if (error.name === 'JsonWebTokenError') {
18
- throw new errors_utils_1.UnauthorizedError({ message: 'Invalid token' }, error);
18
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Invalid token' }, error);
19
19
  }
20
- throw new errors_utils_1.UnauthorizedError({ message: 'Failed to verify token' }, error);
20
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Failed to verify token' }, error);
21
21
  }
22
22
  };
23
23
  exports.verifyToken = verifyToken;
@@ -30,12 +30,12 @@ const verifyTokenWithOptions = (token, secret, options = {}) => {
30
30
  }
31
31
  catch (error) {
32
32
  if (error.name === 'TokenExpiredError') {
33
- throw new errors_utils_1.UnauthorizedError({ message: 'Token has expired' }, error);
33
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Token has expired' }, error);
34
34
  }
35
35
  if (error.name === 'JsonWebTokenError') {
36
- throw new errors_utils_1.UnauthorizedError({ message: 'Invalid token' }, error);
36
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Invalid token' }, error);
37
37
  }
38
- throw new errors_utils_1.UnauthorizedError({ message: 'Failed to verify token' }, error);
38
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Failed to verify token' }, error);
39
39
  }
40
40
  };
41
41
  exports.verifyTokenWithOptions = verifyTokenWithOptions;
@@ -50,13 +50,13 @@ const safeVerifyToken = (token, secret) => {
50
50
  catch (error) {
51
51
  let wrappedError;
52
52
  if (error.name === 'TokenExpiredError') {
53
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Token has expired' }, error);
53
+ wrappedError = new errors_utils_1.UnauthorizedError({ reason: 'Token has expired' }, error);
54
54
  }
55
55
  else if (error.name === 'JsonWebTokenError') {
56
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Invalid token' }, error);
56
+ wrappedError = new errors_utils_1.UnauthorizedError({ reason: 'Invalid token' }, error);
57
57
  }
58
58
  else {
59
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Failed to verify token' }, error);
59
+ wrappedError = new errors_utils_1.UnauthorizedError({ reason: 'Failed to verify token' }, error);
60
60
  }
61
61
  return { valid: false, error: wrappedError };
62
62
  }
@@ -73,13 +73,15 @@ const safeVerifyTokenWithOptions = (token, secret, options = {}) => {
73
73
  catch (error) {
74
74
  let wrappedError;
75
75
  if (error.name === 'TokenExpiredError') {
76
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Token has expired' }, error);
76
+ wrappedError = new errors_utils_1.UnauthorizedError({ reason: 'Token has expired' }, error instanceof Error ? error : undefined);
77
77
  }
78
78
  else if (error.name === 'JsonWebTokenError') {
79
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Invalid token' }, error);
79
+ wrappedError = new errors_utils_1.UnauthorizedError({
80
+ reason: 'Invalid token',
81
+ }, error instanceof Error ? error : undefined);
80
82
  }
81
83
  else {
82
- wrappedError = new errors_utils_1.UnauthorizedError({ message: 'Failed to verify token' }, error);
84
+ wrappedError = new errors_utils_1.UnauthorizedError({ reason: 'Failed to verify token' }, error instanceof Error ? error : undefined);
83
85
  }
84
86
  return { valid: false, error: wrappedError };
85
87
  }
@@ -18,8 +18,8 @@ const hashPassword = async (password, saltRounds = 10) => {
18
18
  const salt = await bcryptjs_1.default.genSalt(saltRounds);
19
19
  return bcryptjs_1.default.hash(password, salt);
20
20
  }
21
- catch (_err) {
22
- throw new errors_utils_1.InternalServerError({ message: 'Password hashing failed' });
21
+ catch (error) {
22
+ throw new errors_utils_1.InternalServerError({ reason: 'Password hashing failed' }, error instanceof Error ? error : undefined);
23
23
  }
24
24
  };
25
25
  exports.hashPassword = hashPassword;
@@ -35,8 +35,8 @@ const hashPasswordSync = (password, saltRounds = 10) => {
35
35
  const salt = bcryptjs_1.default.genSaltSync(saltRounds);
36
36
  return bcryptjs_1.default.hashSync(password, salt);
37
37
  }
38
- catch (_error) {
39
- throw new errors_utils_1.InternalServerError({ message: 'Password hashing failed' });
38
+ catch (error) {
39
+ throw new errors_utils_1.InternalServerError({ reason: 'Password hashing failed' }, error instanceof Error ? error : undefined);
40
40
  }
41
41
  };
42
42
  exports.hashPasswordSync = hashPasswordSync;
@@ -37,10 +37,11 @@ class PasswordManager {
37
37
  return { hash, salt: finalSalt };
38
38
  }
39
39
  catch (error) {
40
- if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
40
+ if (error instanceof errors_utils_1.BadRequestError ||
41
+ error instanceof errors_utils_1.ValidationError) {
41
42
  throw error;
42
43
  }
43
- throw new errors_utils_1.BadRequestError({ message: 'Failed to hash password' }, error instanceof Error ? error : undefined);
44
+ throw new errors_utils_1.BadRequestError({ reason: 'Failed to hash password' }, error instanceof Error ? error : undefined);
44
45
  }
45
46
  }
46
47
  /**
@@ -63,7 +64,9 @@ class PasswordManager {
63
64
  generate(length = 16, options = {}) {
64
65
  const config = { ...this.defaultConfig, ...options };
65
66
  if (length < config.minLength || length > config.maxLength) {
66
- throw new errors_utils_1.ValidationError({ message: `Password length must be between ${config.minLength} and ${config.maxLength}` });
67
+ throw new errors_utils_1.ValidationError({
68
+ reason: `Password length must be between ${config.minLength} and ${config.maxLength}`,
69
+ });
67
70
  }
68
71
  let charset = 'abcdefghijklmnopqrstuvwxyz';
69
72
  if (config.requireUppercase)
@@ -114,7 +117,11 @@ class PasswordManager {
114
117
  errors.push(rule.message);
115
118
  });
116
119
  }
117
- return { isValid: errors.length === 0, errors, strength: this.checkStrength(password) };
120
+ return {
121
+ isValid: errors.length === 0,
122
+ errors,
123
+ strength: this.checkStrength(password),
124
+ };
118
125
  }
119
126
  /**
120
127
  * Check password strength
@@ -190,7 +197,8 @@ class PasswordManager {
190
197
  label = 'strong';
191
198
  suggestions.push('Your password is very secure');
192
199
  break;
193
- default: label = 'very-weak';
200
+ default:
201
+ label = 'very-weak';
194
202
  }
195
203
  return { score, label, feedback, suggestions };
196
204
  }
@@ -4,18 +4,24 @@ exports.isPasswordStrong = void 0;
4
4
  const errors_utils_1 = require("@naman_deep_singh/errors-utils");
5
5
  const isPasswordStrong = (password, options = {}) => {
6
6
  if (!password)
7
- throw new errors_utils_1.BadRequestError({ message: 'Invalid password provided' });
7
+ throw new errors_utils_1.BadRequestError({ reason: 'Invalid password provided' });
8
8
  const { minLength = 8, requireUppercase = true, requireLowercase = true, requireNumbers = true, requireSymbols = false, } = options;
9
9
  if (password.length < minLength)
10
- throw new errors_utils_1.ValidationError(`Password must be at least ${minLength} characters`);
10
+ throw new errors_utils_1.ValidationError({
11
+ reason: `Password must be at least ${minLength} characters long`,
12
+ });
11
13
  if (requireUppercase && !/[A-Z]/.test(password))
12
- throw new errors_utils_1.ValidationError({ message: 'Password must include uppercase letters' });
14
+ throw new errors_utils_1.ValidationError({
15
+ reason: 'Password must include uppercase letters',
16
+ });
13
17
  if (requireLowercase && !/[a-z]/.test(password))
14
- throw new errors_utils_1.ValidationError({ message: 'Password must include lowercase letters' });
18
+ throw new errors_utils_1.ValidationError({
19
+ reason: 'Password must include lowercase letters',
20
+ });
15
21
  if (requireNumbers && !/[0-9]/.test(password))
16
- throw new errors_utils_1.ValidationError({ message: 'Password must include numbers' });
22
+ throw new errors_utils_1.ValidationError({ reason: 'Password must include numbers' });
17
23
  if (requireSymbols && !/[^A-Za-z0-9]/.test(password))
18
- throw new errors_utils_1.ValidationError({ message: 'Password must include symbols' });
24
+ throw new errors_utils_1.ValidationError({ reason: 'Password must include symbols' });
19
25
  return true;
20
26
  };
21
27
  exports.isPasswordStrong = isPasswordStrong;
@@ -14,7 +14,7 @@ const errors_utils_1 = require("@naman_deep_singh/errors-utils");
14
14
  */
15
15
  function ensureValidPassword(password) {
16
16
  if (!password || typeof password !== 'string') {
17
- throw new errors_utils_1.BadRequestError({ message: 'Invalid password provided' });
17
+ throw new errors_utils_1.BadRequestError({ reason: 'Invalid password provided' });
18
18
  }
19
19
  }
20
20
  /**
@@ -15,11 +15,11 @@ const verifyPassword = async (password, hash) => {
15
15
  try {
16
16
  const result = await bcryptjs_1.default.compare(password, hash);
17
17
  if (!result)
18
- throw new errors_utils_1.UnauthorizedError({ message: 'Password verification failed' });
18
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Password verification failed' });
19
19
  return result;
20
20
  }
21
21
  catch {
22
- throw new errors_utils_1.UnauthorizedError({ message: 'Password verification failed' });
22
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Password verification failed' });
23
23
  }
24
24
  };
25
25
  exports.verifyPassword = verifyPassword;
@@ -33,11 +33,11 @@ const verifyPasswordSync = (password, hash) => {
33
33
  try {
34
34
  const result = bcryptjs_1.default.compareSync(password, hash);
35
35
  if (!result)
36
- throw new errors_utils_1.UnauthorizedError({ message: 'Password verification failed' });
36
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Password verification failed' });
37
37
  return result;
38
38
  }
39
39
  catch (_error) {
40
- throw new errors_utils_1.UnauthorizedError({ message: 'Password verification failed' });
40
+ throw new errors_utils_1.UnauthorizedError({ reason: 'Password verification failed' });
41
41
  }
42
42
  };
43
43
  exports.verifyPasswordSync = verifyPasswordSync;
@@ -1,4 +1,4 @@
1
- import { InternalServerError } from '@naman_deep_singh/errors-utils';
1
+ import { CryptoIntegrityError } from '@naman_deep_singh/errors-utils';
2
2
  import { decrypt as functionalDecrypt, encrypt as functionalEncrypt, hmacSign as functionalHmacSign, hmacVerify as functionalHmacVerify, randomToken as functionalRandomToken, } from './index';
3
3
  /**
4
4
  * Default configuration
@@ -35,10 +35,10 @@ export class CryptoManager {
35
35
  try {
36
36
  return functionalEncrypt(plaintext, key);
37
37
  }
38
- catch (err) {
39
- throw new InternalServerError(undefined, {
40
- message: 'Encryption failed',
41
- }, err instanceof Error ? err : undefined);
38
+ catch (error) {
39
+ throw new CryptoIntegrityError({
40
+ reason: 'Encryption failed',
41
+ }, error instanceof Error ? error : undefined);
42
42
  }
43
43
  }
44
44
  /**
@@ -48,10 +48,10 @@ export class CryptoManager {
48
48
  try {
49
49
  return functionalDecrypt(encryptedData, key);
50
50
  }
51
- catch (err) {
52
- throw new InternalServerError(undefined, {
53
- message: 'Decryption failed',
54
- }, err instanceof Error ? err : undefined);
51
+ catch (error) {
52
+ throw new CryptoIntegrityError({
53
+ reason: 'Decryption failed',
54
+ }, error instanceof Error ? error : undefined);
55
55
  }
56
56
  }
57
57
  /**
@@ -82,11 +82,11 @@ export class CryptoManager {
82
82
  deriveKey(password, salt, iterations = 100000, keyLength = 32) {
83
83
  return new Promise((resolve, reject) => {
84
84
  const crypto = require('crypto');
85
- crypto.pbkdf2(password, salt, iterations, keyLength, 'sha256', (err, derivedKey) => {
86
- if (err) {
87
- reject(new InternalServerError(undefined, {
88
- message: 'Key derivation failed',
89
- }, err instanceof Error ? err : undefined));
85
+ crypto.pbkdf2(password, salt, iterations, keyLength, 'sha256', (error, derivedKey) => {
86
+ if (error) {
87
+ reject(new CryptoIntegrityError({
88
+ reason: 'Key derivation failed',
89
+ }, error instanceof Error ? error : undefined));
90
90
  }
91
91
  else {
92
92
  resolve(derivedKey.toString('hex'));
@@ -163,10 +163,10 @@ export class CryptoManager {
163
163
  const signature = sign.sign(privateKey, 'base64');
164
164
  resolve(signature);
165
165
  }
166
- catch (err) {
167
- reject(new InternalServerError(undefined, {
168
- message: 'RSA signing failed',
169
- }, err instanceof Error ? err : undefined));
166
+ catch (error) {
167
+ reject(new CryptoIntegrityError({
168
+ reason: 'RSA signing failed',
169
+ }, error instanceof Error ? error : undefined));
170
170
  }
171
171
  });
172
172
  }
@@ -183,10 +183,10 @@ export class CryptoManager {
183
183
  const isValid = verify.verify(publicKey, signature, 'base64');
184
184
  resolve(isValid);
185
185
  }
186
- catch (err) {
187
- reject(new InternalServerError(undefined, {
188
- message: 'RSA verification failed',
189
- }, err instanceof Error ? err : undefined));
186
+ catch (error) {
187
+ reject(new CryptoIntegrityError({
188
+ reason: 'RSA verification failed',
189
+ }, error instanceof Error ? error : undefined));
190
190
  }
191
191
  });
192
192
  }
@@ -1,6 +1,6 @@
1
+ import { BadRequestError } from '@naman_deep_singh/errors-utils';
1
2
  // src/jwt/decodeToken.ts
2
3
  import { decode } from 'jsonwebtoken';
3
- import { BadRequestError } from '@naman_deep_singh/errors-utils';
4
4
  /**
5
5
  * Flexible decode
6
6
  * Returns: null | string | JwtPayload
@@ -17,7 +17,7 @@ export function decodeTokenStrict(token) {
17
17
  const decoded = decode(token);
18
18
  if (!decoded || typeof decoded === 'string') {
19
19
  throw new BadRequestError({
20
- message: 'Invalid JWT payload structure',
20
+ reason: 'Invalid JWT payload structure',
21
21
  });
22
22
  }
23
23
  return decoded;
@@ -1,6 +1,6 @@
1
+ import { TokenMalformedError } from '@naman_deep_singh/errors-utils';
1
2
  import { signToken } from './signToken';
2
3
  import { verifyToken } from './verify';
3
- import { TokenMalformedError } from '@naman_deep_singh/errors-utils';
4
4
  // Helper function to create branded tokens
5
5
  /* const createBrandedToken = <T extends string>(token: string, _brand: T): T => {
6
6
  return token as T
@@ -21,7 +21,7 @@ export function rotateRefreshToken(oldToken, secret) {
21
21
  const decoded = verifyToken(oldToken, secret);
22
22
  if (typeof decoded === 'string') {
23
23
  throw new TokenMalformedError({
24
- message: 'Invalid token payload — expected JWT payload object',
24
+ reason: 'Invalid token payload — expected JWT payload object',
25
25
  });
26
26
  }
27
27
  const payload = { ...decoded };
@@ -25,33 +25,37 @@ export class JWTManager {
25
25
  catch (error) {
26
26
  if (error instanceof BadRequestError || error instanceof ValidationError)
27
27
  throw error;
28
- throw new BadRequestError({ message: 'Failed to generate tokens' }, error instanceof Error ? error : undefined);
28
+ throw new BadRequestError({ reason: 'Failed to generate tokens' }, error instanceof Error ? error : undefined);
29
29
  }
30
30
  }
31
31
  /** Generate access token */
32
32
  async generateAccessToken(payload) {
33
33
  try {
34
34
  this.validatePayload(payload);
35
- const token = signToken(payload, this.accessSecret, this.accessExpiry, { algorithm: 'HS256' });
35
+ const token = signToken(payload, this.accessSecret, this.accessExpiry, {
36
+ algorithm: 'HS256',
37
+ });
36
38
  return token;
37
39
  }
38
40
  catch (error) {
39
41
  if (error instanceof BadRequestError || error instanceof ValidationError)
40
42
  throw error;
41
- throw new BadRequestError({ message: 'Failed to generate access token' }, error instanceof Error ? error : undefined);
43
+ throw new BadRequestError({ reason: 'Failed to generate access token' }, error instanceof Error ? error : undefined);
42
44
  }
43
45
  }
44
46
  /** Generate refresh token */
45
47
  async generateRefreshToken(payload) {
46
48
  try {
47
49
  this.validatePayload(payload);
48
- const token = signToken(payload, this.refreshSecret, this.refreshExpiry, { algorithm: 'HS256' });
50
+ const token = signToken(payload, this.refreshSecret, this.refreshExpiry, {
51
+ algorithm: 'HS256',
52
+ });
49
53
  return token;
50
54
  }
51
55
  catch (error) {
52
56
  if (error instanceof BadRequestError || error instanceof ValidationError)
53
57
  throw error;
54
- throw new BadRequestError({ message: 'Failed to generate refresh token' }, error instanceof Error ? error : undefined);
58
+ throw new BadRequestError({ reason: 'Failed to generate refresh token' }, error instanceof Error ? error : undefined);
55
59
  }
56
60
  }
57
61
  /** Verify access token */
@@ -86,7 +90,9 @@ export class JWTManager {
86
90
  /** Rotate refresh token */
87
91
  async rotateRefreshToken(oldToken) {
88
92
  if (!oldToken || typeof oldToken !== 'string') {
89
- throw new ValidationError({ message: 'Old refresh token must be a non-empty string' });
93
+ throw new ValidationError({
94
+ reason: 'Old refresh token must be a non-empty string',
95
+ });
90
96
  }
91
97
  const decoded = await this.verifyRefreshToken(oldToken);
92
98
  const payload = { ...decoded };
@@ -132,29 +138,42 @@ export class JWTManager {
132
138
  /** Private helper methods */
133
139
  validatePayload(payload) {
134
140
  if (!payload || typeof payload !== 'object') {
135
- throw new ValidationError({ message: 'Payload must be a non-null object' });
141
+ throw new ValidationError({
142
+ reason: 'Payload must be a non-null object',
143
+ });
136
144
  }
137
145
  if (Object.keys(payload).length === 0) {
138
- throw new ValidationError({ message: 'Payload cannot be empty' });
146
+ throw new ValidationError({ reason: 'Payload cannot be empty' });
139
147
  }
140
148
  }
141
149
  async verifyTokenWithCache(token, secret, type) {
142
150
  if (!token || typeof token !== 'string') {
143
- throw new ValidationError({ message: `${type} token must be a non-empty string` });
151
+ throw new ValidationError({
152
+ reason: `${type} token must be a non-empty string`,
153
+ });
144
154
  }
145
155
  const cacheKey = `${type}_${token}`;
146
156
  if (this.cache) {
147
157
  const cached = this.cache.get(cacheKey);
148
158
  if (cached && Date.now() - cached.timestamp <= this.cacheTTL) {
149
159
  if (!cached.valid)
150
- throw new UnauthorizedError({ message: `${type} token is invalid or expired` });
160
+ throw new UnauthorizedError({
161
+ reason: `${type} token is invalid or expired`,
162
+ });
151
163
  return cached.payload;
152
164
  }
153
165
  }
154
166
  const { valid, payload, error } = safeVerifyToken(token, secret);
155
167
  if (!valid || !payload || typeof payload === 'string') {
156
- this.cache?.set(cacheKey, { valid: false, payload: {}, timestamp: Date.now() });
157
- throw new UnauthorizedError({ message: `${type} token is invalid or expired`, cause: error });
168
+ this.cache?.set(cacheKey, {
169
+ valid: false,
170
+ payload: {},
171
+ timestamp: Date.now(),
172
+ });
173
+ throw new UnauthorizedError({
174
+ reason: `${type} token is invalid or expired`,
175
+ cause: error,
176
+ });
158
177
  }
159
178
  this.cache?.set(cacheKey, { valid: true, payload, timestamp: Date.now() });
160
179
  return payload;
@@ -1,4 +1,4 @@
1
- import { ValidationError } from "@naman_deep_singh/errors-utils";
1
+ import { ValidationError } from '@naman_deep_singh/errors-utils';
2
2
  const TIME_UNITS = {
3
3
  s: 1,
4
4
  m: 60,
@@ -16,12 +16,12 @@ export function parseDuration(input) {
16
16
  const value = Number.parseInt(match[1], 10);
17
17
  const unit = match[2].toLowerCase();
18
18
  if (!TIME_UNITS[unit]) {
19
- throw new ValidationError({ message: `Invalid time unit: ${unit}` });
19
+ throw new ValidationError({ reason: `Invalid time unit: ${unit}` });
20
20
  }
21
21
  totalSeconds += value * TIME_UNITS[unit];
22
22
  }
23
23
  if (totalSeconds === 0) {
24
- throw new ValidationError({ message: `Invalid expiry format: "${input}"` });
24
+ throw new ValidationError({ reason: `Invalid expiry format: "${input}"` });
25
25
  }
26
26
  return totalSeconds;
27
27
  }
@@ -1,13 +1,13 @@
1
+ import { ValidationError } from '@naman_deep_singh/errors-utils';
1
2
  import { sign } from 'jsonwebtoken';
2
3
  import { parseDuration } from './parseDuration';
3
- import { ValidationError } from '@naman_deep_singh/errors-utils';
4
4
  function getExpiryTimestamp(seconds) {
5
5
  return Math.floor(Date.now() / 1000) + seconds;
6
6
  }
7
7
  export const signToken = (payload, secret, expiresIn = '1h', options = {}) => {
8
8
  const seconds = parseDuration(expiresIn);
9
9
  if (!seconds || seconds < 10) {
10
- throw new ValidationError({ message: 'Token expiry too small' });
10
+ throw new ValidationError({ reason: 'Token expiry too small' });
11
11
  }
12
12
  const tokenPayload = {
13
13
  ...payload,
@@ -4,24 +4,30 @@ import { ValidationError } from '@naman_deep_singh/errors-utils';
4
4
  * Throws ValidationError if validation fails.
5
5
  */
6
6
  export function validateTokenPayload(payload, rules = { requiredFields: ['exp', 'iat'] }) {
7
- const { requiredFields = [], forbiddenFields = [], validateTypes = {} } = rules;
7
+ const { requiredFields = [], forbiddenFields = [], validateTypes = {}, } = rules;
8
8
  // 1. Required fields
9
9
  for (const field of requiredFields) {
10
10
  if (!(field in payload)) {
11
- throw new ValidationError(`Missing required field: ${field}`);
11
+ throw new ValidationError({
12
+ reason: `Missing required field: ${field}`,
13
+ });
12
14
  }
13
15
  }
14
16
  // 2. Forbidden fields
15
17
  for (const field of forbiddenFields) {
16
18
  if (field in payload) {
17
- throw new ValidationError(`Forbidden field in token: ${field}`);
19
+ throw new ValidationError({
20
+ reason: `Forbidden field in token: ${field}`,
21
+ });
18
22
  }
19
23
  }
20
24
  // 3. Type validation
21
25
  for (const key in validateTypes) {
22
26
  const expectedType = validateTypes[key];
23
27
  if (key in payload && typeof payload[key] !== expectedType) {
24
- throw new ValidationError(`Invalid type for ${key}. Expected ${expectedType}, got ${typeof payload[key]}`);
28
+ throw new ValidationError({
29
+ reason: `Invalid type for ${key}. Expected ${expectedType}, got ${typeof payload[key]}`,
30
+ });
25
31
  }
26
32
  }
27
33
  }
@@ -1,5 +1,5 @@
1
- import { type JwtPayload, type Secret, VerifyOptions } from 'jsonwebtoken';
2
- import { VerificationResult } from './types';
1
+ import { type JwtPayload, type Secret, type VerifyOptions } from 'jsonwebtoken';
2
+ import type { VerificationResult } from './types';
3
3
  /**
4
4
  * Verify token (throws UnauthorizedError if invalid or expired)
5
5
  */
@@ -1,5 +1,5 @@
1
- import { verify } from 'jsonwebtoken';
2
1
  import { UnauthorizedError } from '@naman_deep_singh/errors-utils';
2
+ import { verify, } from 'jsonwebtoken';
3
3
  /**
4
4
  * Verify token (throws UnauthorizedError if invalid or expired)
5
5
  */
@@ -9,12 +9,12 @@ export const verifyToken = (token, secret) => {
9
9
  }
10
10
  catch (error) {
11
11
  if (error.name === 'TokenExpiredError') {
12
- throw new UnauthorizedError({ message: 'Token has expired' }, error);
12
+ throw new UnauthorizedError({ reason: 'Token has expired' }, error);
13
13
  }
14
14
  if (error.name === 'JsonWebTokenError') {
15
- throw new UnauthorizedError({ message: 'Invalid token' }, error);
15
+ throw new UnauthorizedError({ reason: 'Invalid token' }, error);
16
16
  }
17
- throw new UnauthorizedError({ message: 'Failed to verify token' }, error);
17
+ throw new UnauthorizedError({ reason: 'Failed to verify token' }, error);
18
18
  }
19
19
  };
20
20
  /**
@@ -26,12 +26,12 @@ export const verifyTokenWithOptions = (token, secret, options = {}) => {
26
26
  }
27
27
  catch (error) {
28
28
  if (error.name === 'TokenExpiredError') {
29
- throw new UnauthorizedError({ message: 'Token has expired' }, error);
29
+ throw new UnauthorizedError({ reason: 'Token has expired' }, error);
30
30
  }
31
31
  if (error.name === 'JsonWebTokenError') {
32
- throw new UnauthorizedError({ message: 'Invalid token' }, error);
32
+ throw new UnauthorizedError({ reason: 'Invalid token' }, error);
33
33
  }
34
- throw new UnauthorizedError({ message: 'Failed to verify token' }, error);
34
+ throw new UnauthorizedError({ reason: 'Failed to verify token' }, error);
35
35
  }
36
36
  };
37
37
  /**
@@ -45,13 +45,13 @@ export const safeVerifyToken = (token, secret) => {
45
45
  catch (error) {
46
46
  let wrappedError;
47
47
  if (error.name === 'TokenExpiredError') {
48
- wrappedError = new UnauthorizedError({ message: 'Token has expired' }, error);
48
+ wrappedError = new UnauthorizedError({ reason: 'Token has expired' }, error);
49
49
  }
50
50
  else if (error.name === 'JsonWebTokenError') {
51
- wrappedError = new UnauthorizedError({ message: 'Invalid token' }, error);
51
+ wrappedError = new UnauthorizedError({ reason: 'Invalid token' }, error);
52
52
  }
53
53
  else {
54
- wrappedError = new UnauthorizedError({ message: 'Failed to verify token' }, error);
54
+ wrappedError = new UnauthorizedError({ reason: 'Failed to verify token' }, error);
55
55
  }
56
56
  return { valid: false, error: wrappedError };
57
57
  }
@@ -67,13 +67,15 @@ export const safeVerifyTokenWithOptions = (token, secret, options = {}) => {
67
67
  catch (error) {
68
68
  let wrappedError;
69
69
  if (error.name === 'TokenExpiredError') {
70
- wrappedError = new UnauthorizedError({ message: 'Token has expired' }, error);
70
+ wrappedError = new UnauthorizedError({ reason: 'Token has expired' }, error instanceof Error ? error : undefined);
71
71
  }
72
72
  else if (error.name === 'JsonWebTokenError') {
73
- wrappedError = new UnauthorizedError({ message: 'Invalid token' }, error);
73
+ wrappedError = new UnauthorizedError({
74
+ reason: 'Invalid token',
75
+ }, error instanceof Error ? error : undefined);
74
76
  }
75
77
  else {
76
- wrappedError = new UnauthorizedError({ message: 'Failed to verify token' }, error);
78
+ wrappedError = new UnauthorizedError({ reason: 'Failed to verify token' }, error instanceof Error ? error : undefined);
77
79
  }
78
80
  return { valid: false, error: wrappedError };
79
81
  }
@@ -10,8 +10,8 @@ export const hashPassword = async (password, saltRounds = 10) => {
10
10
  const salt = await bcrypt.genSalt(saltRounds);
11
11
  return bcrypt.hash(password, salt);
12
12
  }
13
- catch (_err) {
14
- throw new InternalServerError({ message: 'Password hashing failed' });
13
+ catch (error) {
14
+ throw new InternalServerError({ reason: 'Password hashing failed' }, error instanceof Error ? error : undefined);
15
15
  }
16
16
  };
17
17
  export function hashPasswordWithPepper(password, pepper) {
@@ -26,8 +26,8 @@ export const hashPasswordSync = (password, saltRounds = 10) => {
26
26
  const salt = bcrypt.genSaltSync(saltRounds);
27
27
  return bcrypt.hashSync(password, salt);
28
28
  }
29
- catch (_error) {
30
- throw new InternalServerError({ message: 'Password hashing failed' });
29
+ catch (error) {
30
+ throw new InternalServerError({ reason: 'Password hashing failed' }, error instanceof Error ? error : undefined);
31
31
  }
32
32
  };
33
33
  export function hashPasswordWithPepperSync(password, pepper) {
@@ -31,10 +31,11 @@ export class PasswordManager {
31
31
  return { hash, salt: finalSalt };
32
32
  }
33
33
  catch (error) {
34
- if (error instanceof BadRequestError || error instanceof ValidationError) {
34
+ if (error instanceof BadRequestError ||
35
+ error instanceof ValidationError) {
35
36
  throw error;
36
37
  }
37
- throw new BadRequestError({ message: 'Failed to hash password' }, error instanceof Error ? error : undefined);
38
+ throw new BadRequestError({ reason: 'Failed to hash password' }, error instanceof Error ? error : undefined);
38
39
  }
39
40
  }
40
41
  /**
@@ -57,7 +58,9 @@ export class PasswordManager {
57
58
  generate(length = 16, options = {}) {
58
59
  const config = { ...this.defaultConfig, ...options };
59
60
  if (length < config.minLength || length > config.maxLength) {
60
- throw new ValidationError({ message: `Password length must be between ${config.minLength} and ${config.maxLength}` });
61
+ throw new ValidationError({
62
+ reason: `Password length must be between ${config.minLength} and ${config.maxLength}`,
63
+ });
61
64
  }
62
65
  let charset = 'abcdefghijklmnopqrstuvwxyz';
63
66
  if (config.requireUppercase)
@@ -108,7 +111,11 @@ export class PasswordManager {
108
111
  errors.push(rule.message);
109
112
  });
110
113
  }
111
- return { isValid: errors.length === 0, errors, strength: this.checkStrength(password) };
114
+ return {
115
+ isValid: errors.length === 0,
116
+ errors,
117
+ strength: this.checkStrength(password),
118
+ };
112
119
  }
113
120
  /**
114
121
  * Check password strength
@@ -184,7 +191,8 @@ export class PasswordManager {
184
191
  label = 'strong';
185
192
  suggestions.push('Your password is very secure');
186
193
  break;
187
- default: label = 'very-weak';
194
+ default:
195
+ label = 'very-weak';
188
196
  }
189
197
  return { score, label, feedback, suggestions };
190
198
  }
@@ -1,17 +1,23 @@
1
1
  import { BadRequestError, ValidationError, } from '@naman_deep_singh/errors-utils';
2
2
  export const isPasswordStrong = (password, options = {}) => {
3
3
  if (!password)
4
- throw new BadRequestError({ message: 'Invalid password provided' });
4
+ throw new BadRequestError({ reason: 'Invalid password provided' });
5
5
  const { minLength = 8, requireUppercase = true, requireLowercase = true, requireNumbers = true, requireSymbols = false, } = options;
6
6
  if (password.length < minLength)
7
- throw new ValidationError(`Password must be at least ${minLength} characters`);
7
+ throw new ValidationError({
8
+ reason: `Password must be at least ${minLength} characters long`,
9
+ });
8
10
  if (requireUppercase && !/[A-Z]/.test(password))
9
- throw new ValidationError({ message: 'Password must include uppercase letters' });
11
+ throw new ValidationError({
12
+ reason: 'Password must include uppercase letters',
13
+ });
10
14
  if (requireLowercase && !/[a-z]/.test(password))
11
- throw new ValidationError({ message: 'Password must include lowercase letters' });
15
+ throw new ValidationError({
16
+ reason: 'Password must include lowercase letters',
17
+ });
12
18
  if (requireNumbers && !/[0-9]/.test(password))
13
- throw new ValidationError({ message: 'Password must include numbers' });
19
+ throw new ValidationError({ reason: 'Password must include numbers' });
14
20
  if (requireSymbols && !/[^A-Za-z0-9]/.test(password))
15
- throw new ValidationError({ message: 'Password must include symbols' });
21
+ throw new ValidationError({ reason: 'Password must include symbols' });
16
22
  return true;
17
23
  };
@@ -5,7 +5,7 @@ import { BadRequestError } from '@naman_deep_singh/errors-utils';
5
5
  */
6
6
  export function ensureValidPassword(password) {
7
7
  if (!password || typeof password !== 'string') {
8
- throw new BadRequestError({ message: 'Invalid password provided' });
8
+ throw new BadRequestError({ reason: 'Invalid password provided' });
9
9
  }
10
10
  }
11
11
  /**
@@ -7,11 +7,11 @@ export const verifyPassword = async (password, hash) => {
7
7
  try {
8
8
  const result = await bcrypt.compare(password, hash);
9
9
  if (!result)
10
- throw new UnauthorizedError({ message: 'Password verification failed' });
10
+ throw new UnauthorizedError({ reason: 'Password verification failed' });
11
11
  return result;
12
12
  }
13
13
  catch {
14
- throw new UnauthorizedError({ message: 'Password verification failed' });
14
+ throw new UnauthorizedError({ reason: 'Password verification failed' });
15
15
  }
16
16
  };
17
17
  export async function verifyPasswordWithPepper(password, pepper, hash) {
@@ -24,11 +24,11 @@ export const verifyPasswordSync = (password, hash) => {
24
24
  try {
25
25
  const result = bcrypt.compareSync(password, hash);
26
26
  if (!result)
27
- throw new UnauthorizedError({ message: 'Password verification failed' });
27
+ throw new UnauthorizedError({ reason: 'Password verification failed' });
28
28
  return result;
29
29
  }
30
30
  catch (_error) {
31
- throw new UnauthorizedError({ message: 'Password verification failed' });
31
+ throw new UnauthorizedError({ reason: 'Password verification failed' });
32
32
  }
33
33
  };
34
34
  export async function verifyPasswordWithPepperSync(password, pepper, hash) {
@@ -1,5 +1,5 @@
1
- import { type JwtPayload, type Secret, VerifyOptions } from 'jsonwebtoken';
2
- import { VerificationResult } from './types';
1
+ import { type JwtPayload, type Secret, type VerifyOptions } from 'jsonwebtoken';
2
+ import type { VerificationResult } from './types';
3
3
  /**
4
4
  * Verify token (throws UnauthorizedError if invalid or expired)
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naman_deep_singh/security",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Security utilities for password hashing and JWT token management with TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -28,7 +28,7 @@
28
28
  "author": "Naman Deep Singh",
29
29
  "license": "ISC",
30
30
  "dependencies": {
31
- "@naman_deep_singh/errors-utils": "^1.3.4",
31
+ "@naman_deep_singh/errors-utils": "^1.4.2",
32
32
  "@naman_deep_singh/js-extensions": "^1.3.2",
33
33
  "bcryptjs": "^3.0.3",
34
34
  "jsonwebtoken": "^9.0.2"