@adventurelabs/scout-core 1.4.51 → 1.4.52

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.
@@ -13,7 +13,7 @@ export interface UseScoutRefreshOptions {
13
13
  * @param options.onRefreshComplete - Callback function called when refresh completes
14
14
  * @param options.cacheFirst - Whether to load from cache first, then refresh (default: true)
15
15
  * @param options.cacheTtlMs - Cache time-to-live in milliseconds (default: 24 hours)
16
- * @param options.onlineRefetchMinIntervalMs - Min ms since last refresh before refetch on "online" (default: 60s)
16
+ * @param options.onlineRefetchMinIntervalMs - Min ms since last refresh before refetch on "online" (default: 15s)
17
17
  *
18
18
  * @returns Object containing:
19
19
  * - handleRefresh: Function to manually trigger a refresh
@@ -15,7 +15,7 @@ import { createBrowserClient } from "@supabase/ssr";
15
15
  * @param options.onRefreshComplete - Callback function called when refresh completes
16
16
  * @param options.cacheFirst - Whether to load from cache first, then refresh (default: true)
17
17
  * @param options.cacheTtlMs - Cache time-to-live in milliseconds (default: 24 hours)
18
- * @param options.onlineRefetchMinIntervalMs - Min ms since last refresh before refetch on "online" (default: 60s)
18
+ * @param options.onlineRefetchMinIntervalMs - Min ms since last refresh before refetch on "online" (default: 15s)
19
19
  *
20
20
  * @returns Object containing:
21
21
  * - handleRefresh: Function to manually trigger a refresh
@@ -33,7 +33,7 @@ import { createBrowserClient } from "@supabase/ssr";
33
33
  */
34
34
  export function useScoutRefresh(options = {}) {
35
35
  const { autoRefresh = true, onRefreshComplete, cacheFirst = true, cacheTtlMs = 24 * 60 * 60 * 1000, // 24 hours default (1 day)
36
- onlineRefetchMinIntervalMs = 60 * 1000, // 1 minute
36
+ onlineRefetchMinIntervalMs = 15 * 1000, // 15 seconds
37
37
  } = options;
38
38
  const dispatch = useAppDispatch();
39
39
  const store = useStore();
@@ -83,6 +83,49 @@ export function useScoutRefresh(options = {}) {
83
83
  const startTime = Date.now();
84
84
  timingRefs.current.startTime = startTime;
85
85
  const isOffline = typeof navigator === "undefined" || !navigator.onLine;
86
+ const fetchUserWithOneRetry = async () => {
87
+ const startTotal = Date.now();
88
+ let lastError;
89
+ for (let attempt = 0; attempt < 2; attempt++) {
90
+ try {
91
+ const { data } = await supabase.auth.getUser();
92
+ if (!data.user) {
93
+ throw new Error("Invalid user response");
94
+ }
95
+ const totalMs = Date.now() - startTotal;
96
+ timingRefs.current.userApiDuration = totalMs;
97
+ dispatch(setUserApiDuration(totalMs));
98
+ dispatch(setUser(data.user));
99
+ return data.user;
100
+ }
101
+ catch (e) {
102
+ lastError = e;
103
+ }
104
+ }
105
+ throw lastError;
106
+ };
107
+ const fetchUserWithOneRetryBackground = async () => {
108
+ const startTotal = Date.now();
109
+ for (let attempt = 0; attempt < 2; attempt++) {
110
+ try {
111
+ const { data } = await supabase.auth.getUser();
112
+ if (data.user) {
113
+ const totalMs = Date.now() - startTotal;
114
+ timingRefs.current.userApiDuration = totalMs;
115
+ dispatch(setUserApiDuration(totalMs));
116
+ dispatch(setUser(data.user));
117
+ return data.user;
118
+ }
119
+ }
120
+ catch {
121
+ // retry once
122
+ }
123
+ }
124
+ const totalMs = Date.now() - startTotal;
125
+ timingRefs.current.userApiDuration = totalMs;
126
+ dispatch(setUserApiDuration(totalMs));
127
+ return null;
128
+ };
86
129
  try {
87
130
  dispatch(setStatus(EnumScoutStateStatus.LOADING));
88
131
  dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.LOADING));
@@ -117,17 +160,7 @@ export function useScoutRefresh(options = {}) {
117
160
  // Background fetch fresh data without blocking
118
161
  (async () => {
119
162
  try {
120
- const userPromise = (async () => {
121
- const start = Date.now();
122
- const { data } = await supabase.auth.getUser();
123
- const duration = Date.now() - start;
124
- timingRefs.current.userApiDuration = duration;
125
- dispatch(setUserApiDuration(duration));
126
- if (data.user) {
127
- dispatch(setUser(data.user));
128
- }
129
- return data.user ?? null;
130
- })();
163
+ const userPromise = fetchUserWithOneRetryBackground();
131
164
  let backgroundHerdModulesResult;
132
165
  try {
133
166
  const start = Date.now();
@@ -228,18 +261,7 @@ export function useScoutRefresh(options = {}) {
228
261
  }
229
262
  // Step 2: Load fresh data from API (user resolves independently; Redux gets user as soon as getUser returns)
230
263
  const parallelStartTime = Date.now();
231
- const userPromise = (async () => {
232
- const start = Date.now();
233
- const { data } = await supabase.auth.getUser();
234
- const duration = Date.now() - start;
235
- timingRefs.current.userApiDuration = duration;
236
- dispatch(setUserApiDuration(duration));
237
- if (!data.user) {
238
- throw new Error("Invalid user response");
239
- }
240
- dispatch(setUser(data.user));
241
- return data.user;
242
- })();
264
+ const userPromise = fetchUserWithOneRetry();
243
265
  let herdModulesResult;
244
266
  try {
245
267
  herdModulesResult = await (async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adventurelabs/scout-core",
3
- "version": "1.4.51",
3
+ "version": "1.4.52",
4
4
  "description": "Core utilities and helpers for Adventure Labs Scout applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",