@adventurelabs/scout-core 1.4.67 → 1.4.69
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/index.d.ts +3 -0
- package/dist/helpers/index.js +3 -0
- package/dist/helpers/lifecycle.d.ts +14 -0
- package/dist/helpers/lifecycle.js +74 -0
- package/dist/helpers/parts.d.ts +19 -13
- package/dist/helpers/parts.js +51 -47
- package/dist/helpers/pubsub_token.d.ts +5 -0
- package/dist/helpers/pubsub_token.js +14 -0
- package/dist/helpers/pubsub_token_server.d.ts +7 -0
- package/dist/helpers/pubsub_token_server.js +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/providers/ScoutRefreshProvider.d.ts +208 -15
- package/dist/types/db.d.ts +2 -0
- package/dist/types/pubsub_token.d.ts +7 -0
- package/dist/types/supabase.d.ts +217 -17
- package/dist/types/supabase.js +2 -2
- package/package.json +1 -1
- package/dist/helpers/components.d.ts +0 -14
- package/dist/helpers/components.js +0 -155
- package/dist/helpers/operator.d.ts +0 -5
- package/dist/helpers/operator.js +0 -64
- package/dist/hooks/useHerdData.d.ts +0 -167
- package/dist/hooks/useHerdData.js +0 -153
- package/dist/hooks/useScoutBrowserClient.d.ts +0 -11
- package/dist/hooks/useScoutBrowserClient.js +0 -17
- package/dist/hooks/useScoutDbListener.d.ts +0 -3
- package/dist/hooks/useScoutDbListener.js +0 -134
- package/dist/hooks/useScoutRealtimeConnectivity copy.d.ts +0 -3
- package/dist/hooks/useScoutRealtimeConnectivity copy.js +0 -159
- package/dist/hooks/useScoutRealtimeDevices copy.d.ts +0 -3
- package/dist/hooks/useScoutRealtimeDevices copy.js +0 -55
- package/dist/types/data.d.ts +0 -4
- /package/dist/types/{data.js → pubsub_token.js} +0 -0
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useAppDispatch } from "../store/hooks";
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
4
|
-
import { addDevice, addPlan, addTag, addSessionToStore, deleteDevice, deletePlan, deleteSessionFromStore, deleteTag, updateDevice, updatePlan, updateSessionInStore, updateTag, } from "../store/scout";
|
|
5
|
-
export function useScoutDbListener(scoutSupabase) {
|
|
6
|
-
const supabase = useRef(null);
|
|
7
|
-
const channels = useRef([]);
|
|
8
|
-
const dispatch = useAppDispatch();
|
|
9
|
-
function handleTagInserts(payload) {
|
|
10
|
-
console.log("[DB Listener] Tag INSERT received:", payload.new);
|
|
11
|
-
dispatch(addTag(payload.new));
|
|
12
|
-
}
|
|
13
|
-
function handleTagDeletes(payload) {
|
|
14
|
-
console.log("[DB Listener] Tag DELETE received:", payload.old);
|
|
15
|
-
if (!payload.old || !payload.old.id) {
|
|
16
|
-
console.error("[DB Listener] Tag DELETE - Invalid payload, missing tag data");
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
dispatch(deleteTag(payload.old));
|
|
20
|
-
}
|
|
21
|
-
function handleTagUpdates(payload) {
|
|
22
|
-
console.log("[DB Listener] Tag UPDATE received:", payload.new);
|
|
23
|
-
dispatch(updateTag(payload.new));
|
|
24
|
-
}
|
|
25
|
-
function handleDeviceInserts(payload) {
|
|
26
|
-
console.log("[DB Listener] Device INSERT received:", payload.new);
|
|
27
|
-
dispatch(addDevice(payload.new));
|
|
28
|
-
}
|
|
29
|
-
function handleDeviceDeletes(payload) {
|
|
30
|
-
console.log("[DB Listener] Device DELETE received:", payload.old);
|
|
31
|
-
dispatch(deleteDevice(payload.old));
|
|
32
|
-
}
|
|
33
|
-
function handleDeviceUpdates(payload) {
|
|
34
|
-
console.log("[DB Listener] Device UPDATE received:", payload.new);
|
|
35
|
-
dispatch(updateDevice(payload.new));
|
|
36
|
-
}
|
|
37
|
-
function handlePlanInserts(payload) {
|
|
38
|
-
console.log("[DB Listener] Plan INSERT received:", payload.new);
|
|
39
|
-
dispatch(addPlan(payload.new));
|
|
40
|
-
}
|
|
41
|
-
function handlePlanDeletes(payload) {
|
|
42
|
-
console.log("[DB Listener] Plan DELETE received:", payload.old);
|
|
43
|
-
dispatch(deletePlan(payload.old));
|
|
44
|
-
}
|
|
45
|
-
function handlePlanUpdates(payload) {
|
|
46
|
-
console.log("[DB Listener] Plan UPDATE received:", payload.new);
|
|
47
|
-
dispatch(updatePlan(payload.new));
|
|
48
|
-
}
|
|
49
|
-
function handleSessionInserts(payload) {
|
|
50
|
-
console.log("[DB Listener] Session INSERT received:", payload.new);
|
|
51
|
-
dispatch(addSessionToStore(payload.new));
|
|
52
|
-
}
|
|
53
|
-
function handleSessionDeletes(payload) {
|
|
54
|
-
console.log("[DB Listener] Session DELETE received:", payload.old);
|
|
55
|
-
if (!payload.old || !payload.old.id) {
|
|
56
|
-
console.error("[DB Listener] Session DELETE - Invalid payload, missing session data");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
dispatch(deleteSessionFromStore(payload.old));
|
|
60
|
-
}
|
|
61
|
-
function handleSessionUpdates(payload) {
|
|
62
|
-
console.log("[DB Listener] Session UPDATE received:", payload.new);
|
|
63
|
-
dispatch(updateSessionInStore(payload.new));
|
|
64
|
-
}
|
|
65
|
-
function handleConnectivityInserts(payload) {
|
|
66
|
-
console.log("[DB Listener] Connectivity INSERT received:", payload.new);
|
|
67
|
-
}
|
|
68
|
-
function handleConnectivityDeletes(payload) {
|
|
69
|
-
console.log("[DB Listener] Connectivity DELETE received:", payload.old);
|
|
70
|
-
}
|
|
71
|
-
function handleConnectivityUpdates(payload) {
|
|
72
|
-
console.log("[DB Listener] Connectivity UPDATE received:", payload.new);
|
|
73
|
-
}
|
|
74
|
-
// Clean up all channels
|
|
75
|
-
const cleanupChannels = () => {
|
|
76
|
-
channels.current.forEach((channel) => {
|
|
77
|
-
if (channel) {
|
|
78
|
-
scoutSupabase.removeChannel(channel);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
channels.current = [];
|
|
82
|
-
};
|
|
83
|
-
// Setup channel with event handlers
|
|
84
|
-
const setupChannel = () => {
|
|
85
|
-
if (!scoutSupabase)
|
|
86
|
-
return null;
|
|
87
|
-
const channelId = `scout_realtime_${Date.now()}_${Math.random()
|
|
88
|
-
.toString(36)
|
|
89
|
-
.substr(2, 9)}`;
|
|
90
|
-
const mainChannel = scoutSupabase.channel(channelId);
|
|
91
|
-
console.log(`[DB Listener] Creating channel: ${channelId}`);
|
|
92
|
-
// Subscribe to all events
|
|
93
|
-
mainChannel
|
|
94
|
-
.on("postgres_changes", { event: "INSERT", schema: "public", table: "plans" }, handlePlanInserts)
|
|
95
|
-
.on("postgres_changes", { event: "DELETE", schema: "public", table: "plans" }, handlePlanDeletes)
|
|
96
|
-
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "plans" }, handlePlanUpdates)
|
|
97
|
-
.on("postgres_changes", { event: "INSERT", schema: "public", table: "devices" }, handleDeviceInserts)
|
|
98
|
-
.on("postgres_changes", { event: "DELETE", schema: "public", table: "devices" }, handleDeviceDeletes)
|
|
99
|
-
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "devices" }, handleDeviceUpdates)
|
|
100
|
-
.on("postgres_changes", { event: "INSERT", schema: "public", table: "tags" }, handleTagInserts)
|
|
101
|
-
.on("postgres_changes", { event: "DELETE", schema: "public", table: "tags" }, handleTagDeletes)
|
|
102
|
-
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "tags" }, handleTagUpdates)
|
|
103
|
-
.on("postgres_changes", { event: "INSERT", schema: "public", table: "connectivity" }, handleConnectivityInserts)
|
|
104
|
-
.on("postgres_changes", { event: "DELETE", schema: "public", table: "connectivity" }, handleConnectivityDeletes)
|
|
105
|
-
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "connectivity" }, handleConnectivityUpdates)
|
|
106
|
-
.on("postgres_changes", { event: "INSERT", schema: "public", table: "sessions" }, handleSessionInserts)
|
|
107
|
-
.on("postgres_changes", { event: "DELETE", schema: "public", table: "sessions" }, handleSessionDeletes)
|
|
108
|
-
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "sessions" }, handleSessionUpdates)
|
|
109
|
-
.subscribe((status) => {
|
|
110
|
-
console.log("[DB Listener] Subscription status:", status);
|
|
111
|
-
if (status === "SUBSCRIBED") {
|
|
112
|
-
console.log("[DB Listener] ✅ Successfully subscribed to real-time updates");
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
return mainChannel;
|
|
116
|
-
};
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
if (!scoutSupabase) {
|
|
119
|
-
console.error("[DB Listener] No Supabase client available");
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
supabase.current = scoutSupabase;
|
|
123
|
-
// Initial channel setup
|
|
124
|
-
const mainChannel = setupChannel();
|
|
125
|
-
if (mainChannel) {
|
|
126
|
-
channels.current.push(mainChannel);
|
|
127
|
-
}
|
|
128
|
-
// Cleanup function
|
|
129
|
-
return () => {
|
|
130
|
-
console.log("[DB Listener] 🧹 Cleaning up channels");
|
|
131
|
-
cleanupChannels();
|
|
132
|
-
};
|
|
133
|
-
}, [scoutSupabase, dispatch]);
|
|
134
|
-
}
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useAppDispatch } from "../store/hooks";
|
|
3
|
-
import { useSelector } from "react-redux";
|
|
4
|
-
import { useEffect, useRef, useCallback, useMemo } from "react";
|
|
5
|
-
import { setActiveHerdGpsTrackersConnectivity } from "../store/scout";
|
|
6
|
-
import { server_get_connectivity_by_device_id } from "../helpers/connectivity";
|
|
7
|
-
import { EnumWebResponse } from "../types/requests";
|
|
8
|
-
import { getHoursAgoTimestamp } from "../helpers/time";
|
|
9
|
-
export function useScoutRealtimeConnectivity(scoutSupabase) {
|
|
10
|
-
const channels = useRef([]);
|
|
11
|
-
const dispatch = useAppDispatch();
|
|
12
|
-
const activeHerdId = useSelector((state) => state.scout.active_herd_id);
|
|
13
|
-
const connectivity = useSelector((state) => state.scout.active_herd_gps_trackers_connectivity);
|
|
14
|
-
const herdModules = useSelector((state) => state.scout.herd_modules);
|
|
15
|
-
// Create stable reference for GPS device IDs to prevent unnecessary refetching
|
|
16
|
-
const gpsDeviceIds = useMemo(() => {
|
|
17
|
-
if (!activeHerdId)
|
|
18
|
-
return "";
|
|
19
|
-
const activeHerdModule = herdModules.find((hm) => hm.herd.id.toString() === activeHerdId);
|
|
20
|
-
if (!activeHerdModule)
|
|
21
|
-
return "";
|
|
22
|
-
const gpsDevices = activeHerdModule.devices.filter((device) => device.device_type &&
|
|
23
|
-
["gps_tracker", "gps_tracker_vehicle", "gps_tracker_person"].includes(device.device_type));
|
|
24
|
-
return gpsDevices
|
|
25
|
-
.map((d) => d.id)
|
|
26
|
-
.filter(Boolean)
|
|
27
|
-
.sort()
|
|
28
|
-
.join(",");
|
|
29
|
-
}, [activeHerdId, herdModules]);
|
|
30
|
-
// Handle connectivity broadcasts
|
|
31
|
-
const handleConnectivityBroadcast = useCallback((payload) => {
|
|
32
|
-
const { event, payload: data } = payload;
|
|
33
|
-
const connectivityData = data.record || data.old_record;
|
|
34
|
-
// Only process GPS tracker data (no session_id)
|
|
35
|
-
if (!connectivityData?.device_id || connectivityData.session_id) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const deviceId = connectivityData.device_id;
|
|
39
|
-
const updatedConnectivity = { ...connectivity };
|
|
40
|
-
switch (data.operation) {
|
|
41
|
-
case "INSERT":
|
|
42
|
-
console.log(`[CONNECTIVITY] INSERT for ${deviceId}, ${JSON.stringify(connectivityData)}`);
|
|
43
|
-
if (!updatedConnectivity[deviceId]) {
|
|
44
|
-
updatedConnectivity[deviceId] = {
|
|
45
|
-
most_recent: connectivityData,
|
|
46
|
-
history: [],
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const newHistory = [
|
|
51
|
-
updatedConnectivity[deviceId].most_recent,
|
|
52
|
-
...updatedConnectivity[deviceId].history,
|
|
53
|
-
].slice(0, 99);
|
|
54
|
-
updatedConnectivity[deviceId] = {
|
|
55
|
-
most_recent: connectivityData,
|
|
56
|
-
history: newHistory,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
break;
|
|
60
|
-
case "UPDATE":
|
|
61
|
-
if (updatedConnectivity[deviceId]) {
|
|
62
|
-
if (updatedConnectivity[deviceId].most_recent.id ===
|
|
63
|
-
connectivityData.id) {
|
|
64
|
-
updatedConnectivity[deviceId] = {
|
|
65
|
-
...updatedConnectivity[deviceId],
|
|
66
|
-
most_recent: connectivityData,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
const historyIndex = updatedConnectivity[deviceId].history.findIndex((c) => c.id === connectivityData.id);
|
|
71
|
-
if (historyIndex >= 0) {
|
|
72
|
-
const newHistory = [...updatedConnectivity[deviceId].history];
|
|
73
|
-
newHistory[historyIndex] = connectivityData;
|
|
74
|
-
updatedConnectivity[deviceId] = {
|
|
75
|
-
...updatedConnectivity[deviceId],
|
|
76
|
-
history: newHistory,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
break;
|
|
82
|
-
case "DELETE":
|
|
83
|
-
if (updatedConnectivity[deviceId]) {
|
|
84
|
-
if (updatedConnectivity[deviceId].most_recent.id ===
|
|
85
|
-
connectivityData.id) {
|
|
86
|
-
if (updatedConnectivity[deviceId].history.length === 0) {
|
|
87
|
-
delete updatedConnectivity[deviceId];
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
updatedConnectivity[deviceId] = {
|
|
91
|
-
most_recent: updatedConnectivity[deviceId].history[0],
|
|
92
|
-
history: updatedConnectivity[deviceId].history.slice(1),
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
updatedConnectivity[deviceId] = {
|
|
98
|
-
...updatedConnectivity[deviceId],
|
|
99
|
-
history: updatedConnectivity[deviceId].history.filter((c) => c.id !== connectivityData.id),
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
dispatch(setActiveHerdGpsTrackersConnectivity(updatedConnectivity));
|
|
106
|
-
}, [connectivity, dispatch]);
|
|
107
|
-
// Fetch initial connectivity data
|
|
108
|
-
const fetchInitialData = useCallback(async () => {
|
|
109
|
-
if (!gpsDeviceIds)
|
|
110
|
-
return;
|
|
111
|
-
const deviceIds = gpsDeviceIds.split(",").filter(Boolean).map(Number);
|
|
112
|
-
if (deviceIds.length === 0) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const timestampFilter = getHoursAgoTimestamp(1);
|
|
116
|
-
const connectivityData = {};
|
|
117
|
-
await Promise.all(deviceIds.map(async (deviceId) => {
|
|
118
|
-
try {
|
|
119
|
-
const response = await server_get_connectivity_by_device_id(deviceId, timestampFilter);
|
|
120
|
-
if (response.status === EnumWebResponse.SUCCESS && response.data) {
|
|
121
|
-
const trackerData = response.data.filter((conn) => !conn.session_id);
|
|
122
|
-
if (trackerData.length > 0) {
|
|
123
|
-
const sortedData = trackerData
|
|
124
|
-
.sort((a, b) => new Date(b.timestamp_start || 0).getTime() -
|
|
125
|
-
new Date(a.timestamp_start || 0).getTime())
|
|
126
|
-
.slice(0, 100);
|
|
127
|
-
connectivityData[deviceId] = {
|
|
128
|
-
most_recent: sortedData[0],
|
|
129
|
-
history: sortedData.slice(1), // Exclude the most recent item
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
catch (error) {
|
|
135
|
-
// Silent error handling
|
|
136
|
-
}
|
|
137
|
-
}));
|
|
138
|
-
dispatch(setActiveHerdGpsTrackersConnectivity(connectivityData));
|
|
139
|
-
}, [gpsDeviceIds, dispatch]);
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
if (!scoutSupabase || gpsDeviceIds === "")
|
|
142
|
-
return;
|
|
143
|
-
// Clean up existing channels
|
|
144
|
-
channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
|
|
145
|
-
channels.current = [];
|
|
146
|
-
// Create connectivity channel
|
|
147
|
-
const channel = scoutSupabase
|
|
148
|
-
.channel(`${activeHerdId}-connectivity`, { config: { private: true } })
|
|
149
|
-
.on("broadcast", { event: "*" }, handleConnectivityBroadcast)
|
|
150
|
-
.subscribe();
|
|
151
|
-
channels.current.push(channel);
|
|
152
|
-
// Fetch initial data
|
|
153
|
-
fetchInitialData();
|
|
154
|
-
return () => {
|
|
155
|
-
channels.current.forEach((ch) => scoutSupabase.removeChannel(ch));
|
|
156
|
-
channels.current = [];
|
|
157
|
-
};
|
|
158
|
-
}, [scoutSupabase, gpsDeviceIds, activeHerdId, handleConnectivityBroadcast]);
|
|
159
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useAppDispatch } from "../store/hooks";
|
|
3
|
-
import { useSelector } from "react-redux";
|
|
4
|
-
import { useEffect, useRef, useCallback } from "react";
|
|
5
|
-
import { addDevice, deleteDevice, updateDevice } from "../store/scout";
|
|
6
|
-
export function useScoutRealtimeDevices(scoutSupabase) {
|
|
7
|
-
const channels = useRef([]);
|
|
8
|
-
const dispatch = useAppDispatch();
|
|
9
|
-
const activeHerdId = useSelector((state) => state.scout.active_herd_id);
|
|
10
|
-
// Device broadcast handler
|
|
11
|
-
const handleDeviceBroadcast = useCallback((payload) => {
|
|
12
|
-
console.log("[Devices] Broadcast received:", payload.payload.operation);
|
|
13
|
-
const data = payload.payload;
|
|
14
|
-
switch (data.operation) {
|
|
15
|
-
case "INSERT":
|
|
16
|
-
if (data.record)
|
|
17
|
-
dispatch(addDevice(data.record));
|
|
18
|
-
break;
|
|
19
|
-
case "UPDATE":
|
|
20
|
-
if (data.record)
|
|
21
|
-
dispatch(updateDevice(data.record));
|
|
22
|
-
break;
|
|
23
|
-
case "DELETE":
|
|
24
|
-
if (data.old_record)
|
|
25
|
-
dispatch(deleteDevice(data.old_record));
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
}, [dispatch]);
|
|
29
|
-
const cleanupChannels = () => {
|
|
30
|
-
channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
|
|
31
|
-
channels.current = [];
|
|
32
|
-
};
|
|
33
|
-
const createDevicesChannel = (herdId) => {
|
|
34
|
-
return scoutSupabase
|
|
35
|
-
.channel(`${herdId}-devices`, { config: { private: true } })
|
|
36
|
-
.on("broadcast", { event: "*" }, handleDeviceBroadcast)
|
|
37
|
-
.subscribe((status) => {
|
|
38
|
-
if (status === "SUBSCRIBED") {
|
|
39
|
-
console.log(`[Devices] ✅ Connected to herd ${herdId}`);
|
|
40
|
-
}
|
|
41
|
-
else if (status === "CHANNEL_ERROR") {
|
|
42
|
-
console.warn(`[Devices] 🟡 Failed to connect to herd ${herdId}`);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
cleanupChannels();
|
|
48
|
-
// Create devices channel for active herd
|
|
49
|
-
if (activeHerdId) {
|
|
50
|
-
const channel = createDevicesChannel(activeHerdId);
|
|
51
|
-
channels.current.push(channel);
|
|
52
|
-
}
|
|
53
|
-
return cleanupChannels;
|
|
54
|
-
}, [activeHerdId]);
|
|
55
|
-
}
|
package/dist/types/data.d.ts
DELETED
|
File without changes
|