nextauthz 1.2.0 → 1.2.3

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/dist/index.d.mts CHANGED
@@ -2,40 +2,45 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default from 'react';
4
4
 
5
- type AuthContextType<UserType> = {
5
+ type User$1 = {
6
+ [key: string]: any;
7
+ };
8
+
9
+ type AuthContextType<UserType extends User$1 = User$1> = {
6
10
  user: UserType | null;
7
- login: (tokens: Record<string, string>, user: UserType) => void;
11
+ role: string | null;
12
+ isAuthenticated: boolean;
13
+ login: (tokens: Record<string, string>, userData: UserType, role: string) => void;
8
14
  logout: () => void;
9
- setUser: (user: UserType) => void;
10
- loading: boolean;
11
- error: Error | null;
15
+ setUser: (user: UserType | null) => void;
16
+ tokenKey: string;
12
17
  };
13
18
 
14
19
  type AuthGuardProps = {
15
20
  children: React__default.ReactNode;
16
21
  redirectTo?: string;
17
- tokenKey?: string;
18
- refreshToken?: () => Promise<string | null>;
22
+ fallback?: React__default.ReactNode;
19
23
  };
20
- declare const AuthGuard: ({ children, redirectTo, tokenKey, refreshToken, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
24
+ declare const AuthGuard: ({ children, redirectTo, fallback, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
21
25
 
22
26
  type RoleGuardProps = {
23
27
  children: React__default.ReactNode;
24
28
  allowedRoles: string[];
25
29
  redirectTo?: string;
30
+ fallback?: React__default.ReactNode;
26
31
  };
27
- declare const RoleGuard: ({ children, allowedRoles, redirectTo, }: RoleGuardProps) => react_jsx_runtime.JSX.Element;
32
+ declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: RoleGuardProps) => react_jsx_runtime.JSX.Element | null;
28
33
 
29
- type User = any;
30
- declare function createAppAuth(storage?: 'localStorage' | 'sessionStorage' | 'cookie'): {
34
+ type User = Record<string, any>;
35
+ /**
36
+ * Factory to create isolated auth instance
37
+ */
38
+ declare function createAppAuth(storage?: 'localStorage' | 'sessionStorage' | 'cookie', tokenKey?: string): {
31
39
  AuthProvider: ({ children }: {
32
40
  children: React.ReactNode;
33
41
  }) => react_jsx_runtime.JSX.Element;
34
- useAuth: () => AuthContextType<any>;
42
+ useAuth: () => AuthContextType<User$1>;
43
+ tokenKey: string;
35
44
  };
36
- declare const AuthProvider: ({ children }: {
37
- children: React.ReactNode;
38
- }) => react_jsx_runtime.JSX.Element;
39
- declare const useAuth: () => AuthContextType<any>;
40
45
 
41
- export { AuthGuard, AuthProvider, RoleGuard, type User, createAppAuth, useAuth };
46
+ export { AuthGuard, RoleGuard, type User, createAppAuth };
package/dist/index.d.ts CHANGED
@@ -2,40 +2,45 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default from 'react';
4
4
 
5
- type AuthContextType<UserType> = {
5
+ type User$1 = {
6
+ [key: string]: any;
7
+ };
8
+
9
+ type AuthContextType<UserType extends User$1 = User$1> = {
6
10
  user: UserType | null;
7
- login: (tokens: Record<string, string>, user: UserType) => void;
11
+ role: string | null;
12
+ isAuthenticated: boolean;
13
+ login: (tokens: Record<string, string>, userData: UserType, role: string) => void;
8
14
  logout: () => void;
9
- setUser: (user: UserType) => void;
10
- loading: boolean;
11
- error: Error | null;
15
+ setUser: (user: UserType | null) => void;
16
+ tokenKey: string;
12
17
  };
13
18
 
14
19
  type AuthGuardProps = {
15
20
  children: React__default.ReactNode;
16
21
  redirectTo?: string;
17
- tokenKey?: string;
18
- refreshToken?: () => Promise<string | null>;
22
+ fallback?: React__default.ReactNode;
19
23
  };
20
- declare const AuthGuard: ({ children, redirectTo, tokenKey, refreshToken, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
24
+ declare const AuthGuard: ({ children, redirectTo, fallback, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
21
25
 
22
26
  type RoleGuardProps = {
23
27
  children: React__default.ReactNode;
24
28
  allowedRoles: string[];
25
29
  redirectTo?: string;
30
+ fallback?: React__default.ReactNode;
26
31
  };
27
- declare const RoleGuard: ({ children, allowedRoles, redirectTo, }: RoleGuardProps) => react_jsx_runtime.JSX.Element;
32
+ declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: RoleGuardProps) => react_jsx_runtime.JSX.Element | null;
28
33
 
29
- type User = any;
30
- declare function createAppAuth(storage?: 'localStorage' | 'sessionStorage' | 'cookie'): {
34
+ type User = Record<string, any>;
35
+ /**
36
+ * Factory to create isolated auth instance
37
+ */
38
+ declare function createAppAuth(storage?: 'localStorage' | 'sessionStorage' | 'cookie', tokenKey?: string): {
31
39
  AuthProvider: ({ children }: {
32
40
  children: React.ReactNode;
33
41
  }) => react_jsx_runtime.JSX.Element;
34
- useAuth: () => AuthContextType<any>;
42
+ useAuth: () => AuthContextType<User$1>;
43
+ tokenKey: string;
35
44
  };
36
- declare const AuthProvider: ({ children }: {
37
- children: React.ReactNode;
38
- }) => react_jsx_runtime.JSX.Element;
39
- declare const useAuth: () => AuthContextType<any>;
40
45
 
41
- export { AuthGuard, AuthProvider, RoleGuard, type User, createAppAuth, useAuth };
46
+ export { AuthGuard, RoleGuard, type User, createAppAuth };
package/dist/index.js CHANGED
@@ -22,10 +22,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
24
  AuthGuard: () => AuthGuard_default,
25
- AuthProvider: () => AuthProvider,
26
25
  RoleGuard: () => RoleGuard_default,
27
- createAppAuth: () => createAppAuth,
28
- useAuth: () => useAuth
26
+ createAppAuth: () => createAppAuth
29
27
  });
30
28
  module.exports = __toCommonJS(index_exports);
31
29
 
@@ -37,139 +35,126 @@ var import_react_token_manager = require("react-token-manager");
37
35
  var import_zustand = require("zustand");
38
36
  var useAuthStore = (0, import_zustand.create)((set) => ({
39
37
  user: null,
38
+ role: null,
40
39
  isAuthenticated: false,
41
40
  isAuthChecked: false,
41
+ loading: true,
42
42
  error: null,
43
43
  setUser: (user) => set({ user }),
44
+ setRole: (role) => set({ role }),
44
45
  setAuth: (isAuth) => set({ isAuthenticated: isAuth }),
45
46
  setAuthChecked: (checked) => set({ isAuthChecked: checked }),
47
+ setLoading: (loading) => set({ loading }),
46
48
  setError: (err) => set({ error: err }),
47
49
  resetAuth: () => set({
48
50
  user: null,
51
+ role: null,
49
52
  isAuthenticated: false,
50
53
  isAuthChecked: false,
54
+ loading: false,
51
55
  error: null
52
56
  })
53
57
  }));
54
58
 
55
59
  // src/AuthProvider.tsx
56
60
  var import_jsx_runtime = require("react/jsx-runtime");
57
- function createAuthContext(options) {
58
- const AuthContext = (0, import_react.createContext)(null);
59
- const AuthProvider2 = ({ children }) => {
60
- const storageType = options?.storage || "cookie";
61
+ function createAuthContext(option) {
62
+ const AuthContext = (0, import_react.createContext)(void 0);
63
+ const AuthProvider = ({ children }) => {
64
+ const storage = option?.storage ?? "cookie";
65
+ const tokenKey = option?.tokenKey ?? "access_token";
61
66
  (0, import_react.useEffect)(() => {
62
- (0, import_react_token_manager.configureTokenManager)({ storage: storageType });
63
- }, [storageType]);
67
+ (0, import_react_token_manager.configureTokenManager)({ storage });
68
+ }, [storage]);
64
69
  const manager = (0, import_react_token_manager.useTokenManager)();
65
- const [loading, setLoading] = (0, import_react.useState)(true);
66
- const rawUser = useAuthStore((state) => state.user);
67
- const error = useAuthStore((state) => state.error);
68
- const user = rawUser;
70
+ const {
71
+ user,
72
+ role,
73
+ setUser,
74
+ setRole,
75
+ resetAuth,
76
+ isAuthenticated,
77
+ setAuth,
78
+ setAuthChecked
79
+ } = useAuthStore();
69
80
  (0, import_react.useEffect)(() => {
70
- const savedUser = manager.getSingleToken("user");
71
- if (savedUser) {
81
+ const storedUser = manager.getSingleToken("user");
82
+ const token = manager.getSingleToken(tokenKey);
83
+ if (storedUser && token && !manager.isExpired(token)) {
72
84
  try {
73
- const parsedUser = JSON.parse(savedUser);
74
- useAuthStore.getState().setUser(parsedUser);
75
- useAuthStore.getState().setError(null);
85
+ const parsedUser = JSON.parse(storedUser);
86
+ setUser(parsedUser);
87
+ setRole(parsedUser?.role ?? null);
88
+ setAuth(true);
76
89
  } catch {
77
- useAuthStore.getState().resetAuth();
78
- useAuthStore.getState().setError(new Error("Failed to parse saved user"));
90
+ resetAuth();
79
91
  }
92
+ } else {
93
+ resetAuth();
80
94
  }
81
- setLoading(false);
82
- }, [manager]);
83
- const setUser = (userData) => {
84
- useAuthStore.getState().setUser(userData);
85
- useAuthStore.getState().setError(null);
86
- manager.setTokens({ user: JSON.stringify(userData) });
87
- };
88
- const login = (tokens, userData) => {
89
- try {
90
- manager.setTokens(tokens);
91
- setUser(userData);
92
- } catch (err) {
93
- useAuthStore.getState().setError(
94
- err instanceof Error ? err : new Error(String(err))
95
- );
96
- }
95
+ setAuthChecked(true);
96
+ }, [manager, tokenKey, setUser, setRole, setAuth, resetAuth, setAuthChecked]);
97
+ const login = (tokens, userData, role2) => {
98
+ const tokenValue = tokens[tokenKey] ?? tokens["access_token"] ?? Object.values(tokens)[0];
99
+ manager.setTokens({
100
+ ...tokens,
101
+ [tokenKey]: tokenValue,
102
+ user: JSON.stringify(userData)
103
+ });
104
+ setUser(userData);
105
+ setRole(role2);
106
+ setAuth(true);
97
107
  };
98
108
  const logout = () => {
99
- try {
100
- manager.clearTokens();
101
- useAuthStore.getState().resetAuth();
102
- } catch (err) {
103
- useAuthStore.getState().setError(
104
- err instanceof Error ? err : new Error(String(err))
105
- );
106
- }
109
+ manager.clearTokens();
110
+ resetAuth();
107
111
  };
108
112
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
109
113
  AuthContext.Provider,
110
114
  {
111
- value: { user, login, logout, setUser, loading, error },
115
+ value: {
116
+ user,
117
+ role,
118
+ isAuthenticated,
119
+ login,
120
+ logout,
121
+ setUser: (u) => setUser(u),
122
+ tokenKey
123
+ },
112
124
  children
113
125
  }
114
126
  );
115
127
  };
116
- const useAuth2 = () => {
117
- const ctx = (0, import_react.useContext)(AuthContext);
118
- if (!ctx) throw new Error("useAuth must be used inside AuthProvider");
119
- return ctx;
128
+ const useAuth = () => {
129
+ const context = (0, import_react.useContext)(AuthContext);
130
+ if (!context) throw new Error("useAuth must be used within AuthProvider");
131
+ return context;
132
+ };
133
+ return {
134
+ AuthProvider,
135
+ useAuth,
136
+ tokenKey: option?.tokenKey ?? "access_token"
120
137
  };
121
- return { AuthProvider: AuthProvider2, useAuth: useAuth2 };
122
138
  }
123
139
 
124
140
  // src/AuthGuard.tsx
125
141
  var import_react2 = require("react");
126
142
  var import_navigation = require("next/navigation");
127
- var import_react_token_manager2 = require("react-token-manager");
128
143
  var import_jsx_runtime2 = require("react/jsx-runtime");
129
144
  var AuthGuard = ({
130
145
  children,
131
146
  redirectTo = "/login",
132
- tokenKey = "access_token",
133
- refreshToken
147
+ fallback = null
134
148
  }) => {
135
- const manager = (0, import_react_token_manager2.useTokenManager)();
136
149
  const router = (0, import_navigation.useRouter)();
137
- const isAuthChecked = useAuthStore((state) => state.isAuthChecked);
138
- const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
139
- const error = useAuthStore((state) => state.error);
150
+ const { isAuthenticated, isAuthChecked } = useAuthStore();
140
151
  (0, import_react2.useEffect)(() => {
141
- const checkAuth = async () => {
142
- try {
143
- let token = manager.getSingleToken(tokenKey);
144
- if (!token || manager.isExpired(token)) {
145
- if (refreshToken) {
146
- const newToken = await refreshToken();
147
- if (newToken) {
148
- manager.setTokens({ [tokenKey]: newToken });
149
- token = newToken;
150
- }
151
- }
152
- }
153
- const isValid = token && !manager.isExpired(token);
154
- useAuthStore.getState().setAuth(Boolean(isValid));
155
- if (!isValid) {
156
- router.replace(redirectTo);
157
- }
158
- } catch (err) {
159
- useAuthStore.getState().setError(err instanceof Error ? err : new Error(String(err)));
160
- useAuthStore.getState().setAuth(false);
161
- router.replace(redirectTo);
162
- } finally {
163
- useAuthStore.getState().setAuthChecked(true);
164
- }
165
- };
166
- checkAuth();
167
- }, [manager, router, redirectTo, tokenKey, refreshToken]);
168
- if (!isAuthChecked) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: "Loading..." });
169
- if (error) return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
170
- "Error: ",
171
- error.message
172
- ] });
152
+ if (!isAuthChecked) return;
153
+ if (!isAuthenticated) {
154
+ router.replace(redirectTo);
155
+ }
156
+ }, [isAuthenticated, isAuthChecked, redirectTo, router]);
157
+ if (!isAuthChecked) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
173
158
  if (!isAuthenticated) return null;
174
159
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
175
160
  };
@@ -182,34 +167,30 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
182
167
  var RoleGuard = ({
183
168
  children,
184
169
  allowedRoles,
185
- redirectTo = "/unauthorized"
170
+ redirectTo = "/unauthorized",
171
+ fallback = null
186
172
  }) => {
187
- const { user, loading } = useAuth();
188
173
  const router = (0, import_navigation2.useRouter)();
189
- const [isChecking, setIsChecking] = (0, import_react3.useState)(true);
174
+ const { role, isAuthChecked } = useAuthStore();
190
175
  (0, import_react3.useEffect)(() => {
191
- if (!user) return;
192
- const hasAccess = allowedRoles.includes(user?.role);
193
- if (!hasAccess) {
176
+ if (!isAuthChecked) return;
177
+ if (!role || !allowedRoles.includes(role)) {
194
178
  router.replace(redirectTo);
195
179
  }
196
- setIsChecking(false);
197
- }, [user, allowedRoles, redirectTo, router]);
198
- if (loading || !user || isChecking) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: "Loading..." });
180
+ }, [role, isAuthChecked, allowedRoles, redirectTo, router]);
181
+ if (!isAuthChecked) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
182
+ if (!role || !allowedRoles.includes(role)) return null;
199
183
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
200
184
  };
