@adventurelabs/scout-core 1.4.95 → 1.5.0

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.
Files changed (108) hide show
  1. package/dist/api_keys/actions.d.ts +1 -2
  2. package/dist/api_keys/actions.js +4 -83
  3. package/dist/api_keys/queries.d.ts +4 -0
  4. package/dist/api_keys/queries.js +52 -0
  5. package/dist/helpers/artifacts.d.ts +10 -15
  6. package/dist/helpers/artifacts.internal.d.ts +22 -0
  7. package/dist/helpers/artifacts.internal.js +151 -0
  8. package/dist/helpers/artifacts.js +48 -81
  9. package/dist/helpers/client_abilities_jwt_keys.d.ts +3 -4
  10. package/dist/helpers/client_abilities_jwt_keys.js +7 -7
  11. package/dist/helpers/client_abilities_jwt_keys_internal.d.ts +9 -0
  12. package/dist/helpers/client_abilities_jwt_keys_internal.js +20 -0
  13. package/dist/helpers/client_abilities_token_server.d.ts +1 -5
  14. package/dist/helpers/client_abilities_token_server.js +2 -2
  15. package/dist/helpers/connectivity.d.ts +2 -3
  16. package/dist/helpers/connectivity.internal.d.ts +10 -0
  17. package/dist/helpers/connectivity.internal.js +47 -0
  18. package/dist/helpers/connectivity.js +6 -7
  19. package/dist/helpers/devices.d.ts +1 -3
  20. package/dist/helpers/devices.js +3 -12
  21. package/dist/helpers/devices.queries.d.ts +5 -0
  22. package/dist/helpers/devices.queries.js +10 -0
  23. package/dist/helpers/embeddings.d.ts +1 -3
  24. package/dist/helpers/embeddings.internal.d.ts +5 -0
  25. package/dist/helpers/embeddings.internal.js +14 -0
  26. package/dist/helpers/embeddings.js +2 -2
  27. package/dist/helpers/events.d.ts +4 -6
  28. package/dist/helpers/events.internal.d.ts +13 -0
  29. package/dist/helpers/events.internal.js +88 -0
  30. package/dist/helpers/events.js +16 -17
  31. package/dist/helpers/herd_allowed_domains.d.ts +1 -3
  32. package/dist/helpers/herd_allowed_domains.js +2 -2
  33. package/dist/helpers/herd_allowed_domains_internal.d.ts +5 -0
  34. package/dist/helpers/herd_allowed_domains_internal.js +12 -0
  35. package/dist/helpers/herd_modules.queries.d.ts +3 -0
  36. package/dist/helpers/herd_modules.queries.js +106 -0
  37. package/dist/helpers/herd_roles.d.ts +12 -14
  38. package/dist/helpers/herd_roles.js +26 -34
  39. package/dist/helpers/herd_roles_internal.d.ts +18 -0
  40. package/dist/helpers/herd_roles_internal.js +159 -0
  41. package/dist/helpers/herd_scoped.queries.d.ts +7 -0
  42. package/dist/helpers/herd_scoped.queries.js +45 -0
  43. package/dist/helpers/herds.d.ts +2 -4
  44. package/dist/helpers/herds.js +11 -142
  45. package/dist/helpers/herds.queries.d.ts +5 -0
  46. package/dist/helpers/herds.queries.js +12 -0
  47. package/dist/helpers/invitations.d.ts +4 -6
  48. package/dist/helpers/invitations.js +8 -8
  49. package/dist/helpers/invitations_internal.d.ts +10 -0
  50. package/dist/helpers/invitations_internal.js +63 -0
  51. package/dist/helpers/layers.d.ts +1 -3
  52. package/dist/helpers/layers.js +3 -18
  53. package/dist/helpers/layers.queries.d.ts +5 -0
  54. package/dist/helpers/layers.queries.js +20 -0
  55. package/dist/helpers/plans.d.ts +1 -3
  56. package/dist/helpers/plans.js +3 -18
  57. package/dist/helpers/plans.queries.d.ts +5 -0
  58. package/dist/helpers/plans.queries.js +20 -0
  59. package/dist/helpers/providers.d.ts +1 -3
  60. package/dist/helpers/providers.js +3 -18
  61. package/dist/helpers/providers.queries.d.ts +5 -0
  62. package/dist/helpers/providers.queries.js +20 -0
  63. package/dist/helpers/pubsub_token_server.d.ts +1 -5
  64. package/dist/helpers/pubsub_token_server.js +2 -2
  65. package/dist/helpers/session_summaries.d.ts +3 -4
  66. package/dist/helpers/session_summaries.js +13 -43
  67. package/dist/helpers/session_summaries.queries.d.ts +14 -0
  68. package/dist/helpers/session_summaries.queries.js +19 -0
  69. package/dist/helpers/sessions.d.ts +7 -8
  70. package/dist/helpers/sessions.js +23 -58
  71. package/dist/helpers/sessions.queries.d.ts +4 -0
  72. package/dist/helpers/sessions.queries.js +22 -0
  73. package/dist/helpers/storage.d.ts +2 -4
  74. package/dist/helpers/storage.js +7 -54
  75. package/dist/helpers/storage_internal.d.ts +4 -0
  76. package/dist/helpers/storage_internal.js +29 -0
  77. package/dist/helpers/tags.js +5 -5
  78. package/dist/helpers/users.d.ts +7 -8
  79. package/dist/helpers/users.js +13 -41
  80. package/dist/helpers/users.queries.d.ts +5 -0
  81. package/dist/helpers/users.queries.js +30 -0
  82. package/dist/helpers/versions_software_internal.d.ts +6 -0
  83. package/dist/helpers/versions_software_internal.js +53 -0
  84. package/dist/helpers/versions_software_server.d.ts +2 -3
  85. package/dist/helpers/versions_software_server.js +20 -18
  86. package/dist/hooks/index.d.ts +5 -0
  87. package/dist/hooks/index.js +5 -0
  88. package/dist/hooks/useScoutRealtimeAnalysisJobs.js +4 -58
  89. package/dist/hooks/useScoutRealtimeAnalysisTasks.js +4 -58
  90. package/dist/hooks/useScoutRealtimeBroadcast.d.ts +8 -0
  91. package/dist/hooks/useScoutRealtimeBroadcast.js +44 -0
  92. package/dist/hooks/useScoutRealtimeContacts.d.ts +5 -0
  93. package/dist/hooks/useScoutRealtimeContacts.js +7 -0
  94. package/dist/hooks/useScoutRealtimeDocuments.d.ts +7 -0
  95. package/dist/hooks/useScoutRealtimeDocuments.js +22 -0
  96. package/dist/hooks/useScoutRealtimeMaintenanceRequests.d.ts +5 -0
  97. package/dist/hooks/useScoutRealtimeMaintenanceRequests.js +7 -0
  98. package/dist/hooks/useScoutRealtimeParts.js +2 -68
  99. package/dist/hooks/useScoutRealtimePlans.js +2 -61
  100. package/dist/hooks/useScoutRealtimeSessionIncidents.d.ts +5 -0
  101. package/dist/hooks/useScoutRealtimeSessionIncidents.js +7 -0
  102. package/dist/hooks/useScoutRealtimeVersionsSoftware.js +4 -63
  103. package/dist/index.d.ts +6 -0
  104. package/dist/index.js +6 -0
  105. package/dist/supabase/server.d.ts +4 -1
  106. package/dist/supabase/server.js +6 -5
  107. package/dist/types/supabase.d.ts +33 -0
  108. package/package.json +1 -1
