@adventurelabs/scout-core 1.0.46 → 1.0.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api_keys/actions.d.ts +1 -0
- package/dist/api_keys/actions.js +76 -30
- package/dist/helpers/tags.d.ts +1 -0
- package/dist/helpers/tags.js +42 -16
- package/dist/types/herd_module.js +8 -20
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IApiKeyScout } from "../types/db";
|
|
2
|
+
export declare function test_api_key_loading(device_id: string): Promise<boolean>;
|
|
2
3
|
export declare function server_list_api_keys(device_id: string): Promise<IApiKeyScout[]>;
|
|
3
4
|
export declare function server_list_api_keys_batch(device_ids: string[]): Promise<{
|
|
4
5
|
[device_id: number]: IApiKeyScout[];
|
package/dist/api_keys/actions.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
|
+
// Test function to verify individual API key loading works
|
|
4
|
+
export async function test_api_key_loading(device_id) {
|
|
5
|
+
try {
|
|
6
|
+
console.log(`[API Key Test] Testing individual API key loading for device ${device_id}`);
|
|
7
|
+
const api_keys = await server_list_api_keys(device_id);
|
|
8
|
+
console.log(`[API Key Test] Successfully loaded ${api_keys.length} API keys for device ${device_id}`);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
console.error(`[API Key Test] Failed to load API keys for device ${device_id}:`, error);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
3
16
|
export async function server_list_api_keys(device_id) {
|
|
4
17
|
const supabase = await newServerClient();
|
|
5
18
|
const { data, error } = await supabase.rpc("load_api_keys", {
|
|
@@ -19,37 +32,70 @@ export async function server_list_api_keys(device_id) {
|
|
|
19
32
|
}
|
|
20
33
|
export async function server_list_api_keys_batch(device_ids) {
|
|
21
34
|
const startTime = Date.now();
|
|
22
|
-
console.log(`[API Keys Batch] Starting batch load for ${device_ids.length} devices at ${new Date().toISOString()}`);
|
|
23
|
-
console.log(`[API Keys Batch] Debug: device_ids array:`, device_ids);
|
|
24
|
-
console.log(`[API Keys Batch] Debug: device_ids types:`, device_ids.map((id) => ({ id, type: typeof id })));
|
|
25
35
|
const supabase = await newServerClient();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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[parseInt(device_id)] = api_keys;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.warn(`[API Keys Batch] Failed for device ${device_id}:`, err);
|
|
60
|
+
result[parseInt(device_id)] = [];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
await Promise.all(promises);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
if (!data) {
|
|
67
|
+
return {};
|
|
46
68
|
}
|
|
47
|
-
result
|
|
48
|
-
|
|
49
|
-
|
|
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.toString(),
|
|
78
|
+
key: item.api_key_key,
|
|
79
|
+
});
|
|
50
80
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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[parseInt(device_id)] = api_keys;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.warn(`[API Keys Batch] Failed for device ${device_id}:`, err);
|
|
95
|
+
result[parseInt(device_id)] = [];
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
await Promise.all(promises);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
55
101
|
}
|
package/dist/helpers/tags.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IEventWithTags, ITag } from "../types/db";
|
|
2
2
|
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
+
export declare function test_event_loading(device_id: number): Promise<boolean>;
|
|
3
4
|
export declare function server_create_tags(tags: ITag[]): Promise<IWebResponseCompatible<ITag[]>>;
|
|
4
5
|
export declare function server_delete_tags_by_ids(tag_ids: number[]): Promise<IWebResponseCompatible<boolean>>;
|
|
5
6
|
export declare function server_update_tags(tags: ITag[]): Promise<IWebResponseCompatible<ITag[]>>;
|
package/dist/helpers/tags.js
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
import { newServerClient } from "../supabase/server";
|
|
4
4
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
5
5
|
import { addSignedUrlsToEvents, addSignedUrlToEvent } from "./storage";
|
|
6
|
+
// Test function to verify individual event loading works
|
|
7
|
+
export async function test_event_loading(device_id) {
|
|
8
|
+
try {
|
|
9
|
+
console.log(`[Event Test] Testing individual event loading for device ${device_id}`);
|
|
10
|
+
const events_response = await server_get_events_and_tags_for_device(device_id, 1);
|
|
11
|
+
if (events_response.status === EnumWebResponse.SUCCESS) {
|
|
12
|
+
console.log(`[Event Test] Successfully loaded ${events_response.data?.length || 0} events for device ${device_id}`);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.error(`[Event Test] Failed to load events for device ${device_id}:`, events_response.msg);
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error(`[Event Test] Failed to load events for device ${device_id}:`, error);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
6
25
|
export async function server_create_tags(tags) {
|
|
7
26
|
const supabase = await newServerClient();
|
|
8
27
|
// remove id key from tags
|
|
@@ -148,30 +167,39 @@ export async function server_get_events_and_tags_for_device(device_id, limit = 3
|
|
|
148
167
|
}
|
|
149
168
|
export async function server_get_events_and_tags_for_devices_batch(device_ids, limit = 1) {
|
|
150
169
|
const startTime = Date.now();
|
|
151
|
-
console.log(`[Events Batch] Starting batch load for ${device_ids.length} devices (limit: ${limit}) at ${new Date().toISOString()}`);
|
|
152
|
-
console.log(`[Events Batch] Debug: device_ids array:`, device_ids);
|
|
153
|
-
console.log(`[Events Batch] Debug: device_ids types:`, device_ids.map((id) => ({ id, type: typeof id })));
|
|
154
170
|
const supabase = await newServerClient();
|
|
155
|
-
console.log(`[Events Batch] Making RPC call to get_events_and_tags_for_devices_batch...`);
|
|
156
171
|
// Use single RPC call for all devices
|
|
157
172
|
const { data, error } = await supabase.rpc("get_events_and_tags_for_devices_batch", {
|
|
158
173
|
device_ids: device_ids,
|
|
159
174
|
limit_per_device: limit,
|
|
160
175
|
});
|
|
161
|
-
const duration = Date.now() - startTime;
|
|
162
176
|
if (error) {
|
|
163
|
-
console.error(`[Events Batch]
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
177
|
+
console.error(`[Events Batch] Database error:`, error.message);
|
|
178
|
+
console.log(`[Events Batch] Falling back to individual calls...`);
|
|
179
|
+
// Fallback to individual event loading
|
|
180
|
+
const result = {};
|
|
181
|
+
const promises = device_ids.map(async (device_id) => {
|
|
182
|
+
try {
|
|
183
|
+
const events_response = await server_get_events_and_tags_for_device(parseInt(device_id), limit);
|
|
184
|
+
if (events_response.status === EnumWebResponse.SUCCESS &&
|
|
185
|
+
events_response.data) {
|
|
186
|
+
result[parseInt(device_id)] = events_response.data;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
result[parseInt(device_id)] = [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
console.warn(`[Events Batch] Failed for device ${device_id}:`, err);
|
|
194
|
+
result[parseInt(device_id)] = [];
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
await Promise.all(promises);
|
|
198
|
+
return IWebResponse.success(result).to_compatible();
|
|
169
199
|
}
|
|
170
200
|
if (!data) {
|
|
171
|
-
console.log(`[Events Batch] No data returned after ${duration}ms`);
|
|
172
201
|
return IWebResponse.success({}).to_compatible();
|
|
173
202
|
}
|
|
174
|
-
console.log(`[Events Batch] RPC completed in ${duration}ms, received ${data.length} event records`);
|
|
175
203
|
// Group events by device_id
|
|
176
204
|
const eventsByDevice = {};
|
|
177
205
|
data.forEach((row) => {
|
|
@@ -179,7 +207,7 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
179
207
|
if (!eventsByDevice[device_id]) {
|
|
180
208
|
eventsByDevice[device_id] = [];
|
|
181
209
|
}
|
|
182
|
-
// Create event object from the
|
|
210
|
+
// Create event object from the database function structure
|
|
183
211
|
const event = {
|
|
184
212
|
id: row.event_id,
|
|
185
213
|
inserted_at: row.inserted_at,
|
|
@@ -206,8 +234,6 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
206
234
|
const eventsWithSignedUrls = await addSignedUrlsToEvents(events, supabase);
|
|
207
235
|
result[parseInt(device_id)] = eventsWithSignedUrls;
|
|
208
236
|
}
|
|
209
|
-
const totalDuration = Date.now() - startTime;
|
|
210
|
-
console.log(`[Events Batch] COMPLETED in ${totalDuration}ms - returning events for ${Object.keys(result).length} devices`);
|
|
211
237
|
return IWebResponse.success(result).to_compatible();
|
|
212
238
|
}
|
|
213
239
|
export async function get_event_and_tags_by_event_id(event_id) {
|
|
@@ -52,7 +52,7 @@ export class HerdModule {
|
|
|
52
52
|
let response_new_devices = await get_devices_by_herd(herd.id, client);
|
|
53
53
|
if (response_new_devices.status == EnumWebResponse.ERROR ||
|
|
54
54
|
!response_new_devices.data) {
|
|
55
|
-
console.warn(
|
|
55
|
+
console.warn(`[HerdModule] No devices found for herd ${herd.id}`);
|
|
56
56
|
return new HerdModule(herd, [], [], Date.now());
|
|
57
57
|
}
|
|
58
58
|
const new_devices = response_new_devices.data;
|
|
@@ -61,60 +61,48 @@ export class HerdModule {
|
|
|
61
61
|
if (new_devices.length > 0) {
|
|
62
62
|
const batchStartTime = Date.now();
|
|
63
63
|
try {
|
|
64
|
-
console.log(`[HerdModule] Debug: new_devices array:`, new_devices.map((d) => ({
|
|
65
|
-
id: d.id,
|
|
66
|
-
type: typeof d.id,
|
|
67
|
-
created_by: d.created_by,
|
|
68
|
-
name: d.name,
|
|
69
|
-
})));
|
|
70
64
|
const device_ids = new_devices.map((device) => (device.id ?? 0).toString());
|
|
71
|
-
console.log(`[HerdModule] Starting parallel batch load for ${device_ids.length} devices at ${new Date().toISOString()}:`, device_ids);
|
|
72
65
|
// Load API keys and events in parallel
|
|
73
|
-
console.log(`[HerdModule] Initiating Promise.all for API keys and events...`);
|
|
74
66
|
const [api_keys_batch, events_response] = await Promise.all([
|
|
75
67
|
server_list_api_keys_batch(device_ids),
|
|
76
68
|
server_get_events_and_tags_for_devices_batch(device_ids, 1),
|
|
77
69
|
]);
|
|
78
|
-
const batchDuration = Date.now() - batchStartTime;
|
|
79
|
-
console.log(`[HerdModule] Parallel batch load completed in ${batchDuration}ms`);
|
|
80
70
|
// Assign API keys to devices
|
|
81
71
|
for (let i = 0; i < new_devices.length; i++) {
|
|
82
72
|
const device_id = new_devices[i].id ?? 0;
|
|
83
73
|
new_devices[i].api_keys_scout = api_keys_batch[device_id] || [];
|
|
84
74
|
}
|
|
85
|
-
console.log(`[HerdModule] API keys loaded for ${Object.keys(api_keys_batch).length} devices`);
|
|
86
75
|
// Process events response
|
|
87
76
|
if (events_response.status === EnumWebResponse.SUCCESS &&
|
|
88
77
|
events_response.data) {
|
|
89
78
|
recent_events_batch = events_response.data;
|
|
90
|
-
console.log(`[HerdModule] Events loaded for ${Object.keys(recent_events_batch).length} devices`);
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
81
|
catch (error) {
|
|
94
|
-
console.error(`[HerdModule]
|
|
82
|
+
console.error(`[HerdModule] Batch load error:`, error);
|
|
95
83
|
// Continue without API keys and events
|
|
96
84
|
}
|
|
97
85
|
}
|
|
98
86
|
// Run all remaining requests in parallel with individual error handling
|
|
99
87
|
const [res_zones, res_user_roles, total_event_count, res_plans, res_sessions,] = await Promise.allSettled([
|
|
100
88
|
server_get_more_zones_and_actions_for_herd(herd.id, 0, 10).catch((error) => {
|
|
101
|
-
console.warn(
|
|
89
|
+
console.warn(`[HerdModule] Failed to get zones and actions:`, error);
|
|
102
90
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
103
91
|
}),
|
|
104
92
|
server_get_users_with_herd_access(herd.id).catch((error) => {
|
|
105
|
-
console.warn(
|
|
93
|
+
console.warn(`[HerdModule] Failed to get user roles:`, error);
|
|
106
94
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
107
95
|
}),
|
|
108
96
|
server_get_total_events_by_herd(herd.id, EnumSessionsVisibility.Exclude).catch((error) => {
|
|
109
|
-
console.warn(
|
|
97
|
+
console.warn(`[HerdModule] Failed to get total events count:`, error);
|
|
110
98
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
111
99
|
}),
|
|
112
100
|
server_get_plans_by_herd(herd.id).catch((error) => {
|
|
113
|
-
console.warn(
|
|
101
|
+
console.warn(`[HerdModule] Failed to get plans:`, error);
|
|
114
102
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
115
103
|
}),
|
|
116
104
|
getSessionsByHerdId(client, herd.id).catch((error) => {
|
|
117
|
-
console.warn(
|
|
105
|
+
console.warn(`[HerdModule] Failed to get sessions:`, error);
|
|
118
106
|
return [];
|
|
119
107
|
}),
|
|
120
108
|
]);
|
|
@@ -151,7 +139,7 @@ export class HerdModule {
|
|
|
151
139
|
return new HerdModule(herd, new_devices, [], Date.now(), user_roles, 0, total_events, total_events, newLabels, plans, zones, sessions);
|
|
152
140
|
}
|
|
153
141
|
catch (error) {
|
|
154
|
-
console.error(
|
|
142
|
+
console.error(`[HerdModule] Critical error in HerdModule.from_herd:`, error);
|
|
155
143
|
// Return a minimal but valid HerdModule instance to prevent complete failure
|
|
156
144
|
return new HerdModule(herd, [], [], Date.now());
|
|
157
145
|
}
|