201
185
  var RoleGuard_default = RoleGuard;
202
186
 
203
187
  // src/index.ts
204
- function createAppAuth(storage = "cookie") {
205
- return createAuthContext({ storage });
188
+ function createAppAuth(storage = "cookie", tokenKey = "access_token") {
189
+ return createAuthContext({ storage, tokenKey });
206
190
  }
207
- var { AuthProvider, useAuth } = createAppAuth();
208
191
  // Annotate the CommonJS export names for ESM import in node:
209
192
  0 && (module.exports = {
210
193
  AuthGuard,
211
- AuthProvider,
212
194
  RoleGuard,
213
- createAppAuth,
214
- useAuth
195
+ createAppAuth
215
196
  });
package/dist/index.mjs CHANGED
@@ -1,185 +1,168 @@
1
1
  "use client";
2
2
 
3
3
  // src/AuthProvider.tsx
4
- import { createContext, useContext, useEffect, useState } from "react";
4
+ import { createContext, useContext, useEffect } from "react";
5
5
  import { configureTokenManager, useTokenManager } from "react-token-manager";
6
6
 
7
7
  // store/useGuardStore.ts
8
8
  import { create } from "zustand";
9
9
  var useAuthStore = create((set) => ({
10
10
  user: null,
11
+ role: null,
11
12
  isAuthenticated: false,
12
13
  isAuthChecked: false,
14
+ loading: true,
13
15
  error: null,
14
16
  setUser: (user) => set({ user }),
17
+ setRole: (role) => set({ role }),
15
18
  setAuth: (isAuth) => set({ isAuthenticated: isAuth }),
16
19
  setAuthChecked: (checked) => set({ isAuthChecked: checked }),
20
+ setLoading: (loading) => set({ loading }),
17
21
  setError: (err) => set({ error: err }),
18
22
  resetAuth: () => set({
19
23
  user: null,
24
+ role: null,
20
25
  isAuthenticated: false,
21
26
  isAuthChecked: false,
27
+ loading: false,
22
28
  error: null
23
29
  })
24
30
  }));
25
31
 
26
32
  // src/AuthProvider.tsx
27
33
  import { jsx } from "react/jsx-runtime";
28
- function createAuthContext(options) {
29
- const AuthContext = createContext(null);
30
- const AuthProvider2 = ({ children }) => {
31
- const storageType = options?.storage || "cookie";
34
+ function createAuthContext(option) {
35
+ const AuthContext = createContext(void 0);
36
+ const AuthProvider = ({ children }) => {
37
+ const storage = option?.storage ?? "cookie";
38
+ const tokenKey = option?.tokenKey ?? "access_token";
32
39
  useEffect(() => {
33
- configureTokenManager({ storage: storageType });
34
- }, [storageType]);
40
+ configureTokenManager({ storage });
41
+ }, [storage]);
35
42
  const manager = useTokenManager();
36
- const [loading, setLoading] = useState(true);
37
- const rawUser = useAuthStore((state) => state.user);
38
- const error = useAuthStore((state) => state.error);
39
- const user = rawUser;
43
+ const {
44
+ user,
45
+ role,
46
+ setUser,
47
+ setRole,
48
+ resetAuth,
49
+ isAuthenticated,
50
+ setAuth,
51
+ setAuthChecked
52
+ } = useAuthStore();
40
53
  useEffect(() => {
41
- const savedUser = manager.getSingleToken("user");
42
- if (savedUser) {
54
+ const storedUser = manager.getSingleToken("user");
55
+ const token = manager.getSingleToken(tokenKey);
56
+ if (storedUser && token && !manager.isExpired(token)) {
43
57
  try {
44
- const parsedUser = JSON.parse(savedUser);
45
- useAuthStore.getState().setUser(parsedUser);
46
- useAuthStore.getState().setError(null);
58
+ const parsedUser = JSON.parse(storedUser);
59
+ setUser(parsedUser);
60
+ setRole(parsedUser?.role ?? null);
61
+ setAuth(true);
47
62
  } catch {
48
- useAuthStore.getState().resetAuth();
49
- useAuthStore.getState().setError(new Error("Failed to parse saved user"));
63
+ resetAuth();
50
64
  }
65
+ } else {
66
+ resetAuth();
51
67
  }
52
- setLoading(false);
53
- }, [manager]);
54
- const setUser = (userData) => {
55
- useAuthStore.getState().setUser(userData);
56
- useAuthStore.getState().setError(null);
57
- manager.setTokens({ user: JSON.stringify(userData) });
58
- };
59
- const login = (tokens, userData) => {
60
- try {
61
- manager.setTokens(tokens);
62
- setUser(userData);
63
- } catch (err) {
64
- useAuthStore.getState().setError(
65
- err instanceof Error ? err : new Error(String(err))
66
- );
67
- }
68
+ setAuthChecked(true);
69
+ }, [manager, tokenKey, setUser, setRole, setAuth, resetAuth, setAuthChecked]);
70
+ const login = (tokens, userData, role2) => {
71
+ const tokenValue = tokens[tokenKey] ?? tokens["access_token"] ?? Object.values(tokens)[0];
72
+ manager.setTokens({
73
+ ...tokens,
74
+ [tokenKey]: tokenValue,
75
+ user: JSON.stringify(userData)
76
+ });
77
+ setUser(userData);
78
+ setRole(role2);
79
+ setAuth(true);
68
80
  };
69
81
  const logout = () => {
70
- try {
71
- manager.clearTokens();
72
- useAuthStore.getState().resetAuth();
73
- } catch (err) {
74
- useAuthStore.getState().setError(
75
- err instanceof Error ? err : new Error(String(err))
76
- );
77
- }
82
+ manager.clearTokens();
83
+ resetAuth();
78
84
  };
79
85
  return /* @__PURE__ */ jsx(
80
86
  AuthContext.Provider,
81
87
  {
82
- value: { user, login, logout, setUser, loading, error },
88
+ value: {
89
+ user,
90
+ role,
91
+ isAuthenticated,
92
+ login,
93
+ logout,
94
+ setUser: (u) => setUser(u),
95
+ tokenKey
96
+ },
83
97
  children
84
98
  }
85
99
  );
86
100
  };
87
- const useAuth2 = () => {
88
- const ctx = useContext(AuthContext);
89
- if (!ctx) throw new Error("useAuth must be used inside AuthProvider");
90
- return ctx;
101
+ const useAuth = () => {
102
+ const context = useContext(AuthContext);
103
+ if (!context) throw new Error("useAuth must be used within AuthProvider");
104
+ return context;
105
+ };
106
+ return {
107
+ AuthProvider,
108
+ useAuth,
109
+ tokenKey: option?.tokenKey ?? "access_token"
91
110
  };
92
- return { AuthProvider: AuthProvider2, useAuth: useAuth2 };
93
111
  }
94
112
 
95
113
  // src/AuthGuard.tsx
96
114
  import { useEffect as useEffect2 } from "react";
97
115
  import { useRouter } from "next/navigation";
98
- import { useTokenManager as useTokenManager2 } from "react-token-manager";
99
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
116
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
100
117
  var AuthGuard = ({
101
118
  children,
102
119
  redirectTo = "/login",
103
- tokenKey = "access_token",
104
- refreshToken
120
+ fallback = null
105
121
  }) => {
106
- const manager = useTokenManager2();
107
122
  const router = useRouter();
108
- const isAuthChecked = useAuthStore((state) => state.isAuthChecked);
109
- const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
110
- const error = useAuthStore((state) => state.error);
123
+ const { isAuthenticated, isAuthChecked } = useAuthStore();
111
124
  useEffect2(() => {
112
- const checkAuth = async () => {
113
- try {
114
- let token = manager.getSingleToken(tokenKey);
115
- if (!token || manager.isExpired(token)) {
116
- if (refreshToken) {
117
- const newToken = await refreshToken();
118
- if (newToken) {
119
- manager.setTokens({ [tokenKey]: newToken });
120
- token = newToken;
121
- }
122
- }
123
- }
124
- const isValid = token && !manager.isExpired(token);
125
- useAuthStore.getState().setAuth(Boolean(isValid));
126
- if (!isValid) {
127
- router.replace(redirectTo);
128
- }
129
- } catch (err) {
130
- useAuthStore.getState().setError(err instanceof Error ? err : new Error(String(err)));
131
- useAuthStore.getState().setAuth(false);
132
- router.replace(redirectTo);
133
- } finally {
134
- useAuthStore.getState().setAuthChecked(true);
135
- }
136
- };
137
- checkAuth();
138
- }, [manager, router, redirectTo, tokenKey, refreshToken]);
139
- if (!isAuthChecked) return /* @__PURE__ */ jsx2("div", { children: "Loading..." });
140
- if (error) return /* @__PURE__ */ jsxs("div", { children: [
141
- "Error: ",
142
- error.message
143
- ] });
125
+ if (!isAuthChecked) return;
126
+ if (!isAuthenticated) {
127
+ router.replace(redirectTo);
128
+ }
129
+ }, [isAuthenticated, isAuthChecked, redirectTo, router]);
130
+ if (!isAuthChecked) return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
144
131
  if (!isAuthenticated) return null;
145
132
  return /* @__PURE__ */ jsx2(Fragment, { children });
146
133
  };
