@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
@@ -1,29 +1,24 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
- import { generateSignedUrlsBatch, } from "./storage";
4
+ import { generateSignedUrlsBatchWithClient } from "./storage_internal";
5
5
  import { isNonEmptyStorageFilePath } from "./storagePath";
6
+ import { get_session_usage_over_time_by_herd_query } from "./sessions.queries";
6
7
  // Get session by ID with coordinates
7
- export async function server_get_session_by_id(sessionId, client) {
8
- const supabase = client || (await newServerClient());
8
+ export async function server_get_session_by_id(sessionId) {
9
+ const supabase = await newServerClient();
9
10
  const { data, error } = await supabase.rpc("get_session_by_id", {
10
11
  session_id_caller: sessionId,
11
12
  });
12
13
  if (error) {
13
14
  console.warn("Error fetching session by id:", error.message);
14
- return {
15
- status: EnumWebResponse.ERROR,
16
- msg: error.message,
17
- data: null,
18
- };
15
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
19
16
  }
20
- // The RPC returns an array, but we want a single session or null
21
- const session = data && data.length > 0 ? data[0] : null;
22
- return IWebResponse.success(session).to_compatible();
17
+ return IWebResponse.success(data && data.length > 0 ? data[0] : null).to_compatible();
23
18
  }
24
19
  /** Existing sessions within tolerance of start/end timestamps. */
25
- export async function server_match_sessions(deviceId, timestampStart, timestampEnd, toleranceSec, client) {
26
- const supabase = client || (await newServerClient());
20
+ export async function server_match_sessions(deviceId, timestampStart, timestampEnd, toleranceSec) {
21
+ const supabase = await newServerClient();
27
22
  const { data, error } = await supabase.rpc("match_sessions", {
28
23
  device_id_caller: deviceId,
29
24
  timestamp_start_caller: timestampStart,
@@ -36,28 +31,12 @@ export async function server_match_sessions(deviceId, timestampStart, timestampE
36
31
  return IWebResponse.success(data || []).to_compatible();
37
32
  }
38
33
  // Get session usage over time by herd
39
- export async function server_get_session_usage_over_time_by_herd(herd_id, client, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
40
- const supabase = client || (await newServerClient());
41
- const { data, error } = await supabase.rpc("get_session_usage_over_time", {
42
- start_date_caller: undefined,
43
- end_date_caller: undefined,
44
- device_id_caller: undefined,
45
- herd_id_caller: herd_id,
46
- min_duration_minutes_caller,
47
- min_distance_meters_caller,
48
- product_numbers_caller,
49
- });
50
- if (error) {
51
- return IWebResponse.error(error.message).to_compatible();
52
- }
53
- if (!data) {
54
- return IWebResponse.error("No session usage data returned").to_compatible();
55
- }
56
- return IWebResponse.success(data).to_compatible();
34
+ export async function server_get_session_usage_over_time_by_herd(herd_id, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
35
+ return get_session_usage_over_time_by_herd_query(await newServerClient(), herd_id, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller);
57
36
  }
58
37
  // Get session usage over time by device
59
- export async function server_get_session_usage_over_time_by_device(device_id, client, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
60
- const supabase = client || (await newServerClient());
38
+ export async function server_get_session_usage_over_time_by_device(device_id, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
39
+ const supabase = await newServerClient();
61
40
  const { data, error } = await supabase.rpc("get_session_usage_over_time", {
62
41
  start_date_caller: undefined,
63
42
  end_date_caller: undefined,
@@ -97,7 +76,7 @@ export async function server_get_events_and_tags_by_session_id(sessionId, limit
97
76
  .filter(isNonEmptyStorageFilePath);
98
77
  let eventsWithSignedUrls = eventData;
99
78
  if (filePaths.length > 0) {
100
- const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
79
+ const signedUrls = await generateSignedUrlsBatchWithClient(supabase, filePaths);
101
80
  const urlMap = new Map();
102
81
  filePaths.forEach((path, index) => {
103
82
  urlMap.set(path, signedUrls[index]);
@@ -112,8 +91,8 @@ export async function server_get_events_and_tags_by_session_id(sessionId, limit
112
91
  return IWebResponse.success(eventsWithSignedUrls).to_compatible();
113
92
  }
114
93
  // Insert new sessions (accepts array for batch operations)
115
- export async function server_insert_session(sessions, client) {
116
- const supabase = client || (await newServerClient());
94
+ export async function server_insert_session(sessions) {
95
+ const supabase = await newServerClient();
117
96
  const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
118
97
  const { data, error } = await supabase
119
98
  .from("sessions")
@@ -121,23 +100,18 @@ export async function server_insert_session(sessions, client) {
121
100
  .select("*");
122
101
  if (error) {
123
102
  console.warn("Error inserting sessions:", error.message);
124
- return {
125
- status: EnumWebResponse.ERROR,
126
- msg: error.message,
127
- data: [],
128
- };
103
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
129
104
  }
130
105
  return IWebResponse.success(data || []).to_compatible();
131
106
  }
132
107
  // Update existing sessions (accepts array for batch operations)
133
108
  // Each session in the array must include an 'id' field
134
- export async function server_update_session(sessions, client) {
135
- const supabase = client || (await newServerClient());
109
+ export async function server_update_session(sessions) {
110
+ const supabase = await newServerClient();
136
111
  const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
137
112
  const updatedSessions = [];
138
113
  for (const session of sessionsArray) {
139
114
  const { id, ...updateData } = session;
140
- // Remove fields that shouldn't be updated
141
115
  delete updateData.inserted_at;
142
116
  const { data, error } = await supabase
143
117
  .from("sessions")
@@ -147,31 +121,22 @@ export async function server_update_session(sessions, client) {
147
121
  .single();
148
122
  if (error) {
149
123
  console.warn("Error updating session:", error.message);
150
- return {
151
- status: EnumWebResponse.ERROR,
152
- msg: error.message,
153
- data: [],
154
- };
124
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
155
125
  }
156
- if (data) {
126
+ if (data)
157
127
  updatedSessions.push(data);
158
- }
159
128
  }
160
129
  return IWebResponse.success(updatedSessions).to_compatible();
161
130
  }
162
131
  /** Artifact IDs for a session (same device, overlapping session interval). Empty if session or timestamps missing. */
163
- export async function server_get_artifact_ids_for_session(sessionId, client) {
164
- const supabase = client || (await newServerClient());
132
+ export async function server_get_artifact_ids_for_session(sessionId) {
133
+ const supabase = await newServerClient();
165
134
  const { data, error } = await supabase.rpc("get_artifact_ids_for_session", {
166
135
  session_id_caller: sessionId,
167
136
  });
168
137
  if (error) {
169
138
  console.warn("Error fetching artifact IDs for session:", error.message);
170
- return {
171
- status: EnumWebResponse.ERROR,
172
- msg: error.message,
173
- data: [],
174
- };
139
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
175
140
  }
176
141
  return IWebResponse.success(Array.isArray(data) ? data : []).to_compatible();
177
142
  }
@@ -0,0 +1,4 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { ISessionUsageOverTime } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ export declare function get_session_usage_over_time_by_herd_query(client: SupabaseClient, herd_id: number, min_duration_minutes_caller?: number, min_distance_meters_caller?: number, product_numbers_caller?: string[]): Promise<IWebResponseCompatible<ISessionUsageOverTime>>;
@@ -0,0 +1,22 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ async function get_session_usage_over_time_query(client, herd_id, device_id, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
3
+ const { data, error } = await client.rpc("get_session_usage_over_time", {
4
+ start_date_caller: undefined,
5
+ end_date_caller: undefined,
6
+ device_id_caller: device_id,
7
+ herd_id_caller: herd_id,
8
+ min_duration_minutes_caller,
9
+ min_distance_meters_caller,
10
+ product_numbers_caller,
11
+ });
12
+ if (error) {
13
+ return IWebResponse.error(error.message).to_compatible();
14
+ }
15
+ if (!data) {
16
+ return IWebResponse.error("No session usage data returned").to_compatible();
17
+ }
18
+ return IWebResponse.success(data).to_compatible();
19
+ }
20
+ export function get_session_usage_over_time_by_herd_query(client, herd_id, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller) {
21
+ return get_session_usage_over_time_query(client, herd_id, undefined, min_duration_minutes_caller, min_distance_meters_caller, product_numbers_caller);
22
+ }
@@ -1,4 +1,2 @@
1
- import { SupabaseClient } from "@supabase/supabase-js";
2
- import { Database } from "../types/supabase";
3
- export declare function generateSignedUrl(filePath: string, expiresIn?: number, supabaseClient?: SupabaseClient<Database>): Promise<string | null>;
4
- export declare function generateSignedUrlsBatch(filePaths: string[], expiresIn?: number, supabaseClient?: SupabaseClient<Database>): Promise<(string | null)[]>;
1
+ export declare function generateSignedUrl(filePath: string, expiresIn?: number): Promise<string | null>;
2
+ export declare function generateSignedUrlsBatch(filePaths: string[], expiresIn?: number): Promise<(string | null)[]>;
@@ -1,58 +1,11 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
- import { SIGNED_URL_EXPIRATION_SECONDS } from "../constants/db";
4
- import { parseStorageFilePath } from "./storagePath";
5
- export async function generateSignedUrl(filePath, expiresIn = SIGNED_URL_EXPIRATION_SECONDS, supabaseClient) {
6
- try {
7
- const supabase = supabaseClient || (await newServerClient());
8
- const parsed = parseStorageFilePath(filePath);
9
- if (!parsed) {
10
- console.error("Invalid file path:", filePath);
11
- return null;
12
- }
13
- const { data, error } = await supabase.storage
14
- .from(parsed.bucket)
15
- .createSignedUrl(parsed.objectPath, expiresIn);
16
- if (error) {
17
- console.error("Error generating signed URL:", error.message);
18
- return null;
19
- }
20
- return data.signedUrl;
21
- }
22
- catch (error) {
23
- console.error("Error in generateSignedUrl:", error);
24
- return null;
25
- }
3
+ import { generateSignedUrlsBatchWithClient, generateSignedUrlWithClient, } from "./storage_internal";
4
+ export async function generateSignedUrl(filePath, expiresIn) {
5
+ const supabase = await newServerClient();
6
+ return generateSignedUrlWithClient(supabase, filePath, expiresIn);
26
7
  }
27
- export async function generateSignedUrlsBatch(filePaths, expiresIn = SIGNED_URL_EXPIRATION_SECONDS, supabaseClient) {
28
- try {
29
- const supabase = supabaseClient || (await newServerClient());
30
- const signedUrlPromises = filePaths.map(async (filePath) => {
31
- try {
32
- const parsed = parseStorageFilePath(filePath);
33
- if (!parsed) {
34
- console.error("Invalid file path:", filePath);
35
- return null;
36
- }
37
- const { data, error } = await supabase.storage
38
- .from(parsed.bucket)
39
- .createSignedUrl(parsed.objectPath, expiresIn);
40
- if (error) {
41
- console.warn(`Error generating signed URL for ${filePath}:`, error.message);
42
- return null;
43
- }
44
- return data.signedUrl;
45
- }
46
- catch (error) {
47
- console.warn(`Exception generating signed URL for ${filePath}:`, error);
48
- return null;
49
- }
50
- });
51
- const results = await Promise.all(signedUrlPromises);
52
- return results;
53
- }
54
- catch (error) {
55
- console.error("Error in generateSignedUrlsBatch:", error);
56
- return new Array(filePaths.length).fill(null);
57
- }
8
+ export async function generateSignedUrlsBatch(filePaths, expiresIn) {
9
+ const supabase = await newServerClient();
10
+ return generateSignedUrlsBatchWithClient(supabase, filePaths, expiresIn);
58
11
  }
@@ -0,0 +1,4 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { Database } from "../types/supabase";
3
+ export declare function generateSignedUrlsBatchWithClient(supabase: SupabaseClient<Database>, filePaths: string[], expiresIn?: number): Promise<(string | null)[]>;
4
+ export declare function generateSignedUrlWithClient(supabase: SupabaseClient<Database>, filePath: string, expiresIn?: number): Promise<string | null>;
@@ -0,0 +1,29 @@
1
+ import { SIGNED_URL_EXPIRATION_SECONDS } from "../constants/db";
2
+ import { parseStorageFilePath } from "./storagePath";
3
+ export async function generateSignedUrlsBatchWithClient(supabase, filePaths, expiresIn = SIGNED_URL_EXPIRATION_SECONDS) {
4
+ return Promise.all(filePaths.map(async (filePath) => {
5
+ try {
6
+ const parsed = parseStorageFilePath(filePath);
7
+ if (!parsed) {
8
+ console.error("Invalid file path:", filePath);
9
+ return null;
10
+ }
11
+ const { data, error } = await supabase.storage
12
+ .from(parsed.bucket)
13
+ .createSignedUrl(parsed.objectPath, expiresIn);
14
+ if (error) {
15
+ console.warn(`Error generating signed URL for ${filePath}:`, error.message);
16
+ return null;
17
+ }
18
+ return data.signedUrl;
19
+ }
20
+ catch (error) {
21
+ console.warn(`Exception generating signed URL for ${filePath}:`, error);
22
+ return null;
23
+ }
24
+ }));
25
+ }
26
+ export async function generateSignedUrlWithClient(supabase, filePath, expiresIn = SIGNED_URL_EXPIRATION_SECONDS) {
27
+ const [signedUrl] = await generateSignedUrlsBatchWithClient(supabase, [filePath], expiresIn);
28
+ return signedUrl ?? null;
29
+ }
@@ -2,7 +2,7 @@
2
2
  // add tag to db
3
3
  import { newServerClient } from "../supabase/server";
4
4
  import { EnumWebResponse, IWebResponse, } from "../types/requests";
5
- import { generateSignedUrlsBatch, generateSignedUrl, } from "./storage";
5
+ import { generateSignedUrlsBatchWithClient, generateSignedUrlWithClient, } from "./storage_internal";
6
6
  import { isNonEmptyStorageFilePath } from "./storagePath";
7
7
  // Helper functions to extract coordinates from location field
8
8
  function extractLatitude(location) {
@@ -177,7 +177,7 @@ export async function server_get_more_events_with_tags_by_herd(herd_id, offset,
177
177
  .filter(isNonEmptyStorageFilePath);
178
178
  let eventsWithSignedUrls = filtered_data;
179
179
  if (filePaths.length > 0) {
180
- const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
180
+ const signedUrls = await generateSignedUrlsBatchWithClient(supabase, filePaths, undefined);
181
181
  const urlMap = new Map();
182
182
  filePaths.forEach((path, index) => {
183
183
  urlMap.set(path, signedUrls[index]);
@@ -213,7 +213,7 @@ export async function server_get_events_and_tags_for_device(device_id, limit = 3
213
213
  .filter(isNonEmptyStorageFilePath);
214
214
  let eventsWithSignedUrls = eventData;
215
215
  if (filePaths.length > 0) {
216
- const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
216
+ const signedUrls = await generateSignedUrlsBatchWithClient(supabase, filePaths, undefined);
217
217
  const urlMap = new Map();
218
218
  filePaths.forEach((path, index) => {
219
219
  urlMap.set(path, signedUrls[index]);
@@ -307,7 +307,7 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
307
307
  }
308
308
  // Generate all signed URLs at once
309
309
  const signedUrls = allFilePaths.length > 0
310
- ? await generateSignedUrlsBatch(allFilePaths, undefined, supabase)
310
+ ? await generateSignedUrlsBatchWithClient(supabase, allFilePaths, undefined)
311
311
  : [];
312
312
  const urlMap = new Map();
313
313
  allFilePaths.forEach((path, index) => {
@@ -461,7 +461,7 @@ export async function get_event_and_tags_by_event_id(event_id) {
461
461
  // Generate signed URL for event
462
462
  let eventWithSignedUrl = transformedData;
463
463
  if (isNonEmptyStorageFilePath(transformedData.file_path)) {
464
- const signedUrl = await generateSignedUrl(transformedData.file_path, undefined, supabase);
464
+ const signedUrl = await generateSignedUrlWithClient(supabase, transformedData.file_path, undefined);
465
465
  eventWithSignedUrl = {
466
466
  ...transformedData,
467
467
  media_url: signedUrl,
@@ -1,13 +1,12 @@
1
1
  import { IUser, IUserAndRole, IUserProfileRow, IUserRolePerHerd } from "../types/db";
2
- import { IWebResponseCompatible } from "../types/requests";
3
- import { SupabaseClient } from "@supabase/supabase-js";
4
2
  import { Database } from "../types/supabase";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ export type UserProfileUpdate = Database["public"]["Tables"]["users"]["Update"];
5
5
  export declare function server_get_user_roles(herd_id: number): Promise<IWebResponseCompatible<IUserRolePerHerd[]>>;
6
6
  export declare function server_get_user(): Promise<IWebResponseCompatible<IUser | null>>;
7
- export declare function server_get_users_with_herd_access(herd_id: number, supabaseClient?: SupabaseClient): Promise<IWebResponseCompatible<IUserAndRole[]>>;
8
- export declare function server_get_users_with_herd_access_batch(herd_ids: number[], client: SupabaseClient): Promise<IWebResponseCompatible<Record<number, IUserAndRole[]>>>;
7
+ export declare function server_get_users_with_herd_access(herd_id: number): Promise<IWebResponseCompatible<IUserAndRole[]>>;
8
+ export declare function server_get_users_with_herd_access_batch(herd_ids: number[]): Promise<IWebResponseCompatible<Record<number, IUserAndRole[]>>>;
9
9
  export declare function server_upsert_user_herd_role(herd_id: number, username: string, herd_role_id: number): Promise<IWebResponseCompatible<IUserAndRole | null>>;
10
- export type UserProfileUpdate = Database["public"]["Tables"]["users"]["Update"];
11
- export declare function update_user_profile(client: SupabaseClient<Database>, user_id: string, patch: UserProfileUpdate): Promise<IWebResponseCompatible<IUserProfileRow | null>>;
12
- export declare function leave_herd_for_current_user(herd_id: number, supabaseClient?: SupabaseClient<Database>): Promise<IWebResponseCompatible<IUserRolePerHerd | null>>;
13
- export declare function remove_user_from_herd_for_admin(herd_id: number, user_id: string, supabaseClient?: SupabaseClient<Database>): Promise<IWebResponseCompatible<IUserRolePerHerd | null>>;
10
+ export declare function update_user_profile(user_id: string, patch: UserProfileUpdate): Promise<IWebResponseCompatible<IUserProfileRow | null>>;
11
+ export declare function leave_herd_for_current_user(herd_id: number): Promise<IWebResponseCompatible<IUserRolePerHerd | null>>;
12
+ export declare function remove_user_from_herd_for_admin(herd_id: number, user_id: string): Promise<IWebResponseCompatible<IUserRolePerHerd | null>>;
@@ -1,6 +1,7 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { IWebResponse, EnumWebResponse, } from "../types/requests";
4
+ import { get_users_with_herd_access_batch_query, } from "./users.queries";
4
5
  export async function server_get_user_roles(herd_id) {
5
6
  const supabase = await newServerClient();
6
7
  // fetch user role for herd
@@ -25,8 +26,8 @@ export async function server_get_user() {
25
26
  const new_user = data.user;
26
27
  return IWebResponse.success(new_user).to_compatible();
27
28
  }
28
- export async function server_get_users_with_herd_access(herd_id, supabaseClient) {
29
- const supabase = supabaseClient || (await newServerClient());
29
+ export async function server_get_users_with_herd_access(herd_id) {
30
+ const supabase = await newServerClient();
30
31
  const { data, error } = await supabase
31
32
  .from("users_roles_per_herd")
32
33
  .select(`
@@ -36,11 +37,7 @@ export async function server_get_users_with_herd_access(herd_id, supabaseClient)
36
37
  `)
37
38
  .eq("herd_id", herd_id);
38
39
  if (error) {
39
- return {
40
- status: EnumWebResponse.ERROR,
41
- msg: error.message,
42
- data: null,
43
- };
40
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
44
41
  }
45
42
  const transformedData = (data ?? []).map((item) => ({
46
43
  user: item.users,
@@ -50,34 +47,8 @@ export async function server_get_users_with_herd_access(herd_id, supabaseClient)
50
47
  return IWebResponse.success(transformedData).to_compatible();
51
48
  }
52
49
  // Fetches users-with-role for many herds in one query, grouped by herd_id.
53
- export async function server_get_users_with_herd_access_batch(herd_ids, client) {
54
- var _a;
55
- if (herd_ids.length === 0) {
56
- return IWebResponse.success({}).to_compatible();
57
- }
58
- const { data, error } = await client
59
- .from("users_roles_per_herd")
60
- .select(`
61
- herd_id,
62
- herd_role_id,
63
- herd_roles (*),
64
- users!users_roles_per_herd_user_id_fkey (*)
65
- `)
66
- .in("herd_id", herd_ids)
67
- .order("herd_id", { ascending: true })
68
- .order("user_id", { ascending: true });
69
- if (error) {
70
- return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
71
- }
72
- const grouped = {};
73
- for (const item of (data ?? [])) {
74
- (grouped[_a = item.herd_id] ?? (grouped[_a] = [])).push({
75
- user: item.users,
76
- herd_role_id: item.herd_role_id,
77
- herd_role: item.herd_roles,
78
- });
79
- }
80
- return IWebResponse.success(grouped).to_compatible();
50
+ export async function server_get_users_with_herd_access_batch(herd_ids) {
51
+ return get_users_with_herd_access_batch_query(await newServerClient(), herd_ids);
81
52
  }
82
53
  export async function server_upsert_user_herd_role(herd_id, username, herd_role_id) {
83
54
  const supabase = await newServerClient();
@@ -115,8 +86,9 @@ export async function server_upsert_user_herd_role(herd_id, username, herd_role_
115
86
  herd_role: herdRole,
116
87
  }).to_compatible();
117
88
  }
118
- export async function update_user_profile(client, user_id, patch) {
119
- const { data, error } = await client
89
+ export async function update_user_profile(user_id, patch) {
90
+ const supabase = await newServerClient();
91
+ const { data, error } = await supabase
120
92
  .from("users")
121
93
  .update(patch)
122
94
  .eq("id", user_id)
@@ -130,8 +102,8 @@ export async function update_user_profile(client, user_id, patch) {
130
102
  }
131
103
  return IWebResponse.success(data).to_compatible();
132
104
  }
133
- export async function leave_herd_for_current_user(herd_id, supabaseClient) {
134
- const supabase = supabaseClient ?? (await newServerClient());
105
+ export async function leave_herd_for_current_user(herd_id) {
106
+ const supabase = await newServerClient();
135
107
  const { data, error } = await supabase.rpc("leave_herd_for_current_user", {
136
108
  p_herd_id: herd_id,
137
109
  });
@@ -140,8 +112,8 @@ export async function leave_herd_for_current_user(herd_id, supabaseClient) {
140
112
  }
141
113
  return IWebResponse.success(data).to_compatible();
142
114
  }
143
- export async function remove_user_from_herd_for_admin(herd_id, user_id, supabaseClient) {
144
- const supabase = supabaseClient ?? (await newServerClient());
115
+ export async function remove_user_from_herd_for_admin(herd_id, user_id) {
116
+ const supabase = await newServerClient();
145
117
  const { data, error } = await supabase.rpc("remove_user_from_herd_for_admin", {
146
118
  p_herd_id: herd_id,
147
119
  p_user_id: user_id,
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IUserAndRole } from "../types/db";
3
+ import { Database } from "../types/supabase";
4
+ import { IWebResponseCompatible } from "../types/requests";
5
+ export declare function get_users_with_herd_access_batch_query(client: SupabaseClient<Database>, herd_ids: number[]): Promise<IWebResponseCompatible<Record<number, IUserAndRole[]>>>;
@@ -0,0 +1,30 @@
1
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
2
+ export async function get_users_with_herd_access_batch_query(client, herd_ids) {
3
+ var _a;
4
+ if (herd_ids.length === 0) {
5
+ return IWebResponse.success({}).to_compatible();
6
+ }
7
+ const { data, error } = await client
8
+ .from("users_roles_per_herd")
9
+ .select(`
10
+ herd_id,
11
+ herd_role_id,
12
+ herd_roles (*),
13
+ users!users_roles_per_herd_user_id_fkey (*)
14
+ `)
15
+ .in("herd_id", herd_ids)
16
+ .order("herd_id", { ascending: true })
17
+ .order("user_id", { ascending: true });
18
+ if (error) {
19
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
20
+ }
21
+ const grouped = {};
22
+ for (const item of data ?? []) {
23
+ (grouped[_a = item.herd_id] ?? (grouped[_a] = [])).push({
24
+ user: item.users,
25
+ herd_role_id: item.herd_role_id,
26
+ herd_role: item.herd_roles,
27
+ });
28
+ }
29
+ return IWebResponse.success(grouped).to_compatible();
30
+ }
@@ -0,0 +1,6 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IVersionsSoftwareWithBuildUrl } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import { Database } from "../types/supabase";
5
+ export declare function get_versions_software(client: SupabaseClient<Database>): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
6
+ export declare function get_versions_software_by_system(client: SupabaseClient<Database>, system: string): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
@@ -0,0 +1,53 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ import { generateSignedUrlsBatchWithClient } from "./storage_internal";
3
+ async function attachBuildArtifactUrls(client, data) {
4
+ const uniquePaths = Array.from(new Set(data
5
+ .map((version) => version.path_build_artifact)
6
+ .filter((path) => !!path)));
7
+ if (uniquePaths.length === 0) {
8
+ return data.map((version) => ({
9
+ ...version,
10
+ build_artifact_url: null,
11
+ }));
12
+ }
13
+ const signedUrls = await generateSignedUrlsBatchWithClient(client, uniquePaths);
14
+ const urlMap = new Map();
15
+ uniquePaths.forEach((path, index) => {
16
+ urlMap.set(path, signedUrls[index]);
17
+ });
18
+ return data.map((version) => ({
19
+ ...version,
20
+ build_artifact_url: version.path_build_artifact
21
+ ? urlMap.get(version.path_build_artifact) ?? null
22
+ : null,
23
+ }));
24
+ }
25
+ export async function get_versions_software(client) {
26
+ const { data, error } = await client
27
+ .from("versions_software")
28
+ .select("*")
29
+ .order("created_at", { ascending: false });
30
+ if (error) {
31
+ return IWebResponse.error(error.message).to_compatible();
32
+ }
33
+ if (!data) {
34
+ return IWebResponse.error("No software versions found").to_compatible();
35
+ }
36
+ const withUrls = await attachBuildArtifactUrls(client, data);
37
+ return IWebResponse.success(withUrls).to_compatible();
38
+ }
39
+ export async function get_versions_software_by_system(client, system) {
40
+ const { data, error } = await client
41
+ .from("versions_software")
42
+ .select("*")
43
+ .eq("system", system)
44
+ .order("created_at", { ascending: false });
45
+ if (error) {
46
+ return IWebResponse.error(error.message).to_compatible();
47
+ }
48
+ if (!data) {
49
+ return IWebResponse.error(`No software versions found for system: ${system}`).to_compatible();
50
+ }
51
+ const withUrls = await attachBuildArtifactUrls(client, data);
52
+ return IWebResponse.success(withUrls).to_compatible();
53
+ }
@@ -1,5 +1,4 @@
1
1
  import { IVersionsSoftwareWithBuildUrl } from "../types/db";
2
2
  import { IWebResponseCompatible } from "../types/requests";
3
- import { SupabaseClient } from "@supabase/supabase-js";
4
- export declare function server_get_versions_software(client?: SupabaseClient): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
5
- export declare function server_get_versions_software_by_system(system: string, client?: SupabaseClient): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
3
+ export declare function server_get_versions_software(): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
4
+ export declare function server_get_versions_software_by_system(system: string): Promise<IWebResponseCompatible<IVersionsSoftwareWithBuildUrl[]>>;
@@ -1,30 +1,32 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { IWebResponse } from "../types/requests";
4
- import { generateSignedUrlsBatch } from "./storage";
5
- /** Resolves path_build_artifact to signed URLs. Paths must be full storage paths (e.g. software_build_artifacts/...). */
6
- async function attachBuildArtifactUrls(data, client) {
4
+ import { generateSignedUrlsBatchWithClient } from "./storage_internal";
5
+ async function attachBuildArtifactUrls(client, data) {
7
6
  const uniquePaths = Array.from(new Set(data
8
- .map((v) => v.path_build_artifact)
7
+ .map((version) => version.path_build_artifact)
9
8
  .filter((path) => !!path)));
10
9
  if (uniquePaths.length === 0) {
11
- return data.map((v) => ({ ...v, build_artifact_url: null }));
10
+ return data.map((version) => ({
11
+ ...version,
12
+ build_artifact_url: null,
13
+ }));
12
14
  }
13
- const signedUrls = await generateSignedUrlsBatch(uniquePaths, undefined, client);
15
+ const signedUrls = await generateSignedUrlsBatchWithClient(client, uniquePaths);
14
16
  const urlMap = new Map();
15
17
  uniquePaths.forEach((path, index) => {
16
18
  urlMap.set(path, signedUrls[index]);
17
19
  });
18
- return data.map((v) => ({
19
- ...v,
20
- build_artifact_url: v.path_build_artifact
21
- ? urlMap.get(v.path_build_artifact) ?? null
20
+ return data.map((version) => ({
21
+ ...version,
22
+ build_artifact_url: version.path_build_artifact
23
+ ? urlMap.get(version.path_build_artifact) ?? null
22
24
  : null,
23
25
  }));
24
26
  }
25
- export async function server_get_versions_software(client) {
26
- const supabase = client || (await newServerClient());
27
- const { data, error } = await supabase
27
+ export async function server_get_versions_software() {
28
+ const client = await newServerClient();
29
+ const { data, error } = await client
28
30
  .from("versions_software")
29
31
  .select("*")
30
32
  .order("created_at", { ascending: false });
@@ -34,12 +36,12 @@ export async function server_get_versions_software(client) {
34
36
  if (!data) {
35
37
  return IWebResponse.error("No software versions found").to_compatible();
36
38
  }
37
- const withUrls = await attachBuildArtifactUrls(data, client);
39
+ const withUrls = await attachBuildArtifactUrls(client, data);
38
40
  return IWebResponse.success(withUrls).to_compatible();
39
41
  }
40
- export async function server_get_versions_software_by_system(system, client) {
41
- const supabase = client || (await newServerClient());
42
- const { data, error } = await supabase
42
+ export async function server_get_versions_software_by_system(system) {
43
+ const client = await newServerClient();
44
+ const { data, error } = await client
43
45
  .from("versions_software")
44
46
  .select("*")
45
47
  .eq("system", system)
@@ -50,6 +52,6 @@ export async function server_get_versions_software_by_system(system, client) {
50
52
  if (!data) {
51
53
  return IWebResponse.error(`No software versions found for system: ${system}`).to_compatible();
52
54
  }
53
- const withUrls = await attachBuildArtifactUrls(data, client);
55
+ const withUrls = await attachBuildArtifactUrls(client, data);
54
56
  return IWebResponse.success(withUrls).to_compatible();
55
57
  }