@imtbl/auth-next-client 2.12.6-alpha.2 → 2.12.6-alpha.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.
@@ -189,11 +189,11 @@ function useImmutableSession() {
189
189
  const currentlyAuthenticated = status === "authenticated" && !!session;
190
190
  const wasAuthenticatedRef = (0, import_react3.useRef)(false);
191
191
  (0, import_react3.useEffect)(() => {
192
- if (!isRefreshing) {
192
+ if (!isRefreshing && !isLoading) {
193
193
  wasAuthenticatedRef.current = currentlyAuthenticated;
194
194
  }
195
- }, [currentlyAuthenticated, isRefreshing]);
196
- const isAuthenticated = isRefreshing && wasAuthenticatedRef.current ? true : currentlyAuthenticated;
195
+ }, [currentlyAuthenticated, isRefreshing, isLoading]);
196
+ const isAuthenticated = (isRefreshing || isLoading) && wasAuthenticatedRef.current ? true : currentlyAuthenticated;
197
197
  const sessionRef = (0, import_react3.useRef)(session);
198
198
  sessionRef.current = session;
199
199
  const updateRef = (0, import_react3.useRef)(update);
@@ -170,11 +170,11 @@ function useImmutableSession() {
170
170
  const currentlyAuthenticated = status === "authenticated" && !!session;
171
171
  const wasAuthenticatedRef = useRef2(false);
172
172
  useEffect2(() => {
173
- if (!isRefreshing) {
173
+ if (!isRefreshing && !isLoading) {
174
174
  wasAuthenticatedRef.current = currentlyAuthenticated;
175
175
  }
176
- }, [currentlyAuthenticated, isRefreshing]);
177
- const isAuthenticated = isRefreshing && wasAuthenticatedRef.current ? true : currentlyAuthenticated;
176
+ }, [currentlyAuthenticated, isRefreshing, isLoading]);
177
+ const isAuthenticated = (isRefreshing || isLoading) && wasAuthenticatedRef.current ? true : currentlyAuthenticated;
178
178
  const sessionRef = useRef2(session);
179
179
  sessionRef.current = session;
180
180
  const updateRef = useRef2(update);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth-next-client",
3
- "version": "2.12.6-alpha.2",
3
+ "version": "2.12.6-alpha.3",
4
4
  "description": "Immutable Auth.js v5 integration for Next.js - Client-side components",
5
5
  "author": "Immutable",
6
6
  "license": "Apache-2.0",
@@ -27,8 +27,8 @@
27
27
  }
28
28
  },
29
29
  "dependencies": {
30
- "@imtbl/auth": "2.12.6-alpha.2",
31
- "@imtbl/auth-next-server": "2.12.6-alpha.2"
30
+ "@imtbl/auth": "2.12.6-alpha.3",
31
+ "@imtbl/auth-next-server": "2.12.6-alpha.3"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "next": "^15.0.0",
package/src/hooks.tsx CHANGED
@@ -94,7 +94,7 @@ export interface UseImmutableSessionReturn {
94
94
  export function useImmutableSession(): UseImmutableSessionReturn {
95
95
  const { data: sessionData, status, update } = useSession();
96
96
 
97
- // Track when a refresh is in progress to prevent brief false states
97
+ // Track when a manual refresh is in progress (via getUser(true))
98
98
  const [isRefreshing, setIsRefreshing] = useState(false);
99
99
 
100
100
  // Cast session to our extended type
@@ -105,23 +105,30 @@ export function useImmutableSession(): UseImmutableSessionReturn {
105
105
  // Core authentication check from NextAuth
106
106
  const currentlyAuthenticated = status === 'authenticated' && !!session;
107
107
 
108
- // Track the last known authenticated state to prevent brief false states during refresh.
109
- // When NextAuth's update() is called, it can briefly set status to 'loading' or
110
- // 'unauthenticated' before the refreshed session is available. This ref helps
111
- // maintain isAuthenticated = true during that brief window.
108
+ // Track the last known authenticated state to prevent brief false states.
109
+ // This handles two scenarios:
110
+ // 1. When NextAuth's update() is called (manual refresh via getUser(true))
111
+ // 2. When NextAuth automatically refetches the session (on window focus, polling, etc.)
112
+ // In both cases, status can briefly become 'loading' before the refreshed session is available.
112
113
  const wasAuthenticatedRef = useRef(false);
113
114
 
114
- // Update the ref when we have a stable authenticated state (not during refresh)
115
+ // Update the ref when we have a stable authenticated state (not during loading or refresh)
115
116
  useEffect(() => {
116
- if (!isRefreshing) {
117
+ // Only update the ref when we have a definitive auth state.
118
+ // During loading or manual refresh, we keep the previous value.
119
+ if (!isRefreshing && !isLoading) {
117
120
  wasAuthenticatedRef.current = currentlyAuthenticated;
118
121
  }
119
- }, [currentlyAuthenticated, isRefreshing]);
120
-
121
- // Prevent isAuthenticated from going false during a refresh.
122
- // If we were authenticated before the refresh started, maintain that state
123
- // until the refresh completes to avoid triggering logout/reset logic in consumers.
124
- const isAuthenticated = isRefreshing && wasAuthenticatedRef.current
122
+ }, [currentlyAuthenticated, isRefreshing, isLoading]);
123
+
124
+ // Prevent isAuthenticated from going false during any session loading/refresh.
125
+ // If we were authenticated before the loading started, maintain that state
126
+ // until the loading completes to avoid triggering logout/reset logic in consumers.
127
+ // This covers:
128
+ // - Manual refresh via getUser(true) - isRefreshing provides immediate protection
129
+ // before NextAuth's status transitions to 'loading'
130
+ // - Automatic NextAuth session refetch (window focus, polling, token expiry)
131
+ const isAuthenticated = (isRefreshing || isLoading) && wasAuthenticatedRef.current
125
132
  ? true
126
133
  : currentlyAuthenticated;
127
134