@naman_deep_singh/security 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/core/crypto/cryptoManager.js +9 -3
  3. package/dist/cjs/core/crypto/decrypt.js +6 -6
  4. package/dist/cjs/core/crypto/encrypt.js +4 -4
  5. package/dist/cjs/core/crypto/hmac.js +1 -1
  6. package/dist/cjs/core/crypto/index.d.ts +5 -5
  7. package/dist/cjs/core/crypto/random.js +2 -2
  8. package/dist/cjs/core/jwt/decode.d.ts +1 -1
  9. package/dist/cjs/core/jwt/decode.js +2 -2
  10. package/dist/cjs/core/jwt/extractToken.js +7 -7
  11. package/dist/cjs/core/jwt/generateTokens.d.ts +2 -2
  12. package/dist/cjs/core/jwt/generateTokens.js +10 -6
  13. package/dist/cjs/core/jwt/index.d.ts +8 -8
  14. package/dist/cjs/core/jwt/jwtManager.d.ts +3 -2
  15. package/dist/cjs/core/jwt/jwtManager.js +66 -86
  16. package/dist/cjs/core/jwt/parseDuration.js +3 -3
  17. package/dist/cjs/core/jwt/signToken.d.ts +1 -1
  18. package/dist/cjs/core/jwt/signToken.js +7 -7
  19. package/dist/cjs/core/jwt/types.d.ts +1 -1
  20. package/dist/cjs/core/jwt/validateToken.d.ts +2 -2
  21. package/dist/cjs/core/jwt/validateToken.js +3 -3
  22. package/dist/cjs/core/jwt/verify.d.ts +3 -2
  23. package/dist/cjs/core/password/hash.js +1 -1
  24. package/dist/cjs/core/password/index.d.ts +3 -3
  25. package/dist/cjs/core/password/passwordManager.d.ts +1 -1
  26. package/dist/cjs/core/password/passwordManager.js +32 -31
  27. package/dist/cjs/core/password/strength.d.ts +1 -1
  28. package/dist/cjs/core/password/strength.js +4 -4
  29. package/dist/cjs/core/password/utils.js +2 -2
  30. package/dist/cjs/core/password/verify.js +1 -1
  31. package/dist/cjs/index.d.ts +6 -6
  32. package/dist/cjs/index.js +2 -2
  33. package/dist/cjs/interfaces/jwt.interface.d.ts +1 -1
  34. package/dist/esm/core/crypto/cryptoManager.js +10 -4
  35. package/dist/esm/core/crypto/decrypt.js +7 -7
  36. package/dist/esm/core/crypto/encrypt.js +5 -5
  37. package/dist/esm/core/crypto/hmac.js +2 -2
  38. package/dist/esm/core/crypto/index.d.ts +5 -5
  39. package/dist/esm/core/crypto/index.js +5 -5
  40. package/dist/esm/core/crypto/random.js +3 -3
  41. package/dist/esm/core/jwt/decode.d.ts +1 -1
  42. package/dist/esm/core/jwt/decode.js +3 -3
  43. package/dist/esm/core/jwt/extractToken.js +7 -7
  44. package/dist/esm/core/jwt/generateTokens.d.ts +2 -2
  45. package/dist/esm/core/jwt/generateTokens.js +12 -8
  46. package/dist/esm/core/jwt/index.d.ts +8 -8
  47. package/dist/esm/core/jwt/index.js +8 -8
  48. package/dist/esm/core/jwt/jwtManager.d.ts +3 -2
  49. package/dist/esm/core/jwt/jwtManager.js +70 -90
  50. package/dist/esm/core/jwt/parseDuration.js +3 -3
  51. package/dist/esm/core/jwt/signToken.d.ts +1 -1
  52. package/dist/esm/core/jwt/signToken.js +9 -9
  53. package/dist/esm/core/jwt/types.d.ts +1 -1
  54. package/dist/esm/core/jwt/validateToken.d.ts +2 -2
  55. package/dist/esm/core/jwt/validateToken.js +3 -3
  56. package/dist/esm/core/jwt/verify.d.ts +3 -2
  57. package/dist/esm/core/jwt/verify.js +1 -1
  58. package/dist/esm/core/password/hash.js +3 -3
  59. package/dist/esm/core/password/index.d.ts +3 -3
  60. package/dist/esm/core/password/index.js +3 -3
  61. package/dist/esm/core/password/passwordManager.d.ts +1 -1
  62. package/dist/esm/core/password/passwordManager.js +34 -33
  63. package/dist/esm/core/password/strength.d.ts +1 -1
  64. package/dist/esm/core/password/strength.js +5 -5
  65. package/dist/esm/core/password/utils.js +4 -4
  66. package/dist/esm/core/password/verify.js +2 -2
  67. package/dist/esm/index.d.ts +6 -6
  68. package/dist/esm/index.js +7 -7
  69. package/dist/esm/interfaces/jwt.interface.d.ts +1 -1
  70. package/dist/types/core/crypto/index.d.ts +5 -5
  71. package/dist/types/core/jwt/decode.d.ts +1 -1
  72. package/dist/types/core/jwt/generateTokens.d.ts +2 -2
  73. package/dist/types/core/jwt/index.d.ts +8 -8
  74. package/dist/types/core/jwt/jwtManager.d.ts +3 -2
  75. package/dist/types/core/jwt/signToken.d.ts +1 -1
  76. package/dist/types/core/jwt/types.d.ts +1 -1
  77. package/dist/types/core/jwt/validateToken.d.ts +2 -2
  78. package/dist/types/core/jwt/verify.d.ts +3 -2
  79. package/dist/types/core/password/index.d.ts +3 -3
  80. package/dist/types/core/password/passwordManager.d.ts +1 -1
  81. package/dist/types/core/password/strength.d.ts +1 -1
  82. package/dist/types/index.d.ts +6 -6
  83. package/dist/types/interfaces/jwt.interface.d.ts +1 -1
  84. package/package.json +4 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @naman_deep_singh/security
