react-token-manager 1.0.2 → 1.0.4

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
@@ -19,7 +19,6 @@ import { configureTokenManager } from 'react-token-manager'
19
19
 
20
20
  configureTokenManager({
21
21
  storage: 'localStorage', // 'localStorage' | 'sessionStorage' | 'cookie'
22
- tokenKey: 'access_token', // default: 'access_token'
23
22
  })
24
23
  ```
25
24
  ## Using the Hook useTokenManager
@@ -28,18 +27,43 @@ configureTokenManager({
28
27
  import { useTokenManager } from 'react-token-manager'
29
28
 
30
29
  export default function Dashboard() {
31
- const { token, setToken, removeToken, isExpired, decode } = useTokenManager()
32
-
33
- const handleLogin = () => setToken('your.jwt.token.here')
34
- const handleLogout = () => removeToken()
30
+ const {
31
+ setTokens,
32
+ getTokens,
33
+ removeTokens,
34
+ clearAllTokens,
35
+ decodeToken,
36
+ isExpired
37
+ } = useTokenManager()
38
+
39
+ // Set multiple tokens at once
40
+ setTokens({
41
+ access_token: 'abc123',
42
+ refresh_token: 'xyz789',
43
+ })
44
+
45
+ // Get multiple tokens
46
+ const tokens = getTokens(['access_token', 'refresh_token'])
47
+ console.log(tokens.access_token) // 'abc123'
48
+ console.log(tokens.refresh_token) // 'xyz789'
49
+
50
+ // Decode a token
51
+ const payload = decodeToken(tokens.access_token!)
52
+
53
+ // Check if a token is expired
54
+ console.log(isExpired(tokens.access_token!))
55
+
56
+ // Remove multiple tokens
57
+ removeTokens(['access_token', 'refresh_token'])
58
+
59
+ // Clear all tracked tokens
60
+ clearAllTokens()
35
61
 
36
62
  return (
37
63
  <div>
38
- <p>Token: {token}</p>
39
- <p>Expired? {isExpired() ? 'Yes' : 'No'}</p>
40
- <p>Decoded Payload: {JSON.stringify(decode())}</p>
41
- <button onClick={handleLogin}>Login</button>
42
- <button onClick={handleLogout}>Logout</button>
64
+ <p>Access Token: {tokens.access_token}</p>
65
+ <p>Refresh Token: {tokens.refresh_token}</p>
66
+ <p>Decoded Payload: {JSON.stringify(payload)}</p>
43
67
  </div>
44
68
  )
45
69
  }
@@ -52,54 +76,65 @@ You can override storage or tokenKey per hook if needed.
52
76
  ```bash
53
77
  import { TokenManager } from 'react-token-manager'
54
78
 
55
- const manager = new TokenManager({ storage: 'cookie', tokenKey: 'access_token' })
79
+ const manager = new TokenManager({ storage: 'cookie' })
80
+
81
+ // Set multiple tokens
82
+ manager.set({
83
+ access_token: 'abc123',
84
+ refresh_token: 'xyz789',
85
+ })
86
+
87
+ // Get multiple tokens
88
+ const tokens = manager.get(['access_token', 'refresh_token'])
89
+ console.log(tokens.access_token) // 'abc123'
90
+
91
+ // Remove multiple tokens
92
+ manager.remove(['access_token', 'refresh_token'])
93
+
94
+ // Clear all tracked tokens
95
+ manager.clearAll()
96
+
97
+ // Decode and check expiration
98
+ console.log(manager.decode(tokens.access_token!))
99
+ console.log(manager.isExpired(tokens.access_token!))
56
100
 
57
- manager.set('your.jwt.token')
58
- console.log(manager.get())
59
- console.log(manager.decode()) // decoded JWT payload
60
- console.log(manager.isExpired())
61
- manager.remove()
62
101
  ```
63
102
 
64
103
  ## API Reference
65
104
 
66
- configureTokenManager(options: TokenManagerOptions)
67
-
68
105
  Set global options.
69
106
 
70
107
  ```bash
