@adventurelabs/scout-core 1.4.96 → 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 (89) 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/supabase/server.d.ts +4 -1
  87. package/dist/supabase/server.js +6 -5
  88. package/dist/types/supabase.d.ts +33 -0
  89. package/package.json +1 -1
@@ -1,7 +1,6 @@
1
1
  import { IApiKeyScout } from "../types/db";
2
- import { SupabaseClient } from "@supabase/supabase-js";
3
2
  export declare function test_api_key_loading(device_id: number): Promise<boolean>;
4
3
  export declare function server_list_api_keys(device_id: number): Promise<IApiKeyScout[]>;
5
- export declare function server_list_api_keys_batch(device_ids: number[], client?: SupabaseClient): Promise<{
4
+ export declare function server_list_api_keys_batch(device_ids: number[]): Promise<{
6
5
  [device_id: number]: IApiKeyScout[];
7
6
  }>;
@@ -1,5 +1,6 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
+ import { list_api_keys_batch_query, list_api_keys_query } from "./queries";
3
4
  // Test function to verify individual API key loading works
4
5
  export async function test_api_key_loading(device_id) {
5
6
  try {
@@ -14,88 +15,8 @@ export async function test_api_key_loading(device_id) {
14
15
  }
15
16
  }
16
17
  export async function server_list_api_keys(device_id) {
17
- const supabase = await newServerClient();
18
- const { data, error } = await supabase.rpc("load_api_keys", {
19
- id_of_device: device_id,
20
- });
21
- if (error) {
22
- console.error("Error listing API keys:", error.message);
23
- }
24
- if (!data)
25
- return [];
26
- const data_to_return = [];
27
- for (let i = 0; i < data.length; i++) {
28
- // Parse the JSON string from the text array
29
- const converted_data = JSON.parse(data[i]);
30
- data_to_return.push(converted_data);
31
- }
32
- return data_to_return;
18
+ return list_api_keys_query(await newServerClient(), device_id);
33
19
  }
34
- export async function server_list_api_keys_batch(device_ids, client) {
35
- const supabase = client || (await newServerClient());
36
- // Check if the batch function exists by trying a simple call
37
- try {
38
- const { data, error } = await supabase.rpc("load_api_keys_batch", {
39
- device_ids: device_ids,
40
- });
41
- if (error) {
42
- // Check if it's a "function does not exist" error
43
- if (error.message.includes("function") &&
44
- error.message.includes("does not exist")) {
45
- console.log(`[API Keys Batch] Batch function not deployed, using individual calls...`);
46
- }
47
- else {
48
- console.error(`[API Keys Batch] Database error:`, error.message);
49
- }
50
- console.log(`[API Keys Batch] Falling back to individual calls...`);
51
- // Fallback to individual API key loading
52
- const result = {};
53
- const promises = device_ids.map(async (device_id) => {
54
- try {
55
- const api_keys = await server_list_api_keys(device_id);
56
- result[device_id] = api_keys;
57
- }
58
- catch (err) {
59
- console.warn(`[API Keys Batch] Failed for device ${device_id}:`, err);
60
- result[device_id] = [];
61
- }
62
- });
63
- await Promise.all(promises);
64
- return result;
65
- }
66
- if (!data) {
67
- return {};
68
- }
69
- const result = {};
70
- // Group API keys by device_id
71
- data.forEach((item) => {
72
- const device_id = item.device_id;
73
- if (!result[device_id]) {
74
- result[device_id] = [];
75
- }
76
- result[device_id].push({
77
- id: item.api_key_id, // Now a string, no need for toString()
78
- key: item.api_key_key,
79
- });
80
- });
81
- return result;
82
- }
83
- catch (err) {
84
- console.error(`[API Keys Batch] Unexpected error:`, err);
85
- console.log(`[API Keys Batch] Falling back to individual calls...`);
86
- // Fallback to individual API key loading
87
- const result = {};
88
- const promises = device_ids.map(async (device_id) => {
89
- try {
90
- const api_keys = await server_list_api_keys(device_id);
91
- result[device_id] = api_keys;
92
- }
93
- catch (err) {
94
- console.warn(`[API Keys Batch] Failed for device ${device_id}:`, err);
95
- result[device_id] = [];
96
- }
97
- });
98
- await Promise.all(promises);
99
- return result;
100
- }
20
+ export async function server_list_api_keys_batch(device_ids) {
21
+ return list_api_keys_batch_query(await newServerClient(), device_ids);
101
22
  }
@@ -0,0 +1,4 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IApiKeyScout } from "../types/db";
3
+ export declare function list_api_keys_query(client: SupabaseClient, device_id: number): Promise<IApiKeyScout[]>;
4
+ export declare function list_api_keys_batch_query(client: SupabaseClient, device_ids: number[]): Promise<Record<number, IApiKeyScout[]>>;
@@ -0,0 +1,52 @@
1
+ export async function list_api_keys_query(client, device_id) {
2
+ const { data, error } = await client.rpc("load_api_keys", {
3
+ id_of_device: device_id,
4
+ });
5
+ if (error)
6
+ console.error("Error listing API keys:", error.message);
7
+ return (data ?? []).map((value) => JSON.parse(value));
8
+ }
9
+ export async function list_api_keys_batch_query(client, device_ids) {
10
+ var _a;
11
+ try {
12
+ const { data, error } = await client.rpc("load_api_keys_batch", {
13
+ device_ids,
14
+ });
15
+ if (error) {
16
+ if (error.message.includes("function") &&
17
+ error.message.includes("does not exist")) {
18
+ console.log("[API Keys Batch] Batch function not deployed, using individual calls...");
19
+ }
20
+ else {
21
+ console.error("[API Keys Batch] Database error:", error.message);
22
+ }
23
+ return list_api_keys_individually(client, device_ids);
24
+ }
25
+ const result = {};
26
+ for (const item of data ?? []) {
27
+ (result[_a = item.device_id] ?? (result[_a] = [])).push({
28
+ id: item.api_key_id,
29
+ key: item.api_key_key,
30
+ });
31
+ }
32
+ return result;
33
+ }
34
+ catch (error) {
35
+ console.error("[API Keys Batch] Unexpected error:", error);
36
+ return list_api_keys_individually(client, device_ids);
37
+ }
38
+ }
39
+ async function list_api_keys_individually(client, device_ids) {
40
+ console.log("[API Keys Batch] Falling back to individual calls...");
41
+ const result = {};
42
+ await Promise.all(device_ids.map(async (device_id) => {
43
+ try {
44
+ result[device_id] = await list_api_keys_query(client, device_id);
45
+ }
46
+ catch (error) {
47
+ console.warn(`[API Keys Batch] Failed for device ${device_id}:`, error);
48
+ result[device_id] = [];
49
+ }
50
+ }));
51
+ return result;
52
+ }
@@ -1,30 +1,25 @@
1
1
  import { IArtifact, IArtifactWithMediaUrl, ArtifactInsert, ArtifactUpdate } from "../types/db";
2
2
  import { IWebResponseCompatible } from "../types/requests";
3
- import { SupabaseClient } from "@supabase/supabase-js";
4
- export declare function server_get_artifact_by_id(id: number, client?: SupabaseClient): Promise<IWebResponseCompatible<IArtifactWithMediaUrl | null>>;
5
- export declare function server_get_artifacts_by_herd(herd_id: number, limit?: number, offset?: number, options?: {
3
+ interface ArtifactTimeRangeOptions {
6
4
  start_timestamp?: string;
7
5
  end_timestamp?: string;
8
- client?: SupabaseClient;
9
- }): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
10
- export declare function server_get_artifacts_by_device_id(device_id: number, limit?: number, offset?: number, client?: SupabaseClient): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
6
+ }
7
+ export declare function server_get_artifact_by_id(id: number): Promise<IWebResponseCompatible<IArtifactWithMediaUrl | null>>;
8
+ export declare function server_get_artifacts_by_herd(herd_id: number, limit?: number, offset?: number, options?: ArtifactTimeRangeOptions): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
9
+ export declare function server_get_artifacts_by_device_id(device_id: number, limit?: number, offset?: number): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
11
10
  export declare function server_get_total_artifacts_by_herd(herd_id: number): Promise<IWebResponseCompatible<number>>;
12
- export declare function server_get_artifacts_by_device_ids_batch(device_ids: number[], limit_per_device?: number, options?: {
13
- start_timestamp?: string;
14
- end_timestamp?: string;
15
- client?: SupabaseClient;
16
- }): Promise<{
11
+ export declare function server_get_artifacts_by_device_ids_batch(device_ids: number[], limit_per_device?: number, options?: ArtifactTimeRangeOptions): Promise<{
17
12
  [device_id: number]: IArtifactWithMediaUrl[];
18
13
  }>;
19
- export declare function server_insert_artifact(artifact: ArtifactInsert | ArtifactInsert[], client?: SupabaseClient): Promise<IWebResponseCompatible<IArtifact[]>>;
14
+ export declare function server_insert_artifact(artifact: ArtifactInsert | ArtifactInsert[]): Promise<IWebResponseCompatible<IArtifact[]>>;
20
15
  export declare function server_update_artifact(artifact: (ArtifactUpdate & {
21
16
  id: number;
22
17
  }) | (ArtifactUpdate & {
23
18
  id: number;
24
- })[], client?: SupabaseClient): Promise<IWebResponseCompatible<IArtifact[]>>;
25
- export declare function server_delete_artifact(id: number | number[], client?: SupabaseClient): Promise<IWebResponseCompatible<boolean>>;
19
+ })[]): Promise<IWebResponseCompatible<IArtifact[]>>;
20
+ export declare function server_delete_artifact(id: number | number[]): Promise<IWebResponseCompatible<boolean>>;
26
21
  /** Semantic search over artifacts using Vertex multimodal embedding (embedding_vertex_mm_01). */
