@adventurelabs/scout-core 1.2.5 → 1.3.1
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.js +3 -1
- package/dist/helpers/pins.d.ts +2 -0
- package/dist/helpers/pins.js +58 -42
- package/dist/helpers/session_summaries.d.ts +6 -0
- package/dist/helpers/session_summaries.js +51 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/useHerdData.d.ts +167 -0
- package/dist/hooks/useHerdData.js +153 -0
- package/dist/hooks/useInfiniteQuery.d.ts +24 -0
- package/dist/hooks/useInfiniteQuery.js +360 -0
- package/dist/hooks/useScoutRealtimeEvents.d.ts +1 -1
- package/dist/hooks/useScoutRealtimeEvents.js +18 -23
- package/dist/hooks/useScoutRealtimeSessions.d.ts +1 -1
- package/dist/hooks/useScoutRealtimeSessions.js +20 -12
- package/dist/hooks/useScoutRealtimeTags.d.ts +1 -1
- package/dist/hooks/useScoutRealtimeTags.js +15 -12
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/providers/ScoutRefreshProvider.d.ts +123 -6
- package/dist/store/api.d.ts +968 -0
- package/dist/store/api.js +377 -0
- package/dist/store/configureStore.d.ts +96 -0
- package/dist/store/configureStore.js +40 -0
- package/dist/store/hooks.d.ts +5 -0
- package/dist/store/hooks.js +21 -3
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.js +1 -0
- package/dist/store/scout.d.ts +13 -50
- package/dist/store/scout.js +33 -141
- package/dist/types/db.d.ts +18 -0
- package/dist/types/herd_module.d.ts +4 -16
- package/dist/types/herd_module.js +17 -23
- package/dist/types/supabase.d.ts +123 -6
- package/package.json +1 -1
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react";
|
|
2
|
+
import { generateSignedUrlsBatch } from "../helpers/storage";
|
|
3
|
+
// Create the API slice
|
|
4
|
+
export const scoutApi = createApi({
|
|
5
|
+
reducerPath: "scoutApi",
|
|
6
|
+
baseQuery: fakeBaseQuery(),
|
|
7
|
+
tagTypes: ["Session", "Event", "Artifact"],
|
|
8
|
+
endpoints: (builder) => ({
|
|
9
|
+
// =====================================================
|
|
10
|
+
// SESSIONS INFINITE QUERIES
|
|
11
|
+
// =====================================================
|
|
12
|
+
getSessionsInfiniteByHerd: builder.query({
|
|
13
|
+
async queryFn({ herdId, limit = 20, cursor, supabase }) {
|
|
14
|
+
try {
|
|
15
|
+
if (!herdId) {
|
|
16
|
+
return {
|
|
17
|
+
error: { status: "CUSTOM_ERROR", error: "Herd ID is required" },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const { data, error } = await supabase.rpc("get_sessions_infinite_by_herd", {
|
|
21
|
+
herd_id_caller: herdId,
|
|
22
|
+
limit_caller: limit + 1, // Fetch one extra to determine if there are more
|
|
23
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
24
|
+
cursor_id: cursor?.id || null,
|
|
25
|
+
});
|
|
26
|
+
if (error) {
|
|
27
|
+
return {
|
|
28
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const sessions = data || [];
|
|
32
|
+
const hasMore = sessions.length > limit;
|
|
33
|
+
const resultSessions = hasMore ? sessions.slice(0, limit) : sessions;
|
|
34
|
+
const nextCursor = hasMore && resultSessions.length > 0
|
|
35
|
+
? {
|
|
36
|
+
timestamp: resultSessions[resultSessions.length - 1].timestamp_start ||
|
|
37
|
+
"",
|
|
38
|
+
id: resultSessions[resultSessions.length - 1].id || 0,
|
|
39
|
+
}
|
|
40
|
+
: null;
|
|
41
|
+
return {
|
|
42
|
+
data: {
|
|
43
|
+
sessions: resultSessions,
|
|
44
|
+
nextCursor,
|
|
45
|
+
hasMore,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
providesTags: (result) => result
|
|
54
|
+
? [
|
|
55
|
+
...result.sessions.map(({ id }) => ({
|
|
56
|
+
type: "Session",
|
|
57
|
+
id: id || "unknown",
|
|
58
|
+
})),
|
|
59
|
+
{ type: "Session", id: "LIST" },
|
|
60
|
+
]
|
|
61
|
+
: [{ type: "Session", id: "LIST" }],
|
|
62
|
+
}),
|
|
63
|
+
getSessionsInfiniteByDevice: builder.query({
|
|
64
|
+
async queryFn({ deviceId, limit = 20, cursor, supabase }) {
|
|
65
|
+
try {
|
|
66
|
+
if (!deviceId) {
|
|
67
|
+
return {
|
|
68
|
+
error: { status: "CUSTOM_ERROR", error: "Device ID is required" },
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const { data, error } = await supabase.rpc("get_sessions_infinite_by_device", {
|
|
72
|
+
device_id_caller: deviceId,
|
|
73
|
+
limit_caller: limit + 1,
|
|
74
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
75
|
+
cursor_id: cursor?.id || null,
|
|
76
|
+
});
|
|
77
|
+
if (error) {
|
|
78
|
+
return {
|
|
79
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const sessions = data || [];
|
|
83
|
+
const hasMore = sessions.length > limit;
|
|
84
|
+
const resultSessions = hasMore ? sessions.slice(0, limit) : sessions;
|
|
85
|
+
const nextCursor = hasMore && resultSessions.length > 0
|
|
86
|
+
? {
|
|
87
|
+
timestamp: resultSessions[resultSessions.length - 1].timestamp_start ||
|
|
88
|
+
"",
|
|
89
|
+
id: resultSessions[resultSessions.length - 1].id || 0,
|
|
90
|
+
}
|
|
91
|
+
: null;
|
|
92
|
+
return {
|
|
93
|
+
data: {
|
|
94
|
+
sessions: resultSessions,
|
|
95
|
+
nextCursor,
|
|
96
|
+
hasMore,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
providesTags: (result) => result
|
|
105
|
+
? [
|
|
106
|
+
...result.sessions.map(({ id }) => ({
|
|
107
|
+
type: "Session",
|
|
108
|
+
id: id || "unknown",
|
|
109
|
+
})),
|
|
110
|
+
{ type: "Session", id: "LIST" },
|
|
111
|
+
]
|
|
112
|
+
: [{ type: "Session", id: "LIST" }],
|
|
113
|
+
}),
|
|
114
|
+
// =====================================================
|
|
115
|
+
// EVENTS INFINITE QUERIES
|
|
116
|
+
// =====================================================
|
|
117
|
+
getEventsInfiniteByHerd: builder.query({
|
|
118
|
+
async queryFn({ herdId, limit = 20, cursor, supabase }) {
|
|
119
|
+
try {
|
|
120
|
+
if (!herdId) {
|
|
121
|
+
return {
|
|
122
|
+
error: { status: "CUSTOM_ERROR", error: "Herd ID is required" },
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const { data, error } = await supabase.rpc("get_events_infinite_by_herd", {
|
|
126
|
+
herd_id_caller: herdId,
|
|
127
|
+
limit_caller: limit + 1,
|
|
128
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
129
|
+
cursor_id: cursor?.id || null,
|
|
130
|
+
});
|
|
131
|
+
if (error) {
|
|
132
|
+
return {
|
|
133
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const events = data || [];
|
|
137
|
+
const hasMore = events.length > limit;
|
|
138
|
+
const resultEvents = hasMore ? events.slice(0, limit) : events;
|
|
139
|
+
const nextCursor = hasMore && resultEvents.length > 0
|
|
140
|
+
? {
|
|
141
|
+
timestamp: resultEvents[resultEvents.length - 1]
|
|
142
|
+
.timestamp_observation || "",
|
|
143
|
+
id: resultEvents[resultEvents.length - 1].id || 0,
|
|
144
|
+
}
|
|
145
|
+
: null;
|
|
146
|
+
return {
|
|
147
|
+
data: {
|
|
148
|
+
events: resultEvents,
|
|
149
|
+
nextCursor,
|
|
150
|
+
hasMore,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
providesTags: (result) => result
|
|
159
|
+
? [
|
|
160
|
+
...result.events.map(({ id }) => ({
|
|
161
|
+
type: "Event",
|
|
162
|
+
id: id || "unknown",
|
|
163
|
+
})),
|
|
164
|
+
{ type: "Event", id: "LIST" },
|
|
165
|
+
]
|
|
166
|
+
: [{ type: "Event", id: "LIST" }],
|
|
167
|
+
}),
|
|
168
|
+
getEventsInfiniteByDevice: builder.query({
|
|
169
|
+
async queryFn({ deviceId, limit = 20, cursor, supabase }) {
|
|
170
|
+
try {
|
|
171
|
+
if (!deviceId) {
|
|
172
|
+
return {
|
|
173
|
+
error: { status: "CUSTOM_ERROR", error: "Device ID is required" },
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const { data, error } = await supabase.rpc("get_events_infinite_by_device", {
|
|
177
|
+
device_id_caller: deviceId,
|
|
178
|
+
limit_caller: limit + 1,
|
|
179
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
180
|
+
cursor_id: cursor?.id || null,
|
|
181
|
+
});
|
|
182
|
+
if (error) {
|
|
183
|
+
return {
|
|
184
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const events = data || [];
|
|
188
|
+
const hasMore = events.length > limit;
|
|
189
|
+
const resultEvents = hasMore ? events.slice(0, limit) : events;
|
|
190
|
+
const nextCursor = hasMore && resultEvents.length > 0
|
|
191
|
+
? {
|
|
192
|
+
timestamp: resultEvents[resultEvents.length - 1]
|
|
193
|
+
.timestamp_observation || "",
|
|
194
|
+
id: resultEvents[resultEvents.length - 1].id || 0,
|
|
195
|
+
}
|
|
196
|
+
: null;
|
|
197
|
+
return {
|
|
198
|
+
data: {
|
|
199
|
+
events: resultEvents,
|
|
200
|
+
nextCursor,
|
|
201
|
+
hasMore,
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
providesTags: (result) => result
|
|
210
|
+
? [
|
|
211
|
+
...result.events.map(({ id }) => ({
|
|
212
|
+
type: "Event",
|
|
213
|
+
id: id || "unknown",
|
|
214
|
+
})),
|
|
215
|
+
{ type: "Event", id: "LIST" },
|
|
216
|
+
]
|
|
217
|
+
: [{ type: "Event", id: "LIST" }],
|
|
218
|
+
}),
|
|
219
|
+
// =====================================================
|
|
220
|
+
// ARTIFACTS INFINITE QUERIES
|
|
221
|
+
// =====================================================
|
|
222
|
+
getArtifactsInfiniteByHerd: builder.query({
|
|
223
|
+
async queryFn({ herdId, limit = 20, cursor, supabase }) {
|
|
224
|
+
try {
|
|
225
|
+
if (!herdId) {
|
|
226
|
+
return {
|
|
227
|
+
error: { status: "CUSTOM_ERROR", error: "Herd ID is required" },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const { data, error } = await supabase.rpc("get_artifacts_infinite_by_herd", {
|
|
231
|
+
herd_id_caller: herdId,
|
|
232
|
+
limit_caller: limit + 1,
|
|
233
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
234
|
+
cursor_id: cursor?.id || null,
|
|
235
|
+
});
|
|
236
|
+
if (error) {
|
|
237
|
+
return {
|
|
238
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const artifacts = data || [];
|
|
242
|
+
const hasMore = artifacts.length > limit;
|
|
243
|
+
const resultArtifacts = hasMore
|
|
244
|
+
? artifacts.slice(0, limit)
|
|
245
|
+
: artifacts;
|
|
246
|
+
// Generate signed URLs for artifacts
|
|
247
|
+
const uniqueFilePaths = Array.from(new Set(resultArtifacts
|
|
248
|
+
.map((artifact) => artifact.file_path)
|
|
249
|
+
.filter((path) => path !== null && path !== undefined)));
|
|
250
|
+
let urlMap = new Map();
|
|
251
|
+
if (uniqueFilePaths.length > 0) {
|
|
252
|
+
try {
|
|
253
|
+
const urlResults = await generateSignedUrlsBatch(uniqueFilePaths);
|
|
254
|
+
urlResults.forEach((url, index) => {
|
|
255
|
+
if (url) {
|
|
256
|
+
urlMap.set(uniqueFilePaths[index], url);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
catch (urlError) {
|
|
261
|
+
console.warn("Failed to generate signed URLs for artifacts:", urlError);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const artifactsWithUrls = resultArtifacts.map((artifact) => ({
|
|
265
|
+
...artifact,
|
|
266
|
+
media_url: artifact.file_path
|
|
267
|
+
? urlMap.get(artifact.file_path) || null
|
|
268
|
+
: null,
|
|
269
|
+
}));
|
|
270
|
+
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
271
|
+
? {
|
|
272
|
+
timestamp: resultArtifacts[resultArtifacts.length - 1].created_at,
|
|
273
|
+
id: resultArtifacts[resultArtifacts.length - 1].id,
|
|
274
|
+
}
|
|
275
|
+
: null;
|
|
276
|
+
return {
|
|
277
|
+
data: {
|
|
278
|
+
artifacts: artifactsWithUrls,
|
|
279
|
+
nextCursor,
|
|
280
|
+
hasMore,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
providesTags: (result) => result
|
|
289
|
+
? [
|
|
290
|
+
...result.artifacts.map(({ id }) => ({
|
|
291
|
+
type: "Artifact",
|
|
292
|
+
id,
|
|
293
|
+
})),
|
|
294
|
+
{ type: "Artifact", id: "LIST" },
|
|
295
|
+
]
|
|
296
|
+
: [{ type: "Artifact", id: "LIST" }],
|
|
297
|
+
}),
|
|
298
|
+
getArtifactsInfiniteByDevice: builder.query({
|
|
299
|
+
async queryFn({ deviceId, limit = 20, cursor, supabase }) {
|
|
300
|
+
try {
|
|
301
|
+
if (!deviceId) {
|
|
302
|
+
return {
|
|
303
|
+
error: { status: "CUSTOM_ERROR", error: "Device ID is required" },
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const { data, error } = await supabase.rpc("get_artifacts_infinite_by_device", {
|
|
307
|
+
device_id_caller: deviceId,
|
|
308
|
+
limit_caller: limit + 1,
|
|
309
|
+
cursor_timestamp: cursor?.timestamp || null,
|
|
310
|
+
cursor_id: cursor?.id || null,
|
|
311
|
+
});
|
|
312
|
+
if (error) {
|
|
313
|
+
return {
|
|
314
|
+
error: { status: "SUPABASE_ERROR", error: error.message },
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const artifacts = data || [];
|
|
318
|
+
const hasMore = artifacts.length > limit;
|
|
319
|
+
const resultArtifacts = hasMore
|
|
320
|
+
? artifacts.slice(0, limit)
|
|
321
|
+
: artifacts;
|
|
322
|
+
// Generate signed URLs for artifacts
|
|
323
|
+
const uniqueFilePaths = Array.from(new Set(resultArtifacts
|
|
324
|
+
.map((artifact) => artifact.file_path)
|
|
325
|
+
.filter((path) => path !== null && path !== undefined)));
|
|
326
|
+
let urlMap = new Map();
|
|
327
|
+
if (uniqueFilePaths.length > 0) {
|
|
328
|
+
try {
|
|
329
|
+
const urlResults = await generateSignedUrlsBatch(uniqueFilePaths);
|
|
330
|
+
urlResults.forEach((url, index) => {
|
|
331
|
+
if (url) {
|
|
332
|
+
urlMap.set(uniqueFilePaths[index], url);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (urlError) {
|
|
337
|
+
console.warn("Failed to generate signed URLs for artifacts:", urlError);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const artifactsWithUrls = resultArtifacts.map((artifact) => ({
|
|
341
|
+
...artifact,
|
|
342
|
+
media_url: artifact.file_path
|
|
343
|
+
? urlMap.get(artifact.file_path) || null
|
|
344
|
+
: null,
|
|
345
|
+
}));
|
|
346
|
+
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
347
|
+
? {
|
|
348
|
+
timestamp: resultArtifacts[resultArtifacts.length - 1].created_at,
|
|
349
|
+
id: resultArtifacts[resultArtifacts.length - 1].id,
|
|
350
|
+
}
|
|
351
|
+
: null;
|
|
352
|
+
return {
|
|
353
|
+
data: {
|
|
354
|
+
artifacts: artifactsWithUrls,
|
|
355
|
+
nextCursor,
|
|
356
|
+
hasMore,
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
return { error: { status: "FETCH_ERROR", error: String(err) } };
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
providesTags: (result) => result
|
|
365
|
+
? [
|
|
366
|
+
...result.artifacts.map(({ id }) => ({
|
|
367
|
+
type: "Artifact",
|
|
368
|
+
id,
|
|
369
|
+
})),
|
|
370
|
+
{ type: "Artifact", id: "LIST" },
|
|
371
|
+
]
|
|
372
|
+
: [{ type: "Artifact", id: "LIST" }],
|
|
373
|
+
}),
|
|
374
|
+
}),
|
|
375
|
+
});
|
|
376
|
+
// Export hooks for usage in functional components
|
|
377
|
+
export const { useGetSessionsInfiniteByHerdQuery, useGetSessionsInfiniteByDeviceQuery, useGetEventsInfiniteByHerdQuery, useGetEventsInfiniteByDeviceQuery, useGetArtifactsInfiniteByHerdQuery, useGetArtifactsInfiniteByDeviceQuery, } = scoutApi;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export declare const configureScoutStore: () => import("@reduxjs/toolkit").EnhancedStore<{
|
|
2
|
+
scout: import("./scout").ScoutState;
|
|
3
|
+
scoutApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
4
|
+
getSessionsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
5
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
6
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
7
|
+
getSessionsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
8
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
9
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
10
|
+
getEventsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
11
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
12
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
13
|
+
getEventsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
14
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
15
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
16
|
+
getArtifactsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
17
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
18
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
19
|
+
getArtifactsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
20
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
21
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
22
|
+
}, "Session" | "Event" | "Artifact", "scoutApi">;
|
|
23
|
+
}, import("redux").UnknownAction, import("@reduxjs/toolkit").Tuple<[import("redux").StoreEnhancer<{
|
|
24
|
+
dispatch: import("redux-thunk").ThunkDispatch<{
|
|
25
|
+
scout: import("./scout").ScoutState;
|
|
26
|
+
scoutApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
27
|
+
getSessionsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
28
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
29
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
30
|
+
getSessionsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
31
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
32
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
33
|
+
getEventsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
34
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
35
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
36
|
+
getEventsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
37
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
38
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
39
|
+
getArtifactsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
40
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
41
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
42
|
+
getArtifactsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
43
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
44
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
45
|
+
}, "Session" | "Event" | "Artifact", "scoutApi">;
|
|
46
|
+
}, undefined, import("redux").UnknownAction>;
|
|
47
|
+
}>, import("redux").StoreEnhancer]>>;
|
|
48
|
+
export type RootState = ReturnType<ReturnType<typeof configureScoutStore>["getState"]>;
|
|
49
|
+
export type AppDispatch = ReturnType<typeof configureScoutStore>["dispatch"];
|
|
50
|
+
export declare const store: import("@reduxjs/toolkit").EnhancedStore<{
|
|
51
|
+
scout: import("./scout").ScoutState;
|
|
52
|
+
scoutApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
53
|
+
getSessionsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
54
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
55
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
56
|
+
getSessionsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
57
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
58
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
59
|
+
getEventsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
60
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
61
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
62
|
+
getEventsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
63
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
64
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
65
|
+
getArtifactsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
66
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
67
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
68
|
+
getArtifactsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
69
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
70
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
71
|
+
}, "Session" | "Event" | "Artifact", "scoutApi">;
|
|
72
|
+
}, import("redux").UnknownAction, import("@reduxjs/toolkit").Tuple<[import("redux").StoreEnhancer<{
|
|
73
|
+
dispatch: import("redux-thunk").ThunkDispatch<{
|
|
74
|
+
scout: import("./scout").ScoutState;
|
|
75
|
+
scoutApi: import("@reduxjs/toolkit/query").CombinedState<{
|
|
76
|
+
getSessionsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
77
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
78
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
79
|
+
getSessionsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
80
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
81
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").SessionsInfiniteResponse, "scoutApi", unknown>;
|
|
82
|
+
getEventsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
83
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
84
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
85
|
+
getEventsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
86
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
87
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").EventsInfiniteResponse, "scoutApi", unknown>;
|
|
88
|
+
getArtifactsInfiniteByHerd: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
89
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
90
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
91
|
+
getArtifactsInfiniteByDevice: import("@reduxjs/toolkit/query").QueryDefinition<import("./api").InfiniteQueryArgs & {
|
|
92
|
+
supabase: import("@supabase/supabase-js").SupabaseClient;
|
|
93
|
+
}, import("@reduxjs/toolkit/query").BaseQueryFn<any, unknown, unknown, {}, {}>, "Session" | "Event" | "Artifact", import("./api").ArtifactsInfiniteResponse, "scoutApi", unknown>;
|
|
94
|
+
}, "Session" | "Event" | "Artifact", "scoutApi">;
|
|
95
|
+
}, undefined, import("redux").UnknownAction>;
|
|
96
|
+
}>, import("redux").StoreEnhancer]>>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { configureStore } from "@reduxjs/toolkit";
|
|
2
|
+
import { setupListeners } from "@reduxjs/toolkit/query";
|
|
3
|
+
import scoutReducer from "./scout";
|
|
4
|
+
import { scoutApi } from "./api";
|
|
5
|
+
// Configure the Redux store
|
|
6
|
+
export const configureScoutStore = () => {
|
|
7
|
+
const store = configureStore({
|
|
8
|
+
reducer: {
|
|
9
|
+
scout: scoutReducer,
|
|
10
|
+
[scoutApi.reducerPath]: scoutApi.reducer,
|
|
11
|
+
},
|
|
12
|
+
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
|
|
13
|
+
serializableCheck: {
|
|
14
|
+
// Ignore these action types for serializable check
|
|
15
|
+
ignoredActions: [
|
|
16
|
+
"persist/PERSIST",
|
|
17
|
+
"persist/REHYDRATE",
|
|
18
|
+
"persist/REGISTER",
|
|
19
|
+
// RTK Query actions
|
|
20
|
+
"scoutApi/executeQuery/pending",
|
|
21
|
+
"scoutApi/executeQuery/fulfilled",
|
|
22
|
+
"scoutApi/executeQuery/rejected",
|
|
23
|
+
"scoutApi/executeMutation/pending",
|
|
24
|
+
"scoutApi/executeMutation/fulfilled",
|
|
25
|
+
"scoutApi/executeMutation/rejected",
|
|
26
|
+
],
|
|
27
|
+
// Ignore these field paths in all actions
|
|
28
|
+
ignoredActionsPaths: ["meta.arg", "payload.timestamp"],
|
|
29
|
+
// Ignore these paths in the state
|
|
30
|
+
ignoredPaths: ["scoutApi.queries", "scoutApi.mutations"],
|
|
31
|
+
},
|
|
32
|
+
}).concat(scoutApi.middleware),
|
|
33
|
+
devTools: process.env.NODE_ENV !== "production",
|
|
34
|
+
});
|
|
35
|
+
// Enable listener behavior for the store
|
|
36
|
+
setupListeners(store.dispatch);
|
|
37
|
+
return store;
|
|
38
|
+
};
|
|
39
|
+
// Create a default store instance
|
|
40
|
+
export const store = configureScoutStore();
|
package/dist/store/hooks.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { LoadingPerformance } from "./scout";
|
|
2
|
+
import { ISessionSummary } from "../types/db";
|
|
1
3
|
export declare const useAppDispatch: import("react-redux").UseDispatch<import("redux").Dispatch<import("redux").UnknownAction>>;
|
|
2
4
|
export declare const useHerdModulesLoadingState: () => any;
|
|
3
5
|
export declare const useIsHerdModulesLoading: () => boolean;
|
|
@@ -5,4 +7,7 @@ export declare const useIsHerdModulesLoaded: () => boolean;
|
|
|
5
7
|
export declare const useIsHerdModulesFailed: () => boolean;
|
|
6
8
|
export declare const useHerdModulesLoadedAt: () => any;
|
|
7
9
|
export declare const useHerdModulesLoadingDuration: () => any;
|
|
10
|
+
export declare const useLoadingPerformance: () => LoadingPerformance;
|
|
11
|
+
export declare const useSessionSummariesByHerd: (herdId: number) => ISessionSummary | null;
|
|
12
|
+
export declare const useHasSessionSummaries: (herdId: number) => boolean;
|
|
8
13
|
export declare const useHerdModulesLoadingTimeAgo: () => string | null;
|
package/dist/store/hooks.js
CHANGED
|
@@ -23,18 +23,36 @@ export const useIsHerdModulesFailed = () => {
|
|
|
23
23
|
};
|
|
24
24
|
// Selector hook for getting when herd modules were last loaded
|
|
25
25
|
export const useHerdModulesLoadedAt = () => {
|
|
26
|
-
return useSelector((state) => state.scout.herd_modules_loaded_in_ms);
|
|
26
|
+
return useSelector((state) => state.scout.loading_performance.herd_modules_loaded_in_ms);
|
|
27
27
|
};
|
|
28
28
|
// Selector hook for getting the loading duration in milliseconds
|
|
29
29
|
export const useHerdModulesLoadingDuration = () => {
|
|
30
30
|
return useSelector((state) => {
|
|
31
|
-
return state.scout.herd_modules_loaded_in_ms;
|
|
31
|
+
return state.scout.loading_performance.herd_modules_loaded_in_ms;
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
// Selector hook for getting the complete loading performance object
|
|
35
|
+
export const useLoadingPerformance = () => {
|
|
36
|
+
return useSelector((state) => state.scout.loading_performance);
|
|
37
|
+
};
|
|
38
|
+
// Selector hook for getting session summaries for a specific herd
|
|
39
|
+
export const useSessionSummariesByHerd = (herdId) => {
|
|
40
|
+
return useSelector((state) => {
|
|
41
|
+
const herdModule = state.scout.herd_modules.find((hm) => hm.herd.id === herdId);
|
|
42
|
+
return herdModule?.session_summaries || null;
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
// Selector hook for checking if session summaries are available for a herd
|
|
46
|
+
export const useHasSessionSummaries = (herdId) => {
|
|
47
|
+
return useSelector((state) => {
|
|
48
|
+
const herdModule = state.scout.herd_modules.find((hm) => hm.herd.id === herdId);
|
|
49
|
+
return !!herdModule?.session_summaries;
|
|
32
50
|
});
|
|
33
51
|
};
|
|
34
52
|
// Selector hook for getting formatted loading time (e.g., "2.5s ago")
|
|
35
53
|
export const useHerdModulesLoadingTimeAgo = () => {
|
|
36
54
|
return useSelector((state) => {
|
|
37
|
-
const loadingDuration = state.scout.herd_modules_loaded_in_ms;
|
|
55
|
+
const loadingDuration = state.scout.loading_performance.herd_modules_loaded_in_ms;
|
|
38
56
|
if (!loadingDuration)
|
|
39
57
|
return null;
|
|
40
58
|
// Since we store the duration, we need to calculate when it was loaded
|
package/dist/store/index.d.ts
CHANGED
package/dist/store/index.js
CHANGED