71
108
  {
72
109
  storage?: 'localStorage' | 'sessionStorage' | 'cookie';
73
- tokenKey?: string;
74
110
  }
75
111
 
112
+
76
113
  useTokenManager(options?: TokenManagerOptions)
77
114
 
78
115
  Returns:
116
+ setTokens(tokens: Record<string, string>) // Set multiple tokens
79
117
 
80
- token: string | null current token
118
+ getTokens(keys: string | string[]) // Get multiple tokens
81
119
 
82
- setToken(value: string) set a new token
120
+ removeTokens(keys: string | string[]) // Remove multiple tokens
83
121
 
84
- removeToken() remove the token
122
+ decodeToken<T = unknown>(token: string) // Decode a single token
85
123
 
86
- isExpired(): boolean check expiration
124
+ isExpired(token: string) // Check if a token is expired
87
125
 
88
- decode<T>(): T | null — decode JWT payload
89
126
 
90
127
  TokenManager Class Methods
128
+ set(tokens: Record<string, string>) // Store multiple tokens
91
129
 
92
- set(token: string) store token
130
+ get(keys: string | string[]) // Retrieve multiple tokens
93
131
 
94
- get(): string | null retrieve token
132
+ remove(keys: string | string[]) // Delete multiple tokens
95
133
 
96
- remove() delete token
134
+ decode<T = unknown>(token: string) // Decode a single token
97
135
 
98
- decode<T = unknown>(): T | null decode JWT payload
136
+ isExpired(token: string) // Check if a token is expired
99
137
 
100
- isExpired(): boolean — check if token is expired
101
-
102
- getValid(): string | null — get token only if valid
103
138
 
104
139
  ```
105
140
 
@@ -108,25 +143,31 @@ TokenManager Class Methods
108
143
  Multiple Tokens
109
144
 
110
145
  ```bash
111
- const { token: accessToken, setToken: setAccess } = useTokenManager({ tokenKey: 'access_token' })
112
- const { token: refreshToken, setToken: setRefresh } = useTokenManager({ tokenKey: 'refresh_token' })
146
+ const { setTokens, getTokens } = useTokenManager()
147
+
148
+ setTokens({
149
+ access_token: 'abc',
150
+ refresh_token: 'xyz',
151
+ })
113
152
 
114
- setAccess('abc')
115
- setRefresh('xyz')
153
+ const tokens = getTokens(['access_token', 'refresh_token'])
154
+ console.log(tokens.access_token) // 'abc'
155
+ console.log(tokens.refresh_token) // 'xyz'
116
156
  ```
117
157
 
118
158
  ##Using Cookies
119
159
  ```bash
120
- configureTokenManager({ storage: 'cookie', tokenKey: 'access_token' })
160
+ configureTokenManager({ storage: 'cookie' })
121
161
  ```
122
162
 
123
163
  Checking Expiry Before API Call
124
164
 
125
165
  ```bash
126
- const manager = useTokenManager()
166
+ const { getTokens, isExpired } = useTokenManager()
167
+ const { access_token } = getTokens(['access_token'])
127
168
 
