@adventurelabs/scout-core 1.0.78 → 1.0.80

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.
@@ -33,12 +33,18 @@ export class ScoutCache {
33
33
  const db = event.target.result;
34
34
  // Create herd modules store
35
35
  if (!db.objectStoreNames.contains(HERD_MODULES_STORE)) {
36
- const herdModulesStore = db.createObjectStore(HERD_MODULES_STORE, { keyPath: "herdId" });
37
- herdModulesStore.createIndex("timestamp", "timestamp", { unique: false });
36
+ const herdModulesStore = db.createObjectStore(HERD_MODULES_STORE, {
37
+ keyPath: "herdId",
38
+ });
39
+ herdModulesStore.createIndex("timestamp", "timestamp", {
40
+ unique: false,
41
+ });
38
42
  }
39
43
  // Create cache metadata store
40
44
  if (!db.objectStoreNames.contains(CACHE_METADATA_STORE)) {
41
- const metadataStore = db.createObjectStore(CACHE_METADATA_STORE, { keyPath: "key" });
45
+ const metadataStore = db.createObjectStore(CACHE_METADATA_STORE, {
46
+ keyPath: "key",
47
+ });
42
48
  }
43
49
  console.log("[ScoutCache] Database schema upgraded");
44
50
  };
@@ -104,8 +110,9 @@ export class ScoutCache {
104
110
  getAllRequest.onsuccess = () => {
105
111
  const cacheEntries = getAllRequest.result;
106
112
  const herdModules = cacheEntries
107
- .map(entry => entry.data)
108
- .sort((a, b) => a.herd.name.localeCompare(b.herd.name));
113
+ .filter((entry) => entry.data && entry.data.herd && entry.data.herd.slug)
114
+ .map((entry) => entry.data)
115
+ .sort((a, b) => (a.herd?.slug || "").localeCompare(b.herd?.slug || ""));
109
116
  // Update stats
110
117
  if (herdModules.length > 0) {
111
118
  this.stats.hits++;
@@ -186,7 +193,10 @@ export class ScoutCache {
186
193
  return { shouldRefresh: true, reason: "Cache is stale" };
187
194
  }
188
195
  if (maxAgeMs && result.age > maxAgeMs) {
189
- return { shouldRefresh: true, reason: `Cache age (${Math.round(result.age / 1000)}s) exceeds max age (${Math.round(maxAgeMs / 1000)}s)` };
196
+ return {
197
+ shouldRefresh: true,
198
+ reason: `Cache age (${Math.round(result.age / 1000)}s) exceeds max age (${Math.round(maxAgeMs / 1000)}s)`,
199
+ };
190
200
  }
191
201
  return { shouldRefresh: false, reason: "Cache is valid and fresh" };
192
202
  }
@@ -77,7 +77,7 @@ export function useScoutRefresh(options = {}) {
77
77
  if (cacheResult.data && cacheResult.data.length > 0) {
78
78
  cachedHerdModules = cacheResult.data;
79
79
  console.log(`[useScoutRefresh] Loaded ${cachedHerdModules.length} herd modules from cache in ${cacheLoadDuration}ms (age: ${Math.round(cacheResult.age / 1000)}s, stale: ${cacheResult.isStale})`);
80
- // Set data source to CACHE
80
+ // Set data source to CACHE initially
81
81
  dispatch(setDataSource(EnumDataSource.CACHE));
82
82
  dispatch(setDataSourceInfo({
83
83
  source: EnumDataSource.CACHE,
@@ -88,22 +88,65 @@ export function useScoutRefresh(options = {}) {
88
88
  // Immediately update the store with cached data
89
89
  dispatch(setHerdModules(cachedHerdModules));
90
90
  dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED));
91
- // If cache is fresh, we can return early
91
+ // Always load user data from API
92
+ const userStartTime = Date.now();
93
+ const res_new_user = await server_get_user();
94
+ const userApiDuration = Date.now() - userStartTime;
95
+ timingRefs.current.userApiDuration = userApiDuration;
96
+ dispatch(setUserApiDuration(userApiDuration));
97
+ if (res_new_user && res_new_user.data) {
98
+ dispatch(setUser(res_new_user.data));
99
+ }
100
+ // If cache is fresh, we still background fetch but don't wait
92
101
  if (!cacheResult.isStale) {
93
- console.log("[useScoutRefresh] Cache is fresh, skipping API call");
94
- // Still need to load user data
95
- const userStartTime = Date.now();
96
- const res_new_user = await server_get_user();
97
- const userApiDuration = Date.now() - userStartTime;
98
- timingRefs.current.userApiDuration = userApiDuration;
99
- dispatch(setUserApiDuration(userApiDuration));
100
- if (res_new_user && res_new_user.data) {
101
- dispatch(setUser(res_new_user.data));
102
- }
102
+ console.log("[useScoutRefresh] Cache is fresh, background fetching fresh data...");
103
+ // Background fetch fresh data without blocking
104
+ (async () => {
105
+ try {
106
+ console.log("[useScoutRefresh] Starting background fetch...");
107
+ const backgroundStartTime = Date.now();
108
+ const [backgroundHerdModulesResult, backgroundUserResult] = await Promise.all([
109
+ server_load_herd_modules(),
110
+ server_get_user()
111
+ ]);
112
+ const backgroundDuration = Date.now() - backgroundStartTime;
113
+ console.log(`[useScoutRefresh] Background fetch completed in ${backgroundDuration}ms`);
114
+ // Validate background responses
115
+ if (backgroundHerdModulesResult.data &&
116
+ Array.isArray(backgroundHerdModulesResult.data) &&
117
+ backgroundUserResult &&
118
+ backgroundUserResult.data) {
119
+ // Update cache with fresh data
120
+ try {
121
+ await scoutCache.setHerdModules(backgroundHerdModulesResult.data, cacheTtlMs);
122
+ console.log(`[useScoutRefresh] Background cache updated with TTL: ${Math.round(cacheTtlMs / 1000)}s`);
123
+ }
124
+ catch (cacheError) {
125
+ console.warn("[useScoutRefresh] Background cache save failed:", cacheError);
126
+ }
127
+ // Update store with fresh data
128
+ dispatch(setHerdModules(backgroundHerdModulesResult.data));
129
+ dispatch(setUser(backgroundUserResult.data));
130
+ // Update data source to DATABASE
131
+ dispatch(setDataSource(EnumDataSource.DATABASE));
132
+ dispatch(setDataSourceInfo({
133
+ source: EnumDataSource.DATABASE,
134
+ timestamp: Date.now(),
135
+ }));
136
+ console.log("[useScoutRefresh] Background fetch completed and store updated");
137
+ }
138
+ else {
139
+ console.warn("[useScoutRefresh] Background fetch returned invalid data");
140
+ }
141
+ }
142
+ catch (backgroundError) {
143
+ console.warn("[useScoutRefresh] Background fetch failed:", backgroundError);
144
+ }
145
+ })();
103
146
  const totalDuration = Date.now() - startTime;
104
147
  dispatch(setHerdModulesLoadedInMs(totalDuration));
105
148
  dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
106
- console.log(`[useScoutRefresh] Cache-first refresh completed in ${totalDuration}ms`);
149
+ console.log(`[useScoutRefresh] Cache-first refresh completed in ${totalDuration}ms (background fetch in progress)`);
107
150
  onRefreshComplete?.();
108
151
  return;
109
152
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adventurelabs/scout-core",
3
- "version": "1.0.78",
3
+ "version": "1.0.80",
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",