2
2
 
3
- **Version:** 1.3.0
3
+ **Version:** 1.3.1
4
4
 
5
5
  A complete, lightweight security toolkit for Node.js & TypeScript providing:
6
6
 
@@ -8,7 +8,7 @@ const index_1 = require("./index");
8
8
  const DEFAULT_CONFIG = {
9
9
  defaultAlgorithm: 'aes-256-gcm',
10
10
  defaultEncoding: 'utf8',
11
- hmacAlgorithm: 'sha256'
11
+ hmacAlgorithm: 'sha256',
12
12
  };
13
13
  /**
14
14
  * CryptoManager - Class-based wrapper for all cryptographic operations
@@ -106,8 +106,14 @@ class CryptoManager {
106
106
  const crypto = require('crypto');
107
107
  const keyPair = crypto.generateKeyPairSync('rsa', {
108
108
  modulusLength: options?.modulusLength || 2048,
109
- publicKeyEncoding: options?.publicKeyEncoding || { type: 'spki', format: 'pem' },
110
- privateKeyEncoding: options?.privateKeyEncoding || { type: 'pkcs8', format: 'pem' }
109
+ publicKeyEncoding: options?.publicKeyEncoding || {
110
+ type: 'spki',
111
+ format: 'pem',
112
+ },
113
+ privateKeyEncoding: options?.privateKeyEncoding || {
114
+ type: 'pkcs8',
115
+ format: 'pem',
116
+ },
111
117
  });
112
118
  resolve(keyPair);
113
119
  });
@@ -5,17 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.decrypt = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
- const ALGO = "AES-256-GCM";
8
+ const ALGO = 'AES-256-GCM';
9
9
  const decrypt = (data, secret) => {
10
- const [ivHex, encryptedHex] = data.split(":");
11
- const iv = Buffer.from(ivHex, "hex");
12
- const encrypted = Buffer.from(encryptedHex, "hex");
13
- const key = crypto_1.default.createHash("sha256").update(secret).digest();
10
+ const [ivHex, encryptedHex] = data.split(':');
11
+ const iv = Buffer.from(ivHex, 'hex');
12
+ const encrypted = Buffer.from(encryptedHex, 'hex');
13
+ const key = crypto_1.default.createHash('sha256').update(secret).digest();
14
14
  const decipher = crypto_1.default.createDecipheriv(ALGO, key, iv);
15
15
  const decrypted = Buffer.concat([
16
16
  decipher.update(encrypted),
17
17
  decipher.final(),
18
18
  ]);
19
- return decrypted.toString("utf8");
19
+ return decrypted.toString('utf8');
20
20
  };
21
21
  exports.decrypt = decrypt;
@@ -5,12 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.encrypt = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
- const ALGO = "AES-256-GCM";
8
+ const ALGO = 'AES-256-GCM';
9
9
  const encrypt = (text, secret) => {
10
- const key = crypto_1.default.createHash("sha256").update(secret).digest();
10
+ const key = crypto_1.default.createHash('sha256').update(secret).digest();
11
11
  const iv = crypto_1.default.randomBytes(16);
12
12
  const cipher = crypto_1.default.createCipheriv(ALGO, key, iv);
13
- const encrypted = Buffer.concat([cipher.update(text, "utf8"), cipher.final()]);
14
- return `${iv.toString("hex")}:${encrypted.toString("hex")}`;
13
+ const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
14
+ return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
15
15
  };
16
16
  exports.encrypt = encrypt;
@@ -9,7 +9,7 @@ const crypto_1 = __importDefault(require("crypto"));
9
9
  * Sign message using HMAC SHA-256
10
10
  */