128
- if (!manager.isExpired()) {
129
- callApi(manager.token)
169
+ if (!isExpired(access_token!)) {
170
+ callApi(access_token)
130
171
  }
131
172
  ```
132
173
 
package/dist/index.d.mts CHANGED
@@ -1,28 +1,34 @@
1
1
  type StorageType = 'localStorage' | 'sessionStorage' | 'cookie';
2
2
  interface TokenManagerOptions {
3
3
  storage?: StorageType;
4
- tokenKey?: string;
5
4
  }
6
5
  declare const configureTokenManager: (options: TokenManagerOptions) => void;
7
6
  declare class TokenManager {
8
7
  private storage;
9
- private tokenKey;
10
8
  constructor(options?: TokenManagerOptions);
11
- set(token: string): void;
12
- get(): string | null;
13
- remove(): void;
14
- decode<T = unknown>(): T | null;
15
- isExpired(): boolean;
16
- getValid(): string | null;
9
+ /** Set multiple tokens at once */
10
+ set(tokens: Record<string, string>): void;
11
+ /** Get single token by key or all tokens in an array of keys */
12
+ get(keys: string | string[]): Record<string, string | null>;
13
+ /** Remove multiple tokens by keys */
14
+ remove(keys: string | string[]): void;
15
+ /** Decode a single token by key */
16
+ decode<T = unknown>(token: string): T | null;
17
+ /** Check if a token is expired */
18
+ isExpired(token: string): boolean;
17
19
  }
18
20
 
19
- interface UseTokenManagerReturn {
20
- token: string | null;
21
- setToken: (value: string) => void;
22
- removeToken: () => void;
23
- isExpired: () => boolean;
24
- decode: <T = unknown>() => T | null;
25
- }
26
- declare const useTokenManager: (options?: TokenManagerOptions) => UseTokenManagerReturn;
21
+ declare const useTokenManager: () => {
22
+ /** Set multiple tokens */
23
+ setTokens: (tokens: Record<string, string>) => void;
24
+ /** Get multiple tokens by keys */
25
+ getTokens: (keys: string | string[]) => Record<string, string | null>;
26
+ /** Remove multiple tokens by keys */
27
+ removeTokens: (keys: string | string[]) => void;
28
+ /** Decode a single token */
29
+ decodeToken: <T = unknown>(token: string) => T | null;
30
+ /** Check expiration of a single token */
31
+ isExpired: (token: string) => boolean;
32
+ };
27
33
 
28
- export { type StorageType, TokenManager, type TokenManagerOptions, type UseTokenManagerReturn, configureTokenManager, useTokenManager };
34
+ export { type StorageType, TokenManager, type TokenManagerOptions, configureTokenManager, useTokenManager };
package/dist/index.d.ts CHANGED
@@ -1,28 +1,34 @@
1
1
  type StorageType = 'localStorage' | 'sessionStorage' | 'cookie';
2
2
  interface TokenManagerOptions {
3
3
  storage?: StorageType;
4
- tokenKey?: string;
5
4
  }
6
5
  declare const configureTokenManager: (options: TokenManagerOptions) => void;
7
6
  declare class TokenManager {
8
7
  private storage;
9
- private tokenKey;
10
8
  constructor(options?: TokenManagerOptions);
11
- set(token: string): void;
12
- get(): string | null;
13
- remove(): void;
14
- decode<T = unknown>(): T | null;
15
- isExpired(): boolean;
16
- getValid(): string | null;
9
+ /** Set multiple tokens at once */
10
+ set(tokens: Record<string, string>): void;
11
+ /** Get single token by key or all tokens in an array of keys */
12
+ get(keys: string | string[]): Record<string, string | null>;
13
+ /** Remove multiple tokens by keys */
14
+ remove(keys: string | string[]): void;
15
+ /** Decode a single token by key */
16
+ decode<T = unknown>(token: string): T | null;
17
+ /** Check if a token is expired */
18
+ isExpired(token: string): boolean;
17
19
  }
18
20
 
19
- interface UseTokenManagerReturn {
20
- token: string | null;
21
- setToken: (value: string) => void;
22
- removeToken: () => void;
23
- isExpired: () => boolean;
24
- decode: <T = unknown>() => T | null;
25
- }
26
- declare const useTokenManager: (options?: TokenManagerOptions) => UseTokenManagerReturn;
21
+ declare const useTokenManager: () => {
22
+ /** Set multiple tokens */
23
+ setTokens: (tokens: Record<string, string>) => void;
24
+ /** Get multiple tokens by keys */
25
+ getTokens: (keys: string | string[]) => Record<string, string | null>;
26
+ /** Remove multiple tokens by keys */
27
+ removeTokens: (keys: string | string[]) => void;
28
+ /** Decode a single token */
29
+ decodeToken: <T = unknown>(token: string) => T | null;
30
+ /** Check expiration of a single token */
31
+ isExpired: (token: string) => boolean;
32
+ };
27
33
 
28
- export { type StorageType, TokenManager, type TokenManagerOptions, type UseTokenManagerReturn, configureTokenManager, useTokenManager };
34
+ export { type StorageType, TokenManager, type TokenManagerOptions, configureTokenManager, useTokenManager };
package/dist/index.js CHANGED
@@ -40,8 +40,7 @@ module.exports = __toCommonJS(index_exports);
40
40
  var jwtDecodeModule = __toESM(require("jwt-decode"));
41
41
  var jwtDecode = jwtDecodeModule.default || jwtDecodeModule;
42
42
  var globalOptions = {
43
- storage: "localStorage",
44
- tokenKey: "access_token"
43
+ storage: "localStorage"
45
44
  };
46
45
  var configureTokenManager = (options) => {
47
46
  globalOptions = { ...globalOptions, ...options };
@@ -50,26 +49,42 @@ var TokenManager = class {
50
49
  constructor(options) {
51
50
  const opts = options || globalOptions;
52
51
  this.storage = opts.storage || "localStorage";
53
- this.tokenKey = opts.tokenKey || "access_token";
54
52
  }
55
- set(token) {
56
- if (this.storage === "localStorage") localStorage.setItem(this.tokenKey, token);
57
- else if (this.storage === "sessionStorage") sessionStorage.setItem(this.tokenKey, token);
58
- else document.cookie = `${this.tokenKey}=${token}; path=/`;
53
+ /** Set multiple tokens at once */
54
+ set(tokens) {
55
+ Object.entries(tokens).forEach(([key, value]) => {
56
+ if (this.storage === "localStorage") localStorage.setItem(key, value);
57
+ else if (this.storage === "sessionStorage") sessionStorage.setItem(key, value);
58
+ else document.cookie = `${key}=${value}; path=/`;
59
+ });
59
60
  }
60
- get() {
61
- if (this.storage === "localStorage") return localStorage.getItem(this.tokenKey);
62
- if (this.storage === "sessionStorage") return sessionStorage.getItem(this.tokenKey);
63
- const match = document.cookie.match(new RegExp("(^| )" + this.tokenKey + "=([^;]+)"));
64
- return match ? match[2] : null;
61
+ /** Get single token by key or all tokens in an array of keys */
62
+ get(keys) {
63
+ const keyArray = Array.isArray(keys) ? keys : [keys];
64
+ const result = {};
65
+ keyArray.forEach((key) => {
66
+ let value = null;
67
+ if (this.storage === "localStorage") value = localStorage.getItem(key);
68
+ else if (this.storage === "sessionStorage") value = sessionStorage.getItem(key);
69
+ else {
70
+ const match = document.cookie.match(new RegExp("(^| )" + key + "=([^;]+)"));
71
+ value = match ? match[2] : null;
72
+ }
73
+ result[key] = value;
74
+ });
75
+ return result;
65
76
  }
66
- remove() {
67
- if (this.storage === "localStorage") localStorage.removeItem(this.tokenKey);
68
- else if (this.storage === "sessionStorage") sessionStorage.removeItem(this.tokenKey);
69
- else document.cookie = `${this.tokenKey}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
77
+ /** Remove multiple tokens by keys */
78
+ remove(keys) {
79
+ const keyArray = Array.isArray(keys) ? keys : [keys];
80
+ keyArray.forEach((key) => {
81
+ if (this.storage === "localStorage") localStorage.removeItem(key);
82
+ else if (this.storage === "sessionStorage") sessionStorage.removeItem(key);
83
+ else document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
84
+ });
70
85
  }
71
- decode() {
72
- const token = this.get();
86
+ /** Decode a single token by key */
87
+ decode(token) {
73
88
  if (!token) return null;
74
89
  try {
75
90
  return jwtDecode(token);
@@ -77,38 +92,29 @@ var TokenManager = class {
77
92
  return null;
78
93
  }
79
94
  }
80
- isExpired() {
81
- const decoded = this.decode();
95
+ /** Check if a token is expired */
96
+ isExpired(token) {
97
+ const decoded = this.decode(token);
82
98
  if (!decoded || !decoded.exp) return true;
83
99
  return Date.now() >= decoded.exp * 1e3;
84
100
  }
85
- getValid() {
86
- return this.isExpired() ? null : this.get();
87
- }
88
101
  };
89
102
 
90
103
  // src/hook.ts
91
104
  var import_react = require("react");
92
- var useTokenManager = (options) => {
93
- const manager = new TokenManager(options);
94
- const [token, setTokenState] = (0, import_react.useState)(null);
95
- (0, import_react.useEffect)(() => {
96
- setTokenState(manager.getValid());
97
- }, []);
98
- const setToken = (value) => {
99
- manager.set(value);
100
- setTokenState(value);
101
- };
102
- const removeToken = () => {
103
- manager.remove();
104
- setTokenState(null);
105
- };
105
+ var useTokenManager = () => {
106
+ const manager = (0, import_react.useMemo)(() => new TokenManager(), []);
106
107
  return {
107
- token,
108
- setToken,
109
- removeToken,
110
- isExpired: () => manager.isExpired(),
111
- decode: () => manager.decode()
108
+ /** Set multiple tokens */
109
+ setTokens: (tokens) => manager.set(tokens),
110
+ /** Get multiple tokens by keys */
111
+ getTokens: (keys) => manager.get(keys),
112
+ /** Remove multiple tokens by keys */
113
+ removeTokens: (keys) => manager.remove(keys),
114
+ /** Decode a single token */
115
+ decodeToken: (token) => manager.decode(token),
116
+ /** Check expiration of a single token */
117
+ isExpired: (token) => manager.isExpired(token)
112
118
  };
113
119
  };
114
120
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -2,8 +2,7 @@
2
2
  import * as jwtDecodeModule from "jwt-decode";
3
3
  var jwtDecode = jwtDecodeModule.default || jwtDecodeModule;
4
4
  var globalOptions = {
5
- storage: "localStorage",
6
- tokenKey: "access_token"
5
+ storage: "localStorage"
7
6
  };
8
7
  var configureTokenManager = (options) => {
9
8
  globalOptions = { ...globalOptions, ...options };
@@ -12,26 +11,42 @@ var TokenManager = class {
12
11
  constructor(options) {
13
12
  const opts = options || globalOptions;
14
13
  this.storage = opts.storage || "localStorage";
15
- this.tokenKey = opts.tokenKey || "access_token";
16
14
  }
17
- set(token) {
18
- if (this.storage === "localStorage") localStorage.setItem(this.tokenKey, token);
19
- else if (this.storage === "sessionStorage") sessionStorage.setItem(this.tokenKey, token);
20
- else document.cookie = `${this.tokenKey}=${token}; path=/`;
15
+ /** Set multiple tokens at once */
16
+ set(tokens) {
17
+ Object.entries(tokens).forEach(([key, value]) => {
18
+ if (this.storage === "localStorage") localStorage.setItem(key, value);
19
+ else if (this.storage === "sessionStorage") sessionStorage.setItem(key, value);
20
+ else document.cookie = `${key}=${value}; path=/`;
21
+ });
21
22
  }
22
- get() {
23
- if (this.storage === "localStorage") return localStorage.getItem(this.tokenKey);
24
- if (this.storage === "sessionStorage") return sessionStorage.getItem(this.tokenKey);
25
- const match = document.cookie.match(new RegExp("(^| )" + this.tokenKey + "=([^;]+)"));
26
- return match ? match[2] : null;
23
+ /** Get single token by key or all tokens in an array of keys */
24
+ get(keys) {
25
+ const keyArray = Array.isArray(keys) ? keys : [keys];
26
+ const result = {};
27
+ keyArray.forEach((key) => {
28
+ let value = null;
29
+ if (this.storage === "localStorage") value = localStorage.getItem(key);
30
+ else if (this.storage === "sessionStorage") value = sessionStorage.getItem(key);
31
+ else {
32
+ const match = document.cookie.match(new RegExp("(^| )" + key + "=([^;]+)"));
33
+ value = match ? match[2] : null;
34
+ }
35
+ result[key] = value;
36
+ });
37
+ return result;
27
38
  }
28
- remove() {
29
- if (this.storage === "localStorage") localStorage.removeItem(this.tokenKey);
30
- else if (this.storage === "sessionStorage") sessionStorage.removeItem(this.tokenKey);
31
- else document.cookie = `${this.tokenKey}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
39
+ /** Remove multiple tokens by keys */
40
+ remove(keys) {
41
+ const keyArray = Array.isArray(keys) ? keys : [keys];
42
+ keyArray.forEach((key) => {
43
+ if (this.storage === "localStorage") localStorage.removeItem(key);
44
+ else if (this.storage === "sessionStorage") sessionStorage.removeItem(key);
45
+ else document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
46
+ });
32
47
  }
33
- decode() {
34
- const token = this.get();
48
+ /** Decode a single token by key */
49
+ decode(token) {
35
50
  if (!token) return null;
36
51
  try {
37
52
  return jwtDecode(token);
@@ -39,38 +54,29 @@ var TokenManager = class {
39
54
  return null;
40
55
  }
41
56
  }
42
- isExpired() {
43
- const decoded = this.decode();
57
+ /** Check if a token is expired */
58
+ isExpired(token) {
59
+ const decoded = this.decode(token);
44
60
  if (!decoded || !decoded.exp) return true;
45
61
  return Date.now() >= decoded.exp * 1e3;
46
62
  }
47
- getValid() {
48
- return this.isExpired() ? null : this.get();
49
- }
50
63
  };
51
64
 
52
65
  // src/hook.ts
53
- import { useEffect, useState } from "react";
54
- var useTokenManager = (options) => {
55
- const manager = new TokenManager(options);
56
- const [token, setTokenState] = useState(null);
57
- useEffect(() => {
58
- setTokenState(manager.getValid());
59
- }, []);
60
- const setToken = (value) => {
61
- manager.set(value);
62
- setTokenState(value);
63
- };
64
- const removeToken = () => {
65
- manager.remove();
66
- setTokenState(null);
67
- };
66
+ import { useMemo } from "react";
67
+ var useTokenManager = () => {
68
+ const manager = useMemo(() => new TokenManager(), []);
68
69
  return {
69
- token,
70
- setToken,
71
- removeToken,
72
- isExpired: () => manager.isExpired(),
73
- decode: () => manager.decode()
70
+ /** Set multiple tokens */
71
+ setTokens: (tokens) => manager.set(tokens),
72
+ /** Get multiple tokens by keys */
73
+ getTokens: (keys) => manager.get(keys),
74
+ /** Remove multiple tokens by keys */
75
+ removeTokens: (keys) => manager.remove(keys),
76
+ /** Decode a single token */
77
+ decodeToken: (token) => manager.decode(token),
78
+ /** Check expiration of a single token */
79
+ isExpired: (token) => manager.isExpired(token)
74
80
  };
75
81
  };
76
82
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-token-manager",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A simple React library to manage JWT tokens",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/core.ts CHANGED
@@ -1,75 +1,121 @@
1
1
  import type { JwtPayload } from 'jwt-decode'
2
2
  import * as jwtDecodeModule from 'jwt-decode'
3
3
 
4
- // Properly type the callable function
5
- const jwtDecode: <T = unknown>(token: string) => T =
4
+ const jwtDecode: <T = unknown>(token: string) => T =
6
5
  (jwtDecodeModule as any).default || jwtDecodeModule
7
6
 
8
-
9
7
  export type StorageType = 'localStorage' | 'sessionStorage' | 'cookie'
10
8
 
11
9
  export interface TokenManagerOptions {
12
10
  storage?: StorageType
13
- tokenKey?: string
14
11
  }
15
12
 
16
- // ---------------- Global configuration ----------------
17
13
  let globalOptions: TokenManagerOptions = {
18
14
  storage: 'localStorage',
19
- tokenKey: 'access_token',
20
15
  }
21
16
 
22
17
  export const configureTokenManager = (options: TokenManagerOptions) => {
23
18
  globalOptions = { ...globalOptions, ...options }
24
19
  }
25
20
 
26
- // ---------------- TokenManager Class ----------------
27
21
  export class TokenManager {
28
22
  private storage: StorageType
29
- private tokenKey: string
23
+ private trackedKeys: Set<string> = new Set()
30
24
 
31
25
  constructor(options?: TokenManagerOptions) {
32
26
  const opts = options || globalOptions
33
27
  this.storage = opts.storage || 'localStorage'
34
- this.tokenKey = opts.tokenKey || 'access_token'
35
28
  }
36
29
 
37
- set(token: string) {
38
- if (this.storage === 'localStorage') localStorage.setItem(this.tokenKey, token)
39
- else if (this.storage === 'sessionStorage') sessionStorage.setItem(this.tokenKey, token)
40
- else document.cookie = `${this.tokenKey}=${token}; path=/`
30
+ /** Set multiple tokens at once */
31
+ set(tokens: Record<string, string>) {
32
+ Object.entries(tokens).forEach(([key, value]) => {
33
+ this.trackedKeys.add(key)
34
+
35
+ if (this.storage === 'localStorage') localStorage.setItem(key, value)
36
+ else if (this.storage === 'sessionStorage') sessionStorage.setItem(key, value)
37
+ else document.cookie = `${key}=${value}; path=/`
38
+ })
41
39
  }
42
40
 
43
- get(): string | null {
44
- if (this.storage === 'localStorage') return localStorage.getItem(this.tokenKey)
45
- if (this.storage === 'sessionStorage') return sessionStorage.getItem(this.tokenKey)
46
- const match = document.cookie.match(new RegExp('(^| )' + this.tokenKey + '=([^;]+)'))
47
- return match ? match[2] : null
41
+ /** Get token(s) */
42
+ get(keys: string | string[]): Record<string, string | null> {
43
+ const keyArray = Array.isArray(keys) ? keys : [keys]
44
+ const result: Record<string, string | null> = {}
45
+
46
+ keyArray.forEach((key) => {
47
+ let value: string | null = null
48
+
49
+ if (this.storage === 'localStorage') value = localStorage.getItem(key)
50
+ else if (this.storage === 'sessionStorage') value = sessionStorage.getItem(key)
51
+ else {
52
+ const match = document.cookie.match(
53
+ new RegExp('(^| )' + key + '=([^;]+)')
54
+ )
55
+ value = match ? match[2] : null
56
+ }
57
+
58
+ result[key] = value
59
+ })
60
+
61
+ return result
62
+ }
63
+
64
+ /** Remove specific tokens */
65
+ remove(keys: string | string[]) {
66
+ const keyArray = Array.isArray(keys) ? keys : [keys]
67
+
68
+ keyArray.forEach((key) => {
69
+ if (this.storage === 'localStorage') localStorage.removeItem(key)
70
+ else if (this.storage === 'sessionStorage') sessionStorage.removeItem(key)
71
+ else
72
+ document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
73
+
74
+ this.trackedKeys.delete(key)
75
+ })
48
76
  }
49
77
 
50
- remove() {
51
- if (this.storage === 'localStorage') localStorage.removeItem(this.tokenKey)
52
- else if (this.storage === 'sessionStorage') sessionStorage.removeItem(this.tokenKey)
53
- else document.cookie = `${this.tokenKey}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
78
+ /** Clear all tracked auth tokens */
79
+ clearAll() {
80
+ this.trackedKeys.forEach((key) => {
81
+ if (this.storage === 'localStorage') localStorage.removeItem(key)
82
+ else if (this.storage === 'sessionStorage') sessionStorage.removeItem(key)
83
+ else
84
+ document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`
85
+ })
86
+
87
+ this.trackedKeys.clear()
54
88
  }
55
89
 
56
- decode<T = unknown>(): T | null {
57
- const token = this.get()
90
+ /** Decode token */
91
+ decode<T = unknown>(token: string): T | null {
58
92
  if (!token) return null
59
93
  try {
60
- return jwtDecode<T>(token) // Now callable
94
+ return jwtDecode<T>(token)
61
95
  } catch {
62
96
  return null
63
97
  }
64
98
  }
65
99
 
66
- isExpired(): boolean {
67
- const decoded = this.decode<JwtPayload>()
100
+ /** Check if a token is expired
101
+ * If no token is provided, defaults to checking 'access_token'
102
+ */
103
+ isExpired(token?: string): boolean {
104
+ let tokenToCheck = token
105
+
106
+ // If no token passed, try to get access_token
107
+ if (!tokenToCheck) {
108
+ const stored = this.get('access_token')
109
+ tokenToCheck = stored['access_token'] || undefined
110
+ }
111
+
112
+ if (!tokenToCheck) return true
113
+
114
+ const decoded = this.decode<JwtPayload>(tokenToCheck)
115
+
68
116
  if (!decoded || !decoded.exp) return true
117
+
69
118
  return Date.now() >= decoded.exp * 1000
70
119
  }
71
120
 
72
- getValid(): string | null {
73
- return this.isExpired() ? null : this.get()
74
- }
75
121
  }
package/src/hook.ts CHANGED
@@ -1,40 +1,25 @@
1
- import { useEffect, useState } from 'react'
2
- import { TokenManager, TokenManagerOptions } from './core'
1
+ import { useMemo } from 'react'
2
+ import { TokenManager } from './core'
3
3
 
4
- export interface UseTokenManagerReturn {
5
- token: string | null
6
- setToken: (value: string) => void
7
- removeToken: () => void
8
- isExpired: () => boolean
9
- decode: <T = unknown>() => T | null
10
- }
4
+ export const useTokenManager = () => {
5
+ const manager = useMemo(() => new TokenManager(), [])
11
6
 
12
- export const useTokenManager = (
13
- options?: TokenManagerOptions
14
- ): UseTokenManagerReturn => {
15
- const manager = new TokenManager(options)
7
+ return {
8
+ /** Set multiple tokens */
9
+ setTokens: (tokens: Record<string, string>) => manager.set(tokens),
16
10
 
17
- const [token, setTokenState] = useState<string | null>(null)
11
+ /** Get multiple tokens by keys */
12
+ getTokens: (keys: string | string[]) => manager.get(keys),
18
13
 
19
- useEffect(() => {
20
- setTokenState(manager.getValid())
21
- }, [])
14
+ /** Remove multiple tokens by keys */
15
+ removeTokens: (keys: string | string[]) => manager.remove(keys),
22
16
 
23
- const setToken = (value: string) => {
24
- manager.set(value)
25
- setTokenState(value)
26
- }
17
+ clearTokens: () => manager.clearAll(),
27
18
 
28
- const removeToken = () => {
29
- manager.remove()
30
- setTokenState(null)
31
- }
19
+ /** Decode a single token */
20
+ decodeToken: <T = unknown>(token: string) => manager.decode<T>(token),
32
21
 
33
- return {
34
- token,
35
- setToken,
36
- removeToken,
37
- isExpired: () => manager.isExpired(),
38
- decode: <T = unknown>() => manager.decode<T>(),
22
+ /** Check expiration of a single token */
23
+ isExpired: (token: string) => manager.isExpired(token),
39
24
  }
40
25
  }
@@ -1,38 +0,0 @@
1
- import { useEffect, useState, useMemo } from 'react'
2
- import { TokenManager } from './core'
3
-
4
- export interface UseTokenManagerReturn {
5
- token: string | null
6
- setToken: (value: string) => void
7
- removeToken: () => void
8
- isExpired: () => boolean
9
- decode: <T = unknown>() => T | null
10
- }
11
-
12
- export const useTokenManager = (): UseTokenManagerReturn => {
13
- const manager = useMemo(() => new TokenManager(), [])
14
-
15
- const [token, setTokenState] = useState<string | null>(null)
16
-
17
- useEffect(() => {
18
- setTokenState(manager.getValid())
19
- }, [manager])
20
-
21
- const setToken = (value: string) => {
22
- manager.set(value)
23
- setTokenState(value)
24
- }
25
-
26
- const removeToken = () => {
27
- manager.remove()
28
- setTokenState(null)
29
- }
30
-
31
- return {
32
- token,
33
- setToken,
34
- removeToken,
35
- isExpired: () => manager.isExpired(),
36
- decode: <T = unknown>() => manager.decode<T>(),
37
- }
38
- }