@adventurelabs/scout-core 1.0.85 → 1.0.87
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/helpers/cache.d.ts +3 -0
- package/dist/helpers/cache.js +84 -39
- package/dist/hooks/useScoutRefresh.d.ts +2 -0
- package/dist/hooks/useScoutRefresh.js +16 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/types/db.d.ts +1 -0
- package/dist/types/herd_module.d.ts +4 -2
- package/dist/types/herd_module.js +23 -6
- package/package.json +1 -1
package/dist/helpers/cache.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface CacheMetadata {
|
|
|
4
4
|
timestamp: number;
|
|
5
5
|
ttl: number;
|
|
6
6
|
version: string;
|
|
7
|
+
dbVersion: number;
|
|
7
8
|
etag?: string;
|
|
8
9
|
lastModified?: number;
|
|
9
10
|
}
|
|
@@ -53,6 +54,8 @@ export declare class ScoutCache {
|
|
|
53
54
|
}>;
|
|
54
55
|
preloadCache(loadFunction: () => Promise<IHerdModule[]>, ttlMs?: number): Promise<void>;
|
|
55
56
|
getDefaultTtl(): number;
|
|
57
|
+
getCurrentDbVersion(): number;
|
|
58
|
+
isCacheVersionCompatible(): Promise<boolean>;
|
|
56
59
|
resetDatabase(): Promise<void>;
|
|
57
60
|
checkDatabaseHealth(): Promise<DatabaseHealth>;
|
|
58
61
|
}
|
package/dist/helpers/cache.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const DB_NAME = "ScoutCache";
|
|
2
|
-
const DB_VERSION =
|
|
2
|
+
const DB_VERSION = 2; // Increment to invalidate old cache versions
|
|
3
3
|
const HERD_MODULES_STORE = "herd_modules";
|
|
4
4
|
const CACHE_METADATA_STORE = "cache_metadata";
|
|
5
5
|
// Default TTL: 24 hours (1 day)
|
|
@@ -28,45 +28,49 @@ export class ScoutCache {
|
|
|
28
28
|
};
|
|
29
29
|
request.onsuccess = () => {
|
|
30
30
|
this.db = request.result;
|
|
31
|
-
// Validate that required object stores exist
|
|
32
|
-
if (!this.validateDatabaseSchema()) {
|
|
33
|
-
console.error("[ScoutCache] Database schema validation failed");
|
|
34
|
-
this.db.close();
|
|
35
|
-
this.db = null;
|
|
36
|
-
this.initPromise = null;
|
|
37
|
-
reject(new Error("Database schema validation failed"));
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
31
|
console.log("[ScoutCache] IndexedDB initialized successfully");
|
|
32
|
+
// Add error handler for runtime database errors
|
|
33
|
+
this.db.onerror = (event) => {
|
|
34
|
+
console.error("[ScoutCache] Database error:", event);
|
|
35
|
+
};
|
|
41
36
|
resolve();
|
|
42
37
|
};
|
|
43
38
|
request.onupgradeneeded = (event) => {
|
|
44
39
|
const db = event.target.result;
|
|
45
40
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
unique: false,
|
|
53
|
-
});
|
|
54
|
-
console.log("[ScoutCache] Created herd_modules object store");
|
|
41
|
+
console.log(`[ScoutCache] Upgrading database to version ${DB_VERSION}`);
|
|
42
|
+
// Remove all existing object stores to ensure clean slate
|
|
43
|
+
const existingStores = Array.from(db.objectStoreNames);
|
|
44
|
+
for (const storeName of existingStores) {
|
|
45
|
+
console.log(`[ScoutCache] Removing existing object store: ${storeName}`);
|
|
46
|
+
db.deleteObjectStore(storeName);
|
|
55
47
|
}
|
|
48
|
+
// Create herd modules store (unified storage for all herd data)
|
|
49
|
+
const herdModulesStore = db.createObjectStore(HERD_MODULES_STORE, {
|
|
50
|
+
keyPath: "herdId",
|
|
51
|
+
});
|
|
52
|
+
herdModulesStore.createIndex("timestamp", "timestamp", {
|
|
53
|
+
unique: false,
|
|
54
|
+
});
|
|
55
|
+
herdModulesStore.createIndex("dbVersion", "dbVersion", {
|
|
56
|
+
unique: false,
|
|
57
|
+
});
|
|
58
|
+
console.log("[ScoutCache] Created herd_modules object store");
|
|
56
59
|
// Create cache metadata store
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
console.log("[ScoutCache] Database schema upgraded");
|
|
60
|
+
const metadataStore = db.createObjectStore(CACHE_METADATA_STORE, {
|
|
61
|
+
keyPath: "key",
|
|
62
|
+
});
|
|
63
|
+
console.log("[ScoutCache] Created cache_metadata object store");
|
|
64
|
+
console.log(`[ScoutCache] Database schema upgrade to version ${DB_VERSION} completed`);
|
|
64
65
|
}
|
|
65
66
|
catch (error) {
|
|
66
67
|
console.error("[ScoutCache] Error during database upgrade:", error);
|
|
67
68
|
reject(error);
|
|
68
69
|
}
|
|
69
70
|
};
|
|
71
|
+
request.onblocked = () => {
|
|
72
|
+
console.warn("[ScoutCache] Database upgrade blocked - other connections may need to be closed");
|
|
73
|
+
};
|
|
70
74
|
});
|
|
71
75
|
return this.initPromise;
|
|
72
76
|
}
|
|
@@ -87,7 +91,6 @@ export class ScoutCache {
|
|
|
87
91
|
await this.init();
|
|
88
92
|
if (!this.db)
|
|
89
93
|
throw new Error("Database not initialized");
|
|
90
|
-
// Validate schema before creating transaction
|
|
91
94
|
if (!this.validateDatabaseSchema()) {
|
|
92
95
|
throw new Error("Database schema validation failed - required object stores not found");
|
|
93
96
|
}
|
|
@@ -98,13 +101,14 @@ export class ScoutCache {
|
|
|
98
101
|
const herdModulesStore = transaction.objectStore(HERD_MODULES_STORE);
|
|
99
102
|
const metadataStore = transaction.objectStore(CACHE_METADATA_STORE);
|
|
100
103
|
const timestamp = Date.now();
|
|
101
|
-
const version = "
|
|
102
|
-
// Store each herd module
|
|
104
|
+
const version = "2.0.0";
|
|
105
|
+
// Store each herd module (contains all nested data - devices, events, zones, etc.)
|
|
103
106
|
herdModules.forEach((herdModule) => {
|
|
104
107
|
const cacheEntry = {
|
|
105
108
|
herdId: herdModule.herd.id.toString(),
|
|
106
109
|
data: herdModule,
|
|
107
110
|
timestamp,
|
|
111
|
+
dbVersion: DB_VERSION,
|
|
108
112
|
};
|
|
109
113
|
herdModulesStore.put(cacheEntry);
|
|
110
114
|
});
|
|
@@ -114,6 +118,7 @@ export class ScoutCache {
|
|
|
114
118
|
timestamp,
|
|
115
119
|
ttl: ttlMs,
|
|
116
120
|
version,
|
|
121
|
+
dbVersion: DB_VERSION,
|
|
117
122
|
etag,
|
|
118
123
|
lastModified: timestamp,
|
|
119
124
|
};
|
|
@@ -124,7 +129,6 @@ export class ScoutCache {
|
|
|
124
129
|
await this.init();
|
|
125
130
|
if (!this.db)
|
|
126
131
|
throw new Error("Database not initialized");
|
|
127
|
-
// Validate schema before creating transaction
|
|
128
132
|
if (!this.validateDatabaseSchema()) {
|
|
129
133
|
throw new Error("Database schema validation failed - required object stores not found");
|
|
130
134
|
}
|
|
@@ -143,6 +147,17 @@ export class ScoutCache {
|
|
|
143
147
|
resolve({ data: null, isStale: true, age: 0, metadata: null });
|
|
144
148
|
return;
|
|
145
149
|
}
|
|
150
|
+
// Check if cache is from an incompatible DB version
|
|
151
|
+
if (!metadata.dbVersion || metadata.dbVersion !== DB_VERSION) {
|
|
152
|
+
console.log(`[ScoutCache] Cache from incompatible DB version (${metadata.dbVersion || "unknown"} !== ${DB_VERSION}), invalidating`);
|
|
153
|
+
this.stats.misses++;
|
|
154
|
+
// Clear old cache asynchronously
|
|
155
|
+
this.clearHerdModules().catch((error) => {
|
|
156
|
+
console.warn("[ScoutCache] Failed to clear old cache:", error);
|
|
157
|
+
});
|
|
158
|
+
resolve({ data: null, isStale: true, age: 0, metadata: null });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
146
161
|
const age = now - metadata.timestamp;
|
|
147
162
|
const isStale = age > metadata.ttl;
|
|
148
163
|
// Get all herd modules
|
|
@@ -150,7 +165,10 @@ export class ScoutCache {
|
|
|
150
165
|
getAllRequest.onsuccess = () => {
|
|
151
166
|
const cacheEntries = getAllRequest.result;
|
|
152
167
|
const herdModules = cacheEntries
|
|
153
|
-
.filter((entry) => entry.data &&
|
|
168
|
+
.filter((entry) => entry.data &&
|
|
169
|
+
entry.data.herd &&
|
|
170
|
+
entry.data.herd.slug &&
|
|
171
|
+
entry.dbVersion === DB_VERSION)
|
|
154
172
|
.map((entry) => entry.data)
|
|
155
173
|
.sort((a, b) => (a.herd?.slug || "").localeCompare(b.herd?.slug || ""));
|
|
156
174
|
// Update stats
|
|
@@ -174,7 +192,6 @@ export class ScoutCache {
|
|
|
174
192
|
await this.init();
|
|
175
193
|
if (!this.db)
|
|
176
194
|
throw new Error("Database not initialized");
|
|
177
|
-
// Validate schema before creating transaction
|
|
178
195
|
if (!this.validateDatabaseSchema()) {
|
|
179
196
|
throw new Error("Database schema validation failed - required object stores not found");
|
|
180
197
|
}
|
|
@@ -192,7 +209,6 @@ export class ScoutCache {
|
|
|
192
209
|
await this.init();
|
|
193
210
|
if (!this.db)
|
|
194
211
|
throw new Error("Database not initialized");
|
|
195
|
-
// Validate schema before creating transaction
|
|
196
212
|
if (!this.validateDatabaseSchema()) {
|
|
197
213
|
throw new Error("Database schema validation failed - required object stores not found");
|
|
198
214
|
}
|
|
@@ -202,6 +218,7 @@ export class ScoutCache {
|
|
|
202
218
|
transaction.oncomplete = () => resolve();
|
|
203
219
|
const metadataStore = transaction.objectStore(CACHE_METADATA_STORE);
|
|
204
220
|
metadataStore.delete("herd_modules");
|
|
221
|
+
metadataStore.delete("providers");
|
|
205
222
|
});
|
|
206
223
|
}
|
|
207
224
|
async getCacheStats() {
|
|
@@ -228,7 +245,6 @@ export class ScoutCache {
|
|
|
228
245
|
const result = await this.getHerdModules();
|
|
229
246
|
return result.age;
|
|
230
247
|
}
|
|
231
|
-
// Method to check if we should refresh based on various conditions
|
|
232
248
|
async shouldRefresh(maxAgeMs, forceRefresh) {
|
|
233
249
|
if (forceRefresh) {
|
|
234
250
|
return { shouldRefresh: true, reason: "Force refresh requested" };
|
|
@@ -237,6 +253,15 @@ export class ScoutCache {
|
|
|
237
253
|
if (!result.data || result.data.length === 0) {
|
|
238
254
|
return { shouldRefresh: true, reason: "No cached data" };
|
|
239
255
|
}
|
|
256
|
+
// Check for DB version mismatch
|
|
257
|
+
if (!result.metadata ||
|
|
258
|
+
!result.metadata.dbVersion ||
|
|
259
|
+
result.metadata.dbVersion !== DB_VERSION) {
|
|
260
|
+
return {
|
|
261
|
+
shouldRefresh: true,
|
|
262
|
+
reason: `Cache from incompatible DB version (${result.metadata?.dbVersion || "unknown"} !== ${DB_VERSION})`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
240
265
|
if (result.isStale) {
|
|
241
266
|
return { shouldRefresh: true, reason: "Cache is stale" };
|
|
242
267
|
}
|
|
@@ -248,7 +273,6 @@ export class ScoutCache {
|
|
|
248
273
|
}
|
|
249
274
|
return { shouldRefresh: false, reason: "Cache is valid and fresh" };
|
|
250
275
|
}
|
|
251
|
-
// Method to preload cache with background refresh
|
|
252
276
|
async preloadCache(loadFunction, ttlMs = DEFAULT_TTL_MS) {
|
|
253
277
|
try {
|
|
254
278
|
console.log("[ScoutCache] Starting background cache preload...");
|
|
@@ -262,11 +286,25 @@ export class ScoutCache {
|
|
|
262
286
|
console.warn("[ScoutCache] Background preload failed:", error);
|
|
263
287
|
}
|
|
264
288
|
}
|
|
265
|
-
// Get the default TTL value
|
|
266
289
|
getDefaultTtl() {
|
|
267
290
|
return DEFAULT_TTL_MS;
|
|
268
291
|
}
|
|
269
|
-
|
|
292
|
+
getCurrentDbVersion() {
|
|
293
|
+
return DB_VERSION;
|
|
294
|
+
}
|
|
295
|
+
async isCacheVersionCompatible() {
|
|
296
|
+
try {
|
|
297
|
+
const result = await this.getHerdModules();
|
|
298
|
+
if (!result.metadata)
|
|
299
|
+
return false;
|
|
300
|
+
return (result.metadata.dbVersion !== undefined &&
|
|
301
|
+
result.metadata.dbVersion === DB_VERSION);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
console.warn("[ScoutCache] Version compatibility check failed:", error);
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
270
308
|
async resetDatabase() {
|
|
271
309
|
console.log("[ScoutCache] Resetting database...");
|
|
272
310
|
// Close existing connection
|
|
@@ -292,7 +330,6 @@ export class ScoutCache {
|
|
|
292
330
|
};
|
|
293
331
|
});
|
|
294
332
|
}
|
|
295
|
-
// Method to check database health
|
|
296
333
|
async checkDatabaseHealth() {
|
|
297
334
|
const issues = [];
|
|
298
335
|
try {
|
|
@@ -304,9 +341,17 @@ export class ScoutCache {
|
|
|
304
341
|
if (!this.validateDatabaseSchema()) {
|
|
305
342
|
issues.push("Database schema validation failed");
|
|
306
343
|
}
|
|
344
|
+
// Check version compatibility
|
|
345
|
+
const isVersionCompatible = await this.isCacheVersionCompatible();
|
|
346
|
+
if (!isVersionCompatible) {
|
|
347
|
+
issues.push(`Cache version incompatible (current: ${DB_VERSION})`);
|
|
348
|
+
}
|
|
307
349
|
// Try a simple read operation
|
|
308
350
|
try {
|
|
309
|
-
await this.getHerdModules();
|
|
351
|
+
const result = await this.getHerdModules();
|
|
352
|
+
if (result.data === null && result.age === 0) {
|
|
353
|
+
// This is expected for empty cache, not an error
|
|
354
|
+
}
|
|
310
355
|
}
|
|
311
356
|
catch (error) {
|
|
312
357
|
issues.push(`Read operation failed: ${error}`);
|
|
@@ -43,4 +43,6 @@ export declare function useScoutRefresh(options?: UseScoutRefreshOptions): {
|
|
|
43
43
|
getCacheStats: () => Promise<CacheStats>;
|
|
44
44
|
checkDatabaseHealth: () => Promise<DatabaseHealth>;
|
|
45
45
|
resetDatabase: () => Promise<void>;
|
|
46
|
+
isCacheVersionCompatible: () => Promise<boolean>;
|
|
47
|
+
getCurrentDbVersion: () => number;
|
|
46
48
|
};
|
|
@@ -412,6 +412,20 @@ export function useScoutRefresh(options = {}) {
|
|
|
412
412
|
throw error;
|
|
413
413
|
}
|
|
414
414
|
}, []);
|
|
415
|
+
// Utility function to check cache version compatibility
|
|
416
|
+
const isCacheVersionCompatible = useCallback(async () => {
|
|
417
|
+
try {
|
|
418
|
+
return await scoutCache.isCacheVersionCompatible();
|
|
419
|
+
}
|
|
420
|
+
catch (error) {
|
|
421
|
+
console.error("[useScoutRefresh] Failed to check cache version compatibility:", error);
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
}, []);
|
|
425
|
+
// Utility function to get current DB version
|
|
426
|
+
const getCurrentDbVersion = useCallback(() => {
|
|
427
|
+
return scoutCache.getCurrentDbVersion();
|
|
428
|
+
}, []);
|
|
415
429
|
return {
|
|
416
430
|
handleRefresh,
|
|
417
431
|
getTimingStats,
|
|
@@ -419,5 +433,7 @@ export function useScoutRefresh(options = {}) {
|
|
|
419
433
|
getCacheStats,
|
|
420
434
|
checkDatabaseHealth,
|
|
421
435
|
resetDatabase,
|
|
436
|
+
isCacheVersionCompatible,
|
|
437
|
+
getCurrentDbVersion,
|
|
422
438
|
};
|
|
423
439
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export * from "./helpers/zones";
|
|
|
31
31
|
export * from "./helpers/storage";
|
|
32
32
|
export * from "./helpers/eventUtils";
|
|
33
33
|
export * from "./helpers/cache";
|
|
34
|
+
export * from "./helpers/heartbeats";
|
|
34
35
|
export * from "./hooks/useScoutDbListener";
|
|
35
36
|
export * from "./hooks/useScoutRefresh";
|
|
36
37
|
export * from "./providers";
|
|
@@ -40,5 +41,5 @@ export * from "./supabase/middleware";
|
|
|
40
41
|
export * from "./supabase/server";
|
|
41
42
|
export * from "./api_keys/actions";
|
|
42
43
|
export type { HerdModule, IHerdModule } from "./types/herd_module";
|
|
43
|
-
export type { IDevice, IEvent, IUser, IHerd, IEventWithTags, IZoneWithActions, IUserAndRole, IApiKeyScout, ILayer, } from "./types/db";
|
|
44
|
+
export type { IDevice, IEvent, IUser, IHerd, IEventWithTags, IZoneWithActions, IUserAndRole, IApiKeyScout, ILayer, IHeartbeat, } from "./types/db";
|
|
44
45
|
export { EnumSessionsVisibility } from "./types/events";
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ export * from "./helpers/zones";
|
|
|
34
34
|
export * from "./helpers/storage";
|
|
35
35
|
export * from "./helpers/eventUtils";
|
|
36
36
|
export * from "./helpers/cache";
|
|
37
|
+
export * from "./helpers/heartbeats";
|
|
37
38
|
// Hooks
|
|
38
39
|
export * from "./hooks/useScoutDbListener";
|
|
39
40
|
export * from "./hooks/useScoutRefresh";
|
package/dist/types/db.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type IHerd = Database["public"]["Tables"]["herds"]["Row"];
|
|
|
22
22
|
export type ISession = Database["public"]["Tables"]["sessions"]["Row"];
|
|
23
23
|
export type IConnectivity = Database["public"]["Tables"]["connectivity"]["Row"];
|
|
24
24
|
export type IHeartbeat = Database["public"]["Tables"]["heartbeats"]["Row"];
|
|
25
|
+
export type IProvider = Database["public"]["Tables"]["providers"]["Row"];
|
|
25
26
|
export type IEventWithTags = Database["public"]["CompositeTypes"]["event_with_tags"] & {
|
|
26
27
|
earthranger_url: string | null;
|
|
27
28
|
file_path: string | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import { IDevice, IEventWithTags, IHerd, IPlan, ILayer, IUserAndRole, IZoneWithActions, ISessionWithCoordinates } from "../types/db";
|
|
2
|
+
import { IDevice, IEventWithTags, IHerd, IPlan, ILayer, IProvider, IUserAndRole, IZoneWithActions, ISessionWithCoordinates } from "../types/db";
|
|
3
3
|
import { EnumWebResponse } from "./requests";
|
|
4
4
|
export declare enum EnumHerdModulesLoadingState {
|
|
5
5
|
NOT_LOADING = "NOT_LOADING",
|
|
@@ -21,7 +21,8 @@ export declare class HerdModule {
|
|
|
21
21
|
labels: string[];
|
|
22
22
|
plans: IPlan[];
|
|
23
23
|
layers: ILayer[];
|
|
24
|
-
|
|
24
|
+
providers: IProvider[];
|
|
25
|
+
constructor(herd: IHerd, devices: IDevice[], events: IEventWithTags[], timestamp_last_refreshed: number, user_roles?: IUserAndRole[] | null, events_page_index?: number, total_events?: number, total_events_with_filters?: number, labels?: string[], plans?: IPlan[], zones?: IZoneWithActions[], sessions?: ISessionWithCoordinates[], layers?: ILayer[], providers?: IProvider[]);
|
|
25
26
|
to_serializable(): IHerdModule;
|
|
26
27
|
static from_herd(herd: IHerd, client: SupabaseClient): Promise<HerdModule>;
|
|
27
28
|
}
|
|
@@ -39,6 +40,7 @@ export interface IHerdModule {
|
|
|
39
40
|
zones: IZoneWithActions[];
|
|
40
41
|
sessions: ISessionWithCoordinates[];
|
|
41
42
|
layers: ILayer[];
|
|
43
|
+
providers: IProvider[];
|
|
42
44
|
}
|
|
43
45
|
export interface IHerdModulesResponse {
|
|
44
46
|
data: IHerdModule[];
|
|
@@ -4,6 +4,7 @@ import { server_get_total_events_by_herd } from "../helpers/events";
|
|
|
4
4
|
import { EnumSessionsVisibility } from "./events";
|
|
5
5
|
import { server_get_plans_by_herd } from "../helpers/plans";
|
|
6
6
|
import { server_get_layers_by_herd } from "../helpers/layers";
|
|
7
|
+
import { server_get_providers_by_herd } from "../helpers/providers";
|
|
7
8
|
import { server_get_events_and_tags_for_devices_batch } from "../helpers/tags";
|
|
8
9
|
import { server_get_users_with_herd_access } from "../helpers/users";
|
|
9
10
|
import { EnumWebResponse } from "./requests";
|
|
@@ -18,7 +19,7 @@ export var EnumHerdModulesLoadingState;
|
|
|
18
19
|
EnumHerdModulesLoadingState["UNSUCCESSFULLY_LOADED"] = "UNSUCCESSFULLY_LOADED";
|
|
19
20
|
})(EnumHerdModulesLoadingState || (EnumHerdModulesLoadingState = {}));
|
|
20
21
|
export class HerdModule {
|
|
21
|
-
constructor(herd, devices, events, timestamp_last_refreshed, user_roles = null, events_page_index = 0, total_events = 0, total_events_with_filters = 0, labels = [], plans = [], zones = [], sessions = [], layers = []) {
|
|
22
|
+
constructor(herd, devices, events, timestamp_last_refreshed, user_roles = null, events_page_index = 0, total_events = 0, total_events_with_filters = 0, labels = [], plans = [], zones = [], sessions = [], layers = [], providers = []) {
|
|
22
23
|
this.user_roles = null;
|
|
23
24
|
this.events_page_index = 0;
|
|
24
25
|
this.total_events = 0;
|
|
@@ -26,6 +27,7 @@ export class HerdModule {
|
|
|
26
27
|
this.labels = [];
|
|
27
28
|
this.plans = [];
|
|
28
29
|
this.layers = [];
|
|
30
|
+
this.providers = [];
|
|
29
31
|
this.herd = herd;
|
|
30
32
|
this.devices = devices;
|
|
31
33
|
this.events = events;
|
|
@@ -39,6 +41,7 @@ export class HerdModule {
|
|
|
39
41
|
this.zones = zones;
|
|
40
42
|
this.sessions = sessions;
|
|
41
43
|
this.layers = layers;
|
|
44
|
+
this.providers = providers;
|
|
42
45
|
}
|
|
43
46
|
to_serializable() {
|
|
44
47
|
return {
|
|
@@ -55,6 +58,7 @@ export class HerdModule {
|
|
|
55
58
|
zones: this.zones,
|
|
56
59
|
sessions: this.sessions,
|
|
57
60
|
layers: this.layers,
|
|
61
|
+
providers: this.providers,
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
64
|
static async from_herd(herd, client) {
|
|
@@ -95,7 +99,7 @@ export class HerdModule {
|
|
|
95
99
|
}
|
|
96
100
|
}
|
|
97
101
|
// Run all remaining requests in parallel with individual error handling
|
|
98
|
-
const [res_zones, res_user_roles, total_event_count, res_plans, res_sessions, res_layers,] = await Promise.allSettled([
|
|
102
|
+
const [res_zones, res_user_roles, total_event_count, res_plans, res_sessions, res_layers, res_providers,] = await Promise.allSettled([
|
|
99
103
|
server_get_more_zones_and_actions_for_herd(herd.id, 0, 10).catch((error) => {
|
|
100
104
|
console.warn(`[HerdModule] Failed to get zones and actions:`, error);
|
|
101
105
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
@@ -114,12 +118,20 @@ export class HerdModule {
|
|
|
114
118
|
}),
|
|
115
119
|
server_get_sessions_by_herd_id(herd.id).catch((error) => {
|
|
116
120
|
console.warn(`[HerdModule] Failed to get sessions:`, error);
|
|
117
|
-
return {
|
|
121
|
+
return {
|
|
122
|
+
status: EnumWebResponse.ERROR,
|
|
123
|
+
data: [],
|
|
124
|
+
msg: error.message,
|
|
125
|
+
};
|
|
118
126
|
}),
|
|
119
127
|
server_get_layers_by_herd(herd.id).catch((error) => {
|
|
120
128
|
console.warn(`[HerdModule] Failed to get layers:`, error);
|
|
121
129
|
return { status: EnumWebResponse.ERROR, data: null };
|
|
122
130
|
}),
|
|
131
|
+
server_get_providers_by_herd(herd.id).catch((error) => {
|
|
132
|
+
console.warn(`[HerdModule] Failed to get providers:`, error);
|
|
133
|
+
return { status: EnumWebResponse.ERROR, data: null };
|
|
134
|
+
}),
|
|
123
135
|
]);
|
|
124
136
|
// Assign recent events to devices from batch results
|
|
125
137
|
for (let i = 0; i < new_devices.length; i++) {
|
|
@@ -148,23 +160,28 @@ export class HerdModule {
|
|
|
148
160
|
const plans = res_plans.status === "fulfilled" && res_plans.value?.data
|
|
149
161
|
? res_plans.value.data
|
|
150
162
|
: [];
|
|
151
|
-
const sessions = res_sessions.status === "fulfilled" && res_sessions.value?.data
|
|
163
|
+
const sessions = res_sessions.status === "fulfilled" && res_sessions.value?.data
|
|
164
|
+
? res_sessions.value.data
|
|
165
|
+
: [];
|
|
152
166
|
const layers = res_layers.status === "fulfilled" && res_layers.value?.data
|
|
153
167
|
? res_layers.value.data
|
|
154
168
|
: [];
|
|
169
|
+
const providers = res_providers.status === "fulfilled" && res_providers.value?.data
|
|
170
|
+
? res_providers.value.data
|
|
171
|
+
: [];
|
|
155
172
|
// TODO: store in DB and retrieve on load?
|
|
156
173
|
const newLabels = LABELS;
|
|
157
174
|
const endTime = Date.now();
|
|
158
175
|
const loadTime = endTime - startTime;
|
|
159
176
|
console.log(`[HerdModule] Loaded herd ${herd.slug} in ${loadTime}ms (${new_devices.length} devices)`);
|
|
160
|
-
return new HerdModule(herd, new_devices, [], Date.now(), user_roles, 0, total_events, total_events, newLabels, plans, zones, sessions, layers);
|
|
177
|
+
return new HerdModule(herd, new_devices, [], Date.now(), user_roles, 0, total_events, total_events, newLabels, plans, zones, sessions, layers, providers);
|
|
161
178
|
}
|
|
162
179
|
catch (error) {
|
|
163
180
|
const endTime = Date.now();
|
|
164
181
|
const loadTime = endTime - startTime;
|
|
165
182
|
console.error(`[HerdModule] Critical error in HerdModule.from_herd (${loadTime}ms):`, error);
|
|
166
183
|
// Return a minimal but valid HerdModule instance to prevent complete failure
|
|
167
|
-
return new HerdModule(herd, [], [], Date.now(), null, 0, 0, 0, [], [], [], [], []);
|
|
184
|
+
return new HerdModule(herd, [], [], Date.now(), null, 0, 0, 0, [], [], [], [], [], []);
|
|
168
185
|
}
|
|
169
186
|
}
|
|
170
187
|
}
|