@adventurelabs/scout-core 2.0.9 → 2.0.11
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.
|
@@ -60,6 +60,7 @@ export function useScoutRefresh(options = {}, identityOptions = {}) {
|
|
|
60
60
|
const { validatedUserId, onUserValidated } = identityOptions;
|
|
61
61
|
const dispatch = useAppDispatch();
|
|
62
62
|
const refreshIdRef = useRef(0);
|
|
63
|
+
const refreshInProgressIdRef = useRef(null);
|
|
63
64
|
const activeUserIdRef = useRef(null);
|
|
64
65
|
const validatedUserIdRef = useRef(null);
|
|
65
66
|
const providedValidatedUserIdRef = useRef(validatedUserId);
|
|
@@ -91,7 +92,10 @@ export function useScoutRefresh(options = {}, identityOptions = {}) {
|
|
|
91
92
|
}, [dispatch]);
|
|
92
93
|
const cacheIdentityRef = useRef({ supabase, offlineUserId });
|
|
93
94
|
const handleRefresh = useCallback(async ({ force = true } = {}) => {
|
|
95
|
+
if (refreshInProgressIdRef.current !== null && !force)
|
|
96
|
+
return;
|
|
94
97
|
const refreshId = ++refreshIdRef.current;
|
|
98
|
+
refreshInProgressIdRef.current = refreshId;
|
|
95
99
|
const isCurrent = () => refreshIdRef.current === refreshId;
|
|
96
100
|
const startTime = Date.now();
|
|
97
101
|
const isOffline = typeof navigator === "undefined" || !navigator.onLine;
|
|
@@ -268,6 +272,9 @@ export function useScoutRefresh(options = {}, identityOptions = {}) {
|
|
|
268
272
|
}
|
|
269
273
|
}
|
|
270
274
|
finally {
|
|
275
|
+
if (refreshInProgressIdRef.current === refreshId) {
|
|
276
|
+
refreshInProgressIdRef.current = null;
|
|
277
|
+
}
|
|
271
278
|
if (isCurrent()) {
|
|
272
279
|
lastQueryAtRef.current = Date.now();
|
|
273
280
|
}
|
|
@@ -84,6 +84,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
84
84
|
const [error, setError] = useState(null);
|
|
85
85
|
const [offline, setOffline] = useState(isBrowserOffline);
|
|
86
86
|
const refreshIdRef = useRef(0);
|
|
87
|
+
const refreshInProgressRef = useRef(false);
|
|
87
88
|
const authUserIdRef = useRef(null);
|
|
88
89
|
const cacheHydrationIdRef = useRef(0);
|
|
89
90
|
const signedOutRef = useRef(false);
|
|
@@ -106,11 +107,12 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
106
107
|
const refreshMint = useCallback(async (force = true) => {
|
|
107
108
|
if (!enabled || isBrowserOffline())
|
|
108
109
|
return;
|
|
110
|
+
if (refreshInProgressRef.current && !force)
|
|
111
|
+
return;
|
|
112
|
+
refreshInProgressRef.current = true;
|
|
109
113
|
cacheHydrationIdRef.current++;
|
|
110
114
|
const refreshId = ++refreshIdRef.current;
|
|
111
115
|
const isCurrent = () => refreshIdRef.current === refreshId;
|
|
112
|
-
setInFlight(true);
|
|
113
|
-
setError(null);
|
|
114
116
|
try {
|
|
115
117
|
const { data, error: authError } = await supabase.auth.getUser();
|
|
116
118
|
if (authError) {
|
|
@@ -143,6 +145,8 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
143
145
|
!shouldRefreshMint(currentMint, ttlSec, refreshBeforeExpirySec)) {
|
|
144
146
|
return;
|
|
145
147
|
}
|
|
148
|
+
setInFlight(true);
|
|
149
|
+
setError(null);
|
|
146
150
|
const mintResponse = await mintToken(supabase);
|
|
147
151
|
if (!isCurrent() || authUserIdRef.current !== userId)
|
|
148
152
|
return;
|
|
@@ -177,6 +181,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
177
181
|
}
|
|
178
182
|
finally {
|
|
179
183
|
if (isCurrent()) {
|
|
184
|
+
refreshInProgressRef.current = false;
|
|
180
185
|
setInFlight(false);
|
|
181
186
|
}
|
|
182
187
|
}
|
|
@@ -202,10 +207,12 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
202
207
|
authUserIdRef.current = null;
|
|
203
208
|
cacheHydrationIdRef.current++;
|
|
204
209
|
refreshIdRef.current++;
|
|
210
|
+
refreshInProgressRef.current = false;
|
|
205
211
|
updateMint(null);
|
|
206
212
|
setInFlight(false);
|
|
207
213
|
}
|
|
208
214
|
if (!enabled) {
|
|
215
|
+
refreshInProgressRef.current = false;
|
|
209
216
|
updateMint(null);
|
|
210
217
|
setError(null);
|
|
211
218
|
setInFlight(false);
|
|
@@ -220,6 +227,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
220
227
|
authUserIdRef.current = null;
|
|
221
228
|
cacheHydrationIdRef.current++;
|
|
222
229
|
refreshIdRef.current++;
|
|
230
|
+
refreshInProgressRef.current = false;
|
|
223
231
|
updateMint(null);
|
|
224
232
|
setError(null);
|
|
225
233
|
setInFlight(false);
|
|
@@ -274,7 +282,12 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
274
282
|
authUserIdRef.current !== userId) {
|
|
275
283
|
return;
|
|
276
284
|
}
|
|
277
|
-
|
|
285
|
+
if (cached.data && !cached.isStale) {
|
|
286
|
+
updateMint(cached.data);
|
|
287
|
+
}
|
|
288
|
+
else if (!mintRef.current) {
|
|
289
|
+
updateMint(cached.data);
|
|
290
|
+
}
|
|
278
291
|
}
|
|
279
292
|
catch (cacheError) {
|
|
280
293
|
console.warn(`[ScoutRefreshProvider] ${cacheKey} cache load failed:`, cacheError);
|
|
@@ -288,27 +301,47 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
288
301
|
}
|
|
289
302
|
};
|
|
290
303
|
void initializeMint();
|
|
304
|
+
const refreshCurrentMintIfDue = () => {
|
|
305
|
+
const currentMint = mintRef.current;
|
|
306
|
+
if (!currentMint ||
|
|
307
|
+
shouldRefreshMint(currentMint, ttlSec, refreshBeforeExpirySec)) {
|
|
308
|
+
void refreshMint(false);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
291
311
|
const unsubscribeAuth = subscribeToSupabaseAuth(supabase, (event, session) => {
|
|
292
312
|
if (event === "SIGNED_OUT") {
|
|
293
313
|
signedOutRef.current = true;
|
|
294
314
|
authUserIdRef.current = null;
|
|
295
315
|
cacheHydrationIdRef.current++;
|
|
296
316
|
refreshIdRef.current++;
|
|
317
|
+
refreshInProgressRef.current = false;
|
|
297
318
|
updateMint(null);
|
|
298
319
|
setError(null);
|
|
299
320
|
setInFlight(false);
|
|
300
321
|
return;
|
|
301
322
|
}
|
|
302
323
|
if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
|
|
324
|
+
const wasSignedOut = signedOutRef.current;
|
|
303
325
|
signedOutRef.current = false;
|
|
304
|
-
refreshIdRef.current++;
|
|
305
|
-
setInFlight(false);
|
|
306
326
|
const userId = session?.user?.id;
|
|
307
|
-
if (userId) {
|
|
327
|
+
if (!userId) {
|
|
328
|
+
refreshCurrentMintIfDue();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
const knownUserId = authUserIdRef.current;
|
|
332
|
+
const userChanged = wasSignedOut ||
|
|
333
|
+
(knownUserId !== null && knownUserId !== userId);
|
|
334
|
+
if (userChanged) {
|
|
335
|
+
cacheHydrationIdRef.current++;
|
|
336
|
+
refreshIdRef.current++;
|
|
337
|
+
refreshInProgressRef.current = false;
|
|
308
338
|
void initializeMint(userId, true);
|
|
309
339
|
}
|
|
340
|
+
else if (knownUserId === null || !mintRef.current) {
|
|
341
|
+
void initializeMint(userId);
|
|
342
|
+
}
|
|
310
343
|
else {
|
|
311
|
-
|
|
344
|
+
refreshCurrentMintIfDue();
|
|
312
345
|
}
|
|
313
346
|
}
|
|
314
347
|
});
|
|
@@ -326,11 +359,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
326
359
|
setOffline(currentlyOffline);
|
|
327
360
|
if (currentlyOffline)
|
|
328
361
|
return;
|
|
329
|
-
|
|
330
|
-
if (!currentMint ||
|
|
331
|
-
shouldRefreshMint(currentMint, ttlSec, refreshBeforeExpirySec)) {
|
|
332
|
-
void refreshMint(false);
|
|
333
|
-
}
|
|
362
|
+
refreshCurrentMintIfDue();
|
|
334
363
|
};
|
|
335
364
|
window.addEventListener("online", handleOnline);
|
|
336
365
|
window.addEventListener("offline", handleOffline);
|
|
@@ -339,6 +368,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
339
368
|
cancelled = true;
|
|
340
369
|
cacheHydrationIdRef.current++;
|
|
341
370
|
refreshIdRef.current++;
|
|
371
|
+
refreshInProgressRef.current = false;
|
|
342
372
|
unsubscribeAuth();
|
|
343
373
|
window.removeEventListener("online", handleOnline);
|
|
344
374
|
window.removeEventListener("offline", handleOffline);
|
|
@@ -364,7 +394,7 @@ function useJwtMintLifecycle({ enabled, supabase, identity, cacheKey, ttlSec, re
|
|
|
364
394
|
const refreshAtSec = Math.max(expSec - refreshBeforeExpirySec, mint.iat + 1);
|
|
365
395
|
const delayMs = Math.max((refreshAtSec - nowSec) * 1000, 1000);
|
|
366
396
|
const timer = setTimeout(() => {
|
|
367
|
-
void refreshMint();
|
|
397
|
+
void refreshMint(false);
|
|
368
398
|
}, delayMs);
|
|
369
399
|
return () => clearTimeout(timer);
|
|
370
400
|
}, [enabled, mint, ttlSec, refreshBeforeExpirySec, refreshMint]);
|