147
134
  var AuthGuard_default = AuthGuard;
148
135
 
149
136
  // src/RoleGuard.tsx
150
- import { useEffect as useEffect3, useState as useState3 } from "react";
137
+ import { useEffect as useEffect3 } from "react";
151
138
  import { useRouter as useRouter2 } from "next/navigation";
152
139
  import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
153
140
  var RoleGuard = ({
154
141
  children,
155
142
  allowedRoles,
156
- redirectTo = "/unauthorized"
143
+ redirectTo = "/unauthorized",
144
+ fallback = null
157
145
  }) => {
158
- const { user, loading } = useAuth();
159
146
  const router = useRouter2();
160
- const [isChecking, setIsChecking] = useState3(true);
147
+ const { role, isAuthChecked } = useAuthStore();
161
148
  useEffect3(() => {
162
- if (!user) return;
163
- const hasAccess = allowedRoles.includes(user?.role);
164
- if (!hasAccess) {
149
+ if (!isAuthChecked) return;
150
+ if (!role || !allowedRoles.includes(role)) {
165
151
  router.replace(redirectTo);
166
152
  }
167
- setIsChecking(false);
168
- }, [user, allowedRoles, redirectTo, router]);
169
- if (loading || !user || isChecking) return /* @__PURE__ */ jsx3("div", { children: "Loading..." });
153
+ }, [role, isAuthChecked, allowedRoles, redirectTo, router]);
154
+ if (!isAuthChecked) return /* @__PURE__ */ jsx3(Fragment2, { children: fallback });
155
+ if (!role || !allowedRoles.includes(role)) return null;
170
156
  return /* @__PURE__ */ jsx3(Fragment2, { children });
