@adventurelabs/scout-core 1.0.66 → 1.0.68

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.
@@ -0,0 +1,16 @@
1
+ import { IWebResponseCompatible } from "../types/requests";
2
+ import { SupabaseClient } from "@supabase/supabase-js";
3
+ import { TablesInsert } from "../types/supabase";
4
+ export type ChatMessageInsert = TablesInsert<"chat">;
5
+ export declare function server_insert_chat_message(message: string, sender?: string): Promise<IWebResponseCompatible<{
6
+ id: number;
7
+ }>>;
8
+ export declare function server_insert_chat_message_with_client(message: string, supabaseClient: SupabaseClient, sender?: string): Promise<IWebResponseCompatible<{
9
+ id: number;
10
+ }>>;
11
+ export declare function server_get_chat_messages(limit?: number, offset?: number): Promise<IWebResponseCompatible<Array<{
12
+ id: number;
13
+ message: string;
14
+ sender: string | null;
15
+ created_at: string;
16
+ }>>>;
@@ -0,0 +1,46 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { IWebResponse, } from "../types/requests";
4
+ export async function server_insert_chat_message(message, sender) {
5
+ const supabase = await newServerClient();
6
+ const chatMessage = {
7
+ message,
8
+ sender: sender || null,
9
+ };
10
+ const { data, error } = await supabase
11
+ .from("chat")
12
+ .insert(chatMessage)
13
+ .select("id")
14
+ .single();
15
+ if (error) {
16
+ return IWebResponse.error(`Failed to insert chat message: ${error.message}`).to_compatible();
17
+ }
18
+ return IWebResponse.success({ id: data.id }).to_compatible();
19
+ }
20
+ export async function server_insert_chat_message_with_client(message, supabaseClient, sender) {
21
+ const chatMessage = {
22
+ message,
23
+ sender: sender || null,
24
+ };
25
+ const { data, error } = await supabaseClient
26
+ .from("chat")
27
+ .insert(chatMessage)
28
+ .select("id")
29
+ .single();
30
+ if (error) {
31
+ return IWebResponse.error(`Failed to insert chat message: ${error.message}`).to_compatible();
32
+ }
33
+ return IWebResponse.success({ id: data.id }).to_compatible();
34
+ }
35
+ export async function server_get_chat_messages(limit = 50, offset = 0) {
36
+ const supabase = await newServerClient();
37
+ const { data, error } = await supabase
38
+ .from("chat")
39
+ .select("id, message, sender, created_at")
40
+ .order("created_at", { ascending: false })
41
+ .range(offset, offset + limit - 1);
42
+ if (error) {
43
+ return IWebResponse.error(`Failed to fetch chat messages: ${error.message}`).to_compatible();
44
+ }
45
+ return IWebResponse.success(data || []).to_compatible();
46
+ }
@@ -3,12 +3,7 @@ import { newServerClient } from "../supabase/server";
3
3
  import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
4
  import { HerdModule, } from "../types/herd_module";
