@adventurelabs/scout-core 2.0.1 → 2.0.2
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/helpers/cache.d.ts +25 -17
- package/dist/helpers/cache.js +225 -221
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useScoutRealtimeOperatingContexts.d.ts +5 -3
- package/dist/hooks/useScoutRealtimeOperatingContexts.js +8 -0
- package/dist/hooks/useScoutRefresh.d.ts +3 -2
- package/dist/hooks/useScoutRefresh.js +160 -123
- package/dist/providers/ScoutRefreshProvider.js +39 -17
- package/dist/store/scout.d.ts +1 -3
- package/dist/store/scout.js +9 -14
- package/package.json +1 -1
|
@@ -10,6 +10,14 @@ const TABLE_MARKERS = [
|
|
|
10
10
|
["operating_context_equipment_requirements", "equipment_item_id"],
|
|
11
11
|
["operating_context_regions", "is_exclusion"],
|
|
12
12
|
["operating_context_risks", "probability_before"],
|
|
13
|
+
["contact_types", "num_required"],
|
|
14
|
+
["operating_context_point_of_interest_types", "system_name"],
|
|
15
|
+
["operating_permissions", "description"],
|
|
16
|
+
["compliance_resource_types", "system_name"],
|
|
17
|
+
["compliance_resources", "compliance_resource_type_id"],
|
|
18
|
+
["operating_context_points_of_interest", "point_of_interest_type_id"],
|
|
19
|
+
["operating_context_contacts", "contact_id"],
|
|
20
|
+
["herd_operating_permissions", "operating_permission_id"],
|
|
13
21
|
];
|
|
14
22
|
function discriminate(update) {
|
|
15
23
|
if (!update)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clearScoutClientState } from "../helpers/cache";
|
|
1
2
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
3
|
import type { Database } from "../types/supabase";
|
|
3
4
|
export interface UseScoutRefreshOptions {
|
|
@@ -14,10 +15,10 @@ export interface ScoutRefreshRequest {
|
|
|
14
15
|
/**
|
|
15
16
|
* Refreshes Scout state from cache and the API.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
* finish from a fresh cache without requesting the API.
|
|
18
|
+
* Automatic refreshes hydrate from cache before revalidating online.
|
|
19
19
|
*/
|
|
20
20
|
export declare function useScoutRefresh(options?: UseScoutRefreshOptions): {
|
|
21
21
|
handleRefresh: ({ force }?: ScoutRefreshRequest) => Promise<void>;
|
|
22
22
|
clearCache: () => Promise<void>;
|
|
23
|
+
clearScoutClientState: typeof clearScoutClientState;
|
|
23
24
|
};
|
|
@@ -1,28 +1,69 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useEffect, useCallback, useRef, useMemo, startTransition, } from "react";
|
|
3
3
|
import { useAppDispatch } from "../store/hooks";
|
|
4
|
-
import { EnumScoutStateStatus, setHerdModules, setStatus, setHerdModulesLoadingState, setHerdModulesLoadedInMs, setHerdModulesApiServerProcessingDuration, setHerdModulesApiTotalRequestDuration, setUserApiDuration, setDataProcessingDuration, setCacheLoadDuration, setUser, setDataSource, setDataSourceInfo, } from "../store/scout";
|
|
4
|
+
import { EnumScoutStateStatus, setHerdModules, setStatus, setHerdModulesLoadingState, setHerdModulesLoadedInMs, setHerdModulesApiServerProcessingDuration, setHerdModulesApiTotalRequestDuration, setUserApiDuration, setDataProcessingDuration, setCacheLoadDuration, setUser, setDataSource, setDataSourceInfo, resetScoutState, } from "../store/scout";
|
|
5
|
+
import { scoutApi } from "../store/api";
|
|
5
6
|
import { EnumHerdModulesLoadingState, } from "../types/herd_module";
|
|
6
7
|
import { load_herd_modules_query } from "../helpers/herd_modules.queries";
|
|
7
|
-
import { scoutCache } from "../helpers/cache";
|
|
8
|
+
import { clearScoutClientState, scoutCache } from "../helpers/cache";
|
|
8
9
|
import { EnumDataSource } from "../types/data_source";
|
|
9
10
|
import { EnumWebResponse } from "../types/requests";
|
|
10
11
|
import { createScoutBrowserClient } from "../supabase/client";
|
|
12
|
+
import { subscribeToSupabaseAuth } from "../helpers/supabase_auth";
|
|
11
13
|
function dispatchInTransition(dispatch, action) {
|
|
12
14
|
startTransition(() => {
|
|
13
15
|
dispatch(action);
|
|
14
16
|
});
|
|
15
17
|
}
|
|
18
|
+
async function loadAuthenticatedUser(supabase, offline) {
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
if (offline) {
|
|
21
|
+
const { data: { session }, } = await supabase.auth.getSession();
|
|
22
|
+
if (!session?.user) {
|
|
23
|
+
throw new Error("No authenticated user");
|
|
24
|
+
}
|
|
25
|
+
return { user: session.user, duration: Date.now() - startTime };
|
|
26
|
+
}
|
|
27
|
+
let lastError = new Error("Unable to load authenticated user");
|
|
28
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
29
|
+
try {
|
|
30
|
+
const { data } = await supabase.auth.getUser();
|
|
31
|
+
if (!data.user) {
|
|
32
|
+
throw new Error("Invalid user response");
|
|
33
|
+
}
|
|
34
|
+
return { user: data.user, duration: Date.now() - startTime };
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
lastError =
|
|
38
|
+
error instanceof Error ? error : new Error("User request failed");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
throw lastError;
|
|
42
|
+
}
|
|
43
|
+
async function recoverScoutCache(error, operation, userId, retry) {
|
|
44
|
+
if (!(error instanceof Error) ||
|
|
45
|
+
(!error.message.includes("object store") &&
|
|
46
|
+
!error.message.includes("NotFoundError"))) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
await scoutCache.resetDatabase(userId);
|
|
51
|
+
await retry?.();
|
|
52
|
+
}
|
|
53
|
+
catch (resetError) {
|
|
54
|
+
console.error(`[useScoutRefresh] ${operation} reset and retry failed:`, resetError);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
16
57
|
/**
|
|
17
58
|
* Refreshes Scout state from cache and the API.
|
|
18
59
|
*
|
|
19
|
-
*
|
|
20
|
-
* finish from a fresh cache without requesting the API.
|
|
60
|
+
* Automatic refreshes hydrate from cache before revalidating online.
|
|
21
61
|
*/
|
|
22
62
|
export function useScoutRefresh(options = {}) {
|
|
23
63
|
const { supabase: supabaseOption, autoRefresh = true, onRefreshComplete, cacheFirst = true, cacheTtlMs = 24 * 60 * 60 * 1000, onlineRefetchMinIntervalMs = 15 * 1000, } = options;
|
|
24
64
|
const dispatch = useAppDispatch();
|
|
25
|
-
const
|
|
65
|
+
const refreshIdRef = useRef(0);
|
|
66
|
+
const activeUserIdRef = useRef(null);
|
|
26
67
|
const lastQueryAtRef = useRef(0);
|
|
27
68
|
const onRefreshCompleteRef = useRef(onRefreshComplete);
|
|
28
69
|
useEffect(() => {
|
|
@@ -34,62 +75,56 @@ export function useScoutRefresh(options = {}) {
|
|
|
34
75
|
}
|
|
35
76
|
return createScoutBrowserClient();
|
|
36
77
|
}, [supabaseOption]);
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
await scoutCache.resetDatabase();
|
|
43
|
-
if (retryFn) {
|
|
44
|
-
await retryFn();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch (resetError) {
|
|
48
|
-
console.error(`[useScoutRefresh] ${operation} reset and retry failed:`, resetError);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}, []);
|
|
78
|
+
const resetClientState = useCallback(() => {
|
|
79
|
+
dispatch(resetScoutState());
|
|
80
|
+
dispatch(scoutApi.util.resetApiState());
|
|
81
|
+
}, [dispatch]);
|
|
52
82
|
const handleRefresh = useCallback(async ({ force = true } = {}) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
refreshInProgressRef.current = true;
|
|
83
|
+
const refreshId = ++refreshIdRef.current;
|
|
84
|
+
const isCurrent = () => refreshIdRef.current === refreshId;
|
|
57
85
|
const startTime = Date.now();
|
|
58
86
|
const isOffline = typeof navigator === "undefined" || !navigator.onLine;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
const totalMs = Date.now() - startTotal;
|
|
69
|
-
dispatch(setUserApiDuration(totalMs));
|
|
70
|
-
dispatchInTransition(dispatch, setUser(data.user));
|
|
71
|
-
return data.user;
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
lastError = e;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
throw lastError;
|
|
87
|
+
let cachedHerdModules = null;
|
|
88
|
+
const complete = (loadingState) => {
|
|
89
|
+
if (!isCurrent())
|
|
90
|
+
return;
|
|
91
|
+
dispatch(setHerdModulesLoadingState(loadingState));
|
|
92
|
+
dispatch(setHerdModulesLoadedInMs(Date.now() - startTime));
|
|
93
|
+
dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
|
|
94
|
+
onRefreshCompleteRef.current?.();
|
|
78
95
|
};
|
|
79
96
|
try {
|
|
80
97
|
dispatch(setStatus(EnumScoutStateStatus.LOADING));
|
|
81
98
|
dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.LOADING));
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
const { user, duration } = await loadAuthenticatedUser(supabase, isOffline);
|
|
100
|
+
if (!isCurrent())
|
|
101
|
+
return;
|
|
102
|
+
const userId = user.id;
|
|
103
|
+
if (activeUserIdRef.current &&
|
|
104
|
+
activeUserIdRef.current !== userId) {
|
|
105
|
+
resetClientState();
|
|
106
|
+
}
|
|
107
|
+
activeUserIdRef.current = userId;
|
|
108
|
+
dispatch(setUserApiDuration(duration));
|
|
109
|
+
dispatchInTransition(dispatch, setUser(user));
|
|
110
|
+
let cacheReady = false;
|
|
111
|
+
try {
|
|
112
|
+
await scoutCache.setScope(userId);
|
|
113
|
+
cacheReady = true;
|
|
114
|
+
}
|
|
115
|
+
catch (cacheError) {
|
|
116
|
+
console.warn("[useScoutRefresh] Cache unavailable:", cacheError);
|
|
117
|
+
}
|
|
118
|
+
if (cacheFirst && cacheReady && (!force || isOffline)) {
|
|
85
119
|
const cacheStartTime = Date.now();
|
|
86
120
|
try {
|
|
87
|
-
const cacheResult = await scoutCache.getHerdModules();
|
|
121
|
+
const cacheResult = await scoutCache.getHerdModules(userId);
|
|
122
|
+
if (!isCurrent() || activeUserIdRef.current !== userId)
|
|
123
|
+
return;
|
|
88
124
|
const cacheLoadDuration = Date.now() - cacheStartTime;
|
|
89
125
|
dispatch(setCacheLoadDuration(cacheLoadDuration));
|
|
90
|
-
if (cacheResult.data
|
|
126
|
+
if (cacheResult.data !== null) {
|
|
91
127
|
cachedHerdModules = cacheResult.data;
|
|
92
|
-
cachedContentHash = cacheResult.metadata?.etag;
|
|
93
128
|
dispatch(setDataSource(EnumDataSource.CACHE));
|
|
94
129
|
dispatch(setDataSourceInfo({
|
|
95
130
|
source: EnumDataSource.CACHE,
|
|
@@ -99,68 +134,35 @@ export function useScoutRefresh(options = {}) {
|
|
|
99
134
|
}));
|
|
100
135
|
dispatchInTransition(dispatch, setHerdModules({
|
|
101
136
|
modules: cachedHerdModules,
|
|
102
|
-
contentHash: cachedContentHash,
|
|
103
137
|
}));
|
|
104
138
|
dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED));
|
|
105
|
-
if (!cacheResult.isStale && !force) {
|
|
106
|
-
const totalDuration = Date.now() - startTime;
|
|
107
|
-
dispatch(setHerdModulesLoadedInMs(totalDuration));
|
|
108
|
-
dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
|
|
109
|
-
onRefreshCompleteRef.current?.();
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
139
|
}
|
|
113
140
|
}
|
|
114
141
|
catch (cacheError) {
|
|
115
142
|
console.warn("[useScoutRefresh] Cache load failed:", cacheError);
|
|
116
|
-
await
|
|
143
|
+
await recoverScoutCache(cacheError, "cache load", userId);
|
|
117
144
|
}
|
|
118
145
|
}
|
|
119
146
|
if (isOffline) {
|
|
120
|
-
if (cachedHerdModules
|
|
121
|
-
dispatch(setDataSource(EnumDataSource.CACHE));
|
|
122
|
-
dispatch(setDataSourceInfo({
|
|
123
|
-
source: EnumDataSource.CACHE,
|
|
124
|
-
timestamp: Date.now(),
|
|
125
|
-
}));
|
|
126
|
-
dispatchInTransition(dispatch, setHerdModules({
|
|
127
|
-
modules: cachedHerdModules,
|
|
128
|
-
contentHash: cachedContentHash,
|
|
129
|
-
}));
|
|
130
|
-
dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED));
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.UNSUCCESSFULLY_LOADED));
|
|
147
|
+
if (cachedHerdModules === null) {
|
|
134
148
|
dispatch(setDataSource(EnumDataSource.UNKNOWN));
|
|
135
149
|
dispatch(setDataSourceInfo({
|
|
136
150
|
source: EnumDataSource.UNKNOWN,
|
|
137
151
|
timestamp: Date.now(),
|
|
138
152
|
}));
|
|
139
153
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
complete(cachedHerdModules !== null
|
|
155
|
+
? EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED
|
|
156
|
+
: EnumHerdModulesLoadingState.UNSUCCESSFULLY_LOADED);
|
|
143
157
|
return;
|
|
144
158
|
}
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const serverDuration = result.server_processing_time_ms || totalDuration;
|
|
153
|
-
return { result, totalDuration, serverDuration };
|
|
154
|
-
})();
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
157
|
-
await userPromise.catch(() => { });
|
|
158
|
-
throw e;
|
|
159
|
-
}
|
|
160
|
-
await userPromise;
|
|
161
|
-
const herdModulesResponse = herdModulesResult.result;
|
|
162
|
-
const herdModulesServerDuration = herdModulesResult.serverDuration;
|
|
163
|
-
const herdModulesTotalDuration = herdModulesResult.totalDuration;
|
|
159
|
+
const queryStart = Date.now();
|
|
160
|
+
const herdModulesResponse = await load_herd_modules_query(supabase);
|
|
161
|
+
if (!isCurrent() || activeUserIdRef.current !== userId)
|
|
162
|
+
return;
|
|
163
|
+
const herdModulesTotalDuration = Date.now() - queryStart;
|
|
164
|
+
const herdModulesServerDuration = herdModulesResponse.server_processing_time_ms ||
|
|
165
|
+
herdModulesTotalDuration;
|
|
164
166
|
dispatch(setHerdModulesApiServerProcessingDuration(herdModulesServerDuration));
|
|
165
167
|
dispatch(setHerdModulesApiTotalRequestDuration(herdModulesTotalDuration));
|
|
166
168
|
if (herdModulesResponse.status !== EnumWebResponse.SUCCESS ||
|
|
@@ -169,56 +171,90 @@ export function useScoutRefresh(options = {}) {
|
|
|
169
171
|
}
|
|
170
172
|
const freshHerdModules = herdModulesResponse.data;
|
|
171
173
|
const freshContentHash = herdModulesResponse.content_hash;
|
|
174
|
+
if (cacheReady) {
|
|
175
|
+
try {
|
|
176
|
+
await scoutCache.setHerdModules(freshHerdModules, cacheTtlMs, freshContentHash, userId);
|
|
177
|
+
}
|
|
178
|
+
catch (cacheError) {
|
|
179
|
+
console.warn("[useScoutRefresh] Cache save failed:", cacheError);
|
|
180
|
+
await recoverScoutCache(cacheError, "cache save", userId, async () => {
|
|
181
|
+
await scoutCache.setHerdModules(freshHerdModules, cacheTtlMs, freshContentHash, userId);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (!isCurrent() || activeUserIdRef.current !== userId)
|
|
186
|
+
return;
|
|
187
|
+
const dataProcessingStartTime = Date.now();
|
|
172
188
|
dispatch(setDataSource(EnumDataSource.DATABASE));
|
|
173
189
|
dispatch(setDataSourceInfo({
|
|
174
190
|
source: EnumDataSource.DATABASE,
|
|
175
191
|
timestamp: Date.now(),
|
|
176
192
|
}));
|
|
177
|
-
try {
|
|
178
|
-
await scoutCache.setHerdModules(freshHerdModules, cacheTtlMs, freshContentHash);
|
|
179
|
-
}
|
|
180
|
-
catch (cacheError) {
|
|
181
|
-
console.warn("[useScoutRefresh] Cache save failed:", cacheError);
|
|
182
|
-
await handleIndexedDbError(cacheError, "cache save", async () => {
|
|
183
|
-
await scoutCache.setHerdModules(freshHerdModules, cacheTtlMs, freshContentHash);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
const dataProcessingStartTime = Date.now();
|
|
187
193
|
dispatchInTransition(dispatch, setHerdModules({
|
|
188
194
|
modules: freshHerdModules,
|
|
189
195
|
contentHash: freshContentHash,
|
|
190
196
|
}));
|
|
191
|
-
dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED));
|
|
192
197
|
const dataProcessingDuration = Date.now() - dataProcessingStartTime;
|
|
193
198
|
dispatch(setDataProcessingDuration(dataProcessingDuration));
|
|
194
|
-
|
|
195
|
-
dispatch(setHerdModulesLoadedInMs(loadingDuration));
|
|
196
|
-
dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
|
|
197
|
-
onRefreshCompleteRef.current?.();
|
|
199
|
+
complete(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED);
|
|
198
200
|
}
|
|
199
201
|
catch (error) {
|
|
200
|
-
|
|
202
|
+
if (!isCurrent())
|
|
203
|
+
return;
|
|
201
204
|
console.error("Error refreshing scout data:", error);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
if (cachedHerdModules !== null) {
|
|
206
|
+
dispatch(setDataSource(EnumDataSource.CACHE));
|
|
207
|
+
complete(EnumHerdModulesLoadingState.SUCCESSFULLY_LOADED);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
dispatch(setDataSource(EnumDataSource.UNKNOWN));
|
|
211
|
+
dispatch(setDataSourceInfo({
|
|
212
|
+
source: EnumDataSource.UNKNOWN,
|
|
213
|
+
timestamp: Date.now(),
|
|
214
|
+
}));
|
|
215
|
+
complete(EnumHerdModulesLoadingState.UNSUCCESSFULLY_LOADED);
|
|
216
|
+
}
|
|
211
217
|
}
|
|
212
218
|
finally {
|
|
213
|
-
|
|
214
|
-
|
|
219
|
+
if (isCurrent()) {
|
|
220
|
+
lastQueryAtRef.current = Date.now();
|
|
221
|
+
}
|
|
215
222
|
}
|
|
216
|
-
}, [
|
|
223
|
+
}, [
|
|
224
|
+
dispatch,
|
|
225
|
+
supabase,
|
|
226
|
+
cacheFirst,
|
|
227
|
+
cacheTtlMs,
|
|
228
|
+
resetClientState,
|
|
229
|
+
]);
|
|
217
230
|
useEffect(() => {
|
|
218
231
|
if (autoRefresh) {
|
|
219
232
|
void handleRefresh({ force: false });
|
|
220
233
|
}
|
|
221
234
|
}, [autoRefresh, handleRefresh]);
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
return subscribeToSupabaseAuth(supabase, (event, session) => {
|
|
237
|
+
if (event === "SIGNED_OUT") {
|
|
238
|
+
const previousUserId = activeUserIdRef.current ?? scoutCache.getScopeUserId();
|
|
239
|
+
refreshIdRef.current++;
|
|
240
|
+
activeUserIdRef.current = null;
|
|
241
|
+
resetClientState();
|
|
242
|
+
void clearScoutClientState(previousUserId ?? undefined).catch((error) => {
|
|
243
|
+
console.warn("[useScoutRefresh] Sign-out cache clear failed:", error);
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const nextUserId = session?.user?.id;
|
|
248
|
+
if (event === "SIGNED_IN" &&
|
|
249
|
+
nextUserId &&
|
|
250
|
+
nextUserId !== activeUserIdRef.current) {
|
|
251
|
+
refreshIdRef.current++;
|
|
252
|
+
activeUserIdRef.current = nextUserId;
|
|
253
|
+
resetClientState();
|
|
254
|
+
void handleRefresh({ force: true });
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}, [supabase, handleRefresh, resetClientState]);
|
|
222
258
|
useEffect(() => {
|
|
223
259
|
if (!autoRefresh || typeof window === "undefined")
|
|
224
260
|
return;
|
|
@@ -233,7 +269,7 @@ export function useScoutRefresh(options = {}) {
|
|
|
233
269
|
}, [autoRefresh, handleRefresh, onlineRefetchMinIntervalMs]);
|
|
234
270
|
const clearCache = useCallback(async () => {
|
|
235
271
|
try {
|
|
236
|
-
await scoutCache.clearHerdModules();
|
|
272
|
+
await scoutCache.clearHerdModules(activeUserIdRef.current ?? undefined);
|
|
237
273
|
}
|
|
238
274
|
catch (error) {
|
|
239
275
|
console.error("[useScoutRefresh] Failed to clear cache:", error);
|
|
@@ -242,5 +278,6 @@ export function useScoutRefresh(options = {}) {
|
|
|
242
278
|
return {
|
|
243
279
|
handleRefresh,
|
|
244
280
|
clearCache,
|
|
281
|
+
clearScoutClientState,
|
|
245
282
|
};
|
|
246
283
|
}
|
|
@@ -78,23 +78,31 @@ function useJwtMintLifecycle({ enabled, supabase, cacheKey, ttlSec, refreshBefor
|
|
|
78
78
|
const [mint, setMint] = useState(null);
|
|
79
79
|
const [inFlight, setInFlight] = useState(false);
|
|
80
80
|
const [error, setError] = useState(null);
|
|
81
|
-
const
|
|
81
|
+
const refreshIdRef = useRef(0);
|
|
82
|
+
const authUserIdRef = useRef(null);
|
|
82
83
|
const status = useMemo(() => derive_jwt_mint_status(enabled, mint, inFlight, error), [enabled, mint, inFlight, error]);
|
|
83
84
|
const refreshMint = useCallback(async () => {
|
|
84
|
-
if (!enabled
|
|
85
|
+
if (!enabled)
|
|
85
86
|
return;
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
const refreshId = ++refreshIdRef.current;
|
|
88
|
+
const isCurrent = () => refreshIdRef.current === refreshId;
|
|
88
89
|
setInFlight(true);
|
|
89
90
|
setError(null);
|
|
90
91
|
try {
|
|
91
92
|
const { data: { session }, } = await supabase.auth.getSession();
|
|
93
|
+
if (!isCurrent())
|
|
94
|
+
return;
|
|
92
95
|
if (!session) {
|
|
96
|
+
authUserIdRef.current = null;
|
|
93
97
|
setMint(null);
|
|
94
|
-
await scoutCache.clearJwtMint(cacheKey);
|
|
95
98
|
return;
|
|
96
99
|
}
|
|
100
|
+
const userId = session.user.id;
|
|
101
|
+
authUserIdRef.current = userId;
|
|
102
|
+
await scoutCache.setScope(userId);
|
|
97
103
|
const mintResponse = await mintToken(supabase);
|
|
104
|
+
if (!isCurrent() || authUserIdRef.current !== userId)
|
|
105
|
+
return;
|
|
98
106
|
if (mintResponse.status !== EnumWebResponse.SUCCESS ||
|
|
99
107
|
!mintResponse.data) {
|
|
100
108
|
setError(mintResponse.msg ?? "mint failed");
|
|
@@ -109,20 +117,25 @@ function useJwtMintLifecycle({ enabled, supabase, cacheKey, ttlSec, refreshBefor
|
|
|
109
117
|
keys = await loadPublicKeys(true);
|
|
110
118
|
verified = await verifyToken(mintResponse.data, keys);
|
|
111
119
|
}
|
|
120
|
+
if (!isCurrent() || authUserIdRef.current !== userId)
|
|
121
|
+
return;
|
|
112
122
|
setMint(verified);
|
|
113
123
|
try {
|
|
114
|
-
await scoutCache.setJwtMint(cacheKey, verified);
|
|
124
|
+
await scoutCache.setJwtMint(cacheKey, verified, userId);
|
|
115
125
|
}
|
|
116
126
|
catch (cacheError) {
|
|
117
127
|
console.warn(`[ScoutRefreshProvider] ${cacheKey} cache save failed:`, cacheError);
|
|
118
128
|
}
|
|
119
129
|
}
|
|
120
130
|
catch (e) {
|
|
121
|
-
|
|
131
|
+
if (isCurrent()) {
|
|
132
|
+
setError(e instanceof Error ? e.message : "mint failed");
|
|
133
|
+
}
|
|
122
134
|
}
|
|
123
135
|
finally {
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
if (isCurrent()) {
|
|
137
|
+
setInFlight(false);
|
|
138
|
+
}
|
|
126
139
|
}
|
|
127
140
|
}, [enabled, supabase, cacheKey, loadPublicKeys, mintToken, verifyToken]);
|
|
128
141
|
useEffect(() => {
|
|
@@ -135,16 +148,21 @@ function useJwtMintLifecycle({ enabled, supabase, cacheKey, ttlSec, refreshBefor
|
|
|
135
148
|
let signedOut = false;
|
|
136
149
|
const initializeMint = async () => {
|
|
137
150
|
try {
|
|
138
|
-
const
|
|
139
|
-
scoutCache.getJwtMint(cacheKey),
|
|
140
|
-
supabase.auth.getSession(),
|
|
141
|
-
]);
|
|
151
|
+
const sessionResult = await supabase.auth.getSession();
|
|
142
152
|
if (cancelled || signedOut) {
|
|
143
153
|
return;
|
|
144
154
|
}
|
|
145
|
-
if (!sessionResult.data.session) {
|
|
155
|
+
if (!sessionResult.data.session?.user?.id) {
|
|
146
156
|
setMint(null);
|
|
147
|
-
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const userId = sessionResult.data.session.user.id;
|
|
160
|
+
authUserIdRef.current = userId;
|
|
161
|
+
await scoutCache.setScope(userId);
|
|
162
|
+
const cached = await scoutCache.getJwtMint(cacheKey, userId);
|
|
163
|
+
if (cancelled ||
|
|
164
|
+
signedOut ||
|
|
165
|
+
authUserIdRef.current !== userId) {
|
|
148
166
|
return;
|
|
149
167
|
}
|
|
150
168
|
if (cached.data) {
|
|
@@ -162,16 +180,20 @@ function useJwtMintLifecycle({ enabled, supabase, cacheKey, ttlSec, refreshBefor
|
|
|
162
180
|
}
|
|
163
181
|
};
|
|
164
182
|
void initializeMint();
|
|
165
|
-
const unsubscribeAuth = subscribeToSupabaseAuth(supabase, (event) => {
|
|
183
|
+
const unsubscribeAuth = subscribeToSupabaseAuth(supabase, (event, session) => {
|
|
166
184
|
if (event === "SIGNED_OUT") {
|
|
167
185
|
signedOut = true;
|
|
186
|
+
authUserIdRef.current = null;
|
|
187
|
+
refreshIdRef.current++;
|
|
168
188
|
setMint(null);
|
|
169
189
|
setError(null);
|
|
170
|
-
|
|
190
|
+
setInFlight(false);
|
|
171
191
|
return;
|
|
172
192
|
}
|
|
173
193
|
if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
|
|
174
194
|
signedOut = false;
|
|
195
|
+
authUserIdRef.current = session?.user?.id ?? null;
|
|
196
|
+
refreshIdRef.current++;
|
|
175
197
|
void refreshMint();
|
|
176
198
|
}
|
|
177
199
|
});
|
package/dist/store/scout.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type Slice } from "@reduxjs/toolkit";
|
|
2
1
|
import { IUser } from "../types/db";
|
|
3
2
|
import { IHerdModule, EnumHerdModulesLoadingState } from "../types/herd_module";
|
|
4
3
|
import { EnumDataSource, IDataSourceInfo } from "../types/data_source";
|
|
@@ -32,7 +31,6 @@ export interface ScoutState {
|
|
|
32
31
|
export interface RootState {
|
|
33
32
|
scout: ScoutState;
|
|
34
33
|
}
|
|
35
|
-
export declare const
|
|
36
|
-
export declare const setHerdModules: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setStatus: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setHerdModulesLoadingState: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setLoadingPerformance: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setHerdModulesLoadedInMs: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setHerdModulesApiServerProcessingDuration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setHerdModulesApiTotalRequestDuration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setUserApiDuration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setDataProcessingDuration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setCacheLoadDuration: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setActiveHerdId: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setActiveDeviceId: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setDataSource: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setDataSourceInfo: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateSessionSummariesForHerdModule: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, appendPlansToHerdModule: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setUser: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, addNewDeviceToHerdModule: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateDeviceForHerdModule: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, addDevice: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, deleteDevice: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updateDevice: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, addPlan: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, deletePlan: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, updatePlan: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>, setActiveHerdGpsTrackersConnectivity: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<`${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPayload<any, `${string}/${string}`> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, never, any> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, never> | import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<any[], any, `${string}/${string}`, any, any>;
|
|
34
|
+
export declare const resetScoutState: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"scout/resetScoutState">, setHerdModules: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setHerdModules">, setStatus: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setStatus">, setHerdModulesLoadingState: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setHerdModulesLoadingState">, setLoadingPerformance: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setLoadingPerformance">, setHerdModulesLoadedInMs: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setHerdModulesLoadedInMs">, setHerdModulesApiServerProcessingDuration: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setHerdModulesApiServerProcessingDuration">, setHerdModulesApiTotalRequestDuration: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setHerdModulesApiTotalRequestDuration">, setUserApiDuration: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setUserApiDuration">, setDataProcessingDuration: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setDataProcessingDuration">, setCacheLoadDuration: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setCacheLoadDuration">, setActiveHerdId: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setActiveHerdId">, setActiveDeviceId: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setActiveDeviceId">, setDataSource: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setDataSource">, setDataSourceInfo: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setDataSourceInfo">, updateSessionSummariesForHerdModule: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/updateSessionSummariesForHerdModule">, appendPlansToHerdModule: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/appendPlansToHerdModule">, setUser: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setUser">, addNewDeviceToHerdModule: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/addNewDeviceToHerdModule">, updateDeviceForHerdModule: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/updateDeviceForHerdModule">, addDevice: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/addDevice">, deleteDevice: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/deleteDevice">, updateDevice: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/updateDevice">, addPlan: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/addPlan">, deletePlan: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/deletePlan">, updatePlan: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/updatePlan">, setActiveHerdGpsTrackersConnectivity: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "scout/setActiveHerdGpsTrackersConnectivity">;
|
|
37
35
|
declare const _default: import("redux").Reducer<ScoutState>;
|
|
38
36
|
export default _default;
|