@@ -0,0 +1,20 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ export async function upsert_client_abilities_jwt_public_key(client, kid, publicJwk) {
3
+ const { error } = await client.rpc("upsert_client_abilities_jwt_public_key", {
4
+ p_kid: kid,
5
+ p_public_jwk: publicJwk,
6
+ });
7
+ if (error) {
8
+ return IWebResponse.error(error.message).to_compatible();
9
+ }
10
+ return IWebResponse.success(null).to_compatible();
11
+ }
12
+ export async function revoke_client_abilities_jwt_public_key(client, kid) {
13
+ const { error } = await client.rpc("revoke_client_abilities_jwt_public_key", {
14
+ p_kid: kid,
15
+ });
16
+ if (error) {
17
+ return IWebResponse.error(error.message).to_compatible();
18
+ }
19
+ return IWebResponse.success(null).to_compatible();
20
+ }
@@ -1,7 +1,3 @@
1
- import { SupabaseClient } from "@supabase/supabase-js";
2
- import { Database } from "../types/supabase";
3
1
  import { IClientAbilitiesTokenMint } from "../types/client_abilities_token";
4
2
  import { IWebResponseCompatible } from "../types/requests";
5
- export declare function server_mint_client_abilities_token(options?: {
6
- client?: SupabaseClient<Database>;
7
- }): Promise<IWebResponseCompatible<IClientAbilitiesTokenMint>>;
3
+ export declare function server_mint_client_abilities_token(): Promise<IWebResponseCompatible<IClientAbilitiesTokenMint>>;
@@ -1,7 +1,7 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { mint_client_abilities_token } from "./client_abilities_token";
4
- export async function server_mint_client_abilities_token(options) {
5
- const client = options?.client ?? (await newServerClient());
4
+ export async function server_mint_client_abilities_token() {
5
+ const client = await newServerClient();
6
6
  return mint_client_abilities_token(client);
7
7
  }
@@ -1,14 +1,13 @@
1
1
  import { IWebResponseCompatible } from "../types/requests";
2
2
  import { IConnectivityWithCoordinates, IConnectivity, ConnectivityInsert, ConnectivityUpdate } from "../types/db";
3
- import { SupabaseClient } from "@supabase/supabase-js";
4
3
  export declare function server_get_connectivity_by_session_id(sessionId: number): Promise<IWebResponseCompatible<IConnectivityWithCoordinates[]>>;
5
4
  export declare function server_get_connectivity_by_device_id(deviceId: number, timestamp: string): Promise<IWebResponseCompatible<IConnectivityWithCoordinates[]>>;
6
- export declare function server_insert_connectivity(connectivity: ConnectivityInsert | ConnectivityInsert[], client?: SupabaseClient): Promise<IWebResponseCompatible<IConnectivity[]>>;
5
+ export declare function server_insert_connectivity(connectivity: ConnectivityInsert | ConnectivityInsert[]): Promise<IWebResponseCompatible<IConnectivity[]>>;
7
6
  export declare function server_update_connectivity(connectivity: (ConnectivityUpdate & {
8
7
  id: number;
9
8
  }) | (ConnectivityUpdate & {
10
9
  id: number;
11
- })[], client?: SupabaseClient): Promise<IWebResponseCompatible<IConnectivity[]>>;
10
+ })[]): Promise<IWebResponseCompatible<IConnectivity[]>>;
12
11
  /** Pagination info returned with herd time range connectivity. */