5
5
  export async function get_herds(client) {
6
- const queryStartTime = Date.now();
7
- console.log(`[get_herds] Starting database query at ${new Date(queryStartTime).toISOString()}`);
8
6
  const { data: herds } = await client.from("herds").select();
9
- const queryEndTime = Date.now();
10
- const queryDuration = queryEndTime - queryStartTime;
11
- console.log(`[get_herds] Database query completed in ${queryDuration}ms`);
12
7
  if (!herds) {
13
8
  return {
14
9
  status: EnumWebResponse.ERROR,
@@ -70,57 +65,28 @@ export async function createHerd(newHerd) {
70
65
  }
71
66
  }
72
67
  export async function server_load_herd_modules() {
73
- const requestReceivedTime = Date.now();
74
- console.log(`[server_load_herd_modules] Request received at: ${new Date(requestReceivedTime).toISOString()}`);
75
68
  const startTime = Date.now();
76
- // Measure Supabase client creation
77
- const supabaseStartTime = Date.now();
69
+ // load herds
78
70
  const client_supabase = await newServerClient();
79
- const supabaseTime = Date.now() - supabaseStartTime;
80
- console.log(`[server_load_herd_modules] Supabase client creation took: ${supabaseTime}ms`);
81
- // Measure database connection and initial query
82
- const dbStartTime = Date.now();
83
71
  let new_herds = await get_herds(client_supabase);
84
- const dbConnectionTime = Date.now() - dbStartTime;
85
- console.log(`[server_load_herd_modules] Database connection and initial herds query took: ${dbConnectionTime}ms`);
86
72
  if (new_herds.status != EnumWebResponse.SUCCESS || !new_herds.data) {
87
- const errorTime = Date.now();
88
73
  return {
89
74
  status: EnumWebResponse.ERROR,
90
75
  msg: "No herds found",
91
76
  data: null,
92
- time_finished: errorTime,
93
- time_sent: errorTime,
94
- server_processing_time_ms: errorTime - startTime,
77
+ time_finished: Date.now(),
78
+ time_sent: Date.now(),
79
+ server_processing_time_ms: Date.now() - startTime,
95
80
  };
96
81
  }
97
- console.log(`[server_load_herd_modules] Loading ${new_herds.data.length} herds in parallel...`);
98
- // Measure herd module creation
99
- const herdModuleStartTime = Date.now();
100
82
  let new_herd_modules = [];
101
83
  const herdModulePromises = new_herds.data.map((herd) => HerdModule.from_herd(herd, client_supabase));
102
84
  new_herd_modules = await Promise.all(herdModulePromises);
103
- const herdModuleTime = Date.now() - herdModuleStartTime;
104
- console.log(`[server_load_herd_modules] Herd module creation took: ${herdModuleTime}ms`);
105
- // Measure serialization
106
- const serializationStartTime = Date.now();
85
+ // now serialize the herd modules
107
86
  let serialized_herd_modules = new_herd_modules.map((herd_module) => herd_module.to_serializable());
108
- const serializationTime = Date.now() - serializationStartTime;
109
- console.log(`[server_load_herd_modules] Serialization took: ${serializationTime}ms`);
110
87
  const endTime = Date.now();
111
88
  const totalLoadTime = endTime - startTime;
112
- // Calculate detailed timing breakdown
113
- const timeToClient = endTime - requestReceivedTime;
114
- const processingTime = endTime - startTime;
115
89
  console.log(`[server_load_herd_modules] Loaded ${new_herds.data.length} herds in ${totalLoadTime}ms (parallel processing)`);
116
- console.log(`[server_load_herd_modules] Detailed timing breakdown:`);
117
- console.log(` - Request received to start: ${startTime - requestReceivedTime}ms`);
118
- console.log(` - Supabase client creation: ${supabaseTime}ms`);
119
- console.log(` - Database connection & query: ${dbConnectionTime}ms`);
120
- console.log(` - Herd module creation: ${herdModuleTime}ms`);
121
- console.log(` - Serialization: ${serializationTime}ms`);
122
- console.log(` - Total processing time: ${processingTime}ms`);
123
- console.log(` - Total time to client: ${timeToClient}ms`);
124
90
  // Record the time when we're about to send the response
125
91
  const timeSent = Date.now();
126
92
  return {
@@ -1,5 +1,6 @@
1
1
  export * from "./auth";
2
2
  export * from "./bounding_boxes";
3
+ export * from "./chat";
3
4
  export * from "./db";
4
5
  export * from "./devices";
5
6
  export * from "./email";
@@ -1,5 +1,6 @@
1
1
  export * from "./auth";
2
2
  export * from "./bounding_boxes";
3
+ export * from "./chat";
3
4
  export * from "./db";
4
5
  export * from "./devices";
5
6
  export * from "./email";
@@ -6,12 +6,6 @@ export function useScoutDbListener(scoutSupabase) {
6
6
  const supabase = useRef(null);
7
7
  const channels = useRef([]);
8
8
  const dispatch = useAppDispatch();
9
- const reconnectTimeoutRef = useRef(null);
10
- const reconnectAttemptsRef = useRef(0);
11
- const maxReconnectAttempts = 10;
12
- const baseDelay = 1000; // 1 second
13
- const maxDelay = 5000; // 5 seconds
14
- const lastChannelIdRef = useRef(null);
15
9
  function handleTagInserts(payload) {
16
10
  console.log("[DB Listener] Tag INSERT received:", payload.new);
17
11
  dispatch(addTag(payload.new));
@@ -94,7 +88,6 @@ export function useScoutDbListener(scoutSupabase) {
94
88
  .toString(36)
95
89
  .substr(2, 9)}`;
96
90
  const mainChannel = scoutSupabase.channel(channelId);
97
- lastChannelIdRef.current = channelId;
98
91
  console.log(`[DB Listener] Creating channel: ${channelId}`);
99
92
  // Subscribe to all events
100
93
  mainChannel
@@ -117,51 +110,10 @@ export function useScoutDbListener(scoutSupabase) {
117
110
  console.log("[DB Listener] Subscription status:", status);
118
111
  if (status === "SUBSCRIBED") {
119
112
  console.log("[DB Listener] ✅ Successfully subscribed to real-time updates");
120
- reconnectAttemptsRef.current = 0; // Reset reconnect attempts on successful connection
121
- }
122
- else if (status === "CHANNEL_ERROR") {
123
- console.warn("[DB Listener] ❌ Channel error occurred. Reconnecting...");
124
- handleReconnect();
125
- }
126
- else if (status === "TIMED_OUT") {
127
- console.warn("[DB Listener] ⏰ Subscription timed out. Reconnecting...");
128
- handleReconnect();
129
- }
130
- else if (status === "CLOSED") {
131
- console.log(`[DB Listener] 🔒 Channel closed: ${lastChannelIdRef.current}`);
132
- // Only reconnect if this isn't an immediate closure after subscription
133
- if (reconnectAttemptsRef.current > 0) {
134
- console.log("[DB Listener] Reconnecting...");
135
- handleReconnect();
136
- }
137
- else {
138
- console.log("[DB Listener] Channel closed immediately after subscription, not reconnecting");
139
- }
140
113
  }
141
114
  });
142
115
  return mainChannel;
143
116
  };
144
- // Handle reconnection with exponential backoff
145
- const handleReconnect = () => {
146
- if (reconnectAttemptsRef.current >= maxReconnectAttempts) {
147
- console.error("[DB Listener] 🚫 Max reconnection attempts reached");
148
- return;
149
- }
150
- // Clear any existing timeout
151
- if (reconnectTimeoutRef.current) {
152
- clearTimeout(reconnectTimeoutRef.current);
153
- }
154
- const delay = Math.min(baseDelay * (reconnectAttemptsRef.current + 1), maxDelay);
155
- console.log(`[DB Listener] 🔄 Attempting reconnection in ${delay}ms (attempt ${reconnectAttemptsRef.current + 1}/${maxReconnectAttempts})`);
156
- reconnectTimeoutRef.current = setTimeout(() => {
157
- reconnectAttemptsRef.current++;
158
- cleanupChannels();
159
- const newChannel = setupChannel();
160
- if (newChannel) {
161
- channels.current.push(newChannel);
162
- }
163
- }, delay);
164
- };
165
117
  useEffect(() => {
166
118
  if (!scoutSupabase) {
167
119
  console.error("[DB Listener] No Supabase client available");
@@ -176,15 +128,6 @@ export function useScoutDbListener(scoutSupabase) {
176
128
  // Cleanup function
177
129
  return () => {
178
130
  console.log("[DB Listener] 🧹 Cleaning up channels");
179
- // Clear any pending reconnection attempts
180
- if (reconnectTimeoutRef.current) {
181
- clearTimeout(reconnectTimeoutRef.current);
182
- reconnectTimeoutRef.current = null;
183
- }
184
- // Reset reconnect attempts and channel tracking
185
- reconnectAttemptsRef.current = 0;
186
- lastChannelIdRef.current = null;
187
- // Clean up channels
188
131
  cleanupChannels();
189
132
  };
190
133
  }, [scoutSupabase, dispatch]);
@@ -98,37 +98,13 @@ export function useScoutRefresh(options = {}) {
98
98
  if (herdModulesResponse.status === EnumWebResponse.SUCCESS &&
99
99
  herdModulesResponse.data) {
100
100
  const serverFinishTime = herdModulesResponse.time_finished;
101
- const serverSentTime = herdModulesResponse.time_sent;
102
101
  const clientReceiveTime = Date.now();
103
- // More accurate network latency: from when server sent to when client received
104
- const estimatedNetworkLatency = clientReceiveTime - serverSentTime;
102
+ const estimatedNetworkLatency = clientReceiveTime - serverFinishTime;
105
103
  networkLatencyMs = Math.max(0, estimatedNetworkLatency);
106
- // Time between server finishing processing and sending response
107
- const serverOverhead = serverSentTime - serverFinishTime;
108
- console.log(`[useScoutRefresh] Network latency calculation:`);
109
- console.log(` - Server finished processing at: ${new Date(serverFinishTime).toISOString()}`);
110
- console.log(` - Server sent response at: ${new Date(serverSentTime).toISOString()}`);
111
- console.log(` - Client received at: ${new Date(clientReceiveTime).toISOString()}`);
112
- console.log(` - Server processing time: ${herdModulesResponse.server_processing_time_ms}ms`);
113
- console.log(` - Server overhead (finish to send): ${serverOverhead}ms`);
114
- console.log(` - Estimated network latency: ${networkLatencyMs}ms`);
115
- console.log(` - Client total time: ${herdModulesDuration}ms`);
116
- console.log(` - Breakdown: ${herdModulesResponse.server_processing_time_ms}ms (server) + ${serverOverhead}ms (overhead) + ${networkLatencyMs}ms (network) = ${herdModulesResponse.server_processing_time_ms +
117
- serverOverhead +
118
- networkLatencyMs}ms`);
119
- // Additional analysis
120
- if (herdModulesResponse.data.length > 0) {
121
- const totalDevices = herdModulesResponse.data.reduce((sum, hm) => sum + (hm.devices?.length || 0), 0);
122
- const totalEvents = herdModulesResponse.data.reduce((sum, hm) => sum + (hm.events?.length || 0), 0);
123
- console.log(` - Response size analysis:`);
124
- console.log(` * Herds: ${herdModulesResponse.data.length}`);
125
- console.log(` * Total devices: ${totalDevices}`);
126
- console.log(` * Total events: ${totalEvents}`);
127
- console.log(` * Estimated payload: ~${Math.round((herdModulesResponse.data.length * 2 +
128
- totalDevices * 3 +
129
- totalEvents * 5) /
130
- 1024)}KB`);
131
- }
104
+ console.log(`[useScoutRefresh] Herd modules performance:`);
105
+ console.log(` - Server processing: ${herdModulesResponse.server_processing_time_ms}ms`);
106
+ console.log(` - Network latency: ${networkLatencyMs}ms`);
107
+ console.log(` - Total client time: ${herdModulesDuration}ms`);
132
108
  }
133
109
  // Store timing values
134
110
  timingRefs.current.herdModulesDuration = herdModulesDuration;
@@ -139,14 +115,11 @@ export function useScoutRefresh(options = {}) {
139
115
  // Calculate network overhead
140
116
  const totalApiTime = herdModulesDuration + userApiDuration;
141
117
  const networkOverhead = parallelDuration - Math.max(herdModulesDuration, userApiDuration);
142
- console.log(`[useScoutRefresh] API timing breakdown:`);
143
- console.log(` - Herd modules: ${herdModulesDuration}ms (server processing + network)`);
144
- console.log(` - User API: ${userApiDuration}ms (server processing + network)`);
118
+ console.log(`[useScoutRefresh] API performance:`);
119
+ console.log(` - Herd modules: ${herdModulesDuration}ms`);
120
+ console.log(` - User API: ${userApiDuration}ms`);
145
121
  console.log(` - Parallel execution: ${parallelDuration}ms`);
146
- console.log(` - Network overhead: ${networkOverhead}ms`);
147
- if (networkLatencyMs > 0) {
148
- console.log(` - Estimated network latency: ${networkLatencyMs}ms`);
149
- }
122
+ console.log(` - Time saved with parallel: ${totalApiTime - parallelDuration}ms`);
150
123
  // Validate API responses
151
124
  const validationStartTime = Date.now();
152
125
  if (!herdModulesResponse.data ||
@@ -201,16 +174,13 @@ export function useScoutRefresh(options = {}) {
201
174
  const loadingDuration = Date.now() - startTime;
202
175
  dispatch(setHerdModulesLoadedInMs(loadingDuration));
203
176
  dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
204
- // Log comprehensive timing statistics
205
- console.log("[useScoutRefresh] Refresh completed successfully. Full timing breakdown:");
206
- console.log(` - Herd modules API: ${herdModulesDuration}ms`);
177
+ // Log essential performance metrics
178
+ console.log(`[useScoutRefresh] Refresh completed successfully:`);
179
+ console.log(` - Total duration: ${loadingDuration}ms`);
180
+ console.log(` - Herd modules: ${herdModulesDuration}ms`);
207
181
  console.log(` - User API: ${userApiDuration}ms`);
208
182
  console.log(` - Parallel execution: ${parallelDuration}ms`);
209
- console.log(` - Network overhead: ${networkOverhead}ms`);
210
- console.log(` - Data processing: ${dataProcessingDuration}ms`);
211
- console.log(` - LocalStorage operations: ${localStorageDuration}ms`);
212
- console.log(` - Total duration: ${loadingDuration}ms`);
213
- console.log(` - Time saved with parallel execution: ${totalApiTime - parallelDuration}ms`);
183
+ console.log(` - Time saved with parallel: ${totalApiTime - parallelDuration}ms`);
214
184
  onRefreshComplete?.();
215
185
  }
216
186
  catch (error) {
@@ -220,13 +190,11 @@ export function useScoutRefresh(options = {}) {
220
190
  dispatch(setHerdModulesLoadingState(EnumHerdModulesLoadingState.UNSUCCESSFULLY_LOADED));
221
191
  dispatch(setHerdModulesLoadedInMs(loadingDuration));
222
192
  dispatch(setStatus(EnumScoutStateStatus.DONE_LOADING));
223
- // Log timing statistics even on error
224
- console.log("[useScoutRefresh] Refresh failed. Partial timing breakdown:");
225
- console.log(` - Herd modules API: ${timingRefs.current.herdModulesDuration}ms`);
226
- console.log(` - User API: ${timingRefs.current.userApiDuration}ms`);
227
- console.log(` - Data processing: ${timingRefs.current.dataProcessingDuration}ms`);
228
- console.log(` - LocalStorage operations: ${timingRefs.current.localStorageDuration}ms`);
193
+ // Log essential error metrics
194
+ console.log(`[useScoutRefresh] Refresh failed:`);
229
195
  console.log(` - Total duration: ${loadingDuration}ms`);
196
+ console.log(` - Herd modules: ${timingRefs.current.herdModulesDuration}ms`);
197
+ console.log(` - User API: ${timingRefs.current.userApiDuration}ms`);
230
198
  }
231
199
  finally {
232
200
  refreshInProgressRef.current = false;
@@ -46,6 +46,69 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
46
46
  referencedColumns: ["id"];
47
47
  }];
48
48
  };
49
+ artifacts: {
50
+ Row: {
51
+ created_at: string;
52
+ file_path: string;
53
+ id: number;
54
+ session_id: number | null;
55
+ };
56
+ Insert: {
57
+ created_at?: string;
58
+ file_path: string;
59
+ id?: number;
60
+ session_id?: number | null;
61
+ };
62
+ Update: {
63
+ created_at?: string;
64
+ file_path?: string;
65
+ id?: number;
66
+ session_id?: number | null;
67
+ };
68
+ Relationships: [{
69
+ foreignKeyName: "artifacts_session_id_fkey";
70
+ columns: ["session_id"];
71
+ isOneToOne: false;
72
+ referencedRelation: "sessions";
73
+ referencedColumns: ["id"];
74
+ }];
75
+ };
76
+ chat: {
77
+ Row: {
78
+ created_at: string;
79
+ herd_id: number | null;
80
+ id: number;
81
+ message: string;
82
+ sender: string | null;
83
+ };
84
+ Insert: {
85
+ created_at?: string;
86
+ herd_id?: number | null;
87
+ id?: number;
88
+ message: string;
89
+ sender?: string | null;
90
+ };
91
+ Update: {
92
+ created_at?: string;
93
+ herd_id?: number | null;
94
+ id?: number;
95
+ message?: string;
96
+ sender?: string | null;
97
+ };
98
+ Relationships: [{
99
+ foreignKeyName: "chat_herd_id_fkey";
100
+ columns: ["herd_id"];
101
+ isOneToOne: false;
102
+ referencedRelation: "herds";
103
+ referencedColumns: ["id"];
104
+ }, {
105
+ foreignKeyName: "chat_sender_fkey";
106
+ columns: ["sender"];
107
+ isOneToOne: false;
108
+ referencedRelation: "users";
109
+ referencedColumns: ["id"];
110
+ }];
111
+ };
49
112
  connectivity: {
50
113
  Row: {
51
114
  altitude: number;
@@ -340,7 +403,6 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
340
403
  distance_max_from_start: number;
341
404
  distance_total: number;
342
405
  earthranger_url: string | null;
343
- file_paths: string[] | null;
344
406
  id: number;
345
407
  inserted_at: string;
346
408
  locations: unknown;
@@ -359,7 +421,6 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
359
421
  distance_max_from_start: number;
360
422
  distance_total: number;
361
423
  earthranger_url?: string | null;
362
- file_paths?: string[] | null;
363
424
  id?: number;
364
425
  inserted_at?: string;
365
426
  locations: unknown;
@@ -378,7 +439,6 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
378
439
  distance_max_from_start?: number;
379
440
  distance_total?: number;
380
441
  earthranger_url?: string | null;
381
- file_paths?: string[] | null;
382
442
  id?: number;
383
443
  inserted_at?: string;
384
444
  locations?: unknown;
@@ -684,17 +744,17 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
684
744
  };
685
745
  get_events_and_tags_for_session: {
686
746
  Args: {
687
- session_id_caller: number;
688
747
  limit_caller: number;
689
748
  offset_caller: number;
749
+ session_id_caller: number;
690
750
  };
691
751
  Returns: Database["public"]["CompositeTypes"]["event_and_tags_pretty_location"][];
692
752
  };
693
753
  get_events_with_tags_for_herd: {
694
754
  Args: {
695
755
  herd_id_caller: number;
696
- offset_caller: number;
697
756
  limit_caller: number;
757
+ offset_caller: number;
698
758
  };
699
759
  Returns: Database["public"]["CompositeTypes"]["event_with_tags"][];
700
760
  };
@@ -710,16 +770,16 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
710
770
  };
711
771
  Returns: Database["public"]["CompositeTypes"]["session_with_coordinates"][];
712
772
  };
713
- get_total_events_for_session: {
773
+ get_total_events_for_herd_with_session_filter: {
714
774
  Args: {
715
- session_id_caller: number;
775
+ exclude_session_events: boolean;
776
+ herd_id_caller: number;
716
777
  };
717
778
  Returns: number;
718
779
  };
719
- get_total_events_for_herd_with_session_filter: {
780
+ get_total_events_for_session: {
720
781
  Args: {
721
- herd_id_caller: number;
722
- exclude_session_events: boolean;
782
+ session_id_caller: number;
723
783
  };
724
784
  Returns: number;
725
785
  };
@@ -742,9 +802,9 @@ export declare function useSupabase(): SupabaseClient<Database, "public", {
742
802
  device_ids: number[];
743
803
  };
744
804
  Returns: {
745
- device_id: number;
746
805
  api_key_id: string;
747
806
  api_key_key: string;
807
+ device_id: number;
748
808
  }[];
749
809
  };
750
810
  load_api_keys_old: {
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useScoutRefresh } from "../hooks/useScoutRefresh";
4
4
  import { useScoutDbListener } from "../hooks/useScoutDbListener";
5
- import { createContext, useContext, useMemo } from "react";
5
+ import { createContext, useContext, useMemo, useRef } from "react";
6
6
  import { createBrowserClient } from "@supabase/ssr";
7
7
  // Create context for the Supabase client
8
8
  const SupabaseContext = createContext(null);
@@ -24,13 +24,14 @@ export function useConnectionStatus() {
24
24
  return connectionStatus;
25
25
  }
26
26
  export function ScoutRefreshProvider({ children }) {
27
- const url = process.env.NEXT_PUBLIC_SUPABASE_URL || "";
28
- const anon_key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "";
29
- // Create a single Supabase client instance using useMemo to prevent recreation
27
+ // Use refs to store the URL and key to prevent unnecessary recreations
28
+ const urlRef = useRef(process.env.NEXT_PUBLIC_SUPABASE_URL || "");
29
+ const anonKeyRef = useRef(process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "");
30
+ // Create a single Supabase client instance that only runs once
30
31
  const supabaseClient = useMemo(() => {
31
32
  console.log("[ScoutRefreshProvider] Creating Supabase client");
32
- return createBrowserClient(url, anon_key);
33
- }, [url, anon_key]);
33
+ return createBrowserClient(urlRef.current, anonKeyRef.current);
34
+ }, []); // Empty dependency array ensures this only runs once
34
35
  // Use the enhanced DB listener with connection status
35
36
  useScoutDbListener(supabaseClient);
36
37
  useScoutRefresh();
@@ -37,6 +37,69 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
37
37
  referencedColumns: ["id"];
38
38
  }];
39
39
  };
40
+ artifacts: {
41
+ Row: {
42
+ created_at: string;
43
+ file_path: string;
44
+ id: number;
45
+ session_id: number | null;
46
+ };
47
+ Insert: {
48
+ created_at?: string;
49
+ file_path: string;
50
+ id?: number;
51
+ session_id?: number | null;
52
+ };
53
+ Update: {
54
+ created_at?: string;
55
+ file_path?: string;
56
+ id?: number;
57
+ session_id?: number | null;
58
+ };
59
+ Relationships: [{
60
+ foreignKeyName: "artifacts_session_id_fkey";
61
+ columns: ["session_id"];
62
+ isOneToOne: false;
63
+ referencedRelation: "sessions";
64
+ referencedColumns: ["id"];
65
+ }];
66
+ };
67
+ chat: {
68
+ Row: {
69
+ created_at: string;
70
+ herd_id: number | null;
71
+ id: number;
72
+ message: string;
73
+ sender: string | null;
74
+ };
75
+ Insert: {
76
+ created_at?: string;
77
+ herd_id?: number | null;
78
+ id?: number;
79
+ message: string;
80
+ sender?: string | null;
81
+ };
82
+ Update: {
83
+ created_at?: string;
84
+ herd_id?: number | null;
85
+ id?: number;
86
+ message?: string;
87
+ sender?: string | null;
88
+ };
89
+ Relationships: [{
90
+ foreignKeyName: "chat_herd_id_fkey";
91
+ columns: ["herd_id"];
92
+ isOneToOne: false;
93
+ referencedRelation: "herds";
94
+ referencedColumns: ["id"];
95
+ }, {
96
+ foreignKeyName: "chat_sender_fkey";
97
+ columns: ["sender"];
98
+ isOneToOne: false;
99
+ referencedRelation: "users";
100
+ referencedColumns: ["id"];
101
+ }];
102
+ };
40
103
  connectivity: {
41
104
  Row: {
42
105
  altitude: number;
@@ -331,7 +394,6 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
331
394
  distance_max_from_start: number;
332
395
  distance_total: number;
333
396
  earthranger_url: string | null;
334
- file_paths: string[] | null;
335
397
  id: number;
336
398
  inserted_at: string;
337
399
  locations: unknown;
@@ -350,7 +412,6 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
350
412
  distance_max_from_start: number;
351
413
  distance_total: number;
352
414
  earthranger_url?: string | null;
353
- file_paths?: string[] | null;
354
415
  id?: number;
355
416
  inserted_at?: string;
356
417
  locations: unknown;
@@ -369,7 +430,6 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
369
430
  distance_max_from_start?: number;
370
431
  distance_total?: number;
371
432
  earthranger_url?: string | null;
372
- file_paths?: string[] | null;
373
433
  id?: number;
374
434
  inserted_at?: string;
375
435
  locations?: unknown;
@@ -675,17 +735,17 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
675
735
  };
676
736
  get_events_and_tags_for_session: {
677
737
  Args: {
678
- session_id_caller: number;
679
738
  limit_caller: number;
680
739
  offset_caller: number;
740
+ session_id_caller: number;
681
741
  };
682
742
  Returns: Database["public"]["CompositeTypes"]["event_and_tags_pretty_location"][];
683
743
  };
684
744
  get_events_with_tags_for_herd: {
685
745
  Args: {
686
746
  herd_id_caller: number;
687
- offset_caller: number;
688
747
  limit_caller: number;
748
+ offset_caller: number;
689
749
  };
690
750
  Returns: Database["public"]["CompositeTypes"]["event_with_tags"][];
691
751
  };
@@ -701,16 +761,16 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
701
761
  };
702
762
  Returns: Database["public"]["CompositeTypes"]["session_with_coordinates"][];
703
763
  };
704
- get_total_events_for_session: {
764
+ get_total_events_for_herd_with_session_filter: {
705
765
  Args: {
706
- session_id_caller: number;
766
+ exclude_session_events: boolean;
767
+ herd_id_caller: number;
707
768
  };
708
769
  Returns: number;
709
770
  };
710
- get_total_events_for_herd_with_session_filter: {
771
+ get_total_events_for_session: {
711
772
  Args: {
712
- herd_id_caller: number;
713
- exclude_session_events: boolean;
773
+ session_id_caller: number;
714
774
  };
715
775
  Returns: number;
716
776
  };
@@ -733,9 +793,9 @@ export declare function newServerClient(): Promise<import("@supabase/supabase-js
733
793
  device_ids: number[];
734
794
  };
735
795
  Returns: {
736
- device_id: number;
737
796
  api_key_id: string;
738
797
  api_key_key: string;
798
+ device_id: number;
739
799
  }[];
740
800
  };
741
801
  load_api_keys_old: {
@@ -1,14 +1,8 @@
1
1
  import { createServerClient } from "@supabase/ssr";
2
2
  import { cookies } from "next/headers";
3
3
  export async function newServerClient() {
4
- const startTime = Date.now();
5
- console.log(`[newServerClient] Starting client creation at ${new Date(startTime).toISOString()}`);
6
- const cookieStartTime = Date.now();
7
4
  const cookieStore = await cookies();
8
- const cookieTime = Date.now() - cookieStartTime;
9
- console.log(`[newServerClient] Cookie retrieval took: ${cookieTime}ms`);
10
- const supabaseStartTime = Date.now();
11
- const client = createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, {
5
+ return createServerClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, {
12
6
  cookies: {
13
7
  getAll() {
14
8
  return cookieStore.getAll();
@@ -25,9 +19,4 @@ export async function newServerClient() {
25
19
  },
26
20
  },
27
21
  });
28
- const supabaseTime = Date.now() - supabaseStartTime;
29
- console.log(`[newServerClient] Supabase client creation took: ${supabaseTime}ms`);
30
- const totalTime = Date.now() - startTime;
31
- console.log(`[newServerClient] Total client creation time: ${totalTime}ms`);
32
- return client;
33
22
  }
@@ -5,31 +5,6 @@ export type Database = {
5
5
  __InternalSupabase: {
6
6
  PostgrestVersion: "12.2.12 (cd3cf9e)";
7
7
  };
8
- graphql_public: {
9
- Tables: {
10
- [_ in never]: never;
11
- };
12
- Views: {
13
- [_ in never]: never;
14
- };
15
- Functions: {
16
- graphql: {
17
- Args: {
18
- operationName?: string;
19
- query?: string;
20
- variables?: Json;
21
- extensions?: Json;
22
- };
23
- Returns: Json;
24
- };
25
- };
26
- Enums: {
27
- [_ in never]: never;
28
- };
29
- CompositeTypes: {
30
- [_ in never]: never;
31
- };
32
- };
33
8
  public: {
34
9
  Tables: {
35
10
  actions: {
@@ -71,6 +46,74 @@ export type Database = {
71
46
  }
72
47
  ];
73
48
  };
49
+ artifacts: {
50
+ Row: {
51
+ created_at: string;
52
+ file_path: string;
53
+ id: number;
54
+ session_id: number | null;
55
+ };
56
+ Insert: {
57
+ created_at?: string;
58
+ file_path: string;
59
+ id?: number;
60
+ session_id?: number | null;
61
+ };
62
+ Update: {
63
+ created_at?: string;
64
+ file_path?: string;
65
+ id?: number;
66
+ session_id?: number | null;
67
+ };
68
+ Relationships: [
69
+ {
70
+ foreignKeyName: "artifacts_session_id_fkey";
71
+ columns: ["session_id"];
72
+ isOneToOne: false;
73
+ referencedRelation: "sessions";
74
+ referencedColumns: ["id"];
75
+ }
76
+ ];
77
+ };
78
+ chat: {
79
+ Row: {
80
+ created_at: string;
81
+ herd_id: number | null;
82
+ id: number;
83
+ message: string;
84
+ sender: string | null;
85
+ };
86
+ Insert: {
87
+ created_at?: string;
88
+ herd_id?: number | null;
89
+ id?: number;
90
+ message: string;
91
+ sender?: string | null;
92
+ };
93
+ Update: {
94
+ created_at?: string;
95
+ herd_id?: number | null;
96
+ id?: number;
97
+ message?: string;
98
+ sender?: string | null;
99
+ };
100
+ Relationships: [
101
+ {
102
+ foreignKeyName: "chat_herd_id_fkey";
103
+ columns: ["herd_id"];
104
+ isOneToOne: false;
105
+ referencedRelation: "herds";
106
+ referencedColumns: ["id"];
107
+ },
108
+ {
109
+ foreignKeyName: "chat_sender_fkey";
110
+ columns: ["sender"];
111
+ isOneToOne: false;
112
+ referencedRelation: "users";
113
+ referencedColumns: ["id"];
114
+ }
115
+ ];
116
+ };
74
117
  connectivity: {
75
118
  Row: {
76
119
  altitude: number;
@@ -379,7 +422,6 @@ export type Database = {
379
422
  distance_max_from_start: number;
380
423
  distance_total: number;
381
424
  earthranger_url: string | null;
382
- file_paths: string[] | null;
383
425
  id: number;
384
426
  inserted_at: string;
385
427
  locations: unknown;
@@ -398,7 +440,6 @@ export type Database = {
398
440
  distance_max_from_start: number;
399
441
  distance_total: number;
400
442
  earthranger_url?: string | null;
401
- file_paths?: string[] | null;
402
443
  id?: number;
403
444
  inserted_at?: string;
404
445
  locations: unknown;
@@ -417,7 +458,6 @@ export type Database = {
417
458
  distance_max_from_start?: number;
418
459
  distance_total?: number;
419
460
  earthranger_url?: string | null;
420
- file_paths?: string[] | null;
421
461
  id?: number;
422
462
  inserted_at?: string;
423
463
  locations?: unknown;
@@ -744,17 +784,17 @@ export type Database = {
744
784
  };
745
785
  get_events_and_tags_for_session: {
746
786
  Args: {
747
- session_id_caller: number;
748
787
  limit_caller: number;
749
788
  offset_caller: number;
789
+ session_id_caller: number;
750
790
  };
751
791
  Returns: Database["public"]["CompositeTypes"]["event_and_tags_pretty_location"][];
752
792
  };
753
793
  get_events_with_tags_for_herd: {
754
794
  Args: {
755
795
  herd_id_caller: number;
756
- offset_caller: number;
757
796
  limit_caller: number;
797
+ offset_caller: number;
758
798
  };
759
799
  Returns: Database["public"]["CompositeTypes"]["event_with_tags"][];
760
800
  };
@@ -770,16 +810,16 @@ export type Database = {
770
810
  };
771
811
  Returns: Database["public"]["CompositeTypes"]["session_with_coordinates"][];
772
812
  };
773
- get_total_events_for_session: {
813
+ get_total_events_for_herd_with_session_filter: {
774
814
  Args: {
775
- session_id_caller: number;
815
+ exclude_session_events: boolean;
816
+ herd_id_caller: number;
776
817
  };
777
818
  Returns: number;
778
819
  };
779
- get_total_events_for_herd_with_session_filter: {
820
+ get_total_events_for_session: {
780
821
  Args: {
781
- herd_id_caller: number;
782
- exclude_session_events: boolean;
822
+ session_id_caller: number;
783
823
  };
784
824
  Returns: number;
785
825
  };
@@ -802,9 +842,9 @@ export type Database = {
802
842
  device_ids: number[];
803
843
  };
804
844
  Returns: {
805
- device_id: number;
806
845
  api_key_id: string;
807
846
  api_key_key: string;
847
+ device_id: number;
808
848
  }[];
809
849
  };
810
850
  load_api_keys_old: {
@@ -1001,9 +1041,6 @@ export type CompositeTypes<PublicCompositeTypeNameOrOptions extends keyof Defaul
1001
1041
  schema: keyof DatabaseWithoutInternals;
1002
1042
  } ? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] : PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"] ? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] : never;
1003
1043
  export declare const Constants: {
1004
- readonly graphql_public: {
1005
- readonly Enums: {};
1006
- };
1007
1044
  readonly public: {
1008
1045
  readonly Enums: {
1009
1046
  readonly app_permission: readonly ["herds.delete", "events.delete"];
@@ -1,7 +1,4 @@
1
1
  export const Constants = {
2
- graphql_public: {
3
- Enums: {},
4
- },
5
2
  public: {
6
3
  Enums: {
7
4
  app_permission: ["herds.delete", "events.delete"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adventurelabs/scout-core",
3
- "version": "1.0.66",
3
+ "version": "1.0.68",
4
4
  "description": "Core utilities and helpers for Adventure Labs Scout applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",