171
157
  };
172
158
  var RoleGuard_default = RoleGuard;
173
159
 
174
160
  // src/index.ts
175
- function createAppAuth(storage = "cookie") {
176
- return createAuthContext({ storage });
161
+ function createAppAuth(storage = "cookie", tokenKey = "access_token") {
162
+ return createAuthContext({ storage, tokenKey });
177
163
  }
178
- var { AuthProvider, useAuth } = createAppAuth();
179
164
  export {
180
165
  AuthGuard_default as AuthGuard,
181
- AuthProvider,
182
166
  RoleGuard_default as RoleGuard,
183
- createAppAuth,
184
- useAuth
167
+ createAppAuth
185
168
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextauthz",
3
- "version": "1.2.0",
3
+ "version": "1.2.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/readme.md CHANGED
@@ -31,21 +31,18 @@ Wrap your application with AuthProvider to provide global auth state (user, load
31
31
  import { createAppAuth } from 'nextauthz'
32
32
 
33
33
  // Choose storage type
34
- const { AuthProvider } = createAppAuth('localStorage')
34
+ const { AuthProvider, useAuth } = createAuthContext({
35
+ storage: 'localStorage',
36
+ tokenKey: 'auth_token',
37
+ })
35
38
  // Options: 'localStorage' | 'sessionStorage' | 'cookie'
36
-
37
-
38
- If no storage is passed, default is:
39
-
40
- createAppAuth() // defaults to 'cookie'
41
-
39
+ // Defaults to 'cookie' if no storage is passed
42
40
 
43
41
  function App({ children }: { children: React.ReactNode }) {
44
42
  return <AuthProvider>{children}</AuthProvider>
45
43
  }
46
44
 
47
45
  export default App
48
-
49
46
  ```
50
47
 
51
48
  ## Hook: useAuth
@@ -53,25 +50,25 @@ export default App
53
50
  ```bash
54
51
  import { useAuth } from 'nextauthz'
55
52
 
56
- const { user, login, logout, setUser, loading, error } = useAuth()
53
+ const { user, role, login, logout, setUser, isAuthenticated } = useAuth()
57
54
  ```
58
55
 
59
56
  Available Properties
60
57
 
61
- | Name | Type | Description | |
62
- | --------- | ------------------------ | -------------------------------------------- | -------------------------- |
63
- | `user` | `User | null` | Current authenticated user |
64
- | `login` | `(tokens, user) => void` | Login and save tokens + user | |
65
- | `logout` | `() => void` | Clear auth tokens and reset state | |
66
- | `setUser` | `(user) => void` | Update user state manually | |
67
- | `loading` | `boolean` | True while restoring user from token storage | |
68
- | `error` | `Error | null` | Last auth error |
58
+ | Name | Type | Description | |
59
+ | ----------------- | ---------------------------------- | -------------------------------------- | -------------------------- |
60
+ | `user` | `User | null` | Current authenticated user |
61
+ | `role` | `string | null` | User role |
62
+ | `isAuthenticated` | `boolean` | True if the user is logged in | |
63
+ | `login` | `(tokens, userData, role) => void` | Logs in a user and saves tokens + role | |
64
+ | `logout` | `() => void` | Clears auth tokens and resets state | |
65
+ | `setUser` | `(user: User | null) => void` | Update user state manually |
69
66
 
70
67
 
71
68
  Example: Logging in
72
69
 
73
70
  ```bash
74
- const handleLogin = async () => {
71
+ const handleLogin = () => {
75
72
  const tokens = {
76
73
  access_token: 'abc123',
77
74
  refresh_token: 'xyz789',
@@ -83,9 +80,8 @@ const handleLogin = async () => {
83
80
  role: 'admin',
84
81
  }
85
82
 
86
- login(tokens, user)
83
+ login(tokens, user, user.role)
87
84
  }
88
-
89
85
  ```
90
86
 
91
87
  ## AuthGuard
@@ -96,13 +92,11 @@ Protect routes/pages to ensure only authenticated users can access them.
96
92
 
97
93
  Props
98
94
 
99
- | Name | Type | Default | Description |
100
- | -------------- | ----------------------- | -------------- | -------------------------------------- |
101
- | `children` | `ReactNode` | required | Components to render if authenticated |
102
- | `redirectTo` | `string` | `/login` | Page to redirect unauthenticated users |
103
- | `tokenKey` | `string` | `access_token` | Token key to validate |
104
- | `refreshToken` | `() => Promise<string>` | optional | Function to refresh expired token |
105
-
95
+ | Name | Type | Default | Description |
96
+ | ------------ | ----------- | -------- | -------------------------------------- |
97
+ | `children` | `ReactNode` | required | Components to render if authenticated |
98
+ | `redirectTo` | `string` | `/login` | Page to redirect unauthenticated users |
99
+ | `fallback` | `ReactNode` | `null` | Optional loading or fallback UI |
106
100
 
107
101
  ## Usage Example
108
102
 
@@ -111,7 +105,7 @@ import AuthGuard from 'nextauthz'
111
105
 
112
106
  function DashboardPage() {
113
107
  return (
114
- <AuthGuard>
108
+ <AuthGuard fallback={<p>Loading...</p>}>
115
109
  <h1>Dashboard</h1>
116
110
  </AuthGuard>
117
111
  )
@@ -121,37 +115,45 @@ Behavior:
121
115
 
122
116
  ** Redirects to /login if the user is not authenticated.
123
117
 
124
- ** Supports token refresh with refreshToken callback.
125
-
126
118
 
127
119
  ## RoleGuard
128
120
 
129
121
  Purpose
130
122
 
131
- Restrict access to specific roles after authentication.
123
+ RoleGuard restricts access to certain pages or components based on a user’s role. It assumes authentication is already handled (e.g., via AuthGuard or useAuth) and only checks whether the user’s role is allowed to access the content.
132
124
 
133
- | Name | Type | Default | Description |
134
- | -------------- | ----------- | --------------- | -------------------------------------------- |
135
- | `children` | `ReactNode` | required | Components to render if user role is allowed |
136
- | `allowedRoles` | `string[]` | required | Roles allowed to access this page |
137
- | `redirectTo` | `string` | `/unauthorized` | Redirect page for unauthorized roles |
125
+ | Name | Type | Default | Description |
126
+ | -------------- | ----------- | --------------- | ------------------------------------------------------------- |
127
+ | `children` | `ReactNode` | required | Components to render if the user role is allowed |
128
+ | `allowedRoles` | `string[]` | required | List of roles allowed to access this page |
129
+ | `redirectTo` | `string` | `/unauthorized` | Redirect page for unauthorized roles |
130
+ | `fallback` | `ReactNode` | `null` | Optional loading or fallback UI displayed while checking role |
138
131
 
139
132
 
140
133
  Usage Example
141
134
 
142
135
  ```bash
143
- import RoleGuard from '@/auth/RoleGuard'
144
- import { useAuth } from '@/auth'
136
+ import RoleGuard from 'nextauthz'
137
+ import { useAuth } from 'nextauthz'
145
138
 
146
139
  function AdminPage() {
140
+ const { user } = useAuth()
141
+
147
142
  return (
148
- <RoleGuard allowedRoles={['admin']}>
143
+ <RoleGuard allowedRoles={['admin']} fallback={<p>Checking permissions...</p>}>
149
144
  <h1>Admin Dashboard</h1>
145
+ <p>Welcome, {user?.name}</p>
150
146
  </RoleGuard>
151
147
  )
152
148
  }
153
149
  ```
154
150
 
151
+ Behavior:
152
+
153
+ ** RoleGuard will show the fallback UI while the authentication state is loading (isAuthChecked is false).
154
+ **
155
+
156
+
155
157
  ## Storage Options
156
158
 
157
159
  You can configure token storage:
package/src/AuthGuard.tsx CHANGED
@@ -1,64 +1,34 @@
1
1
  'use client'
2
2
 
3
- import React, { useEffect, useState } from 'react'
3
+ import React, { useEffect } from 'react'
4
4
  import { useRouter } from 'next/navigation'
5
- import { useTokenManager } from 'react-token-manager'
6
5
  import { useAuthStore } from '../store/useGuardStore'
7
6
 
8
7
  type AuthGuardProps = {
9
8
  children: React.ReactNode
10
9
  redirectTo?: string
11
- tokenKey?: string
12
- refreshToken?: () => Promise<string | null>
10
+ fallback?: React.ReactNode
13
11
  }
14
12
 
15
13
  const AuthGuard = ({
16
14
  children,
17
15
  redirectTo = '/login',
18
- tokenKey = 'access_token',
19
- refreshToken,
16
+ fallback = null,
20
17
  }: AuthGuardProps) => {
21
- const manager = useTokenManager()
22
18
  const router = useRouter()
23
- const isAuthChecked = useAuthStore((state) => state.isAuthChecked)
24
- const isAuthenticated = useAuthStore((state) => state.isAuthenticated)
25
- const error = useAuthStore((state) => state.error)
26
19
 
27
- useEffect(() => {
28
- const checkAuth = async () => {
29
- try {
30
- let token = manager.getSingleToken(tokenKey)
31
-
32
- if (!token || manager.isExpired(token)) {
33
- if (refreshToken) {
34
- const newToken = await refreshToken()
35
- if (newToken) {
36
- manager.setTokens({ [tokenKey]: newToken })
37
- token = newToken
38
- }
39
- }
40
- }
20
+ const { isAuthenticated, isAuthChecked } = useAuthStore()
41
21
 
42
- const isValid = token && !manager.isExpired(token)
43
- useAuthStore.getState().setAuth(Boolean(isValid))
22
+ useEffect(() => {
23
+ if (!isAuthChecked) return
44
24
 
45
- if (!isValid) {
46
- router.replace(redirectTo)
47
- }
48
- } catch (err: any) {
49
- useAuthStore.getState().setError(err instanceof Error ? err : new Error(String(err)))
50
- useAuthStore.getState().setAuth(false)
51
- router.replace(redirectTo)
52
- } finally {
53
- useAuthStore.getState().setAuthChecked(true)
54
- }
25
+ if (!isAuthenticated) {
26
+ router.replace(redirectTo)
55
27
  }
28
+ }, [isAuthenticated, isAuthChecked, redirectTo, router])
56
29
 
57
- checkAuth()
58
- }, [manager, router, redirectTo, tokenKey, refreshToken])
30
+ if (!isAuthChecked) return <>{fallback}</>
59
31
 
60
- if (!isAuthChecked) return <div>Loading...</div>
61
- if (error) return <div>Error: {error.message}</div>
62
32
  if (!isAuthenticated) return null
63
33
 
64
34
  return <>{children}</>
@@ -1,101 +1,136 @@
1
1
  'use client'
2
2
 
3
- import React, { createContext, useContext, ReactNode, useEffect, useState } from 'react'
3
+ import React, { createContext, useContext, ReactNode, useEffect } from 'react'
4
4
  import { configureTokenManager, useTokenManager } from 'react-token-manager'
5
- import { useAuthStore } from '../store/useGuardStore'
5
+ import { useAuthStore, User } from '../store/useGuardStore'
6
6
 
7
- export type AuthContextType<UserType> = {
7
+ /* ---------------------------------- */
8
+ /* Types */
9
+ /* ---------------------------------- */
10
+
11
+ export type AuthContextType<UserType extends User = User> = {
8
12
  user: UserType | null
9
- login: (tokens: Record<string, string>, user: UserType) => void
13
+ role: string | null
14
+ isAuthenticated: boolean
15
+ login: (tokens: Record<string, string>, userData: UserType, role: string) => void
10
16
  logout: () => void
11
- setUser: (user: UserType) => void
12
- loading: boolean
13
- error: Error | null
17
+ setUser: (user: UserType | null) => void
18
+ tokenKey: string
14
19
  }
15
20
 
16
- export type AuthContextOptions = {
17
- storage?: 'localStorage' | 'sessionStorage' | 'cookie'
18
- }
21
+ /* ---------------------------------- */
22
+ /* Factory */
23
+ /* ---------------------------------- */
19
24
 
20
- /**
21
- * Factory to create AuthProvider + typed useAuth hook
22
- */
23
- export function createAuthContext<UserType>(options?: AuthContextOptions) {
24
- const AuthContext = createContext<AuthContextType<UserType> | null>(null)
25
+ export function createAuthContext<UserType extends User = User>(option?: {
26
+ storage?: 'localStorage' | 'sessionStorage' | 'cookie'
27
+ tokenKey?: string
28
+ }) {
29
+ const AuthContext = createContext<AuthContextType<UserType> | undefined>(undefined)
25
30
 
26
31
  const AuthProvider = ({ children }: { children: ReactNode }) => {
27
- const storageType = options?.storage || 'cookie'
32
+ const storage = option?.storage ?? 'cookie'
33
+ const tokenKey = option?.tokenKey ?? 'access_token'
28
34
 
29
- // Configure token manager once
30
35
  useEffect(() => {
31
- configureTokenManager({ storage: storageType })
32
- }, [storageType])
36
+ configureTokenManager({ storage })
37
+ }, [storage])
33
38
 
34
39
  const manager = useTokenManager()
35
- const [loading, setLoading] = useState(true)
36
40
 
37
- const rawUser = useAuthStore((state) => state.user)
38
- const error = useAuthStore((state) => state.error)
39
- const user = rawUser as UserType | null
41
+ const {
42
+ user,
43
+ role,
44
+ setUser,
45
+ setRole,
46
+ resetAuth,
47
+ isAuthenticated,
48
+ setAuth,
49
+ setAuthChecked,
50
+ } = useAuthStore()
51
+
52
+ /* ---------------------------------- */
53
+ /* Hydrate user from storage */
54
+ /* ---------------------------------- */
40
55
 
41
- // Restore saved user from token manager on mount
42
56
  useEffect(() => {
43
- const savedUser = manager.getSingleToken('user')
44
- if (savedUser) {
57
+ const storedUser = manager.getSingleToken('user')
58
+ const token = manager.getSingleToken(tokenKey)
59
+
60
+ if (storedUser && token && !manager.isExpired(token)) {
45
61
  try {
46
- const parsedUser = JSON.parse(savedUser)
47
- useAuthStore.getState().setUser(parsedUser)
48
- useAuthStore.getState().setError(null)
62
+ const parsedUser = JSON.parse(storedUser) as UserType
63
+ setUser(parsedUser)
64
+ setRole((parsedUser as any)?.role ?? null)
65
+ setAuth(true)
49
66
  } catch {
50
- useAuthStore.getState().resetAuth()
51
- useAuthStore.getState().setError(new Error('Failed to parse saved user'))
67
+ resetAuth()
52
68
  }
69
+ } else {
70
+ resetAuth()
53
71
  }
54
- setLoading(false)
55
- }, [manager])
56
72
 
57
- const setUser = (userData: UserType) => {
58
- useAuthStore.getState().setUser(userData as any)
59
- useAuthStore.getState().setError(null)
60
- manager.setTokens({ user: JSON.stringify(userData) })
61
- }
73
+ setAuthChecked(true)
74
+ }, [manager, tokenKey, setUser, setRole, setAuth, resetAuth, setAuthChecked])
62
75
 
63
- const login = (tokens: Record<string, string>, userData: UserType) => {
64
- try {
65
- manager.setTokens(tokens)
66
- setUser(userData)
67
- } catch (err) {
68
- useAuthStore.getState().setError(
69
- err instanceof Error ? err : new Error(String(err))
70
- )
71
- }
76
+ /* ---------------------------------- */
77
+ /* Login */
78
+ /* ---------------------------------- */
79
+
80
+ const login = (tokens: Record<string, string>, userData: UserType, role: string) => {
81
+ // Use dynamic token key
82
+ const tokenValue = tokens[tokenKey] ?? tokens['access_token'] ?? Object.values(tokens)[0]
83
+
84
+ manager.setTokens({
85
+ ...tokens,
86
+ [tokenKey]: tokenValue,
87
+ user: JSON.stringify(userData),
88
+ })
89
+
90
+ setUser(userData)
91
+ setRole(role)
92
+ setAuth(true)
72
93
  }
73
94
 
95
+ /* ---------------------------------- */
96
+ /* Logout */
97
+ /* ---------------------------------- */
98
+
74
99
  const logout = () => {
75
- try {
76
- manager.clearTokens()
77
- useAuthStore.getState().resetAuth()
78
- } catch (err) {
79
- useAuthStore.getState().setError(
80
- err instanceof Error ? err : new Error(String(err))
81
- )
82
- }
100
+ manager.clearTokens()
101
+ resetAuth()
83
102
  }
84
103
 
85
104
  return (
86
105
  <AuthContext.Provider
87
- value={{ user, login, logout, setUser, loading, error }}
106
+ value={{
107
+ user: user as UserType | null,
108
+ role,
109
+ isAuthenticated,
110
+ login,
111
+ logout,
112
+ setUser: (u) => setUser(u),
113
+ tokenKey,
114
+ }}
88
115
  >
89
116
  {children}
90
117
  </AuthContext.Provider>
91
118
  )
92
119
  }
93
120
 
94
- const useAuth = (): AuthContextType<UserType> => {
95
- const ctx = useContext(AuthContext)
96
- if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
97
- return ctx
121
+ /* ---------------------------------- */
122
+ /* Hook */
123
+ /* ---------------------------------- */
124
+
125
+ const useAuth = () => {
126
+ const context = useContext(AuthContext)
127
+ if (!context) throw new Error('useAuth must be used within AuthProvider')
128
+ return context
98
129
  }
99
130
 
100
- return { AuthProvider, useAuth }
131
+ return {
132
+ AuthProvider,
133
+ useAuth,
134
+ tokenKey: option?.tokenKey ?? 'access_token',
135
+ }
101
136
  }
package/src/RoleGuard.tsx CHANGED
@@ -1,35 +1,39 @@
1
1
  'use client'
2
2
 
3
- import React, { useEffect, useState } from 'react'
3
+ import React, { useEffect } from 'react'
4
4
  import { useRouter } from 'next/navigation'
5
- import { useAuth } from '.'
5
+ import { useAuthStore } from '../store/useGuardStore'
6
6
 
7
7
  type RoleGuardProps = {
8
8
  children: React.ReactNode
9
9
  allowedRoles: string[]
10
10
  redirectTo?: string
11
+ fallback?: React.ReactNode
11
12
  }
12
13
 
13
14
  const RoleGuard = ({
14
15
  children,
15
16
  allowedRoles,
16
17
  redirectTo = '/unauthorized',
18
+ fallback = null,
17
19
  }: RoleGuardProps) => {
18
- const { user, loading } = useAuth()
19
20
  const router = useRouter()
20
- const [isChecking, setIsChecking] = useState(true)
21
+ const { role, isAuthChecked } = useAuthStore()
21
22
 
22
23
  useEffect(() => {
23
- if (!user) return
24
+ if (!isAuthChecked) return
24
25
 
25
- const hasAccess = allowedRoles.includes(user?.role)
26
- if (!hasAccess) {
26
+ // If role not allowed, redirect
27
+ if (!role || !allowedRoles.includes(role)) {
27
28
  router.replace(redirectTo)
28
29
  }
29
- setIsChecking(false)
30
- }, [user, allowedRoles, redirectTo, router])
30
+ }, [role, isAuthChecked, allowedRoles, redirectTo, router])
31
31
 
32
- if (loading || !user || isChecking) return <div>Loading...</div>
32
+ // Show fallback while loading
33
+ if (!isAuthChecked) return <>{fallback}</>
34
+
35
+ // Block rendering if role is not allowed
36
+ if (!role || !allowedRoles.includes(role)) return null
33
37
 
34
38
  return <>{children}</>
35
39
  }
package/src/index.ts CHANGED
@@ -5,14 +5,14 @@ import { createAuthContext } from './AuthProvider'
5
5
  export { default as AuthGuard } from './AuthGuard'
6
6
  export { default as RoleGuard } from './RoleGuard'
7
7
 
8
- export type User = any
8
+ export type User = Record<string, any>
9
9
 
10
- // Factory function for app
10
+ /**
11
+ * Factory to create isolated auth instance
12
+ */
11
13
  export function createAppAuth(
12
- storage: 'localStorage' | 'sessionStorage' | 'cookie' = 'cookie'
14
+ storage: 'localStorage' | 'sessionStorage' | 'cookie' = 'cookie',
15
+ tokenKey: string = 'access_token' // <-- default token key
13
16
  ) {
14
- return createAuthContext<User>({ storage })
17
+ return createAuthContext({ storage, tokenKey })
15
18
  }
16
-
17
- // Default instance (optional)
18
- export const { AuthProvider, useAuth } = createAppAuth()
@@ -7,33 +7,47 @@ export type User = {
7
7
  }
8
8
 
9
9
  type AuthState = {
10
- user: User | null // user can be null
10
+ user: User | null
11
+ role: string | null // ✅ explicit role
12
+
11
13
  isAuthenticated: boolean
12
14
  isAuthChecked: boolean
15
+ loading: boolean
13
16
  error: Error | null
17
+
14
18
  setUser: (user: User | null) => void
19
+ setRole: (role: string | null) => void // ✅ new setter
15
20
  setAuth: (isAuth: boolean) => void
16
21
  setAuthChecked: (checked: boolean) => void
22
+ setLoading: (loading: boolean) => void
17
23
  setError: (err: Error | null) => void
18
24
  resetAuth: () => void
19
25
  }
20
26
 
21
27
  export const useAuthStore = create<AuthState>((set) => ({
22
28
  user: null,
29
+ role: null,
30
+
23
31
  isAuthenticated: false,
24
32
  isAuthChecked: false,
33
+ loading: true,
25
34
  error: null,
26
35
 
27
36
  setUser: (user) => set({ user }),
37
+ setRole: (role) => set({ role }),
38
+
28
39
  setAuth: (isAuth) => set({ isAuthenticated: isAuth }),
29
40
  setAuthChecked: (checked) => set({ isAuthChecked: checked }),
41
+ setLoading: (loading) => set({ loading }),
30
42
  setError: (err) => set({ error: err }),
31
43
 
32
44
  resetAuth: () =>
33
45
  set({
34
46
  user: null,
47
+ role: null,
35
48
  isAuthenticated: false,
36
49
  isAuthChecked: false,
50
+ loading: false,
37
51
  error: null,
38
52
  }),
39
53
  }))