11
11
  const hmacSign = (message, secret) => {
12
- return crypto_1.default.createHmac("sha256", secret).update(message).digest("hex");
12
+ return crypto_1.default.createHmac('sha256', secret).update(message).digest('hex');
13
13
  };
14
14
  exports.hmacSign = hmacSign;
15
15
  /**
@@ -1,5 +1,5 @@
1
- export { decrypt } from "./decrypt";
2
- export { encrypt } from "./encrypt";
3
- export { hmacSign, hmacVerify } from "./hmac";
4
- export { randomToken, generateStrongPassword } from "./random";
5
- export * from "./cryptoManager";
1
+ export { decrypt } from './decrypt';
2
+ export { encrypt } from './encrypt';
3
+ export { hmacSign, hmacVerify } from './hmac';
4
+ export { randomToken, generateStrongPassword } from './random';
5
+ export * from './cryptoManager';
@@ -9,13 +9,13 @@ const crypto_1 = __importDefault(require("crypto"));
9
9
  * Generate cryptographically secure random string
10
10
  */
11
11
  const randomToken = (length = 32) => {
12
- return crypto_1.default.randomBytes(length).toString("hex");
12
+ return crypto_1.default.randomBytes(length).toString('hex');
13
13
  };
14
14
  exports.randomToken = randomToken;
15
15
  /**
16
16
  * Generate a strong random password
17
17
  */
18
18
  const generateStrongPassword = (length = 16) => {
19
- return crypto_1.default.randomBytes(length).toString("hex").slice(0, length);
19
+ return crypto_1.default.randomBytes(length).toString('hex').slice(0, length);
20
20
  };
21
21
  exports.generateStrongPassword = generateStrongPassword;
@@ -1,4 +1,4 @@
1
- import { JwtPayload } from "jsonwebtoken";
1
+ import { type JwtPayload } from 'jsonwebtoken';
2
2
  /**
3
3
  * Flexible decode
4
4
  * Returns: null | string | JwtPayload
@@ -18,8 +18,8 @@ function decodeToken(token) {
18
18
  */
