@adventurelabs/scout-core 1.0.45 → 1.0.47
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 +36 -11
- package/dist/helpers/tags.d.ts +1 -0
- package/dist/helpers/tags.js +50 -16
- package/dist/types/herd_module.js +18 -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,24 +32,38 @@ 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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
// CRITICAL: Check for UUIDs being passed instead of device IDs
|
|
36
|
+
const invalidIds = device_ids.filter((id) => !/^\d+$/.test(id));
|
|
37
|
+
if (invalidIds.length > 0) {
|
|
38
|
+
console.error(`[CRITICAL] UUIDs detected instead of device IDs:`, invalidIds);
|
|
39
|
+
console.error(`[CRITICAL] Valid device IDs should be:`, device_ids.filter((id) => /^\d+$/.test(id)));
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
25
42
|
const supabase = await newServerClient();
|
|
26
|
-
console.log(`[API Keys Batch] Making RPC call to load_api_keys_batch...`);
|
|
27
43
|
const { data, error } = await supabase.rpc("load_api_keys_batch", {
|
|
28
44
|
device_ids: device_ids,
|
|
29
45
|
});
|
|
30
|
-
const duration = Date.now() - startTime;
|
|
31
46
|
if (error) {
|
|
32
|
-
console.error(`[API Keys Batch]
|
|
33
|
-
|
|
47
|
+
console.error(`[API Keys Batch] Database error:`, error.message);
|
|
48
|
+
console.log(`[API Keys Batch] Falling back to individual calls...`);
|
|
49
|
+
// Fallback to individual API key loading
|
|
50
|
+
const result = {};
|
|
51
|
+
const promises = device_ids.map(async (device_id) => {
|
|
52
|
+
try {
|
|
53
|
+
const api_keys = await server_list_api_keys(device_id);
|
|
54
|
+
result[parseInt(device_id)] = api_keys;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
console.warn(`[API Keys Batch] Failed for device ${device_id}:`, err);
|
|
58
|
+
result[parseInt(device_id)] = [];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
await Promise.all(promises);
|
|
62
|
+
return result;
|
|
34
63
|
}
|
|
35
64
|
if (!data) {
|
|
36
|
-
console.log(`[API Keys Batch] No data returned after ${duration}ms`);
|
|
37
65
|
return {};
|
|
38
66
|
}
|
|
39
|
-
console.log(`[API Keys Batch] RPC completed in ${duration}ms, received ${data.length} API key records`);
|
|
40
67
|
const result = {};
|
|
41
68
|
// Group API keys by device_id
|
|
42
69
|
data.forEach((item) => {
|
|
@@ -49,7 +76,5 @@ export async function server_list_api_keys_batch(device_ids) {
|
|
|
49
76
|
key: item.api_key_key,
|
|
50
77
|
});
|
|
51
78
|
});
|
|
52
|
-
const totalDuration = Date.now() - startTime;
|
|
53
|
-
console.log(`[API Keys Batch] COMPLETED in ${totalDuration}ms - returning API keys for ${Object.keys(result).length} devices`);
|
|
54
79
|
return result;
|
|
55
80
|
}
|
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,47 @@ 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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
// CRITICAL: Check for UUIDs being passed instead of device IDs
|
|
171
|
+
const invalidIds = device_ids.filter((id) => !/^\d+$/.test(id));
|
|
172
|
+
if (invalidIds.length > 0) {
|
|
173
|
+
console.error(`[CRITICAL] UUIDs detected instead of device IDs:`, invalidIds);
|
|
174
|
+
console.error(`[CRITICAL] Valid device IDs should be:`, device_ids.filter((id) => /^\d+$/.test(id)));
|
|
175
|
+
return IWebResponse.success({}).to_compatible();
|
|
176
|
+
}
|
|
154
177
|
const supabase = await newServerClient();
|
|
155
|
-
console.log(`[Events Batch] Making RPC call to get_events_and_tags_for_devices_batch...`);
|
|
156
178
|
// Use single RPC call for all devices
|
|
157
179
|
const { data, error } = await supabase.rpc("get_events_and_tags_for_devices_batch", {
|
|
158
180
|
device_ids: device_ids,
|
|
159
181
|
limit_per_device: limit,
|
|
160
182
|
});
|
|
161
|
-
const duration = Date.now() - startTime;
|
|
162
183
|
if (error) {
|
|
163
|
-
console.error(`[Events Batch]
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
184
|
+
console.error(`[Events Batch] Database error:`, error.message);
|
|
185
|
+
console.log(`[Events Batch] Falling back to individual calls...`);
|
|
186
|
+
// Fallback to individual event loading
|
|
187
|
+
const result = {};
|
|
188
|
+
const promises = device_ids.map(async (device_id) => {
|
|
189
|
+
try {
|
|
190
|
+
const device_id_num = parseInt(device_id);
|
|
191
|
+
const events_response = await server_get_events_and_tags_for_device(device_id_num, limit);
|
|
192
|
+
if (events_response.status === EnumWebResponse.SUCCESS &&
|
|
193
|
+
events_response.data) {
|
|
194
|
+
result[device_id_num] = events_response.data;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
result[device_id_num] = [];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
console.warn(`[Events Batch] Failed for device ${device_id}:`, err);
|
|
202
|
+
result[parseInt(device_id)] = [];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
await Promise.all(promises);
|
|
206
|
+
return IWebResponse.success(result).to_compatible();
|
|
169
207
|
}
|
|
170
208
|
if (!data) {
|
|
171
|
-
console.log(`[Events Batch] No data returned after ${duration}ms`);
|
|
172
209
|
return IWebResponse.success({}).to_compatible();
|
|
173
210
|
}
|
|
174
|
-
console.log(`[Events Batch] RPC completed in ${duration}ms, received ${data.length} event records`);
|
|
175
211
|
// Group events by device_id
|
|
176
212
|
const eventsByDevice = {};
|
|
177
213
|
data.forEach((row) => {
|
|
@@ -179,7 +215,7 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
179
215
|
if (!eventsByDevice[device_id]) {
|
|
180
216
|
eventsByDevice[device_id] = [];
|
|
181
217
|
}
|
|
182
|
-
// Create event object from the
|
|
218
|
+
// Create event object from the database function structure
|
|
183
219
|
const event = {
|
|
184
220
|
id: row.event_id,
|
|
185
221
|
inserted_at: row.inserted_at,
|
|
@@ -206,8 +242,6 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
206
242
|
const eventsWithSignedUrls = await addSignedUrlsToEvents(events, supabase);
|
|
207
243
|
result[parseInt(device_id)] = eventsWithSignedUrls;
|
|
208
244
|
}
|
|
209
|
-
const totalDuration = Date.now() - startTime;
|
|
210
|
-
console.log(`[Events Batch] COMPLETED in ${totalDuration}ms - returning events for ${Object.keys(result).length} devices`);
|
|
211
245
|
return IWebResponse.success(result).to_compatible();
|
|
212
246
|
}
|
|
213
247
|
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,58 @@ 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
|
-
|
|
65
|
+
// CRITICAL: Check for UUIDs being passed instead of device IDs
|
|
66
|
+
const invalidDeviceIds = device_ids.filter((id) => !/^\d+$/.test(id));
|
|
67
|
+
if (invalidDeviceIds.length > 0) {
|
|
68
|
+
console.error(`[CRITICAL] UUIDs detected in HerdModule:`, invalidDeviceIds);
|
|
69
|
+
console.error(`[CRITICAL] Device objects:`, new_devices.map((d) => ({ id: d.id, created_by: d.created_by })));
|
|
70
|
+
// Filter out invalid IDs
|
|
71
|
+
const validDeviceIds = device_ids.filter((id) => /^\d+$/.test(id));
|
|
72
|
+
device_ids.length = 0;
|
|
73
|
+
device_ids.push(...validDeviceIds);
|
|
74
|
+
}
|
|
72
75
|
// Load API keys and events in parallel
|
|
73
|
-
console.log(`[HerdModule] Initiating Promise.all for API keys and events...`);
|
|
74
76
|
const [api_keys_batch, events_response] = await Promise.all([
|
|
75
77
|
server_list_api_keys_batch(device_ids),
|
|
76
78
|
server_get_events_and_tags_for_devices_batch(device_ids, 1),
|
|
77
79
|
]);
|
|
78
|
-
const batchDuration = Date.now() - batchStartTime;
|
|
79
|
-
console.log(`[HerdModule] Parallel batch load completed in ${batchDuration}ms`);
|
|
80
80
|
// Assign API keys to devices
|
|
81
81
|
for (let i = 0; i < new_devices.length; i++) {
|
|
82
82
|
const device_id = new_devices[i].id ?? 0;
|
|
83
83
|
new_devices[i].api_keys_scout = api_keys_batch[device_id] || [];
|
|
84
84
|
}
|
|
85
|
-
console.log(`[HerdModule] API keys loaded for ${Object.keys(api_keys_batch).length} devices`);
|
|
86
85
|
// Process events response
|
|
87
86
|
if (events_response.status === EnumWebResponse.SUCCESS &&
|
|
88
87
|
events_response.data) {
|
|
89
88
|
recent_events_batch = events_response.data;
|
|
90
|
-
console.log(`[HerdModule] Events loaded for ${Object.keys(recent_events_batch).length} devices`);
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
catch (error) {
|
|
94
|
-
console.error(`[HerdModule]
|
|
92
|
+
console.error(`[HerdModule] Batch load error:`, error);
|
|
95
93
|
// Continue without API keys and events
|
|
96
94
|
}
|
|
97
95
|
}
|
|
98
96
|
// Run all remaining requests in parallel with individual error handling
|
|
99
97
|
const [res_zones, res_user_roles, total_event_count, res_plans, res_sessions,] = await Promise.allSettled([
|
|
100
98
|
server_get_more_zones_and_actions_for_herd(herd.id, 0, 10).catch((error) => {
|
|
101
|
-
console.warn(
|
|
99
|
+
console.warn(`[HerdModule] Failed to get zones and actions:`, error);
|
|
102
100
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
103
101
|
}),
|
|
104
102
|
server_get_users_with_herd_access(herd.id).catch((error) => {
|
|
105
|
-
console.warn(
|
|
103
|
+
console.warn(`[HerdModule] Failed to get user roles:`, error);
|
|
106
104
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
107
105
|
}),
|
|
108
106
|
server_get_total_events_by_herd(herd.id, EnumSessionsVisibility.Exclude).catch((error) => {
|
|
109
|
-
console.warn(
|
|
107
|
+
console.warn(`[HerdModule] Failed to get total events count:`, error);
|
|
110
108
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
111
109
|
}),
|
|
112
110
|
server_get_plans_by_herd(herd.id).catch((error) => {
|
|
113
|
-
console.warn(
|
|
111
|
+
console.warn(`[HerdModule] Failed to get plans:`, error);
|
|
114
112
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
115
113
|
}),
|
|
116
114
|
getSessionsByHerdId(client, herd.id).catch((error) => {
|
|
117
|
-
console.warn(
|
|
115
|
+
console.warn(`[HerdModule] Failed to get sessions:`, error);
|
|
118
116
|
return [];
|
|
119
117
|
}),
|
|
120
118
|
]);
|
|
@@ -151,7 +149,7 @@ export class HerdModule {
|
|
|
151
149
|
return new HerdModule(herd, new_devices, [], Date.now(), user_roles, 0, total_events, total_events, newLabels, plans, zones, sessions);
|
|
152
150
|
}
|
|
153
151
|
catch (error) {
|
|
154
|
-
console.error(
|
|
152
|
+
console.error(`[HerdModule] Critical error in HerdModule.from_herd:`, error);
|
|
155
153
|
// Return a minimal but valid HerdModule instance to prevent complete failure
|
|
156
154
|
return new HerdModule(herd, [], [], Date.now());
|
|
157
155
|
}
|