27
22
  export declare function server_match_artifacts_by_vertex_embedding(query_embedding: number[], match_threshold: number, match_count: number, options?: {
28
23
  herd_id?: number | null;
29
- client?: SupabaseClient;
30
24
  }): Promise<IWebResponseCompatible<IArtifact[]>>;
25
+ export {};
@@ -0,0 +1,22 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IArtifact, IArtifactWithMediaUrl, ArtifactInsert, ArtifactUpdate } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import type { Database } from "../types/supabase";
5
+ export interface ArtifactTimeRangeOptions {
6
+ start_timestamp?: string;
7
+ end_timestamp?: string;
8
+ }
9
+ export declare function getArtifactByIdWithClient(client: SupabaseClient<Database>, id: number): Promise<IWebResponseCompatible<IArtifactWithMediaUrl | null>>;
10
+ export declare function getArtifactsByHerdWithClient(client: SupabaseClient<Database>, herd_id: number, limit: number, offset: number, options: ArtifactTimeRangeOptions | undefined): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
11
+ export declare function getArtifactsByDeviceIdWithClient(client: SupabaseClient<Database>, device_id: number, limit: number, offset: number): Promise<IWebResponseCompatible<IArtifactWithMediaUrl[]>>;
12
+ export declare function getArtifactsByDeviceIdsBatchWithClient(client: SupabaseClient<Database>, device_ids: number[], limit_per_device: number, options: ArtifactTimeRangeOptions | undefined): Promise<{
13
+ [device_id: number]: IArtifactWithMediaUrl[];
14
+ }>;
15
+ export declare function insertArtifactWithClient(client: SupabaseClient<Database>, artifact: ArtifactInsert | ArtifactInsert[]): Promise<IWebResponseCompatible<IArtifact[]>>;
16
+ export declare function updateArtifactWithClient(client: SupabaseClient<Database>, artifact: (ArtifactUpdate & {
17
+ id: number;
18
+ }) | (ArtifactUpdate & {
19
+ id: number;
20
+ })[]): Promise<IWebResponseCompatible<IArtifact[]>>;
21
+ export declare function deleteArtifactWithClient(client: SupabaseClient<Database>, id: number | number[]): Promise<IWebResponseCompatible<boolean>>;
22
+ export declare function matchArtifactsByVertexEmbeddingWithClient(client: SupabaseClient<Database>, query_embedding: number[], match_threshold: number, match_count: number, herd_id: number | null | undefined): Promise<IWebResponseCompatible<IArtifact[]>>;
@@ -0,0 +1,151 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ import { generateSignedUrlsBatchWithClient, generateSignedUrlWithClient, } from "./storage_internal";
3
+ import { isNonEmptyStorageFilePath } from "./storagePath";
4
+ async function addArtifactMediaUrls(data, client) {
5
+ const uniqueFilePaths = Array.from(new Set(data
6
+ .map((artifact) => artifact.file_path)
7
+ .filter(isNonEmptyStorageFilePath)));
8
+ if (uniqueFilePaths.length === 0) {
9
+ return data;
10
+ }
11
+ const signedUrls = await generateSignedUrlsBatchWithClient(client, uniqueFilePaths);
12
+ const urlMap = new Map();
13
+ uniqueFilePaths.forEach((path, index) => {
14
+ urlMap.set(path, signedUrls[index]);
15
+ });
16
+ return data.map((artifact) => ({
17
+ ...artifact,
18
+ media_url: isNonEmptyStorageFilePath(artifact.file_path)
19
+ ? urlMap.get(artifact.file_path) ?? null
20
+ : null,
21
+ }));
22
+ }
23
+ export async function getArtifactByIdWithClient(client, id) {
24
+ const { data, error } = await client
25
+ .from("artifacts")
26
+ .select("*")
27
+ .eq("id", id)
28
+ .single();
29
+ if (error) {
30
+ return IWebResponse.error(error.message).to_compatible();
31
+ }
32
+ if (!data) {
33
+ return IWebResponse.success(null).to_compatible();
34
+ }
35
+ const artifact = data;
36
+ let media_url = null;
37
+ if (isNonEmptyStorageFilePath(artifact.file_path)) {
38
+ media_url = await generateSignedUrlWithClient(client, artifact.file_path);
39
+ }
40
+ return IWebResponse.success({
41
+ ...artifact,
42
+ media_url,
43
+ }).to_compatible();
44
+ }
45
+ export async function getArtifactsByHerdWithClient(client, herd_id, limit, offset, options) {
46
+ const { data, error } = await client.rpc("get_artifacts_for_herd", {
47
+ herd_id_caller: herd_id,
48
+ limit_caller: limit,
49
+ offset_caller: offset,
50
+ start_timestamp: options?.start_timestamp,
51
+ end_timestamp: options?.end_timestamp,
52
+ });
53
+ if (error) {
54
+ return IWebResponse.error(error.message).to_compatible();
55
+ }
56
+ if (!data) {
57
+ return IWebResponse.error("No artifacts found for herd").to_compatible();
58
+ }
59
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
60
+ return IWebResponse.success(artifactsWithUrls).to_compatible();
61
+ }
62
+ export async function getArtifactsByDeviceIdWithClient(client, device_id, limit, offset) {
63
+ const { data, error } = await client.rpc("get_artifacts_for_device", {
64
+ device_id_caller: device_id,
65
+ limit_caller: limit,
66
+ offset_caller: offset,
67
+ });
68
+ if (error) {
69
+ return IWebResponse.error(error.message).to_compatible();
70
+ }
71
+ if (!data) {
72
+ return IWebResponse.error("No artifacts found for device").to_compatible();
73
+ }
74
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
75
+ return IWebResponse.success(artifactsWithUrls).to_compatible();
76
+ }
77
+ export async function getArtifactsByDeviceIdsBatchWithClient(client, device_ids, limit_per_device, options) {
78
+ if (device_ids.length === 0) {
79
+ return {};
80
+ }
81
+ const { data, error } = await client.rpc("get_artifacts_for_devices_batch", {
82
+ device_ids,
83
+ limit_per_device,
84
+ start_timestamp: options?.start_timestamp,
85
+ end_timestamp: options?.end_timestamp,
86
+ });
87
+ if (error || !data) {
88
+ console.warn("Error fetching artifacts batch:", error?.message);
89
+ return {};
90
+ }
91
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
92
+ const artifactsByDevice = {};
93
+ artifactsWithUrls.forEach((artifact) => {
94
+ if (!artifactsByDevice[artifact.device_id]) {
95
+ artifactsByDevice[artifact.device_id] = [];
96
+ }
97
+ artifactsByDevice[artifact.device_id].push(artifact);
98
+ });
99
+ return artifactsByDevice;
100
+ }
101
+ export async function insertArtifactWithClient(client, artifact) {
102
+ const arr = Array.isArray(artifact) ? artifact : [artifact];
103
+ const { data, error } = await client
104
+ .from("artifacts")
105
+ .insert(arr)
106
+ .select("*");
107
+ if (error) {
108
+ return IWebResponse.error(error.message).to_compatible();
109
+ }
110
+ return IWebResponse.success(data || []).to_compatible();
111
+ }
112
+ export async function updateArtifactWithClient(client, artifact) {
113
+ const arr = Array.isArray(artifact) ? artifact : [artifact];
114
+ const results = [];
115
+ for (const record of arr) {
116
+ const { id, ...updateData } = record;
117
+ delete updateData.created_at;
118
+ const { data, error } = await client
119
+ .from("artifacts")
120
+ .update(updateData)
121
+ .eq("id", id)
122
+ .select("*")
123
+ .single();
124
+ if (error) {
125
+ return IWebResponse.error(error.message).to_compatible();
126
+ }
127
+ if (data)
128
+ results.push(data);
129
+ }
130
+ return IWebResponse.success(results).to_compatible();
131
+ }
132
+ export async function deleteArtifactWithClient(client, id) {
133
+ const ids = Array.isArray(id) ? id : [id];
134
+ const { error } = await client.from("artifacts").delete().in("id", ids);
135
+ if (error) {
136
+ return IWebResponse.error(error.message).to_compatible();
137
+ }
138
+ return IWebResponse.success(true).to_compatible();
139
+ }
140
+ export async function matchArtifactsByVertexEmbeddingWithClient(client, query_embedding, match_threshold, match_count, herd_id) {
141
+ const { data, error } = await client.rpc("match_artifacts_by_vertex_embedding", {
142
+ query_embedding,
143
+ match_threshold,
144
+ match_count,
145
+ herd_id_caller: herd_id ?? null,
146
+ });
147
+ if (error) {
148
+ return IWebResponse.error(error.message).to_compatible();
149
+ }
150
+ return IWebResponse.success((data ?? [])).to_compatible();
151
+ }
@@ -1,11 +1,30 @@
1
1
  "use server";