19
19
  function decodeTokenStrict(token) {
20
20
  const decoded = (0, jsonwebtoken_1.decode)(token);
21
- if (!decoded || typeof decoded === "string") {
22
- throw new Error("Invalid JWT payload structure");
21
+ if (!decoded || typeof decoded === 'string') {
22
+ throw new Error('Invalid JWT payload structure');
23
23
  }
24
24
  return decoded;
25
25
  }
@@ -8,16 +8,16 @@ function extractToken(sources) {
8
8
  const { header, cookies, query, body, wsMessage } = sources;
9
9
  // 1. Authorization: Bearer <token>
10
10
  if (header) {
11
- const parts = header.split(" ");
12
- if (parts.length === 2 && parts[0] === "Bearer")
11
+ const parts = header.split(' ');
12
+ if (parts.length === 2 && parts[0] === 'Bearer')
13
13
  return parts[1];
14
14
  }
15
15
  // 2. Cookies: token / accessToken
16
16
  if (cookies) {
17
- if (cookies["token"])
18
- return cookies["token"];
19
- if (cookies["accessToken"])
20
- return cookies["accessToken"];
17
+ if (cookies['token'])
18
+ return cookies['token'];
19
+ if (cookies['accessToken'])
20
+ return cookies['accessToken'];
21
21
  }
22
22
  // 3. Query params: ?token=xxx
23
23
  if (query?.token)
@@ -30,7 +30,7 @@ function extractToken(sources) {
30
30
  try {
31
31
  let msg = wsMessage;
32
32
  // If it's a JSON string → parse safely
33
- if (typeof wsMessage === "string") {
33
+ if (typeof wsMessage === 'string') {
34
34
  msg = JSON.parse(wsMessage);
35
35
  }
36
36
  // Ensure msg is an object before property access
@@ -1,4 +1,4 @@
1
- import { Secret } from "jsonwebtoken";
2
- import { RefreshToken, TokenPair } from "./types";
1
+ import { type Secret } from 'jsonwebtoken';
2
+ import type { RefreshToken, TokenPair } from './types';
3
3
  export declare const generateTokens: (payload: Record<string, unknown>, accessSecret: Secret, refreshSecret: Secret, accessExpiry?: string | number, refreshExpiry?: string | number) => TokenPair;
4
4
  export declare function rotateRefreshToken(oldToken: string, secret: Secret): RefreshToken;
@@ -8,9 +8,13 @@ const verify_1 = require("./verify");
8
8
  const createBrandedToken = (token, _brand) => {
9
9
  return token;
10
10
  };
11
- const generateTokens = (payload, accessSecret, refreshSecret, accessExpiry = "15m", refreshExpiry = "7d") => {
12
- const accessToken = (0, signToken_1.signToken)(payload, accessSecret, accessExpiry, { algorithm: "HS256" });
13
- const refreshToken = (0, signToken_1.signToken)(payload, refreshSecret, refreshExpiry, { algorithm: "HS256" });
11
+ const generateTokens = (payload, accessSecret, refreshSecret, accessExpiry = '15m', refreshExpiry = '7d') => {
12
+ const accessToken = (0, signToken_1.signToken)(payload, accessSecret, accessExpiry, {
13
+ algorithm: 'HS256',
14
+ });
15
+ const refreshToken = (0, signToken_1.signToken)(payload, refreshSecret, refreshExpiry, {
16
+ algorithm: 'HS256',
17
+ });
14
18
  return {
15
19
  accessToken: accessToken,
16
20
  refreshToken: refreshToken,
@@ -19,12 +23,12 @@ const generateTokens = (payload, accessSecret, refreshSecret, accessExpiry = "15
19
23
  exports.generateTokens = generateTokens;
20
24
  function rotateRefreshToken(oldToken, secret) {
21
25
  const decoded = (0, verify_1.verifyToken)(oldToken, secret);
22
- if (typeof decoded === "string") {
23
- throw new Error("Invalid token payload — expected JWT payload object");
26
+ if (typeof decoded === 'string') {
27
+ throw new Error('Invalid token payload — expected JWT payload object');
24
28
  }
25
29
  const payload = { ...decoded };
26
30
  delete payload.iat;
27
31
  delete payload.exp;
28
- const newToken = (0, signToken_1.signToken)(payload, secret, "7d");
32
+ const newToken = (0, signToken_1.signToken)(payload, secret, '7d');
29
33
  return newToken;
30
34
  }
@@ -1,8 +1,8 @@
1
- export * from "./decode";
2
- export * from "./extractToken";
3
- export * from "./generateTokens";
4
- export * from "./parseDuration";
5
- export * from "./signToken";
6
- export * from "./types";
7
- export * from "./validateToken";
8
- export * from "./verify";
1
+ export * from './decode';
2
+ export * from './extractToken';
3
+ export * from './generateTokens';
4
+ export * from './parseDuration';
5
+ export * from './signToken';
6
+ export * from './types';
7
+ export * from './validateToken';
8
+ export * from './verify';
@@ -1,11 +1,12 @@
1
- import { JwtPayload, Secret } from "jsonwebtoken";
2
- import { ITokenManager, TokenPair, AccessToken, RefreshToken, JWTConfig, TokenValidationOptions } from "../../interfaces/jwt.interface";
1
+ import { type JwtPayload, type Secret } from 'jsonwebtoken';
2
+ import type { AccessToken, ITokenManager, JWTConfig, RefreshToken, TokenPair, TokenValidationOptions } from '../../interfaces/jwt.interface';
3
3
  export declare class JWTManager implements ITokenManager {
4
4
  private accessSecret;
5
5
  private refreshSecret;
6
6
  private accessExpiry;
7
7
  private refreshExpiry;
8
8
  private cache?;
9
+ private cacheTTL;
9
10
  constructor(config: JWTConfig);
10
11
  /**
11
12
  * Generate both access and refresh tokens
@@ -8,51 +8,16 @@ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
8
  const signToken_1 = require("./signToken");
9
9
  const verify_1 = require("./verify");
10
10
  const errors_utils_1 = require("@naman_deep_singh/errors-utils");
11
- // Simple LRU cache for token validation
12
- class TokenCache {
13
- constructor(maxSize = 100, ttl = 5 * 60 * 1000) {
14
- this.cache = new Map();
15
- this.maxSize = maxSize;
16
- this.ttl = ttl;
17
- }
18
- get(key) {
19
- const entry = this.cache.get(key);
20
- if (!entry)
21
- return null;
22
- if (Date.now() - entry.timestamp > this.ttl) {
23
- this.cache.delete(key);
24
- return null;
25
- }
26
- // Move to end (most recently used)
27
- this.cache.delete(key);
28
- this.cache.set(key, entry);
29
- return { valid: entry.valid, payload: entry.payload };
30
- }
31
- set(key, value) {
32
- if (this.cache.has(key)) {
33
- this.cache.delete(key);
34
- }
35
- else if (this.cache.size >= this.maxSize) {
36
- // Remove least recently used (first item)
37
- const firstKey = this.cache.keys().next().value;
38
- if (firstKey !== undefined) {
39
- this.cache.delete(firstKey);
40
- }
41
- }
42
- this.cache.set(key, { ...value, timestamp: Date.now() });
43
- }
44
- clear() {
45
- this.cache.clear();
46
- }
47
- }
11
+ const js_extensions_1 = require("@naman_deep_singh/js-extensions");
48
12
  class JWTManager {
49
13
  constructor(config) {
50
14
  this.accessSecret = config.accessSecret;
51
15
  this.refreshSecret = config.refreshSecret;
52
- this.accessExpiry = config.accessExpiry || "15m";
53
- this.refreshExpiry = config.refreshExpiry || "7d";
16
+ this.accessExpiry = config.accessExpiry || '15m';
17
+ this.refreshExpiry = config.refreshExpiry || '7d';
18
+ this.cacheTTL = 5 * 60 * 1000; // 5 minutes default TTL
54
19
  if (config.enableCaching) {
55
- this.cache = new TokenCache(config.maxCacheSize || 100);
20
+ this.cache = new js_extensions_1.LRUCache(config.maxCacheSize || 100);
56
21
  }
57
22
  }
58
23
  /**
@@ -69,10 +34,11 @@ class JWTManager {
69
34
  };
70
35
  }
71
36
  catch (error) {
72
- if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
37
+ if (error instanceof errors_utils_1.BadRequestError ||
38
+ error instanceof errors_utils_1.ValidationError) {
73
39
  throw error;
74
40
  }
75
- throw new errors_utils_1.BadRequestError("Failed to generate tokens");
41
+ throw new errors_utils_1.BadRequestError('Failed to generate tokens');
76
42
  }
77
43
  }
78
44
  /**
@@ -81,14 +47,17 @@ class JWTManager {
81
47
  async generateAccessToken(payload) {
82
48
  try {
83
49
  this.validatePayload(payload);
84
- const token = (0, signToken_1.signToken)(payload, this.accessSecret, this.accessExpiry, { algorithm: "HS256" });
50
+ const token = (0, signToken_1.signToken)(payload, this.accessSecret, this.accessExpiry, {
51
+ algorithm: 'HS256',
52
+ });
85
53
  return token;
86
54
  }
87
55
  catch (error) {
88
- if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
56
+ if (error instanceof errors_utils_1.BadRequestError ||
57
+ error instanceof errors_utils_1.ValidationError) {
89
58
  throw error;
90
59
  }
91
- throw new errors_utils_1.BadRequestError("Failed to generate access token");
60
+ throw new errors_utils_1.BadRequestError('Failed to generate access token');
92
61
  }
93
62
  }
94
63
  /**
@@ -97,14 +66,17 @@ class JWTManager {
97
66
  async generateRefreshToken(payload) {
98
67
  try {
99
68
  this.validatePayload(payload);
100
- const token = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry, { algorithm: "HS256" });
69
+ const token = (0, signToken_1.signToken)(payload, this.refreshSecret, this.refreshExpiry, {
70
+ algorithm: 'HS256',
71
+ });
101
72
  return token;
102
73
  }
103
74
  catch (error) {
104
- if (error instanceof errors_utils_1.BadRequestError || error instanceof errors_utils_1.ValidationError) {
75
+ if (error instanceof errors_utils_1.BadRequestError ||
76
+ error instanceof errors_utils_1.ValidationError) {
105
77
  throw error;
106
78
  }
107
- throw new errors_utils_1.BadRequestError("Failed to generate refresh token");
79
+ throw new errors_utils_1.BadRequestError('Failed to generate refresh token');
108
80
  }
109
81
  }
110
82
  /**
@@ -112,36 +84,41 @@ class JWTManager {
112
84
  */
113
85
  async verifyAccessToken(token) {
114
86
  try {
115
- if (!token || typeof token !== "string") {
116
- throw new errors_utils_1.ValidationError("Access token must be a non-empty string");
87
+ if (!token || typeof token !== 'string') {
88
+ throw new errors_utils_1.ValidationError('Access token must be a non-empty string');
117
89
  }
118
90
  const cacheKey = `access_${token}`;
119
91
  if (this.cache) {
120
92
  const cached = this.cache.get(cacheKey);
121
- if (cached) {
93
+ if (cached && Date.now() - cached.timestamp <= this.cacheTTL) {
122
94
  if (!cached.valid) {
123
- throw new errors_utils_1.UnauthorizedError("Access token is invalid or expired");
95
+ throw new errors_utils_1.UnauthorizedError('Access token is invalid or expired');
124
96
  }
125
97
  return cached.payload;
126
98
  }
127
99
  }
128
100
  const decoded = (0, verify_1.verifyToken)(token, this.accessSecret);
129
101
  if (this.cache) {
130
- this.cache.set(cacheKey, { valid: true, payload: decoded });
102
+ this.cache.set(cacheKey, {
103
+ valid: true,
104
+ payload: decoded,
105
+ timestamp: Date.now(),
106
+ });
131
107
  }
132
108
  return decoded;
133
109
  }
134
110
  catch (error) {
135
- if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
111
+ if (error instanceof errors_utils_1.ValidationError ||
112
+ error instanceof errors_utils_1.UnauthorizedError) {
136
113
  throw error;
137
114
  }
138
- if (error instanceof Error && error.name === "TokenExpiredError") {
139
- throw new errors_utils_1.UnauthorizedError("Access token has expired");
115
+ if (error instanceof Error && error.name === 'TokenExpiredError') {
116
+ throw new errors_utils_1.UnauthorizedError('Access token has expired');
140
117
  }
141
- if (error instanceof Error && error.name === "JsonWebTokenError") {
142
- throw new errors_utils_1.UnauthorizedError("Access token is invalid");
118
+ if (error instanceof Error && error.name === 'JsonWebTokenError') {
119
+ throw new errors_utils_1.UnauthorizedError('Access token is invalid');
143
120
  }
144
- throw new errors_utils_1.UnauthorizedError("Failed to verify access token");
121
+ throw new errors_utils_1.UnauthorizedError('Failed to verify access token');
145
122
  }
146
123
  }
147
124
  /**
@@ -149,36 +126,37 @@ class JWTManager {
149
126
  */
150
127
  async verifyRefreshToken(token) {
151
128
  try {
152
- if (!token || typeof token !== "string") {
153
- throw new errors_utils_1.ValidationError("Refresh token must be a non-empty string");
129
+ if (!token || typeof token !== 'string') {
130
+ throw new errors_utils_1.ValidationError('Refresh token must be a non-empty string');
154
131
  }
155
132
  const cacheKey = `refresh_${token}`;
156
133
  if (this.cache) {
157
134
  const cached = this.cache.get(cacheKey);
158
135
  if (cached) {
159
136
  if (!cached.valid) {
160
- throw new errors_utils_1.UnauthorizedError("Refresh token is invalid or expired");
137
+ throw new errors_utils_1.UnauthorizedError('Refresh token is invalid or expired');
161
138
  }
162
139
  return cached.payload;
163
140
  }
164
141
  }
165
142
  const decoded = (0, verify_1.verifyToken)(token, this.refreshSecret);
166
143
  if (this.cache) {
167
- this.cache.set(cacheKey, { valid: true, payload: decoded });
144
+ this.cache.set(cacheKey, { valid: true, payload: decoded, timestamp: Date.now() });
168
145
  }
169
146
  return decoded;
170
147
  }
171
148
  catch (error) {
172
- if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
149
+ if (error instanceof errors_utils_1.ValidationError ||
150
+ error instanceof errors_utils_1.UnauthorizedError) {
173
151
  throw error;
174
152
  }
175
- if (error instanceof Error && error.name === "TokenExpiredError") {
176
- throw new errors_utils_1.UnauthorizedError("Refresh token has expired");
153
+ if (error instanceof Error && error.name === 'TokenExpiredError') {
154
+ throw new errors_utils_1.UnauthorizedError('Refresh token has expired');
177
155
  }
178
- if (error instanceof Error && error.name === "JsonWebTokenError") {
179
- throw new errors_utils_1.UnauthorizedError("Refresh token is invalid");
156
+ if (error instanceof Error && error.name === 'JsonWebTokenError') {
157
+ throw new errors_utils_1.UnauthorizedError('Refresh token is invalid');
180
158
  }
181
- throw new errors_utils_1.UnauthorizedError("Failed to verify refresh token");
159
+ throw new errors_utils_1.UnauthorizedError('Failed to verify refresh token');
182
160
  }
183
161
  }
184
162
  /**
@@ -186,8 +164,8 @@ class JWTManager {
186
164
  */
187
165
  decodeToken(token, complete = false) {
188
166
  try {
189
- if (!token || typeof token !== "string") {
190
- throw new errors_utils_1.ValidationError("Token must be a non-empty string");
167
+ if (!token || typeof token !== 'string') {
168
+ throw new errors_utils_1.ValidationError('Token must be a non-empty string');
191
169
  }
192
170
  return jsonwebtoken_1.default.decode(token, { complete });
193
171
  }
@@ -203,11 +181,11 @@ class JWTManager {
203
181
  */
204
182
  extractTokenFromHeader(authHeader) {
205
183
  try {
206
- if (!authHeader || typeof authHeader !== "string") {
184
+ if (!authHeader || typeof authHeader !== 'string') {
207
185
  return null;
208
186
  }
209
- const parts = authHeader.split(" ");
210
- if (parts.length !== 2 || parts[0] !== "Bearer") {
187
+ const parts = authHeader.split(' ');
188
+ if (parts.length !== 2 || parts[0] !== 'Bearer') {
211
189
  return null;
212
190
  }
213
191
  return parts[1];
@@ -221,7 +199,7 @@ class JWTManager {
221
199
  */
222
200
  validateToken(token, secret, options = {}) {
223
201
  try {
224
- if (!token || typeof token !== "string") {
202
+ if (!token || typeof token !== 'string') {
225
203
  return false;
226
204
  }
227
205
  const result = (0, verify_1.safeVerifyToken)(token, secret);
@@ -236,12 +214,12 @@ class JWTManager {
236
214
  */
237
215
  async rotateRefreshToken(oldToken) {
238
216
  try {
239
- if (!oldToken || typeof oldToken !== "string") {
240
- throw new errors_utils_1.ValidationError("Old refresh token must be a non-empty string");
217
+ if (!oldToken || typeof oldToken !== 'string') {
218
+ throw new errors_utils_1.ValidationError('Old refresh token must be a non-empty string');
241
219
  }
242
220
  const decoded = await this.verifyRefreshToken(oldToken);
243
- if (typeof decoded === "string") {
244
- throw new errors_utils_1.ValidationError("Invalid token payload — expected JWT payload object");
221
+ if (typeof decoded === 'string') {
222
+ throw new errors_utils_1.ValidationError('Invalid token payload — expected JWT payload object');
245
223
  }
246
224
  // Create new payload without issued/expired timestamps
247
225
  const payload = { ...decoded };
@@ -252,10 +230,11 @@ class JWTManager {
252
230
  return newToken;
253
231
  }
254
232
  catch (error) {
255
- if (error instanceof errors_utils_1.ValidationError || error instanceof errors_utils_1.UnauthorizedError) {
233
+ if (error instanceof errors_utils_1.ValidationError ||
234
+ error instanceof errors_utils_1.UnauthorizedError) {
256
235
  throw error;
257
236
  }
258
- throw new errors_utils_1.BadRequestError("Failed to rotate refresh token");
237
+ throw new errors_utils_1.BadRequestError('Failed to rotate refresh token');
259
238
  }
260
239
  }
261
240
  /**
@@ -301,18 +280,19 @@ class JWTManager {
301
280
  getCacheStats() {
302
281
  if (!this.cache)
303
282
  return null;
283
+ // Note: LRUCache doesn't expose internal size, so we return maxSize only
304
284
  return {
305
- size: this.cache.cache.size,
306
- maxSize: this.cache.maxSize
285
+ size: -1, // Size not available from LRUCache
286
+ maxSize: this.cache.maxSize,
307
287
  };
308
288
  }
309
289
  // Private helper methods
310
290
  validatePayload(payload) {
311
- if (!payload || typeof payload !== "object") {
312
- throw new errors_utils_1.ValidationError("Payload must be a non-null object");
291
+ if (!payload || typeof payload !== 'object') {
292
+ throw new errors_utils_1.ValidationError('Payload must be a non-null object');
313
293
  }
314
294
  if (Object.keys(payload).length === 0) {
315
- throw new errors_utils_1.ValidationError("Payload cannot be empty");
295
+ throw new errors_utils_1.ValidationError('Payload cannot be empty');
316
296
  }
317
297
  }
318
298
  }
@@ -6,16 +6,16 @@ const TIME_UNITS = {
6
6
  m: 60,
7
7
  h: 3600,
8
8
  d: 86400,
9
- w: 604800
9
+ w: 604800,
10
10
  };
11
11
  function parseDuration(input) {
12
- if (typeof input === "number")
12
+ if (typeof input === 'number')
13
13
  return input;
14
14
  const regex = /(\d+)\s*(s|m|h|d|w)/gi;
15
15
  let totalSeconds = 0;
16
16
  let match;
17
17
  while ((match = regex.exec(input)) !== null) {
18
- const value = parseInt(match[1], 10);
18
+ const value = Number.parseInt(match[1], 10);
19
19
  const unit = match[2].toLowerCase();
20
20
  if (!TIME_UNITS[unit]) {
21
21
  throw new Error(`Invalid time unit: ${unit}`);
@@ -1,2 +1,2 @@
1
- import { Secret, SignOptions } from "jsonwebtoken";
1
+ import { type Secret, type SignOptions } from 'jsonwebtoken';
2
2
  export declare const signToken: (payload: Record<string, unknown>, secret: Secret, expiresIn?: string | number, options?: SignOptions) => string;
@@ -6,21 +6,21 @@ const parseDuration_1 = require("./parseDuration");
6
6
  function getExpiryTimestamp(seconds) {
7
7
  return Math.floor(Date.now() / 1000) + seconds;
8
8
  }
9
- const signToken = (payload, secret, expiresIn = "1h", options = {}) => {
9
+ const signToken = (payload, secret, expiresIn = '1h', options = {}) => {
10
10
  const seconds = (0, parseDuration_1.parseDuration)(expiresIn);
11
11
  if (!seconds || seconds < 10) {
12
- throw new Error("Token expiry too small");
12
+ throw new Error('Token expiry too small');
13
13
  }
14
14
  const tokenPayload = {
15
- ...payload
15
+ ...payload,
16
16
  };
17
- if (!("exp" in payload))
17
+ if (!('exp' in payload))
18
18
  tokenPayload.exp = getExpiryTimestamp(seconds);
19
- if (!("iat" in payload))
19
+ if (!('iat' in payload))
20
20
  tokenPayload.iat = Math.floor(Date.now() / 1000);
21
21
  return (0, jsonwebtoken_1.sign)(tokenPayload, secret, {
22
- algorithm: "HS256",
23
- ...options
22
+ algorithm: 'HS256',
23
+ ...options,
24
24
  });
25
25
  };
26
26
  exports.signToken = signToken;
@@ -1,4 +1,4 @@
1
- import { JwtPayload } from "jsonwebtoken";
1
+ import type { JwtPayload } from 'jsonwebtoken';
2
2
  export interface AccessTokenBrand {
3
3
  readonly access: unique symbol;
4
4
  }
@@ -1,8 +1,8 @@
1
- import { JwtPayload } from "node_modules/@types/jsonwebtoken";
1
+ import type { JwtPayload } from 'node_modules/@types/jsonwebtoken';
2
2
  export interface TokenRequirements {
3
3
  requiredFields?: string[];
4
4
  forbiddenFields?: string[];
5
- validateTypes?: Record<string, "string" | "number" | "boolean">;
5
+ validateTypes?: Record<string, 'string' | 'number' | 'boolean'>;
6
6
  }
7
7
  export declare function validateTokenPayload(payload: Record<string, unknown>, rules?: TokenRequirements): {
8
8
  valid: true;