@adventurelabs/scout-core 1.3.4 → 1.3.6
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 +1 -1
- package/dist/helpers/sessions.d.ts +5 -34
- package/dist/helpers/sessions.js +40 -456
- package/dist/providers/ScoutRefreshProvider.d.ts +21 -0
- package/dist/types/db.d.ts +1 -0
- package/dist/types/herd_module.d.ts +4 -2
- package/dist/types/herd_module.js +16 -42
- package/dist/types/supabase.d.ts +21 -0
- package/package.json +1 -1
package/dist/helpers/cache.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const DB_NAME = "ScoutCache";
|
|
2
|
-
const DB_VERSION =
|
|
2
|
+
const DB_VERSION = 5; // Increment to invalidate old cache versions
|
|
3
3
|
const HERD_MODULES_STORE = "herd_modules";
|
|
4
4
|
const CACHE_METADATA_STORE = "cache_metadata";
|
|
5
5
|
// Default TTL: 24 hours (1 day)
|
|
@@ -1,36 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISessionWithCoordinates, ISessionUsageOverTime, IEventAndTagsPrettyLocation } from "../types/db";
|
|
2
2
|
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export type SessionUpsertInput = SessionInput | SessionUpdateInput;
|
|
8
|
-
export type ConnectivityInput = Omit<IConnectivity, "id" | "inserted_at">;
|
|
9
|
-
export type ConnectivityUpdateInput = Partial<ConnectivityInput> & {
|
|
10
|
-
id: number;
|
|
11
|
-
};
|
|
12
|
-
export type ConnectivityUpsertInput = ConnectivityInput | ConnectivityUpdateInput;
|
|
13
|
-
export declare function server_get_sessions_by_herd_id(herdId: number): Promise<IWebResponseCompatible<ISessionWithCoordinates[]>>;
|
|
14
|
-
export declare function server_get_events_by_session_id(sessionId: number): Promise<IWebResponseCompatible<IEvent[]>>;
|
|
3
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
4
|
+
export declare function server_get_session_by_id(sessionId: number, client?: SupabaseClient): Promise<IWebResponseCompatible<ISessionWithCoordinates | null>>;
|
|
5
|
+
export declare function server_get_session_usage_over_time_by_herd(herd_id: number, client?: SupabaseClient): Promise<IWebResponseCompatible<ISessionUsageOverTime>>;
|
|
6
|
+
export declare function server_get_session_usage_over_time_by_device(device_id: number, client?: SupabaseClient): Promise<IWebResponseCompatible<ISessionUsageOverTime>>;
|
|
15
7
|
export declare function server_get_events_and_tags_by_session_id(sessionId: number, limit?: number, offset?: number): Promise<IWebResponseCompatible<IEventAndTagsPrettyLocation[]>>;
|
|
16
|
-
export declare function server_get_total_events_for_session(sessionId: number): Promise<IWebResponseCompatible<number>>;
|
|
17
|
-
export declare function server_upsert_session(sessionData: SessionUpsertInput): Promise<IWebResponseCompatible<ISession>>;
|
|
18
|
-
export declare function server_upsert_sessions(sessionsData: SessionUpsertInput[]): Promise<IWebResponseCompatible<ISession[]>>;
|
|
19
|
-
export declare function server_upsert_connectivity(connectivityData: ConnectivityUpsertInput): Promise<IWebResponseCompatible<IConnectivity>>;
|
|
20
|
-
export declare function server_upsert_connectivity_batch(connectivityDataArray: ConnectivityUpsertInput[]): Promise<IWebResponseCompatible<IConnectivity[]>>;
|
|
21
|
-
export declare function server_get_session_with_connectivity_and_events(sessionId: number, herdId?: number): Promise<IWebResponseCompatible<{
|
|
22
|
-
session: ISessionWithCoordinates | null;
|
|
23
|
-
connectivity: IConnectivityWithCoordinates[];
|
|
24
|
-
events: IEvent[];
|
|
25
|
-
}>>;
|
|
26
|
-
export declare function server_get_session_with_connectivity_and_events_with_tags(sessionId: number, limit?: number, offset?: number, herdId?: number): Promise<IWebResponseCompatible<{
|
|
27
|
-
session: ISessionWithCoordinates | null;
|
|
28
|
-
connectivity: IConnectivityWithCoordinates[];
|
|
29
|
-
eventsWithTags: IEventAndTagsPrettyLocation[];
|
|
30
|
-
totalEvents: number;
|
|
31
|
-
}>>;
|
|
32
|
-
export declare function server_get_sessions_by_device_id(deviceId: number): Promise<IWebResponseCompatible<ISessionWithCoordinates[]>>;
|
|
33
|
-
export declare function server_delete_session(sessionId: number): Promise<IWebResponseCompatible<boolean>>;
|
|
34
|
-
export declare function server_delete_sessions(sessionIds: number[]): Promise<IWebResponseCompatible<boolean>>;
|
|
35
|
-
export declare function server_delete_connectivity(connectivityId: number): Promise<IWebResponseCompatible<boolean>>;
|
|
36
|
-
export declare function server_delete_connectivity_batch(connectivityIds: number[]): Promise<IWebResponseCompatible<boolean>>;
|
package/dist/helpers/sessions.js
CHANGED
|
@@ -1,47 +1,57 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
herd_id_caller: herdId,
|
|
4
|
+
// Get session by ID with coordinates
|
|
5
|
+
export async function server_get_session_by_id(sessionId, client) {
|
|
6
|
+
const supabase = client || (await newServerClient());
|
|
7
|
+
const { data, error } = await supabase.rpc("get_session_by_id", {
|
|
8
|
+
session_id_caller: sessionId,
|
|
10
9
|
});
|
|
11
10
|
if (error) {
|
|
12
|
-
console.warn("Error fetching
|
|
11
|
+
console.warn("Error fetching session by id:", error.message);
|
|
13
12
|
return {
|
|
14
13
|
status: EnumWebResponse.ERROR,
|
|
15
14
|
msg: error.message,
|
|
16
|
-
data:
|
|
15
|
+
data: null,
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
|
-
//
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
// The RPC returns an array, but we want a single session or null
|
|
19
|
+
const session = data && data.length > 0 ? data[0] : null;
|
|
20
|
+
return IWebResponse.success(session).to_compatible();
|
|
21
|
+
}
|
|
22
|
+
// Get session usage over time by herd
|
|
23
|
+
export async function server_get_session_usage_over_time_by_herd(herd_id, client) {
|
|
24
|
+
const supabase = client || (await newServerClient());
|
|
25
|
+
const { data, error } = await supabase.rpc("get_session_usage_over_time", {
|
|
26
|
+
start_date_caller: undefined,
|
|
27
|
+
end_date_caller: undefined,
|
|
28
|
+
device_id_caller: undefined,
|
|
29
|
+
herd_id_caller: herd_id,
|
|
25
30
|
});
|
|
26
|
-
|
|
31
|
+
if (error) {
|
|
32
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
33
|
+
}
|
|
34
|
+
if (!data) {
|
|
35
|
+
return IWebResponse.error("No session usage data returned").to_compatible();
|
|
36
|
+
}
|
|
37
|
+
return IWebResponse.success(data).to_compatible();
|
|
27
38
|
}
|
|
28
|
-
// Get
|
|
29
|
-
export async function
|
|
30
|
-
const supabase = await newServerClient();
|
|
31
|
-
const { data, error } = await supabase
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
// Get session usage over time by device
|
|
40
|
+
export async function server_get_session_usage_over_time_by_device(device_id, client) {
|
|
41
|
+
const supabase = client || (await newServerClient());
|
|
42
|
+
const { data, error } = await supabase.rpc("get_session_usage_over_time", {
|
|
43
|
+
start_date_caller: undefined,
|
|
44
|
+
end_date_caller: undefined,
|
|
45
|
+
device_id_caller: device_id,
|
|
46
|
+
herd_id_caller: undefined,
|
|
47
|
+
});
|
|
36
48
|
if (error) {
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
status: EnumWebResponse.ERROR,
|
|
40
|
-
msg: error.message,
|
|
41
|
-
data: [],
|
|
42
|
-
};
|
|
49
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
43
50
|
}
|
|
44
|
-
|
|
51
|
+
if (!data) {
|
|
52
|
+
return IWebResponse.error("No session usage data returned").to_compatible();
|
|
53
|
+
}
|
|
54
|
+
return IWebResponse.success(data).to_compatible();
|
|
45
55
|
}
|
|
46
56
|
// Get events with tags by session id using RPC function
|
|
47
57
|
export async function server_get_events_and_tags_by_session_id(sessionId, limit = 50, offset = 0) {
|
|
@@ -61,429 +71,3 @@ export async function server_get_events_and_tags_by_session_id(sessionId, limit
|
|
|
61
71
|
}
|
|
62
72
|
return IWebResponse.success(data || []).to_compatible();
|
|
63
73
|
}
|
|
64
|
-
// Get total count of events for a session
|
|
65
|
-
export async function server_get_total_events_for_session(sessionId) {
|
|
66
|
-
const supabase = await newServerClient();
|
|
67
|
-
const { data, error } = await supabase.rpc("get_total_events_for_session", {
|
|
68
|
-
session_id_caller: sessionId,
|
|
69
|
-
});
|
|
70
|
-
if (error) {
|
|
71
|
-
console.warn("Error fetching total events for session:", error.message);
|
|
72
|
-
return {
|
|
73
|
-
status: EnumWebResponse.ERROR,
|
|
74
|
-
msg: error.message,
|
|
75
|
-
data: 0,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return IWebResponse.success(data || 0).to_compatible();
|
|
79
|
-
}
|
|
80
|
-
// Create or update session
|
|
81
|
-
export async function server_upsert_session(sessionData) {
|
|
82
|
-
const supabase = await newServerClient();
|
|
83
|
-
const isUpdate = "id" in sessionData;
|
|
84
|
-
if (isUpdate) {
|
|
85
|
-
// Update existing session
|
|
86
|
-
const { id, ...updateData } = sessionData;
|
|
87
|
-
const { data, error } = await supabase
|
|
88
|
-
.from("sessions")
|
|
89
|
-
.update(updateData)
|
|
90
|
-
.eq("id", id)
|
|
91
|
-
.select()
|
|
92
|
-
.single();
|
|
93
|
-
if (error) {
|
|
94
|
-
console.warn("Error updating session:", error.message);
|
|
95
|
-
return {
|
|
96
|
-
status: EnumWebResponse.ERROR,
|
|
97
|
-
msg: error.message,
|
|
98
|
-
data: null,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return IWebResponse.success(data).to_compatible();
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
// Create new session
|
|
105
|
-
const { data, error } = await supabase
|
|
106
|
-
.from("sessions")
|
|
107
|
-
.insert(sessionData)
|
|
108
|
-
.select()
|
|
109
|
-
.single();
|
|
110
|
-
if (error) {
|
|
111
|
-
console.warn("Error creating session:", error.message);
|
|
112
|
-
return {
|
|
113
|
-
status: EnumWebResponse.ERROR,
|
|
114
|
-
msg: error.message,
|
|
115
|
-
data: null,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
return IWebResponse.success(data).to_compatible();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// Batch upsert sessions
|
|
122
|
-
export async function server_upsert_sessions(sessionsData) {
|
|
123
|
-
const supabase = await newServerClient();
|
|
124
|
-
if (sessionsData.length === 0) {
|
|
125
|
-
return IWebResponse.success([]).to_compatible();
|
|
126
|
-
}
|
|
127
|
-
// Separate updates and inserts
|
|
128
|
-
const updates = sessionsData.filter((s) => "id" in s);
|
|
129
|
-
const inserts = sessionsData.filter((s) => !("id" in s));
|
|
130
|
-
const results = [];
|
|
131
|
-
// Handle updates
|
|
132
|
-
if (updates.length > 0) {
|
|
133
|
-
for (const sessionData of updates) {
|
|
134
|
-
const updateResult = await server_upsert_session(sessionData);
|
|
135
|
-
if (updateResult.status === EnumWebResponse.SUCCESS &&
|
|
136
|
-
updateResult.data) {
|
|
137
|
-
results.push(updateResult.data);
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
console.warn(`Failed to update session ${sessionData.id}:`, updateResult.msg);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Handle inserts
|
|
145
|
-
if (inserts.length > 0) {
|
|
146
|
-
const { data, error } = await supabase
|
|
147
|
-
.from("sessions")
|
|
148
|
-
.insert(inserts)
|
|
149
|
-
.select();
|
|
150
|
-
if (error) {
|
|
151
|
-
console.warn("Error creating sessions:", error.message);
|
|
152
|
-
return {
|
|
153
|
-
status: EnumWebResponse.ERROR,
|
|
154
|
-
msg: error.message,
|
|
155
|
-
data: results,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
results.push(...(data || []));
|
|
159
|
-
}
|
|
160
|
-
return IWebResponse.success(results).to_compatible();
|
|
161
|
-
}
|
|
162
|
-
// Create or update connectivity
|
|
163
|
-
export async function server_upsert_connectivity(connectivityData) {
|
|
164
|
-
const supabase = await newServerClient();
|
|
165
|
-
const isUpdate = "id" in connectivityData;
|
|
166
|
-
if (isUpdate) {
|
|
167
|
-
// Update existing connectivity
|
|
168
|
-
const { id, ...updateData } = connectivityData;
|
|
169
|
-
const { data, error } = await supabase
|
|
170
|
-
.from("connectivity")
|
|
171
|
-
.update(updateData)
|
|
172
|
-
.eq("id", id)
|
|
173
|
-
.select()
|
|
174
|
-
.single();
|
|
175
|
-
if (error) {
|
|
176
|
-
console.warn("Error updating connectivity:", error.message);
|
|
177
|
-
return {
|
|
178
|
-
status: EnumWebResponse.ERROR,
|
|
179
|
-
msg: error.message,
|
|
180
|
-
data: null,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
return IWebResponse.success(data).to_compatible();
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
// Create new connectivity
|
|
187
|
-
const { data, error } = await supabase
|
|
188
|
-
.from("connectivity")
|
|
189
|
-
.insert(connectivityData)
|
|
190
|
-
.select()
|
|
191
|
-
.single();
|
|
192
|
-
if (error) {
|
|
193
|
-
console.warn("Error creating connectivity:", error.message);
|
|
194
|
-
return {
|
|
195
|
-
status: EnumWebResponse.ERROR,
|
|
196
|
-
msg: error.message,
|
|
197
|
-
data: null,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
return IWebResponse.success(data).to_compatible();
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// Batch upsert connectivity
|
|
204
|
-
export async function server_upsert_connectivity_batch(connectivityDataArray) {
|
|
205
|
-
const supabase = await newServerClient();
|
|
206
|
-
if (connectivityDataArray.length === 0) {
|
|
207
|
-
return IWebResponse.success([]).to_compatible();
|
|
208
|
-
}
|
|
209
|
-
// Separate updates and inserts
|
|
210
|
-
const updates = connectivityDataArray.filter((c) => "id" in c);
|
|
211
|
-
const inserts = connectivityDataArray.filter((c) => !("id" in c));
|
|
212
|
-
const results = [];
|
|
213
|
-
// Handle updates
|
|
214
|
-
if (updates.length > 0) {
|
|
215
|
-
for (const connectivityData of updates) {
|
|
216
|
-
const updateResult = await server_upsert_connectivity(connectivityData);
|
|
217
|
-
if (updateResult.status === EnumWebResponse.SUCCESS &&
|
|
218
|
-
updateResult.data) {
|
|
219
|
-
results.push(updateResult.data);
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
console.warn(`Failed to update connectivity ${connectivityData.id}:`, updateResult.msg);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
// Handle inserts
|
|
227
|
-
if (inserts.length > 0) {
|
|
228
|
-
const { data, error } = await supabase
|
|
229
|
-
.from("connectivity")
|
|
230
|
-
.insert(inserts)
|
|
231
|
-
.select();
|
|
232
|
-
if (error) {
|
|
233
|
-
console.warn("Error creating connectivity entries:", error.message);
|
|
234
|
-
return {
|
|
235
|
-
status: EnumWebResponse.ERROR,
|
|
236
|
-
msg: error.message,
|
|
237
|
-
data: results,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
results.push(...(data || []));
|
|
241
|
-
}
|
|
242
|
-
return IWebResponse.success(results).to_compatible();
|
|
243
|
-
}
|
|
244
|
-
// Get session with connectivity and events using RPC functions
|
|
245
|
-
export async function server_get_session_with_connectivity_and_events(sessionId, herdId) {
|
|
246
|
-
const supabase = await newServerClient();
|
|
247
|
-
let sessionWithCoords = null;
|
|
248
|
-
if (herdId) {
|
|
249
|
-
// Use provided herd ID directly
|
|
250
|
-
const sessionsResult = await server_get_sessions_by_herd_id(herdId);
|
|
251
|
-
if (sessionsResult.status === EnumWebResponse.SUCCESS &&
|
|
252
|
-
sessionsResult.data) {
|
|
253
|
-
sessionWithCoords =
|
|
254
|
-
sessionsResult.data.find((s) => s.id === sessionId) || null;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
// Get the session from the sessions table first to get the device_id
|
|
259
|
-
const { data: sessionData, error: sessionError } = await supabase
|
|
260
|
-
.from("sessions")
|
|
261
|
-
.select("*")
|
|
262
|
-
.eq("id", sessionId)
|
|
263
|
-
.single();
|
|
264
|
-
if (sessionError) {
|
|
265
|
-
console.warn("Error getting session:", sessionError.message);
|
|
266
|
-
return {
|
|
267
|
-
status: EnumWebResponse.ERROR,
|
|
268
|
-
msg: sessionError.message,
|
|
269
|
-
data: {
|
|
270
|
-
session: null,
|
|
271
|
-
connectivity: [],
|
|
272
|
-
events: [],
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
// Get the device to find its herd_id
|
|
277
|
-
const { data: device, error: deviceError } = await supabase
|
|
278
|
-
.from("devices")
|
|
279
|
-
.select("herd_id")
|
|
280
|
-
.eq("id", sessionData.device_id)
|
|
281
|
-
.single();
|
|
282
|
-
if (deviceError) {
|
|
283
|
-
console.warn("Error getting device:", deviceError.message);
|
|
284
|
-
return {
|
|
285
|
-
status: EnumWebResponse.ERROR,
|
|
286
|
-
msg: deviceError.message,
|
|
287
|
-
data: {
|
|
288
|
-
session: null,
|
|
289
|
-
connectivity: [],
|
|
290
|
-
events: [],
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
const sessionsResult = await server_get_sessions_by_herd_id(device.herd_id);
|
|
295
|
-
if (sessionsResult.status === EnumWebResponse.SUCCESS &&
|
|
296
|
-
sessionsResult.data) {
|
|
297
|
-
sessionWithCoords =
|
|
298
|
-
sessionsResult.data.find((s) => s.id === sessionId) || null;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
const [connectivityResult, eventsResult] = await Promise.all([
|
|
302
|
-
server_get_connectivity_by_session_id(sessionId),
|
|
303
|
-
server_get_events_by_session_id(sessionId),
|
|
304
|
-
]);
|
|
305
|
-
const connectivity = connectivityResult.status === EnumWebResponse.SUCCESS
|
|
306
|
-
? connectivityResult.data || []
|
|
307
|
-
: [];
|
|
308
|
-
const events = eventsResult.status === EnumWebResponse.SUCCESS
|
|
309
|
-
? eventsResult.data || []
|
|
310
|
-
: [];
|
|
311
|
-
return IWebResponse.success({
|
|
312
|
-
session: sessionWithCoords,
|
|
313
|
-
connectivity,
|
|
314
|
-
events,
|
|
315
|
-
}).to_compatible();
|
|
316
|
-
}
|
|
317
|
-
// Get session with connectivity and events with tags using RPC functions
|
|
318
|
-
export async function server_get_session_with_connectivity_and_events_with_tags(sessionId, limit = 50, offset = 0, herdId) {
|
|
319
|
-
const supabase = await newServerClient();
|
|
320
|
-
let sessionWithCoords = null;
|
|
321
|
-
let actualHerdId;
|
|
322
|
-
if (herdId) {
|
|
323
|
-
// Use provided herd ID directly
|
|
324
|
-
actualHerdId = herdId;
|
|
325
|
-
const sessionsResult = await server_get_sessions_by_herd_id(herdId);
|
|
326
|
-
if (sessionsResult.status === EnumWebResponse.SUCCESS &&
|
|
327
|
-
sessionsResult.data) {
|
|
328
|
-
sessionWithCoords =
|
|
329
|
-
sessionsResult.data.find((s) => s.id === sessionId) || null;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
// Get the session from the sessions table first to get the device_id
|
|
334
|
-
const { data: sessionData, error: sessionError } = await supabase
|
|
335
|
-
.from("sessions")
|
|
336
|
-
.select("*")
|
|
337
|
-
.eq("id", sessionId)
|
|
338
|
-
.single();
|
|
339
|
-
if (sessionError) {
|
|
340
|
-
console.warn("Error getting session:", sessionError.message);
|
|
341
|
-
return {
|
|
342
|
-
status: EnumWebResponse.ERROR,
|
|
343
|
-
msg: sessionError.message,
|
|
344
|
-
data: {
|
|
345
|
-
session: null,
|
|
346
|
-
connectivity: [],
|
|
347
|
-
eventsWithTags: [],
|
|
348
|
-
totalEvents: 0,
|
|
349
|
-
},
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
// Get the device to find its herd_id
|
|
353
|
-
const { data: device, error: deviceError } = await supabase
|
|
354
|
-
.from("devices")
|
|
355
|
-
.select("herd_id")
|
|
356
|
-
.eq("id", sessionData.device_id)
|
|
357
|
-
.single();
|
|
358
|
-
if (deviceError) {
|
|
359
|
-
console.warn("Error getting device:", deviceError.message);
|
|
360
|
-
return {
|
|
361
|
-
status: EnumWebResponse.ERROR,
|
|
362
|
-
msg: deviceError.message,
|
|
363
|
-
data: {
|
|
364
|
-
session: null,
|
|
365
|
-
connectivity: [],
|
|
366
|
-
eventsWithTags: [],
|
|
367
|
-
totalEvents: 0,
|
|
368
|
-
},
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
actualHerdId = device.herd_id;
|
|
372
|
-
const sessionsResult = await server_get_sessions_by_herd_id(device.herd_id);
|
|
373
|
-
if (sessionsResult.status === EnumWebResponse.SUCCESS &&
|
|
374
|
-
sessionsResult.data) {
|
|
375
|
-
sessionWithCoords =
|
|
376
|
-
sessionsResult.data.find((s) => s.id === sessionId) || null;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
const [connectivityResult, eventsWithTagsResult, totalEventsResult] = await Promise.all([
|
|
380
|
-
server_get_connectivity_by_session_id(sessionId),
|
|
381
|
-
server_get_events_and_tags_by_session_id(sessionId, limit, offset),
|
|
382
|
-
server_get_total_events_for_session(sessionId),
|
|
383
|
-
]);
|
|
384
|
-
const connectivity = connectivityResult.status === EnumWebResponse.SUCCESS
|
|
385
|
-
? connectivityResult.data || []
|
|
386
|
-
: [];
|
|
387
|
-
const eventsWithTags = eventsWithTagsResult.status === EnumWebResponse.SUCCESS
|
|
388
|
-
? eventsWithTagsResult.data || []
|
|
389
|
-
: [];
|
|
390
|
-
const totalEvents = totalEventsResult.status === EnumWebResponse.SUCCESS
|
|
391
|
-
? totalEventsResult.data || 0
|
|
392
|
-
: 0;
|
|
393
|
-
return IWebResponse.success({
|
|
394
|
-
session: sessionWithCoords,
|
|
395
|
-
connectivity,
|
|
396
|
-
eventsWithTags,
|
|
397
|
-
totalEvents,
|
|
398
|
-
}).to_compatible();
|
|
399
|
-
}
|
|
400
|
-
// Get sessions for a device using RPC function
|
|
401
|
-
export async function server_get_sessions_by_device_id(deviceId) {
|
|
402
|
-
const supabase = await newServerClient();
|
|
403
|
-
const { data, error } = await supabase.rpc("get_sessions_with_coordinates_by_device", {
|
|
404
|
-
device_id_caller: deviceId,
|
|
405
|
-
});
|
|
406
|
-
if (error) {
|
|
407
|
-
console.warn("Error fetching sessions by device id:", error.message);
|
|
408
|
-
return {
|
|
409
|
-
status: EnumWebResponse.ERROR,
|
|
410
|
-
msg: error.message,
|
|
411
|
-
data: [],
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
return IWebResponse.success(data || []).to_compatible();
|
|
415
|
-
}
|
|
416
|
-
// Delete session and all related data
|
|
417
|
-
export async function server_delete_session(sessionId) {
|
|
418
|
-
const supabase = await newServerClient();
|
|
419
|
-
const { error } = await supabase
|
|
420
|
-
.from("sessions")
|
|
421
|
-
.delete()
|
|
422
|
-
.eq("id", sessionId);
|
|
423
|
-
if (error) {
|
|
424
|
-
console.warn("Error deleting session:", error.message);
|
|
425
|
-
return {
|
|
426
|
-
status: EnumWebResponse.ERROR,
|
|
427
|
-
msg: error.message,
|
|
428
|
-
data: false,
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
return IWebResponse.success(true).to_compatible();
|
|
432
|
-
}
|
|
433
|
-
// Batch delete sessions
|
|
434
|
-
export async function server_delete_sessions(sessionIds) {
|
|
435
|
-
const supabase = await newServerClient();
|
|
436
|
-
if (sessionIds.length === 0) {
|
|
437
|
-
return IWebResponse.success(true).to_compatible();
|
|
438
|
-
}
|
|
439
|
-
const { error } = await supabase
|
|
440
|
-
.from("sessions")
|
|
441
|
-
.delete()
|
|
442
|
-
.in("id", sessionIds);
|
|
443
|
-
if (error) {
|
|
444
|
-
console.warn("Error deleting sessions:", error.message);
|
|
445
|
-
return {
|
|
446
|
-
status: EnumWebResponse.ERROR,
|
|
447
|
-
msg: error.message,
|
|
448
|
-
data: false,
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
return IWebResponse.success(true).to_compatible();
|
|
452
|
-
}
|
|
453
|
-
// Delete connectivity entry
|
|
454
|
-
export async function server_delete_connectivity(connectivityId) {
|
|
455
|
-
const supabase = await newServerClient();
|
|
456
|
-
const { error } = await supabase
|
|
457
|
-
.from("connectivity")
|
|
458
|
-
.delete()
|
|
459
|
-
.eq("id", connectivityId);
|
|
460
|
-
if (error) {
|
|
461
|
-
console.warn("Error deleting connectivity:", error.message);
|
|
462
|
-
return {
|
|
463
|
-
status: EnumWebResponse.ERROR,
|
|
464
|
-
msg: error.message,
|
|
465
|
-
data: false,
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
return IWebResponse.success(true).to_compatible();
|
|
469
|
-
}
|
|
470
|
-
// Batch delete connectivity entries
|
|
471
|
-
export async function server_delete_connectivity_batch(connectivityIds) {
|
|
472
|
-
const supabase = await newServerClient();
|
|
473
|
-
if (connectivityIds.length === 0) {
|
|
474
|
-
return IWebResponse.success(true).to_compatible();
|
|
475
|
-
}
|
|
476
|
-
const { error } = await supabase
|
|
477
|
-
.from("connectivity")
|
|
478
|
-
.delete()
|
|
479
|
-
.in("id", connectivityIds);
|
|
480
|
-
if (error) {
|
|
481
|
-
console.warn("Error deleting connectivity entries:", error.message);
|
|
482
|
-
return {
|
|
483
|
-
status: EnumWebResponse.ERROR,
|
|
484
|
-
msg: error.message,
|
|
485
|
-
data: false,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
return IWebResponse.success(true).to_compatible();
|
|
489
|
-
}
|
|
@@ -1405,6 +1405,18 @@ export declare function useSupabase(): SupabaseClient<Database, "public", "publi
|
|
|
1405
1405
|
isSetofReturn: true;
|
|
1406
1406
|
};
|
|
1407
1407
|
};
|
|
1408
|
+
get_session_by_id: {
|
|
1409
|
+
Args: {
|
|
1410
|
+
session_id_caller: number;
|
|
1411
|
+
};
|
|
1412
|
+
Returns: Database["public"]["CompositeTypes"]["session_with_coordinates"][];
|
|
1413
|
+
SetofOptions: {
|
|
1414
|
+
from: "*";
|
|
1415
|
+
to: "session_with_coordinates";
|
|
1416
|
+
isOneToOne: false;
|
|
1417
|
+
isSetofReturn: true;
|
|
1418
|
+
};
|
|
1419
|
+
};
|
|
1408
1420
|
get_session_summaries: {
|
|
1409
1421
|
Args: {
|
|
1410
1422
|
device_id_caller?: number;
|
|
@@ -1414,6 +1426,15 @@ export declare function useSupabase(): SupabaseClient<Database, "public", "publi
|
|
|
1414
1426
|
};
|
|
1415
1427
|
Returns: import("../types/supabase").Json;
|
|
1416
1428
|
};
|
|
1429
|
+
get_session_usage_over_time: {
|
|
1430
|
+
Args: {
|
|
1431
|
+
device_id_caller?: number;
|
|
1432
|
+
end_date_caller?: string;
|
|
1433
|
+
herd_id_caller?: number;
|
|
1434
|
+
start_date_caller?: string;
|
|
1435
|
+
};
|
|
1436
|
+
Returns: import("../types/supabase").Json;
|
|
1437
|
+
};
|
|
1417
1438
|
get_sessions_infinite_by_device: {
|
|
1418
1439
|
Args: {
|
|
1419
1440
|
cursor_id?: number;
|
package/dist/types/db.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ export interface ISessionSummary {
|
|
|
48
48
|
herd_id: number | null;
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
+
export type ISessionUsageOverTime = Database["public"]["Functions"]["get_session_usage_over_time"]["Returns"];
|
|
51
52
|
export type ComponentInsert = Database["public"]["Tables"]["components"]["Insert"];
|
|
52
53
|
export type VersionsSoftwareInsert = Database["public"]["Tables"]["versions_software"]["Insert"];
|
|
53
54
|
export type ArtifactInsert = Database["public"]["Tables"]["artifacts"]["Insert"];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import { IDevice, IHerd, IPlan, ILayer, IProvider, IUserAndRole, IZoneWithActions, ISessionSummary } from "../types/db";
|
|
2
|
+
import { IDevice, IHerd, IPlan, ILayer, IProvider, IUserAndRole, IZoneWithActions, ISessionSummary, ISessionUsageOverTime } from "../types/db";
|
|
3
3
|
import { EnumWebResponse } from "./requests";
|
|
4
4
|
export declare enum EnumHerdModulesLoadingState {
|
|
5
5
|
NOT_LOADING = "NOT_LOADING",
|
|
@@ -18,7 +18,8 @@ export declare class HerdModule {
|
|
|
18
18
|
layers: ILayer[];
|
|
19
19
|
providers: IProvider[];
|
|
20
20
|
session_summaries: ISessionSummary | null;
|
|
21
|
-
|
|
21
|
+
session_usage: ISessionUsageOverTime | null;
|
|
22
|
+
constructor(herd: IHerd, devices: IDevice[], timestamp_last_refreshed: number, user_roles?: IUserAndRole[] | null, labels?: string[], plans?: IPlan[], zones?: IZoneWithActions[], layers?: ILayer[], providers?: IProvider[], session_summaries?: ISessionSummary | null, session_usage?: ISessionUsageOverTime | null);
|
|
22
23
|
to_serializable(): IHerdModule;
|
|
23
24
|
static from_herd(herd: IHerd, client: SupabaseClient): Promise<HerdModule>;
|
|
24
25
|
}
|
|
@@ -33,6 +34,7 @@ export interface IHerdModule {
|
|
|
33
34
|
layers: ILayer[];
|
|
34
35
|
providers: IProvider[];
|
|
35
36
|
session_summaries: ISessionSummary | null;
|
|
37
|
+
session_usage: ISessionUsageOverTime | null;
|
|
36
38
|
}
|
|
37
39
|
export interface IHerdModulesResponse {
|
|
38
40
|
data: IHerdModule[];
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { LABELS } from "../constants/annotator";
|
|
2
2
|
import { get_devices_by_herd } from "../helpers/devices";
|
|
3
|
-
import { server_get_total_events_by_herd } from "../helpers/events";
|
|
4
|
-
import { EnumSessionsVisibility } from "./events";
|
|
5
3
|
import { server_get_plans_by_herd } from "../helpers/plans";
|
|
6
4
|
import { server_get_layers_by_herd } from "../helpers/layers";
|
|
7
5
|
import { server_get_providers_by_herd } from "../helpers/providers";
|
|
@@ -9,9 +7,8 @@ import { server_get_users_with_herd_access } from "../helpers/users";
|
|
|
9
7
|
import { EnumWebResponse } from "./requests";
|
|
10
8
|
import { server_get_more_zones_and_actions_for_herd } from "../helpers/zones";
|
|
11
9
|
import { server_list_api_keys_batch } from "../api_keys/actions";
|
|
12
|
-
import { server_get_sessions_by_herd_id } from "../helpers/sessions";
|
|
13
|
-
import { server_get_artifacts_by_herd, server_get_total_artifacts_by_herd, } from "../helpers/artifacts";
|
|
14
10
|
import { server_get_session_summaries_by_herd } from "../helpers/session_summaries";
|
|
11
|
+
import { server_get_session_usage_over_time_by_herd } from "../helpers/sessions";
|
|
15
12
|
export var EnumHerdModulesLoadingState;
|
|
16
13
|
(function (EnumHerdModulesLoadingState) {
|
|
17
14
|
EnumHerdModulesLoadingState["NOT_LOADING"] = "NOT_LOADING";
|
|
@@ -20,13 +17,14 @@ export var EnumHerdModulesLoadingState;
|
|
|
20
17
|
EnumHerdModulesLoadingState["UNSUCCESSFULLY_LOADED"] = "UNSUCCESSFULLY_LOADED";
|
|
21
18
|
})(EnumHerdModulesLoadingState || (EnumHerdModulesLoadingState = {}));
|
|
22
19
|
export class HerdModule {
|
|
23
|
-
constructor(herd, devices, timestamp_last_refreshed, user_roles = null, labels = [], plans = [], zones = [], layers = [], providers = [], session_summaries = null) {
|
|
20
|
+
constructor(herd, devices, timestamp_last_refreshed, user_roles = null, labels = [], plans = [], zones = [], layers = [], providers = [], session_summaries = null, session_usage = null) {
|
|
24
21
|
this.user_roles = null;
|
|
25
22
|
this.labels = [];
|
|
26
23
|
this.plans = [];
|
|
27
24
|
this.layers = [];
|
|
28
25
|
this.providers = [];
|
|
29
26
|
this.session_summaries = null;
|
|
27
|
+
this.session_usage = null;
|
|
30
28
|
this.herd = herd;
|
|
31
29
|
this.devices = devices;
|
|
32
30
|
this.timestamp_last_refreshed = timestamp_last_refreshed;
|
|
@@ -37,6 +35,7 @@ export class HerdModule {
|
|
|
37
35
|
this.layers = layers;
|
|
38
36
|
this.providers = providers;
|
|
39
37
|
this.session_summaries = session_summaries;
|
|
38
|
+
this.session_usage = session_usage;
|
|
40
39
|
}
|
|
41
40
|
to_serializable() {
|
|
42
41
|
return {
|
|
@@ -50,6 +49,7 @@ export class HerdModule {
|
|
|
50
49
|
layers: this.layers,
|
|
51
50
|
providers: this.providers,
|
|
52
51
|
session_summaries: this.session_summaries,
|
|
52
|
+
session_usage: this.session_usage,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
static async from_herd(herd, client) {
|
|
@@ -65,22 +65,10 @@ export class HerdModule {
|
|
|
65
65
|
console.warn(`[HerdModule] Failed to get user roles:`, error);
|
|
66
66
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
67
67
|
}),
|
|
68
|
-
server_get_total_events_by_herd(herd.id, EnumSessionsVisibility.Exclude).catch((error) => {
|
|
69
|
-
console.warn(`[HerdModule] Failed to get total events count:`, error);
|
|
70
|
-
return { status: EnumWebResponse.ERROR, data: null };
|
|
71
|
-
}),
|
|
72
68
|
server_get_plans_by_herd(herd.id).catch((error) => {
|
|
73
69
|
console.warn(`[HerdModule] Failed to get plans:`, error);
|
|
74
70
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
75
71
|
}),
|
|
76
|
-
server_get_sessions_by_herd_id(herd.id).catch((error) => {
|
|
77
|
-
console.warn(`[HerdModule] Failed to get sessions:`, error);
|
|
78
|
-
return {
|
|
79
|
-
status: EnumWebResponse.ERROR,
|
|
80
|
-
data: [],
|
|
81
|
-
msg: error.message,
|
|
82
|
-
};
|
|
83
|
-
}),
|
|
84
72
|
server_get_layers_by_herd(herd.id).catch((error) => {
|
|
85
73
|
console.warn(`[HerdModule] Failed to get layers:`, error);
|
|
86
74
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
@@ -89,18 +77,14 @@ export class HerdModule {
|
|
|
89
77
|
console.warn(`[HerdModule] Failed to get providers:`, error);
|
|
90
78
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
91
79
|
}),
|
|
92
|
-
server_get_artifacts_by_herd(herd.id, 50, 0).catch((error) => {
|
|
93
|
-
console.warn(`[HerdModule] Failed to get artifacts:`, error);
|
|
94
|
-
return { status: EnumWebResponse.ERROR, data: null };
|
|
95
|
-
}),
|
|
96
|
-
server_get_total_artifacts_by_herd(herd.id).catch((error) => {
|
|
97
|
-
console.warn(`[HerdModule] Failed to get total artifacts count:`, error);
|
|
98
|
-
return { status: EnumWebResponse.ERROR, data: null };
|
|
99
|
-
}),
|
|
100
80
|
server_get_session_summaries_by_herd(herd.id, client).catch((error) => {
|
|
101
81
|
console.warn(`[HerdModule] Failed to get session summaries:`, error);
|
|
102
82
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
103
83
|
}),
|
|
84
|
+
server_get_session_usage_over_time_by_herd(herd.id, client).catch((error) => {
|
|
85
|
+
console.warn(`[HerdModule] Failed to get session usage:`, error);
|
|
86
|
+
return { status: EnumWebResponse.ERROR, data: null };
|
|
87
|
+
}),
|
|
104
88
|
]);
|
|
105
89
|
// Load devices
|
|
106
90
|
const devicesPromise = get_devices_by_herd(herd.id, client);
|
|
@@ -133,53 +117,43 @@ export class HerdModule {
|
|
|
133
117
|
}
|
|
134
118
|
}
|
|
135
119
|
// Extract herd-level data with safe fallbacks
|
|
136
|
-
const [res_zones, res_user_roles,
|
|
120
|
+
const [res_zones, res_user_roles, res_plans, res_layers, res_providers, session_summaries_result, session_usage_result,] = herdLevelResults;
|
|
137
121
|
const zones = res_zones.status === "fulfilled" && res_zones.value?.data
|
|
138
122
|
? res_zones.value.data
|
|
139
123
|
: [];
|
|
140
124
|
const user_roles = res_user_roles.status === "fulfilled" && res_user_roles.value?.data
|
|
141
125
|
? res_user_roles.value.data
|
|
142
126
|
: null;
|
|
143
|
-
const total_events = total_event_count.status === "fulfilled" &&
|
|
144
|
-
total_event_count.value?.data
|
|
145
|
-
? total_event_count.value.data
|
|
146
|
-
: 0;
|
|
147
127
|
const plans = res_plans.status === "fulfilled" && res_plans.value?.data
|
|
148
128
|
? res_plans.value.data
|
|
149
129
|
: [];
|
|
150
|
-
const sessions = res_sessions.status === "fulfilled" && res_sessions.value?.data
|
|
151
|
-
? res_sessions.value.data
|
|
152
|
-
: [];
|
|
153
130
|
const layers = res_layers.status === "fulfilled" && res_layers.value?.data
|
|
154
131
|
? res_layers.value.data
|
|
155
132
|
: [];
|
|
156
133
|
const providers = res_providers.status === "fulfilled" && res_providers.value?.data
|
|
157
134
|
? res_providers.value.data
|
|
158
135
|
: [];
|
|
159
|
-
const artifacts = res_artifacts.status === "fulfilled" && res_artifacts.value?.data
|
|
160
|
-
? res_artifacts.value.data
|
|
161
|
-
: [];
|
|
162
|
-
const total_artifacts = total_artifact_count.status === "fulfilled" &&
|
|
163
|
-
total_artifact_count.value?.data
|
|
164
|
-
? total_artifact_count.value.data
|
|
165
|
-
: 0;
|
|
166
136
|
const session_summaries = session_summaries_result.status === "fulfilled" &&
|
|
167
137
|
session_summaries_result.value?.data
|
|
168
138
|
? session_summaries_result.value.data
|
|
169
139
|
: null;
|
|
140
|
+
const session_usage = session_usage_result.status === "fulfilled" &&
|
|
141
|
+
session_usage_result.value?.data
|
|
142
|
+
? session_usage_result.value.data
|
|
143
|
+
: null;
|
|
170
144
|
// TODO: store in DB and retrieve on load?
|
|
171
145
|
const newLabels = LABELS;
|
|
172
146
|
const endTime = Date.now();
|
|
173
147
|
const loadTime = endTime - startTime;
|
|
174
148
|
console.log(`[HerdModule] Loaded herd ${herd.slug} in ${loadTime}ms (${new_devices.length} devices)`);
|
|
175
|
-
return new HerdModule(herd, new_devices, Date.now(), user_roles, newLabels, plans, zones, layers, providers, session_summaries);
|
|
149
|
+
return new HerdModule(herd, new_devices, Date.now(), user_roles, newLabels, plans, zones, layers, providers, session_summaries, session_usage);
|
|
176
150
|
}
|
|
177
151
|
catch (error) {
|
|
178
152
|
const endTime = Date.now();
|
|
179
153
|
const loadTime = endTime - startTime;
|
|
180
154
|
console.error(`[HerdModule] Critical error in HerdModule.from_herd (${loadTime}ms):`, error);
|
|
181
155
|
// Return a minimal but valid HerdModule instance to prevent complete failure
|
|
182
|
-
return new HerdModule(herd, [], Date.now(), null, [], [], [], [], [], null);
|
|
156
|
+
return new HerdModule(herd, [], Date.now(), null, [], [], [], [], [], null, null);
|
|
183
157
|
}
|
|
184
158
|
}
|
|
185
159
|
}
|
package/dist/types/supabase.d.ts
CHANGED
|
@@ -1460,6 +1460,18 @@ export type Database = {
|
|
|
1460
1460
|
isSetofReturn: true;
|
|
1461
1461
|
};
|
|
1462
1462
|
};
|
|
1463
|
+
get_session_by_id: {
|
|
1464
|
+
Args: {
|
|
1465
|
+
session_id_caller: number;
|
|
1466
|
+
};
|
|
1467
|
+
Returns: Database["public"]["CompositeTypes"]["session_with_coordinates"][];
|
|
1468
|
+
SetofOptions: {
|
|
1469
|
+
from: "*";
|
|
1470
|
+
to: "session_with_coordinates";
|
|
1471
|
+
isOneToOne: false;
|
|
1472
|
+
isSetofReturn: true;
|
|
1473
|
+
};
|
|
1474
|
+
};
|
|
1463
1475
|
get_session_summaries: {
|
|
1464
1476
|
Args: {
|
|
1465
1477
|
device_id_caller?: number;
|
|
@@ -1469,6 +1481,15 @@ export type Database = {
|
|
|
1469
1481
|
};
|
|
1470
1482
|
Returns: Json;
|
|
1471
1483
|
};
|
|
1484
|
+
get_session_usage_over_time: {
|
|
1485
|
+
Args: {
|
|
1486
|
+
device_id_caller?: number;
|
|
1487
|
+
end_date_caller?: string;
|
|
1488
|
+
herd_id_caller?: number;
|
|
1489
|
+
start_date_caller?: string;
|
|
1490
|
+
};
|
|
1491
|
+
Returns: Json;
|
|
1492
|
+
};
|
|
1472
1493
|
get_sessions_infinite_by_device: {
|
|
1473
1494
|
Args: {
|
|
1474
1495
|
cursor_id?: number;
|