13
12
  export type HerdConnectivityTimeRangeResponse = IWebResponseCompatible<IConnectivityWithCoordinates[]> & {
14
13
  hasMore: boolean;
@@ -0,0 +1,10 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IConnectivity, ConnectivityInsert, ConnectivityUpdate } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import type { Database } from "../types/supabase";
5
+ export declare function insertConnectivityWithClient(client: SupabaseClient<Database>, connectivity: ConnectivityInsert | ConnectivityInsert[]): Promise<IWebResponseCompatible<IConnectivity[]>>;
6
+ export declare function updateConnectivityWithClient(client: SupabaseClient<Database>, connectivity: (ConnectivityUpdate & {
7
+ id: number;
8
+ }) | (ConnectivityUpdate & {
9
+ id: number;
10
+ })[]): Promise<IWebResponseCompatible<IConnectivity[]>>;
@@ -0,0 +1,47 @@
1
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
2
+ export async function insertConnectivityWithClient(client, connectivity) {
3
+ const connectivityArray = Array.isArray(connectivity)
4
+ ? connectivity
5
+ : [connectivity];
6
+ const { data, error } = await client
7
+ .from("connectivity")
8
+ .insert(connectivityArray)
9
+ .select("*");
10
+ if (error) {
11
+ console.warn("Error inserting connectivity:", error.message);
12
+ return {
13
+ status: EnumWebResponse.ERROR,
14
+ msg: error.message,
15
+ data: [],
16
+ };
17
+ }
18
+ return IWebResponse.success(data || []).to_compatible();
19
+ }
20
+ export async function updateConnectivityWithClient(client, connectivity) {
21
+ const connectivityArray = Array.isArray(connectivity)
22
+ ? connectivity
23
+ : [connectivity];
24
+ const updatedConnectivity = [];
25
+ for (const record of connectivityArray) {
26
+ const { id, ...updateData } = record;
27
+ delete updateData.inserted_at;
28
+ const { data, error } = await client
29
+ .from("connectivity")
30
+ .update(updateData)
31
+ .eq("id", id)
32
+ .select("*")
33
+ .single();
34
+ if (error) {
35
+ console.warn("Error updating connectivity:", error.message);
36
+ return {
37
+ status: EnumWebResponse.ERROR,
38
+ msg: error.message,
39
+ data: [],
40
+ };
41
+ }
42
+ if (data) {
43
+ updatedConnectivity.push(data);
44
+ }
45
+ }
46
+ return IWebResponse.success(updatedConnectivity).to_compatible();
47
+ }
@@ -45,12 +45,12 @@ export async function server_get_connectivity_by_device_id(deviceId, timestamp)
45
45
  return IWebResponse.success(sortedConnectivity).to_compatible();
46
46
  }
47
47
  // Insert new connectivity records (accepts array for batch operations)
