@adventurelabs/scout-core 1.0.53 → 1.0.55
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/events.d.ts +0 -4
- package/dist/helpers/events.js +7 -85
- package/dist/helpers/layers.d.ts +3 -0
- package/dist/helpers/layers.js +21 -0
- package/dist/helpers/tags.d.ts +0 -1
- package/dist/helpers/tags.js +0 -42
- package/dist/hooks/useScoutDbListener.d.ts +1 -16
- package/dist/hooks/useScoutDbListener.js +112 -155
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -0
- package/dist/providers/ScoutRefreshProvider.d.ts +60 -63
- package/dist/supabase/server.d.ts +60 -63
- package/dist/types/db.d.ts +1 -0
- package/dist/types/herd_module.d.ts +4 -2
- package/dist/types/herd_module.js +16 -5
- package/dist/types/supabase.d.ts +64 -64
- package/dist/types/supabase.js +1 -0
- package/package.json +1 -1
package/dist/helpers/events.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { IEvent } from "../types/db";
|
|
2
1
|
import { IWebResponseCompatible } from "../types/requests";
|
|
3
2
|
import { EnumSessionsVisibility } from "../types/events";
|
|
4
|
-
export declare function server_get_events_by_herd(herd_id: number, sessions_visibility: EnumSessionsVisibility): Promise<IWebResponseCompatible<IEvent[]>>;
|
|
5
|
-
export declare function server_get_more_events_by_herd(herd_id: number, offset: number, page_count: number | undefined, sessions_visibility: EnumSessionsVisibility): Promise<IWebResponseCompatible<IEvent[]>>;
|
|
6
3
|
export declare function server_get_total_events_by_herd(herd_id: number, sessions_visibility: EnumSessionsVisibility): Promise<IWebResponseCompatible<number>>;
|
|
7
|
-
export declare function server_create_event(newEvent: any): Promise<IWebResponseCompatible<boolean>>;
|
package/dist/helpers/events.js
CHANGED
|
@@ -1,79 +1,16 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
-
import { addSignedUrlsToEvents } from "./storage";
|
|
5
4
|
import { EnumSessionsVisibility } from "../types/events";
|
|
6
|
-
export async function server_get_events_by_herd(herd_id, sessions_visibility) {
|
|
7
|
-
const supabase = await newServerClient();
|
|
8
|
-
// fetch events and include devices
|
|
9
|
-
// sort by timestamp
|
|
10
|
-
let query = supabase
|
|
11
|
-
.from("events")
|
|
12
|
-
.select(`
|
|
13
|
-
*,
|
|
14
|
-
devices: devices!inner(*)
|
|
15
|
-
`)
|
|
16
|
-
.eq("devices.herd_id", herd_id);
|
|
17
|
-
// Apply session filter based on sessions_visibility
|
|
18
|
-
if (sessions_visibility === EnumSessionsVisibility.Only) {
|
|
19
|
-
query = query.not("session_id", "is", null);
|
|
20
|
-
}
|
|
21
|
-
else if (sessions_visibility === EnumSessionsVisibility.Exclude) {
|
|
22
|
-
query = query.is("session_id", null);
|
|
23
|
-
}
|
|
24
|
-
const { data } = await query.order("timestamp_observation", { ascending: false });
|
|
25
|
-
// Add signed URLs to events using the same client
|
|
26
|
-
const eventsWithSignedUrls = data
|
|
27
|
-
? await addSignedUrlsToEvents(data, supabase)
|
|
28
|
-
: [];
|
|
29
|
-
// TODO: DETERMINE WHEN TO PASS ERROR
|
|
30
|
-
let response = IWebResponse.success(eventsWithSignedUrls);
|
|
31
|
-
return response.to_compatible();
|
|
32
|
-
}
|
|
33
|
-
export async function server_get_more_events_by_herd(herd_id, offset, page_count = 10, sessions_visibility) {
|
|
34
|
-
const from = offset * page_count;
|
|
35
|
-
const to = from + page_count - 1;
|
|
36
|
-
const supabase = await newServerClient();
|
|
37
|
-
// fetch events and include devices
|
|
38
|
-
// sort by timestamp
|
|
39
|
-
let query = supabase
|
|
40
|
-
.from("events")
|
|
41
|
-
.select(`
|
|
42
|
-
*,
|
|
43
|
-
devices: devices!inner(*)
|
|
44
|
-
`)
|
|
45
|
-
.eq("devices.herd_id", herd_id)
|
|
46
|
-
.range(from, to);
|
|
47
|
-
// Apply session filter based on sessions_visibility
|
|
48
|
-
if (sessions_visibility === EnumSessionsVisibility.Only) {
|
|
49
|
-
query = query.not("session_id", "is", null);
|
|
50
|
-
}
|
|
51
|
-
else if (sessions_visibility === EnumSessionsVisibility.Exclude) {
|
|
52
|
-
query = query.is("session_id", null);
|
|
53
|
-
}
|
|
54
|
-
const { data } = await query.order("timestamp_observation", { ascending: false });
|
|
55
|
-
// Add signed URLs to events using the same client
|
|
56
|
-
const eventsWithSignedUrls = data
|
|
57
|
-
? await addSignedUrlsToEvents(data, supabase)
|
|
58
|
-
: [];
|
|
59
|
-
// TODO: DETERMINE WHEN TO PASS ERROR
|
|
60
|
-
let response = IWebResponse.success(eventsWithSignedUrls);
|
|
61
|
-
return response.to_compatible();
|
|
62
|
-
}
|
|
63
5
|
// function to get total number of events for a herd
|
|
64
6
|
export async function server_get_total_events_by_herd(herd_id, sessions_visibility) {
|
|
65
7
|
const supabase = await newServerClient();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
else if (sessions_visibility === EnumSessionsVisibility.Exclude) {
|
|
74
|
-
query = query.is("session_id", null);
|
|
75
|
-
}
|
|
76
|
-
const { count, error } = await query;
|
|
8
|
+
// Convert sessions_visibility to exclude_session_events boolean
|
|
9
|
+
const exclude_session_events = sessions_visibility === EnumSessionsVisibility.Exclude;
|
|
10
|
+
const { data, error } = (await supabase.rpc("get_total_events_for_herd_with_session_filter", {
|
|
11
|
+
herd_id_caller: herd_id,
|
|
12
|
+
exclude_session_events: exclude_session_events,
|
|
13
|
+
}));
|
|
77
14
|
if (error) {
|
|
78
15
|
return {
|
|
79
16
|
status: EnumWebResponse.ERROR,
|
|
@@ -82,21 +19,6 @@ export async function server_get_total_events_by_herd(herd_id, sessions_visibili
|
|
|
82
19
|
};
|
|
83
20
|
}
|
|
84
21
|
else {
|
|
85
|
-
return IWebResponse.success(
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
export async function server_create_event(newEvent) {
|
|
89
|
-
const supabase = await newServerClient();
|
|
90
|
-
// strip id field from herd object
|
|
91
|
-
const { data, error } = await supabase.from("events").insert([newEvent]);
|
|
92
|
-
if (error) {
|
|
93
|
-
return {
|
|
94
|
-
status: EnumWebResponse.ERROR,
|
|
95
|
-
msg: error.message,
|
|
96
|
-
data: null,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
return IWebResponse.success(true).to_compatible();
|
|
22
|
+
return IWebResponse.success(data || 0).to_compatible();
|
|
101
23
|
}
|
|
102
24
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { newServerClient } from "../supabase/server";
|
|
3
|
+
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
+
// function that fetches the layers from our db given a herd id
|
|
5
|
+
export async function server_get_layers_by_herd(herd_id) {
|
|
6
|
+
const supabase = await newServerClient();
|
|
7
|
+
const { data, error } = await supabase
|
|
8
|
+
.from("layers")
|
|
9
|
+
.select("*")
|
|
10
|
+
.eq("herd_id", herd_id);
|
|
11
|
+
if (error) {
|
|
12
|
+
return {
|
|
13
|
+
status: EnumWebResponse.ERROR,
|
|
14
|
+
msg: error.message,
|
|
15
|
+
data: null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return IWebResponse.success(data).to_compatible();
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/helpers/tags.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IEventWithTags, ITag } from "../types/db";
|
|
2
2
|
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
-
export declare function test_event_loading(device_id: number): Promise<boolean>;
|
|
4
3
|
export declare function server_create_tags(tags: ITag[]): Promise<IWebResponseCompatible<ITag[]>>;
|
|
5
4
|
export declare function server_delete_tags_by_ids(tag_ids: number[]): Promise<IWebResponseCompatible<boolean>>;
|
|
6
5
|
export declare function server_update_tags(tags: ITag[]): Promise<IWebResponseCompatible<ITag[]>>;
|
package/dist/helpers/tags.js
CHANGED
|
@@ -3,25 +3,6 @@
|
|
|
3
3
|
import { newServerClient } from "../supabase/server";
|
|
4
4
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
5
5
|
import { addSignedUrlsToEvents, addSignedUrlToEvent } from "./storage";
|
|
6
|
-
// Test function to verify individual event loading works
|
|
7
|
-
export async function test_event_loading(device_id) {
|
|
8
|
-
try {
|
|
9
|
-
console.log(`[Event Test] Testing individual event loading for device ${device_id}`);
|
|
10
|
-
const events_response = await server_get_events_and_tags_for_device(device_id, 1);
|
|
11
|
-
if (events_response.status === EnumWebResponse.SUCCESS) {
|
|
12
|
-
console.log(`[Event Test] Successfully loaded ${events_response.data?.length || 0} events for device ${device_id}`);
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
console.error(`[Event Test] Failed to load events for device ${device_id}:`, events_response.msg);
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
catch (error) {
|
|
21
|
-
console.error(`[Event Test] Failed to load events for device ${device_id}:`, error);
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
6
|
export async function server_create_tags(tags) {
|
|
26
7
|
const supabase = await newServerClient();
|
|
27
8
|
// remove id key from tags
|
|
@@ -94,29 +75,6 @@ export async function server_update_tags(tags) {
|
|
|
94
75
|
}
|
|
95
76
|
return IWebResponse.success(updatedTags).to_compatible();
|
|
96
77
|
}
|
|
97
|
-
// export async function server_get_events_with_tags_by_herd(
|
|
98
|
-
// herd_id: number
|
|
99
|
-
// ): Promise<IWebResponseCompatible<IEventWithTags[]>> {
|
|
100
|
-
// const supabase = await newServerClient();
|
|
101
|
-
// const { data, error } = await supabase
|
|
102
|
-
// .from("events")
|
|
103
|
-
// .select(
|
|
104
|
-
// `
|
|
105
|
-
// *,
|
|
106
|
-
// tags: tags (*)
|
|
107
|
-
// `
|
|
108
|
-
// )
|
|
109
|
-
// .eq("devices.herd_id", herd_id)
|
|
110
|
-
// .order("timestamp_observation", { ascending: false });
|
|
111
|
-
// if (error) {
|
|
112
|
-
// return {
|
|
113
|
-
// status: EnumWebResponse.ERROR,
|
|
114
|
-
// msg: error.message,
|
|
115
|
-
// data: [],
|
|
116
|
-
// };
|
|
117
|
-
// }
|
|
118
|
-
// return IWebResponse.success(data).to_compatible();
|
|
119
|
-
// }
|
|
120
78
|
export async function server_get_more_events_with_tags_by_herd(herd_id, offset, page_count = 10) {
|
|
121
79
|
const from = offset * page_count;
|
|
122
80
|
const to = from + page_count - 1;
|
|
@@ -1,18 +1,3 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
2
|
import { Database } from "../types/supabase";
|
|
3
|
-
declare
|
|
4
|
-
DISCONNECTED = "disconnected",
|
|
5
|
-
CONNECTING = "connecting",
|
|
6
|
-
CONNECTED = "connected",
|
|
7
|
-
ERROR = "error"
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Hook for listening to real-time database changes
|
|
11
|
-
*/
|
|
12
|
-
export declare function useScoutDbListener(scoutSupabase: SupabaseClient<Database>): {
|
|
13
|
-
connectionState: ConnectionState;
|
|
14
|
-
lastError: string | null;
|
|
15
|
-
isConnected: boolean;
|
|
16
|
-
isConnecting: boolean;
|
|
17
|
-
};
|
|
18
|
-
export {};
|
|
3
|
+
export declare function useScoutDbListener(scoutSupabase: SupabaseClient<Database>): void;
|
|
@@ -1,170 +1,127 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useAppDispatch } from "../store/hooks";
|
|
3
|
-
import { useEffect, useRef
|
|
4
|
-
import { addDevice, addPlan, addTag, deleteDevice, deletePlan, deleteTag, updateDevice, updatePlan, updateTag, } from "../store/scout";
|
|
5
|
-
// Connection state enum
|
|
6
|
-
var ConnectionState;
|
|
7
|
-
(function (ConnectionState) {
|
|
8
|
-
ConnectionState["DISCONNECTED"] = "disconnected";
|
|
9
|
-
ConnectionState["CONNECTING"] = "connecting";
|
|
10
|
-
ConnectionState["CONNECTED"] = "connected";
|
|
11
|
-
ConnectionState["ERROR"] = "error";
|
|
12
|
-
})(ConnectionState || (ConnectionState = {}));
|
|
13
|
-
/**
|
|
14
|
-
* Hook for listening to real-time database changes
|
|
15
|
-
*/
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { addDevice, addPlan, addTag, addSessionToStore, deleteDevice, deletePlan, deleteSessionFromStore, deleteTag, updateDevice, updatePlan, updateSessionInStore, updateTag, } from "../store/scout";
|
|
16
5
|
export function useScoutDbListener(scoutSupabase) {
|
|
6
|
+
const supabase = useRef(null);
|
|
17
7
|
const channels = useRef([]);
|
|
18
8
|
const dispatch = useAppDispatch();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
console.warn("[DB Listener] Error removing channel:", error);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
channels.current = [];
|
|
34
|
-
};
|
|
35
|
-
// Create event handlers
|
|
36
|
-
const handlers = {
|
|
37
|
-
tags: {
|
|
38
|
-
INSERT: (payload) => {
|
|
39
|
-
if (payload.new)
|
|
40
|
-
dispatch(addTag(payload.new));
|
|
41
|
-
},
|
|
42
|
-
UPDATE: (payload) => {
|
|
43
|
-
if (payload.new)
|
|
44
|
-
dispatch(updateTag(payload.new));
|
|
45
|
-
},
|
|
46
|
-
DELETE: (payload) => {
|
|
47
|
-
if (payload.old)
|
|
48
|
-
dispatch(deleteTag(payload.old));
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
devices: {
|
|
52
|
-
INSERT: (payload) => {
|
|
53
|
-
if (payload.new)
|
|
54
|
-
dispatch(addDevice(payload.new));
|
|
55
|
-
},
|
|
56
|
-
UPDATE: (payload) => {
|
|
57
|
-
if (payload.new)
|
|
58
|
-
dispatch(updateDevice(payload.new));
|
|
59
|
-
},
|
|
60
|
-
DELETE: (payload) => {
|
|
61
|
-
if (payload.old)
|
|
62
|
-
dispatch(deleteDevice(payload.old));
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
plans: {
|
|
66
|
-
INSERT: (payload) => {
|
|
67
|
-
if (payload.new)
|
|
68
|
-
dispatch(addPlan(payload.new));
|
|
69
|
-
},
|
|
70
|
-
UPDATE: (payload) => {
|
|
71
|
-
if (payload.new)
|
|
72
|
-
dispatch(updatePlan(payload.new));
|
|
73
|
-
},
|
|
74
|
-
DELETE: (payload) => {
|
|
75
|
-
if (payload.old)
|
|
76
|
-
dispatch(deletePlan(payload.old));
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
sessions: {
|
|
80
|
-
INSERT: (payload) => console.log("[DB Listener] Session INSERT:", payload),
|
|
81
|
-
UPDATE: (payload) => console.log("[DB Listener] Session UPDATE:", payload),
|
|
82
|
-
DELETE: (payload) => console.log("[DB Listener] Session DELETE:", payload),
|
|
83
|
-
},
|
|
84
|
-
connectivity: {
|
|
85
|
-
INSERT: (payload) => console.log("[DB Listener] Connectivity INSERT:", payload),
|
|
86
|
-
UPDATE: (payload) => console.log("[DB Listener] Connectivity UPDATE:", payload),
|
|
87
|
-
DELETE: (payload) => console.log("[DB Listener] Connectivity DELETE:", payload),
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
// Set up channels
|
|
91
|
-
const setupChannels = async () => {
|
|
92
|
-
if (!scoutSupabase)
|
|
93
|
-
return false;
|
|
94
|
-
cleanupChannels();
|
|
95
|
-
const tables = Object.keys(handlers);
|
|
96
|
-
let successCount = 0;
|
|
97
|
-
const totalChannels = tables.length;
|
|
98
|
-
for (const tableName of tables) {
|
|
99
|
-
try {
|
|
100
|
-
const channelName = `scout_broadcast_${tableName}_${Date.now()}`;
|
|
101
|
-
const channel = scoutSupabase.channel(channelName, {
|
|
102
|
-
config: { private: false },
|
|
103
|
-
});
|
|
104
|
-
// Set up event handlers
|
|
105
|
-
const tableHandler = handlers[tableName];
|
|
106
|
-
Object.entries(tableHandler).forEach(([event, handler]) => {
|
|
107
|
-
channel.on("broadcast", { event }, handler);
|
|
108
|
-
});
|
|
109
|
-
// Subscribe to the channel
|
|
110
|
-
channel.subscribe((status) => {
|
|
111
|
-
if (status === "SUBSCRIBED") {
|
|
112
|
-
successCount++;
|
|
113
|
-
if (successCount === totalChannels) {
|
|
114
|
-
setConnectionState(ConnectionState.CONNECTED);
|
|
115
|
-
setLastError(null);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
|
|
119
|
-
setLastError(`Channel subscription failed: ${status}`);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
channels.current.push(channel);
|
|
123
|
-
}
|
|
124
|
-
catch (error) {
|
|
125
|
-
console.error(`[DB Listener] Failed to set up ${tableName} channel:`, error);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return successCount > 0;
|
|
129
|
-
};
|
|
130
|
-
// Initialize connection
|
|
131
|
-
const initializeConnection = async () => {
|
|
132
|
-
if (!scoutSupabase)
|
|
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");
|
|
133
17
|
return;
|
|
134
|
-
setConnectionState(ConnectionState.CONNECTING);
|
|
135
|
-
try {
|
|
136
|
-
// Test database connection
|
|
137
|
-
const { error } = await scoutSupabase.from("tags").select("id").limit(1);
|
|
138
|
-
if (error) {
|
|
139
|
-
throw new Error("Database connection test failed");
|
|
140
|
-
}
|
|
141
|
-
// Set up channels
|
|
142
|
-
const success = await setupChannels();
|
|
143
|
-
if (!success) {
|
|
144
|
-
throw new Error("Channel setup failed");
|
|
145
|
-
}
|
|
146
18
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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;
|
|
150
58
|
}
|
|
151
|
-
|
|
152
|
-
|
|
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
|
+
}
|
|
153
74
|
useEffect(() => {
|
|
154
75
|
if (!scoutSupabase) {
|
|
155
|
-
|
|
156
|
-
setLastError("No Supabase client available");
|
|
76
|
+
console.error("[DB Listener] No Supabase client available");
|
|
157
77
|
return;
|
|
158
78
|
}
|
|
159
|
-
|
|
79
|
+
supabase.current = scoutSupabase;
|
|
80
|
+
// Create a single channel for all operations
|
|
81
|
+
const channelName = `scout_realtime_${Date.now()}`;
|
|
82
|
+
const mainChannel = scoutSupabase.channel(channelName);
|
|
83
|
+
// Subscribe to all events
|
|
84
|
+
mainChannel
|
|
85
|
+
.on("postgres_changes", { event: "INSERT", schema: "public", table: "plans" }, handlePlanInserts)
|
|
86
|
+
.on("postgres_changes", { event: "DELETE", schema: "public", table: "plans" }, handlePlanDeletes)
|
|
87
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "plans" }, handlePlanUpdates)
|
|
88
|
+
.on("postgres_changes", { event: "INSERT", schema: "public", table: "devices" }, handleDeviceInserts)
|
|
89
|
+
.on("postgres_changes", { event: "DELETE", schema: "public", table: "devices" }, handleDeviceDeletes)
|
|
90
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "devices" }, handleDeviceUpdates)
|
|
91
|
+
.on("postgres_changes", { event: "INSERT", schema: "public", table: "tags" }, handleTagInserts)
|
|
92
|
+
.on("postgres_changes", { event: "DELETE", schema: "public", table: "tags" }, handleTagDeletes)
|
|
93
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "tags" }, handleTagUpdates)
|
|
94
|
+
.on("postgres_changes", { event: "INSERT", schema: "public", table: "connectivity" }, handleConnectivityInserts)
|
|
95
|
+
.on("postgres_changes", { event: "DELETE", schema: "public", table: "connectivity" }, handleConnectivityDeletes)
|
|
96
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "connectivity" }, handleConnectivityUpdates)
|
|
97
|
+
.on("postgres_changes", { event: "INSERT", schema: "public", table: "sessions" }, handleSessionInserts)
|
|
98
|
+
.on("postgres_changes", { event: "DELETE", schema: "public", table: "sessions" }, handleSessionDeletes)
|
|
99
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "sessions" }, handleSessionUpdates)
|
|
100
|
+
.subscribe((status) => {
|
|
101
|
+
console.log("[DB Listener] Subscription status:", status);
|
|
102
|
+
if (status === "SUBSCRIBED") {
|
|
103
|
+
console.log("[DB Listener] ✅ Successfully subscribed to real-time updates");
|
|
104
|
+
}
|
|
105
|
+
else if (status === "CHANNEL_ERROR") {
|
|
106
|
+
console.error("[DB Listener] ❌ Channel error occurred");
|
|
107
|
+
}
|
|
108
|
+
else if (status === "TIMED_OUT") {
|
|
109
|
+
console.error("[DB Listener] ⏰ Subscription timed out");
|
|
110
|
+
}
|
|
111
|
+
else if (status === "CLOSED") {
|
|
112
|
+
console.log("[DB Listener] 🔒 Channel closed");
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
channels.current.push(mainChannel);
|
|
116
|
+
// Cleanup function
|
|
160
117
|
return () => {
|
|
161
|
-
|
|
118
|
+
console.log("[DB Listener] 🧹 Cleaning up channels");
|
|
119
|
+
channels.current.forEach((channel) => {
|
|
120
|
+
if (channel) {
|
|
121
|
+
scoutSupabase.removeChannel(channel);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
channels.current = [];
|
|
162
125
|
};
|
|
163
|
-
}, [scoutSupabase]);
|
|
164
|
-
return {
|
|
165
|
-
connectionState,
|
|
166
|
-
lastError,
|
|
167
|
-
isConnected: connectionState === ConnectionState.CONNECTED,
|
|
168
|
-
isConnecting: connectionState === ConnectionState.CONNECTING,
|
|
169
|
-
};
|
|
126
|
+
}, [scoutSupabase, dispatch]);
|
|
170
127
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export * from "./helpers/gps";
|
|
|
19
19
|
export * from "./helpers/herds";
|
|
20
20
|
export * from "./helpers/location";
|
|
21
21
|
export * from "./helpers/plans";
|
|
22
|
+
export * from "./helpers/layers";
|
|
22
23
|
export * from "./helpers/sessions";
|
|
23
24
|
export * from "./helpers/tags";
|
|
24
25
|
export * from "./helpers/time";
|
|
@@ -36,7 +37,6 @@ export * from "./store/hooks";
|
|
|
36
37
|
export * from "./supabase/middleware";
|
|
37
38
|
export * from "./supabase/server";
|
|
38
39
|
export * from "./api_keys/actions";
|
|
39
|
-
export type { Database } from "./types/supabase";
|
|
40
40
|
export type { HerdModule, IHerdModule } from "./types/herd_module";
|
|
41
|
-
export type { IDevice, IEvent, IUser, IHerd, IEventWithTags, IZoneWithActions, IUserAndRole, IApiKeyScout, } from "./types/db";
|
|
41
|
+
export type { IDevice, IEvent, IUser, IHerd, IEventWithTags, IZoneWithActions, IUserAndRole, IApiKeyScout, ILayer, } from "./types/db";
|
|
42
42
|
export { EnumSessionsVisibility } from "./types/events";
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ export * from "./helpers/gps";
|
|
|
22
22
|
export * from "./helpers/herds";
|
|
23
23
|
export * from "./helpers/location";
|
|
24
24
|
export * from "./helpers/plans";
|
|
25
|
+
export * from "./helpers/layers";
|
|
25
26
|
export * from "./helpers/sessions";
|
|
26
27
|
export * from "./helpers/tags";
|
|
27
28
|
export * from "./helpers/time";
|