2
2
  import { newServerClient } from "../supabase/server";
3
3
  import { IWebResponse } from "../types/requests";
4
- import { generateSignedUrlsBatch, generateSignedUrl, } from "./storage";
4
+ import { generateSignedUrlsBatchWithClient, generateSignedUrlWithClient, } from "./storage_internal";
5
5
  import { isNonEmptyStorageFilePath } from "./storagePath";
6
- export async function server_get_artifact_by_id(id, client) {
7
- const supabase = client || (await newServerClient());
8
- const { data, error } = await supabase
6
+ async function addArtifactMediaUrls(data, client) {
7
+ const uniqueFilePaths = Array.from(new Set(data
8
+ .map((artifact) => artifact.file_path)
9
+ .filter(isNonEmptyStorageFilePath)));
10
+ if (uniqueFilePaths.length === 0) {
11
+ return data;
12
+ }
13
+ const signedUrls = await generateSignedUrlsBatchWithClient(client, uniqueFilePaths);
14
+ const urlMap = new Map();
15
+ uniqueFilePaths.forEach((path, index) => {
16
+ urlMap.set(path, signedUrls[index]);
17
+ });
18
+ return data.map((artifact) => ({
19
+ ...artifact,
20
+ media_url: isNonEmptyStorageFilePath(artifact.file_path)
21
+ ? urlMap.get(artifact.file_path) ?? null
22
+ : null,
23
+ }));
24
+ }
25
+ export async function server_get_artifact_by_id(id) {
26
+ const client = await newServerClient();
27
+ const { data, error } = await client
9
28
  .from("artifacts")
10
29
  .select("*")
11
30
  .eq("id", id)
@@ -19,7 +38,7 @@ export async function server_get_artifact_by_id(id, client) {
19
38
  const artifact = data;
20
39
  let media_url = null;
21
40
  if (isNonEmptyStorageFilePath(artifact.file_path)) {
22
- media_url = await generateSignedUrl(artifact.file_path, undefined, client);
41
+ media_url = await generateSignedUrlWithClient(client, artifact.file_path);
23
42
  }
24
43
  return IWebResponse.success({
25
44
  ...artifact,
@@ -27,8 +46,8 @@ export async function server_get_artifact_by_id(id, client) {
27
46
  }).to_compatible();
28
47
  }
29
48
  export async function server_get_artifacts_by_herd(herd_id, limit = 50, offset = 0, options) {
30
- const supabase = options?.client || (await newServerClient());
31
- const { data, error } = await supabase.rpc("get_artifacts_for_herd", {
49
+ const client = await newServerClient();
50
+ const { data, error } = await client.rpc("get_artifacts_for_herd", {
32
51
  herd_id_caller: herd_id,
33
52
  limit_caller: limit,
34
53
  offset_caller: offset,
@@ -41,29 +60,12 @@ export async function server_get_artifacts_by_herd(herd_id, limit = 50, offset =
41
60
  if (!data) {
42
61
  return IWebResponse.error("No artifacts found for herd").to_compatible();
43
62
  }
44
- // Generate signed URLs for artifacts
45
- const uniqueFilePaths = Array.from(new Set(data
46
- .map((artifact) => artifact.file_path)
47
- .filter(isNonEmptyStorageFilePath)));
48
- if (uniqueFilePaths.length === 0) {
49
- return IWebResponse.success(data).to_compatible();
50
- }
51
- const signedUrls = await generateSignedUrlsBatch(uniqueFilePaths, undefined, options?.client);
52
- const urlMap = new Map();
53
- uniqueFilePaths.forEach((path, index) => {
54
- urlMap.set(path, signedUrls[index]);
55
- });
56
- const artifactsWithUrls = data.map((artifact) => ({
57
- ...artifact,
58
- media_url: isNonEmptyStorageFilePath(artifact.file_path)
59
- ? urlMap.get(artifact.file_path) ?? null
60
- : null,
61
- }));
63
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
62
64
  return IWebResponse.success(artifactsWithUrls).to_compatible();
63
65
  }
64
- export async function server_get_artifacts_by_device_id(device_id, limit = 50, offset = 0, client) {
65
- const supabase = client || (await newServerClient());
66
- const { data, error } = await supabase.rpc("get_artifacts_for_device", {
66
+ export async function server_get_artifacts_by_device_id(device_id, limit = 50, offset = 0) {
67
+ const client = await newServerClient();
68
+ const { data, error } = await client.rpc("get_artifacts_for_device", {
67
69
  device_id_caller: device_id,
68
70
  limit_caller: limit,
69
71
  offset_caller: offset,
@@ -74,24 +76,7 @@ export async function server_get_artifacts_by_device_id(device_id, limit = 50, o
74
76
  if (!data) {
75
77
  return IWebResponse.error("No artifacts found for device").to_compatible();
76
78
  }
77
- // Generate signed URLs for artifacts
78
- const uniqueFilePaths = Array.from(new Set(data
79
- .map((artifact) => artifact.file_path)
80
- .filter(isNonEmptyStorageFilePath)));
81
- if (uniqueFilePaths.length === 0) {
82
- return IWebResponse.success(data).to_compatible();
83
- }
84
- const signedUrls = await generateSignedUrlsBatch(uniqueFilePaths, undefined, client);
85
- const urlMap = new Map();
86
- uniqueFilePaths.forEach((path, index) => {
87
- urlMap.set(path, signedUrls[index]);
88
- });
89
- const artifactsWithUrls = data.map((artifact) => ({
90
- ...artifact,
91
- media_url: isNonEmptyStorageFilePath(artifact.file_path)
92
- ? urlMap.get(artifact.file_path) ?? null
93
- : null,
94
- }));
79
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
95
80
  return IWebResponse.success(artifactsWithUrls).to_compatible();
96
81
  }
97
82
  export async function server_get_total_artifacts_by_herd(herd_id) {
@@ -105,13 +90,13 @@ export async function server_get_total_artifacts_by_herd(herd_id) {
105
90
  return IWebResponse.success(data || 0).to_compatible();
106
91
  }
107
92
  export async function server_get_artifacts_by_device_ids_batch(device_ids, limit_per_device = 10, options) {
108
- const supabase = options?.client || (await newServerClient());
109
93
  if (device_ids.length === 0) {
110
94
  return {};
111
95
  }
112
- const { data, error } = await supabase.rpc("get_artifacts_for_devices_batch", {
113
- device_ids: device_ids,
114
- limit_per_device: limit_per_device,
96
+ const client = await newServerClient();
97
+ const { data, error } = await client.rpc("get_artifacts_for_devices_batch", {
98
+ device_ids,
99
+ limit_per_device,
115
100
  start_timestamp: options?.start_timestamp,
116
101
  end_timestamp: options?.end_timestamp,
117
102
  });
@@ -119,25 +104,7 @@ export async function server_get_artifacts_by_device_ids_batch(device_ids, limit
119
104
  console.warn("Error fetching artifacts batch:", error?.message);
120
105
  return {};
121
106
  }
122
- // Generate signed URLs for artifacts
123
- const uniqueFilePaths = Array.from(new Set(data
124
- .map((artifact) => artifact.file_path)
125
- .filter(isNonEmptyStorageFilePath)));
126
- let artifactsWithUrls = data;
127
- if (uniqueFilePaths.length > 0) {
128
- const signedUrls = await generateSignedUrlsBatch(uniqueFilePaths, undefined, options?.client);
129
- const urlMap = new Map();
130
- uniqueFilePaths.forEach((path, index) => {
131
- urlMap.set(path, signedUrls[index]);
132
- });
133
- artifactsWithUrls = data.map((artifact) => ({
134
- ...artifact,
135
- media_url: isNonEmptyStorageFilePath(artifact.file_path)
136
- ? urlMap.get(artifact.file_path) ?? null
137
- : null,
138
- }));
139
- }
140
- // Group artifacts by device_id
107
+ const artifactsWithUrls = await addArtifactMediaUrls(data, client);
141
108
  const artifactsByDevice = {};
142
109
  artifactsWithUrls.forEach((artifact) => {
143
110
  if (!artifactsByDevice[artifact.device_id]) {
@@ -147,10 +114,10 @@ export async function server_get_artifacts_by_device_ids_batch(device_ids, limit
147
114
  });
148
115
  return artifactsByDevice;
149
116
  }
150
- export async function server_insert_artifact(artifact, client) {
151
- const supabase = client || (await newServerClient());
117
+ export async function server_insert_artifact(artifact) {
118
+ const client = await newServerClient();
152
119
  const arr = Array.isArray(artifact) ? artifact : [artifact];
153
- const { data, error } = await supabase
120
+ const { data, error } = await client
154
121
  .from("artifacts")
155
122
  .insert(arr)
156
123
  .select("*");
@@ -159,14 +126,14 @@ export async function server_insert_artifact(artifact, client) {
159
126
  }
160
127
  return IWebResponse.success(data || []).to_compatible();
161
128
  }
162
- export async function server_update_artifact(artifact, client) {
163
- const supabase = client || (await newServerClient());
129
+ export async function server_update_artifact(artifact) {
130
+ const client = await newServerClient();
164
131
  const arr = Array.isArray(artifact) ? artifact : [artifact];
165
132
  const results = [];
166
133
  for (const record of arr) {
167
134
  const { id, ...updateData } = record;
168
135
  delete updateData.created_at;
169
- const { data, error } = await supabase
136
+ const { data, error } = await client
170
137
  .from("artifacts")
171
138
  .update(updateData)
172
139
  .eq("id", id)
@@ -180,10 +147,10 @@ export async function server_update_artifact(artifact, client) {
180
147
  }
181
148
  return IWebResponse.success(results).to_compatible();
182
149
  }
183
- export async function server_delete_artifact(id, client) {
184
- const supabase = client || (await newServerClient());
150
+ export async function server_delete_artifact(id) {
151
+ const client = await newServerClient();
185
152
  const ids = Array.isArray(id) ? id : [id];
186
- const { error } = await supabase.from("artifacts").delete().in("id", ids);
153
+ const { error } = await client.from("artifacts").delete().in("id", ids);
187
154
  if (error) {
188
155
  return IWebResponse.error(error.message).to_compatible();
189
156
  }
@@ -191,9 +158,9 @@ export async function server_delete_artifact(id, client) {
191
158
  }
192
159
  /** Semantic search over artifacts using Vertex multimodal embedding (embedding_vertex_mm_01). */
193
160
  export async function server_match_artifacts_by_vertex_embedding(query_embedding, match_threshold, match_count, options) {
194
- const supabase = options?.client ?? (await newServerClient());
195
- const { data, error } = await supabase.rpc("match_artifacts_by_vertex_embedding", {
196
- query_embedding: query_embedding,
161
+ const client = await newServerClient();
162
+ const { data, error } = await client.rpc("match_artifacts_by_vertex_embedding", {
163
+ query_embedding,
197
164
  match_threshold,
198
165
  match_count,
199
166
  herd_id_caller: options?.herd_id ?? null,
@@ -1,10 +1,9 @@
1
- import { SupabaseClient } from "@supabase/supabase-js";
2
- import { Database, Json } from "../types/supabase";
3
1
  import { IWebResponseCompatible } from "../types/requests";
2
+ import { Json } from "../types/supabase";
4
3
  export type ClientAbilitiesPublicJwk = Record<string, Json | undefined> & {
5
4
  kty: string;
6
5
  kid?: string;
7
6
  };
8
7
  /** Register or rotate a verification key (service_role or platform superadmin). */
9
- export declare function server_upsert_client_abilities_jwt_public_key(kid: string, public_jwk: ClientAbilitiesPublicJwk, supabaseClient?: SupabaseClient<Database>): Promise<IWebResponseCompatible<null>>;
10
- export declare function server_revoke_client_abilities_jwt_public_key(kid: string, supabaseClient?: SupabaseClient<Database>): Promise<IWebResponseCompatible<null>>;
8
+ export declare function server_upsert_client_abilities_jwt_public_key(kid: string, public_jwk: ClientAbilitiesPublicJwk): Promise<IWebResponseCompatible<null>>;
9
+ export declare function server_revoke_client_abilities_jwt_public_key(kid: string): Promise<IWebResponseCompatible<null>>;
@@ -1,10 +1,10 @@
1
1
  "use server";
2
- import { IWebResponse } from "../types/requests";
3
2
  import { newServerClient } from "../supabase/server";
3
+ import { IWebResponse } from "../types/requests";
4
4
  /** Register or rotate a verification key (service_role or platform superadmin). */
5
- export async function server_upsert_client_abilities_jwt_public_key(kid, public_jwk, supabaseClient) {
6
- const supabase = supabaseClient ?? (await newServerClient());
7
- const { error } = await supabase.rpc("upsert_client_abilities_jwt_public_key", {
5
+ export async function server_upsert_client_abilities_jwt_public_key(kid, public_jwk) {
6
+ const client = await newServerClient();
7
+ const { error } = await client.rpc("upsert_client_abilities_jwt_public_key", {
8
8
  p_kid: kid,
9
9
  p_public_jwk: public_jwk,
10
10
  });
@@ -13,9 +13,9 @@ export async function server_upsert_client_abilities_jwt_public_key(kid, public_
13
13
  }
14
14
  return IWebResponse.success(null).to_compatible();
15
15
  }
16
- export async function server_revoke_client_abilities_jwt_public_key(kid, supabaseClient) {
17
- const supabase = supabaseClient ?? (await newServerClient());
18
- const { error } = await supabase.rpc("revoke_client_abilities_jwt_public_key", {
16
+ export async function server_revoke_client_abilities_jwt_public_key(kid) {
17
+ const client = await newServerClient();
18
+ const { error } = await client.rpc("revoke_client_abilities_jwt_public_key", {
19
19
  p_kid: kid,
20
20
  });
21
21
  if (error) {
@@ -0,0 +1,9 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ import { Database, Json } from "../types/supabase";
4
+ export type ClientAbilitiesPublicJwk = Record<string, Json | undefined> & {
5
+ kty: string;
6
+ kid?: string;
7
+ };
8
+ export declare function upsert_client_abilities_jwt_public_key(client: SupabaseClient<Database>, kid: string, publicJwk: ClientAbilitiesPublicJwk): Promise<IWebResponseCompatible<null>>;
9
+ export declare function revoke_client_abilities_jwt_public_key(client: SupabaseClient<Database>, kid: string): Promise<IWebResponseCompatible<null>>;