48
- export async function server_insert_connectivity(connectivity, client) {
49
- const supabase = client || (await newServerClient());
48
+ export async function server_insert_connectivity(connectivity) {
49
+ const client = await newServerClient();
50
50
  const connectivityArray = Array.isArray(connectivity)
51
51
  ? connectivity
52
52
  : [connectivity];
53
- const { data, error } = await supabase
53
+ const { data, error } = await client
54
54
  .from("connectivity")
55
55
  .insert(connectivityArray)
56
56
  .select("*");
@@ -66,17 +66,16 @@ export async function server_insert_connectivity(connectivity, client) {
66
66
  }
67
67
  // Update existing connectivity records (accepts array for batch operations)
68
68
  // Each connectivity record in the array must include an 'id' field
69
- export async function server_update_connectivity(connectivity, client) {
70
- const supabase = client || (await newServerClient());
69
+ export async function server_update_connectivity(connectivity) {
70
+ const client = await newServerClient();
71
71
  const connectivityArray = Array.isArray(connectivity)
72
72
  ? connectivity
73
73
  : [connectivity];
74
74
  const updatedConnectivity = [];
75
75
  for (const record of connectivityArray) {
76
76
  const { id, ...updateData } = record;
77
- // Remove fields that shouldn't be updated
78
77
  delete updateData.inserted_at;
79
- const { data, error } = await supabase
78
+ const { data, error } = await client
80
79
  .from("connectivity")
81
80
  .update(updateData)
82
81
  .eq("id", id)
@@ -1,8 +1,6 @@
1
- import { Database } from "../types/supabase";
2
1
  import { DeviceInsert, IDevice } from "../types/db";
3
2
  import { IWebResponseCompatible } from "../types/requests";
4
- import { SupabaseClient } from "@supabase/supabase-js";
5
- export declare function get_devices_by_herd(herd_id: number, client: SupabaseClient<Database>): Promise<IWebResponseCompatible<IDevice[]>>;
3
+ export declare function get_devices_by_herd(herd_id: number): Promise<IWebResponseCompatible<IDevice[]>>;
6
4
  export declare function serverUpdateDevice(updatedDevice: IDevice): Promise<IWebResponseCompatible<IDevice | null>>;
7
5
  export declare function serverCreateDevice(newDevice: DeviceInsert): Promise<IWebResponseCompatible<IDevice | null>>;
8
6
  export declare function serverDeleteDeviceById(device_id: number): Promise<IWebResponseCompatible<IDevice | null>>;
@@ -1,18 +1,9 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { IWebResponse } from "../types/requests";
4
- export async function get_devices_by_herd(herd_id, client) {
5
- // call get_devices_for_herd with rpc
6
- const { data, error } = await client.rpc("get_devices_for_herd", {
7
- herd_id_caller: herd_id,
8
- });
9
- if (!data) {
10
- return IWebResponse.error("No devices found").to_compatible();
11
- }
12
- else {
13
- let response = IWebResponse.success(data);
14
- return response.to_compatible();
15
- }
4
+ import { get_devices_by_herd_query } from "./devices.queries";
5
+ export async function get_devices_by_herd(herd_id) {
6
+ return get_devices_by_herd_query(await newServerClient(), herd_id);
16
7
  }
17
8
  export async function serverUpdateDevice(updatedDevice) {
18
9
  // delete api keys, latitide, and longitude
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IDevice } from "../types/db";
3
+ import { Database } from "../types/supabase";
4
+ import { IWebResponseCompatible } from "../types/requests";
5
+ export declare function get_devices_by_herd_query(client: SupabaseClient<Database>, herd_id: number): Promise<IWebResponseCompatible<IDevice[]>>;
@@ -0,0 +1,10 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ export async function get_devices_by_herd_query(client, herd_id) {
3
+ const { data } = await client.rpc("get_devices_for_herd", {
4
+ herd_id_caller: herd_id,
5
+ });
6
+ if (!data) {
7
+ return IWebResponse.error("No devices found").to_compatible();
8
+ }
9
+ return IWebResponse.success(data).to_compatible();
10
+ }
@@ -1,6 +1,5 @@
1
- import { IWebResponseCompatible } from "../types/requests";
2
1
  import type { IEmbeddingSearchResult } from "../types/db";
3
- import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IWebResponseCompatible } from "../types/requests";
4
3
  /**
5
4
  * Semantic search over the embeddings table (embeddings_vertex_multimodal_001).
6
5
  * Returns matching embedding row ids with event_id, artifact_id, and confidence.
@@ -8,5 +7,4 @@ import { SupabaseClient } from "@supabase/supabase-js";
8
7
  */
9
8
  export declare function server_search_embeddings_vertex_multimodal_001(query_embedding: number[], match_threshold: number, match_count: number, options?: {
10
9
  herd_id?: number | null;
11
- client?: SupabaseClient;
12
10
  }): Promise<IWebResponseCompatible<IEmbeddingSearchResult[]>>;
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import type { IEmbeddingSearchResult } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import type { Database } from "../types/supabase";
5
+ export declare function searchEmbeddingsVertexMultimodal001WithClient(client: SupabaseClient<Database>, query_embedding: number[], match_threshold: number, match_count: number, herd_id: number | null | undefined): Promise<IWebResponseCompatible<IEmbeddingSearchResult[]>>;
@@ -0,0 +1,14 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ export async function searchEmbeddingsVertexMultimodal001WithClient(client, query_embedding, match_threshold, match_count, herd_id) {
3
+ const rpcName = "search_embeddings_vertex_multimodal_001";
4
+ const { data, error } = await client.rpc(rpcName, {
5
+ query_embedding: JSON.stringify(query_embedding),
6
+ match_threshold,
7
+ match_count,
8
+ ...(herd_id != null && { herd_id_caller: herd_id }),
9
+ });
10
+ if (error) {
11
+ return IWebResponse.error(error.message).to_compatible();
12
+ }
13
+ return IWebResponse.success((data ?? [])).to_compatible();
14
+ }
@@ -7,9 +7,9 @@ import { IWebResponse } from "../types/requests";
7
7
  * Use for general embedding search without coupling to events vs artifacts.
8
8
  */
9
9
  export async function server_search_embeddings_vertex_multimodal_001(query_embedding, match_threshold, match_count, options) {
10
- const supabase = options?.client ?? (await newServerClient());
10
+ const client = await newServerClient();
11
11
  const rpcName = "search_embeddings_vertex_multimodal_001";
12
- const { data, error } = await supabase.rpc(rpcName, {
12
+ const { data, error } = await client.rpc(rpcName, {
13
13
  query_embedding: JSON.stringify(query_embedding),
14
14
  match_threshold,
15
15
  match_count,
@@ -1,18 +1,16 @@
1
1
  import { IWebResponseCompatible } from "../types/requests";
2
2
  import { EnumSessionsVisibility } from "../types/events";
3
3
  import { IEvent, IEventWithMediaUrl, EventInsert, EventUpdate } from "../types/db";
4
- import { SupabaseClient } from "@supabase/supabase-js";
5
- export declare function server_get_event_by_id(id: number, client?: SupabaseClient): Promise<IWebResponseCompatible<IEventWithMediaUrl | null>>;
4
+ export declare function server_get_event_by_id(id: number): Promise<IWebResponseCompatible<IEventWithMediaUrl | null>>;
6
5
  export declare function server_get_total_events_by_herd(herd_id: number, sessions_visibility: EnumSessionsVisibility): Promise<IWebResponseCompatible<number>>;
7
- export declare function server_insert_event(events: EventInsert | EventInsert[], client?: SupabaseClient): Promise<IWebResponseCompatible<IEvent[]>>;
6
+ export declare function server_insert_event(events: EventInsert | EventInsert[]): Promise<IWebResponseCompatible<IEvent[]>>;
8
7
  export declare function server_update_event(events: (EventUpdate & {
9
8
  id: number;
10
9
  }) | (EventUpdate & {
11
10
  id: number;
12
- })[], client?: SupabaseClient): Promise<IWebResponseCompatible<IEvent[]>>;
13
- export declare function server_delete_event(id: number | number[], client?: SupabaseClient): Promise<IWebResponseCompatible<boolean>>;
11
+ })[]): Promise<IWebResponseCompatible<IEvent[]>>;
12
+ export declare function server_delete_event(id: number | number[]): Promise<IWebResponseCompatible<boolean>>;
14
13
  /** Semantic search over events using Vertex multimodal embedding (embedding_vertex_mm_01). */
15
14
  export declare function server_match_events_by_vertex_embedding(query_embedding: number[], match_threshold: number, match_count: number, options?: {
16
15
  herd_id?: number | null;
17
- client?: SupabaseClient;
18
16
  }): Promise<IWebResponseCompatible<IEvent[]>>;
@@ -0,0 +1,13 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IEvent, IEventWithMediaUrl, EventInsert, EventUpdate } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import type { Database } from "../types/supabase";
5
+ export declare function getEventByIdWithClient(client: SupabaseClient<Database>, id: number): Promise<IWebResponseCompatible<IEventWithMediaUrl | null>>;
6
+ export declare function insertEventWithClient(client: SupabaseClient<Database>, events: EventInsert | EventInsert[]): Promise<IWebResponseCompatible<IEvent[]>>;
7
+ export declare function updateEventWithClient(client: SupabaseClient<Database>, events: (EventUpdate & {
8
+ id: number;
9
+ }) | (EventUpdate & {
10
+ id: number;
11
+ })[]): Promise<IWebResponseCompatible<IEvent[]>>;
12
+ export declare function deleteEventWithClient(client: SupabaseClient<Database>, id: number | number[]): Promise<IWebResponseCompatible<boolean>>;
13
+ export declare function matchEventsByVertexEmbeddingWithClient(client: SupabaseClient<Database>, query_embedding: number[], match_threshold: number, match_count: number, herd_id: number | null | undefined): Promise<IWebResponseCompatible<IEvent[]>>;
@@ -0,0 +1,88 @@
1
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
2
+ import { generateSignedUrlWithClient } from "./storage_internal";
3
+ import { isNonEmptyStorageFilePath } from "./storagePath";
4
+ export async function getEventByIdWithClient(client, id) {
5
+ const { data, error } = await client
6
+ .from("events")
7
+ .select("*")
8
+ .eq("id", id)
9
+ .single();
10
+ if (error) {
11
+ return IWebResponse.error(error.message).to_compatible();
12
+ }
13
+ if (!data) {
14
+ return IWebResponse.success(null).to_compatible();
15
+ }
16
+ const event = data;
17
+ let media_url = null;
18
+ if (isNonEmptyStorageFilePath(event.file_path)) {
19
+ media_url = await generateSignedUrlWithClient(client, event.file_path);
20
+ }
21
+ return IWebResponse.success({
22
+ ...event,
23
+ media_url,
24
+ }).to_compatible();
25
+ }
26
+ export async function insertEventWithClient(client, events) {
27
+ const eventsArray = Array.isArray(events) ? events : [events];
28
+ const { data, error } = await client
29
+ .from("events")
30
+ .insert(eventsArray)
31
+ .select("*");
32
+ if (error) {
33
+ console.warn("Error inserting events:", error.message);
34
+ return {
35
+ status: EnumWebResponse.ERROR,
36
+ msg: error.message,
37
+ data: [],
38
+ };
39
+ }
40
+ return IWebResponse.success(data || []).to_compatible();
41
+ }
42
+ export async function updateEventWithClient(client, events) {
43
+ const eventsArray = Array.isArray(events) ? events : [events];
44
+ const updatedEvents = [];
45
+ for (const event of eventsArray) {
46
+ const { id, ...updateData } = event;
47
+ delete updateData.inserted_at;
48
+ const { data, error } = await client
49
+ .from("events")
50
+ .update(updateData)
51
+ .eq("id", id)
52
+ .select("*")
53
+ .single();
54
+ if (error) {
55
+ console.warn("Error updating event:", error.message);
56
+ return {
57
+ status: EnumWebResponse.ERROR,
58
+ msg: error.message,
59
+ data: [],
60
+ };
61
+ }
62
+ if (data) {
63
+ updatedEvents.push(data);
64
+ }
65
+ }
66
+ return IWebResponse.success(updatedEvents).to_compatible();
67
+ }
68
+ export async function deleteEventWithClient(client, id) {
69
+ const ids = Array.isArray(id) ? id : [id];
70
+ const { error } = await client.from("events").delete().in("id", ids);
71
+ if (error) {
72
+ return IWebResponse.error(error.message).to_compatible();
73
+ }
74
+ return IWebResponse.success(true).to_compatible();
75
+ }
76
+ export async function matchEventsByVertexEmbeddingWithClient(client, query_embedding, match_threshold, match_count, herd_id) {
77
+ const rpcName = "match_events_by_vertex_embedding";
78
+ const { data, error } = await client.rpc(rpcName, {
79
+ query_embedding: JSON.stringify(query_embedding),
80
+ match_threshold,
81
+ match_count,
82
+ herd_id_caller: herd_id ?? undefined,
83
+ });
84
+ if (error) {
85
+ return IWebResponse.error(error.message).to_compatible();
86
+ }
87
+ return IWebResponse.success((data ?? [])).to_compatible();
88
+ }
@@ -2,11 +2,11 @@
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
4
  import { EnumSessionsVisibility } from "../types/events";
5
- import { generateSignedUrl } from "./storage";
5
+ import { generateSignedUrlWithClient } from "./storage_internal";
6
6
  import { isNonEmptyStorageFilePath } from "./storagePath";
7
- export async function server_get_event_by_id(id, client) {
8
- const supabase = client || (await newServerClient());
9
- const { data, error } = await supabase
7
+ export async function server_get_event_by_id(id) {
8
+ const client = await newServerClient();
9
+ const { data, error } = await client
10
10
  .from("events")
11
11
  .select("*")
12
12
  .eq("id", id)
@@ -20,7 +20,7 @@ export async function server_get_event_by_id(id, client) {
20
20
  const event = data;
21
21
  let media_url = null;
22
22
  if (isNonEmptyStorageFilePath(event.file_path)) {
23
- media_url = await generateSignedUrl(event.file_path, undefined, client);
23
+ media_url = await generateSignedUrlWithClient(client, event.file_path);
24
24
  }
25
25
  return IWebResponse.success({
26
26
  ...event,
@@ -48,10 +48,10 @@ export async function server_get_total_events_by_herd(herd_id, sessions_visibili
48
48
  }
49
49
  }
50
50
  // Insert new events (accepts array for batch operations)
51
- export async function server_insert_event(events, client) {
52
- const supabase = client || (await newServerClient());
51
+ export async function server_insert_event(events) {
52
+ const client = await newServerClient();
53
53
  const eventsArray = Array.isArray(events) ? events : [events];
54
- const { data, error } = await supabase
54
+ const { data, error } = await client
55
55
  .from("events")
56
56
  .insert(eventsArray)
57
57
  .select("*");
@@ -67,15 +67,14 @@ export async function server_insert_event(events, client) {
67
67
  }
68
68
  // Update existing events (accepts array for batch operations)
69
69
  // Each event in the array must include an 'id' field
70
- export async function server_update_event(events, client) {
71
- const supabase = client || (await newServerClient());
70
+ export async function server_update_event(events) {
71
+ const client = await newServerClient();
72
72
  const eventsArray = Array.isArray(events) ? events : [events];
73
73
  const updatedEvents = [];
74
74
  for (const event of eventsArray) {
75
75
  const { id, ...updateData } = event;
76
- // Remove fields that shouldn't be updated
77
76
  delete updateData.inserted_at;
78
- const { data, error } = await supabase
77
+ const { data, error } = await client
79
78
  .from("events")
80
79
  .update(updateData)
81
80
  .eq("id", id)
@@ -95,10 +94,10 @@ export async function server_update_event(events, client) {
95
94
  }
96
95
  return IWebResponse.success(updatedEvents).to_compatible();
97
96
  }
98
- export async function server_delete_event(id, client) {
99
- const supabase = client || (await newServerClient());
97
+ export async function server_delete_event(id) {
98
+ const client = await newServerClient();
100
99
  const ids = Array.isArray(id) ? id : [id];
101
- const { error } = await supabase.from("events").delete().in("id", ids);
100
+ const { error } = await client.from("events").delete().in("id", ids);
102
101
  if (error) {
103
102
  return IWebResponse.error(error.message).to_compatible();
104
103
  }
@@ -106,9 +105,9 @@ export async function server_delete_event(id, client) {
106
105
  }
107
106
  /** Semantic search over events using Vertex multimodal embedding (embedding_vertex_mm_01). */
108
107
  export async function server_match_events_by_vertex_embedding(query_embedding, match_threshold, match_count, options) {
109
- const supabase = options?.client ?? (await newServerClient());
108
+ const client = await newServerClient();
110
109
  const rpcName = "match_events_by_vertex_embedding";
111
- const { data, error } = await supabase.rpc(rpcName, {
110
+ const { data, error } = await client.rpc(rpcName, {
112
111
  query_embedding: JSON.stringify(query_embedding),
113
112
  match_threshold,
114
113
  match_count,
@@ -1,5 +1,3 @@
1
- import { Database } from "../types/supabase";
2
1
  import { IHerdAllowedDomain } from "../types/db";
3
2
  import { IWebResponseCompatible } from "../types/requests";
4
- import { SupabaseClient } from "@supabase/supabase-js";
5
- export declare function server_get_herd_allowed_domains(herd_id: number, supabaseClient?: SupabaseClient<Database>): Promise<IWebResponseCompatible<IHerdAllowedDomain[]>>;
3
+ export declare function server_get_herd_allowed_domains(herd_id: number): Promise<IWebResponseCompatible<IHerdAllowedDomain[]>>;
@@ -1,8 +1,8 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { IWebResponse } from "../types/requests";
4
- export async function server_get_herd_allowed_domains(herd_id, supabaseClient) {
5
- const supabase = supabaseClient ?? (await newServerClient());
4
+ export async function server_get_herd_allowed_domains(herd_id) {
5
+ const supabase = await newServerClient();
6
6
  const { data, error } = await supabase
7
7
  .from("herd_allowed_domains")
8
8
  .select("*")
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IHerdAllowedDomain } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import { Database } from "../types/supabase";
5
+ export declare function getHerdAllowedDomainsWithClient(supabase: SupabaseClient<Database>, herd_id: number): Promise<IWebResponseCompatible<IHerdAllowedDomain[]>>;
@@ -0,0 +1,12 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ export async function getHerdAllowedDomainsWithClient(supabase, herd_id) {
3
+ const { data, error } = await supabase
4
+ .from("herd_allowed_domains")
5
+ .select("*")
6
+ .eq("herd_id", herd_id)
7
+ .order("domain", { ascending: true });
8
+ if (error) {
9
+ return IWebResponse.error(error.message).to_compatible();
10
+ }
11
+ return IWebResponse.success(data ?? []).to_compatible();
12
+ }
@@ -0,0 +1,3 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IHerdModulesResponseWithStatus } from "../types/herd_module";
3
+ export declare function load_herd_modules_query(client: SupabaseClient): Promise<IHerdModulesResponseWithStatus>;
@@ -0,0 +1,106 @@
1
+ import { createHash } from "crypto";
2
+ import { list_api_keys_batch_query } from "../api_keys/queries";
3
+ import { LABELS } from "../constants/annotator";
4
+ import { EnumWebResponse, } from "../types/requests";
5
+ import { get_devices_by_herd_query } from "./devices.queries";
6
+ import { get_herds_with_location_query } from "./herds.queries";
7
+ import { get_layers_by_herd_ids_query, get_plans_by_herd_ids_query, get_providers_by_herd_ids_query, } from "./herd_scoped.queries";
8
+ import { get_parts_by_herd_ids } from "./parts";
9
+ import { get_session_summaries_query } from "./session_summaries.queries";
10
+ import { get_session_usage_over_time_by_herd_query } from "./sessions.queries";
11
+ import { get_users_with_herd_access_batch_query } from "./users.queries";
12
+ import { server_get_more_zones_and_actions_for_herd } from "./zones";
13
+ function hashHerdModules(modules) {
14
+ const stable = modules.map(({ timestamp_last_refreshed: _ts, ...rest }) => rest);
15
+ return createHash("sha1").update(JSON.stringify(stable)).digest("hex");
16
+ }
17
+ export async function load_herd_modules_query(client) {
18
+ const startTime = Date.now();
19
+ const herdsResult = await get_herds_with_location_query(client);
20
+ if (herdsResult.status !== EnumWebResponse.SUCCESS || !herdsResult.data) {
21
+ return {
22
+ status: EnumWebResponse.ERROR,
23
+ msg: herdsResult.msg ?? "Failed to load herds",
24
+ data: null,
25
+ time_finished: Date.now(),
26
+ time_sent: Date.now(),
27
+ server_processing_time_ms: Date.now() - startTime,
28
+ content_hash: "",
29
+ };
30
+ }
31
+ const herds = herdsResult.data.filter((herd) => herd.id != null);
32
+ if (herds.length === 0) {
33
+ const endTime = Date.now();
34
+ console.log(`[server_load_herd_modules] No accessible herds (${endTime - startTime}ms)`);
35
+ return {
36
+ status: EnumWebResponse.SUCCESS,
37
+ msg: "No herds accessible",
38
+ data: [],
39
+ time_finished: endTime,
40
+ time_sent: endTime,
41
+ server_processing_time_ms: endTime - startTime,
42
+ content_hash: hashHerdModules([]),
43
+ };
44
+ }
45
+ const herdIds = herds.map((herd) => herd.id);
46
+ const perHerd = (query) => Promise.all(herds.map((herd) => query(herd.id).catch(() => ({
47
+ status: EnumWebResponse.ERROR,
48
+ msg: "",
49
+ data: null,
50
+ }))));
51
+ const grouped = (query) => query.then((response) => response.data ?? {}).catch(() => ({}));
52
+ const unwrap = (response) => response.status === EnumWebResponse.SUCCESS ? response.data : null;
53
+ const [plansByHerd, layersByHerd, providersByHerd, usersByHerd, partsByDevice, devicesResults, zonesResults, summariesResults, usageResults,] = await Promise.all([
54
+ grouped(get_plans_by_herd_ids_query(client, herdIds)),
55
+ grouped(get_layers_by_herd_ids_query(client, herdIds)),
56
+ grouped(get_providers_by_herd_ids_query(client, herdIds)),
57
+ get_users_with_herd_access_batch_query(client, herdIds)
58
+ .then(unwrap)
59
+ .catch(() => null),
60
+ grouped(get_parts_by_herd_ids(client, herdIds)),
61
+ perHerd((id) => get_devices_by_herd_query(client, id)),
62
+ perHerd((id) => server_get_more_zones_and_actions_for_herd(id, 0, 10, client)),
63
+ perHerd((id) => get_session_summaries_query(client, { herd_id: id })),
64
+ perHerd((id) => get_session_usage_over_time_by_herd_query(client, id)),
65
+ ]);
66
+ const devicesByHerdIndex = devicesResults.map((response) => unwrap(response) ?? []);
67
+ const allDevices = devicesByHerdIndex.flat();
68
+ let apiKeysByDevice = {};
69
+ if (allDevices.length > 0) {
70
+ try {
71
+ apiKeysByDevice = await list_api_keys_batch_query(client, allDevices.map((device) => device.id ?? 0));
72
+ }
73
+ catch (error) {
74
+ console.error("[server_load_herd_modules] Failed to load API keys:", error);
75
+ }
76
+ }
77
+ for (const device of allDevices) {
78
+ const deviceId = device.id ?? 0;
79
+ device.api_keys_scout = apiKeysByDevice[deviceId] || [];
80
+ device.parts = partsByDevice[deviceId] || [];
81
+ }
82
+ const serialized_herd_modules = herds.map((herd, index) => ({
83
+ herd,
84
+ devices: devicesByHerdIndex[index],
85
+ timestamp_last_refreshed: Date.now(),
86
+ user_roles: usersByHerd ? usersByHerd[herd.id] ?? [] : null,
87
+ labels: LABELS,
88
+ plans: plansByHerd[herd.id] ?? [],
89
+ zones: unwrap(zonesResults[index]) ?? [],
90
+ layers: layersByHerd[herd.id] ?? [],
91
+ providers: providersByHerd[herd.id] ?? [],
92
+ session_summaries: unwrap(summariesResults[index]),
93
+ session_usage: unwrap(usageResults[index]),
94
+ }));
95
+ const endTime = Date.now();
96
+ console.log(`[server_load_herd_modules] Loaded ${herds.length} herds in ${endTime - startTime}ms (batched queries)`);
97
+ return {
98
+ status: EnumWebResponse.SUCCESS,
99
+ msg: "Herd modules loaded successfully",
100
+ data: serialized_herd_modules,
101
+ time_finished: endTime,
102
+ time_sent: endTime,
103
+ server_processing_time_ms: endTime - startTime,
104
+ content_hash: hashHerdModules(serialized_herd_modules),
105
+ };
106
+ }