@adventurelabs/scout-core 1.0.80 → 1.0.83

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.
@@ -21,6 +21,7 @@ export type IUserRolePerHerd = Database["public"]["Tables"]["users_roles_per_her
21
21
  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
+ export type IProvider = Database["public"]["Tables"]["providers"]["Row"];
24
25
  export type IEventWithTags = Database["public"]["CompositeTypes"]["event_with_tags"] & {
25
26
  earthranger_url: string | null;
26
27
  file_path: string | null;
@@ -62,3 +63,5 @@ export interface IApiKeyScout {
62
63
  }
63
64
  export type Tag = ITag;
64
65
  export type TagClassName = string;
66
+ export type DeviceInsert = Database["public"]["Tables"]["devices"]["Insert"];
67
+ export type DeviceUpdate = Database["public"]["Tables"]["devices"]["Update"];
@@ -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
- 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[]);
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 { status: EnumWebResponse.ERROR, data: [], msg: error.message };
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 ? 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
  }
@@ -3,7 +3,7 @@ export type Json = string | number | boolean | null | {
3
3
  } | Json[];
4
4
  export type Database = {
5
5
  __InternalSupabase: {
6
- PostgrestVersion: "12.2.12 (cd3cf9e)";
6
+ PostgrestVersion: "13.0.5";
7
7
  };
8
8
  public: {
9
9
  Tables: {
@@ -416,6 +416,41 @@ export type Database = {
416
416
  }
417
417
  ];
418
418
  };
419
+ providers: {
420
+ Row: {
421
+ created_at: string;
422
+ herd_id: number;
423
+ id: number;
424
+ key: string | null;
425
+ source: string;
426
+ type: string;
427
+ };
428
+ Insert: {
429
+ created_at?: string;
430
+ herd_id: number;
431
+ id?: number;
432
+ key?: string | null;
433
+ source: string;
434
+ type: string;
435
+ };
436
+ Update: {
437
+ created_at?: string;
438
+ herd_id?: number;
439
+ id?: number;
440
+ key?: string | null;
441
+ source?: string;
442
+ type?: string;
443
+ };
444
+ Relationships: [
445
+ {
446
+ foreignKeyName: "providers_herd_id_fkey";
447
+ columns: ["herd_id"];
448
+ isOneToOne: false;
449
+ referencedRelation: "herds";
450
+ referencedColumns: ["id"];
451
+ }
452
+ ];
453
+ };
419
454
  sessions: {
420
455
  Row: {
421
456
  altitude_average: number;
@@ -427,9 +462,9 @@ export type Database = {
427
462
  earthranger_url: string | null;
428
463
  id: number;
429
464
  inserted_at: string;
430
- locations: unknown;
465
+ locations: unknown | null;
431
466
  software_version: string;
432
- timestamp_end: string;
467
+ timestamp_end: string | null;
433
468
  timestamp_start: string;
434
469
  velocity_average: number;
435
470
  velocity_max: number;
@@ -445,9 +480,9 @@ export type Database = {
445
480
  earthranger_url?: string | null;
446
481
  id?: number;
447
482
  inserted_at?: string;
448
- locations: unknown;
483
+ locations?: unknown | null;
449
484
  software_version: string;
450
- timestamp_end: string;
485
+ timestamp_end?: string | null;
451
486
  timestamp_start: string;
452
487
  velocity_average: number;
453
488
  velocity_max: number;
@@ -463,9 +498,9 @@ export type Database = {
463
498
  earthranger_url?: string | null;
464
499
  id?: number;
465
500
  inserted_at?: string;
466
- locations?: unknown;
501
+ locations?: unknown | null;
467
502
  software_version?: string;
468
- timestamp_end?: string;
503
+ timestamp_end?: string | null;
469
504
  timestamp_start?: string;
470
505
  velocity_average?: number;
471
506
  velocity_max?: number;
@@ -869,7 +904,7 @@ export type Database = {
869
904
  device_type: "trail_camera" | "drone_fixed_wing" | "drone_quad" | "gps_tracker" | "sentry_tower" | "smart_buoy" | "radio_mesh_base_station" | "radio_mesh_repeater" | "unknown";
870
905
  media_type: "image" | "video" | "audio" | "text";
871
906
  plan_type: "mission" | "fence" | "rally" | "markov";
872
- role: "admin" | "viewer" | "editor";
907
+ role: "admin" | "viewer" | "editor" | "operator";
873
908
  tag_observation_type: "manual" | "auto";
874
909
  user_status: "ONLINE" | "OFFLINE";
875
910
  };
@@ -1068,7 +1103,7 @@ export declare const Constants: {
1068
1103
  readonly device_type: readonly ["trail_camera", "drone_fixed_wing", "drone_quad", "gps_tracker", "sentry_tower", "smart_buoy", "radio_mesh_base_station", "radio_mesh_repeater", "unknown"];
1069
1104
  readonly media_type: readonly ["image", "video", "audio", "text"];
1070
1105
  readonly plan_type: readonly ["mission", "fence", "rally", "markov"];
1071
- readonly role: readonly ["admin", "viewer", "editor"];
1106
+ readonly role: readonly ["admin", "viewer", "editor", "operator"];
1072
1107
  readonly tag_observation_type: readonly ["manual", "auto"];
1073
1108
  readonly user_status: readonly ["ONLINE", "OFFLINE"];
1074
1109
  };
@@ -15,7 +15,7 @@ export const Constants = {
15
15
  ],
16
16
  media_type: ["image", "video", "audio", "text"],
17
17
  plan_type: ["mission", "fence", "rally", "markov"],
18
- role: ["admin", "viewer", "editor"],
18
+ role: ["admin", "viewer", "editor", "operator"],
19
19
  tag_observation_type: ["manual", "auto"],
20
20
  user_status: ["ONLINE", "OFFLINE"],
21
21
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adventurelabs/scout-core",
3
- "version": "1.0.80",
3
+ "version": "1.0.83",
4
4
  "description": "Core utilities and helpers for Adventure Labs Scout applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,12 +38,19 @@
38
38
  "react-dom": ">=18.0.0",
39
39
  "react-redux": ">=9.0.0",
40
40
  "@supabase/supabase-js": "^2.57.4",
41
- "@supabase/ssr": "^0.6.1",
41
+ "@supabase/ssr": "^0.7.0",
42
42
  "@reduxjs/toolkit": "^2.0.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/react": "^18.0.0",
46
46
  "@types/react-dom": "^18.0.0",
47
- "typescript": "^5.0.0"
47
+ "typescript": "^5.0.0",
48
+ "next": ">=15.0.0",
49
+ "react": ">=18.0.0",
50
+ "react-dom": ">=18.0.0",
51
+ "react-redux": ">=9.0.0",
52
+ "@supabase/supabase-js": "^2.57.4",
53
+ "@supabase/ssr": "^0.7.0",
54
+ "@reduxjs/toolkit": "^2.0.0"
48
55
  }
49
56
  }
@@ -1,17 +0,0 @@
1
- /**
2
- * Example usage of the ScoutCache system
3
- * This demonstrates how to use the cache-first loading pattern
4
- */
5
- import { CacheStats, TimingStats } from "./cache";
6
- export declare function ExampleBasicUsage(): {
7
- handleRefresh: () => Promise<void>;
8
- clearCache: () => Promise<void>;
9
- stats: () => TimingStats;
10
- cacheStats: () => Promise<CacheStats>;
11
- };
12
- export declare function ExampleAdvancedCacheManagement(): Promise<void>;
13
- export declare function ExampleBackgroundPreloading(): Promise<void>;
14
- export declare function ExamplePerformanceMonitoring(): {
15
- getTimingStats: () => TimingStats;
16
- getCacheStats: () => Promise<CacheStats>;
17
- };
@@ -1,82 +0,0 @@
1
- /**
2
- * Example usage of the ScoutCache system
3
- * This demonstrates how to use the cache-first loading pattern
4
- */
5
- import { useScoutRefresh } from "../hooks/useScoutRefresh";
6
- import { scoutCache } from "./cache";
7
- // Example 1: Basic usage with cache-first loading
8
- export function ExampleBasicUsage() {
9
- const { handleRefresh, getTimingStats, clearCache, getCacheStats } = useScoutRefresh({
10
- autoRefresh: true,
11
- cacheFirst: true,
12
- cacheTtlMs: 10 * 60 * 1000, // 10 minutes
13
- onRefreshComplete: () => {
14
- console.log("Refresh completed!");
15
- }
16
- });
17
- // Get timing stats
18
- const stats = getTimingStats();
19
- console.log("Performance stats:", stats);
20
- // Get cache stats
21
- const cacheStats = getCacheStats();
22
- console.log("Cache stats:", cacheStats);
23
- return {
24
- handleRefresh,
25
- clearCache,
26
- stats: getTimingStats,
27
- cacheStats: getCacheStats,
28
- };
29
- }
30
- // Example 2: Advanced cache management
31
- export async function ExampleAdvancedCacheManagement() {
32
- // Check if cache is valid
33
- const isValid = await scoutCache.isCacheValid(5 * 60 * 1000); // 5 minutes
34
- console.log("Cache is valid:", isValid);
35
- // Check if we should refresh
36
- const shouldRefresh = await scoutCache.shouldRefresh(2 * 60 * 1000, // max age 2 minutes
37
- false // not forcing refresh
38
- );
39
- console.log("Should refresh:", shouldRefresh);
40
- // Get cache age
41
- const age = await scoutCache.getCacheAge();
42
- console.log("Cache age:", Math.round(age / 1000), "seconds");
43
- // Invalidate cache
44
- await scoutCache.invalidateHerdModules();
45
- console.log("Cache invalidated");
46
- // Clear all cache data
47
- await scoutCache.clearHerdModules();
48
- console.log("Cache cleared");
49
- }
50
- // Example 3: Background preloading
51
- export async function ExampleBackgroundPreloading() {
52
- // Simulate a function that loads herd modules
53
- const loadHerdModules = async () => {
54
- // This would be your actual API call
55
- const response = await fetch("/api/herd-modules");
56
- return response.json();
57
- };
58
- // Preload cache in background
59
- await scoutCache.preloadCache(loadHerdModules, 15 * 60 * 1000); // 15 minutes TTL
60
- console.log("Background preload completed");
61
- }
62
- // Example 4: Performance monitoring
63
- export function ExamplePerformanceMonitoring() {
64
- const { getTimingStats, getCacheStats } = useScoutRefresh({
65
- cacheFirst: true,
66
- onRefreshComplete: async () => {
67
- const stats = getTimingStats();
68
- const cacheStats = await getCacheStats();
69
- console.log("=== Performance Report ===");
70
- console.log("Total duration:", stats.totalDuration, "ms");
71
- console.log("Cache load:", stats.cacheLoad, "ms");
72
- console.log("API calls:", stats.herdModulesApi + stats.userApi, "ms");
73
- console.log("Cache save:", stats.cacheSave, "ms");
74
- console.log("Data processing:", stats.dataProcessing, "ms");
75
- console.log("LocalStorage:", stats.localStorage, "ms");
76
- console.log("Cache hit rate:", (cacheStats.hitRate * 100).toFixed(1) + "%");
77
- console.log("Cache size:", cacheStats.size, "herd modules");
78
- console.log("Cache age:", Math.round((Date.now() - cacheStats.lastUpdated) / 1000), "seconds");
79
- }
80
- });
81
- return { getTimingStats, getCacheStats };
82
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Example components demonstrating how to use data source tracking
3
- */
4
- export declare function DataSourceIndicator(): import("react/jsx-runtime").JSX.Element;
5
- export declare function ConditionalContent(): import("react/jsx-runtime").JSX.Element;
6
- export declare function PerformanceMetrics(): import("react/jsx-runtime").JSX.Element;
7
- export declare function SmartRefreshButton(): import("react/jsx-runtime").JSX.Element;
8
- export declare function HeaderWithDataSource(): import("react/jsx-runtime").JSX.Element;
9
- export declare function DataSourceDebugger(): import("react/jsx-runtime").JSX.Element;
@@ -1,68 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useDataSource, useDataSourceDescription } from './useDataSource';
3
- import { useScoutRefresh } from './useScoutRefresh';
4
- // Example 1: Basic data source display
5
- export function DataSourceIndicator() {
6
- const { dataSource, isFromCache, cacheAge, isStale } = useDataSource();
7
- const description = useDataSourceDescription();
8
- return (_jsxs("div", { className: "data-source-indicator", children: [_jsx("div", { className: `source-badge ${dataSource.toLowerCase()}`, children: dataSource }), _jsxs("div", { className: "source-details", children: [_jsx("p", { children: description }), isFromCache && (_jsxs("div", { className: "cache-info", children: [_jsxs("span", { children: ["Cache age: ", Math.round(cacheAge / 1000), "s"] }), _jsx("span", { className: isStale ? 'stale' : 'fresh', children: isStale ? 'Stale' : 'Fresh' })] }))] })] }));
9
- }
10
- // Example 2: Conditional rendering based on data source
11
- export function ConditionalContent() {
12
- const { isFromCache, isFromDatabase, isStale } = useDataSource();
13
- return (_jsxs("div", { children: [isFromCache && (_jsx("div", { className: "cache-notice", children: isStale ? (_jsx("p", { children: "\u26A0\uFE0F Showing cached data (may be outdated)" })) : (_jsx("p", { children: "\u2705 Showing fresh cached data" })) })), isFromDatabase && (_jsx("div", { className: "database-notice", children: _jsx("p", { children: "\uD83D\uDD04 Showing live data from database" }) }))] }));
14
- }
15
- // Example 3: Performance metrics with data source
16
- export function PerformanceMetrics() {
17
- const { dataSource, cacheAge } = useDataSource();
18
- const { getTimingStats, getCacheStats } = useScoutRefresh();
19
- const handleShowMetrics = () => {
20
- const timing = getTimingStats();
21
- console.log('Performance Metrics:', {
22
- dataSource,
23
- cacheAge: cacheAge ? Math.round(cacheAge / 1000) : 'N/A',
24
- totalDuration: timing.totalDuration,
25
- cacheLoad: timing.cacheLoad,
26
- apiCalls: timing.herdModulesApi + timing.userApi,
27
- });
28
- };
29
- return (_jsxs("div", { className: "performance-metrics", children: [_jsx("h3", { children: "Performance Metrics" }), _jsxs("p", { children: ["Data Source: ", dataSource] }), cacheAge && _jsxs("p", { children: ["Cache Age: ", Math.round(cacheAge / 1000), "s"] }), _jsx("button", { onClick: handleShowMetrics, children: "Show Detailed Metrics" })] }));
30
- }
31
- // Example 4: Data source aware refresh button
32
- export function SmartRefreshButton() {
33
- const { isFromCache, isStale, cacheAge } = useDataSource();
34
- const { handleRefresh } = useScoutRefresh();
35
- const getButtonText = () => {
36
- if (isFromCache) {
37
- if (isStale) {
38
- return 'Refresh Stale Data';
39
- }
40
- else {
41
- const ageSeconds = Math.round(cacheAge / 1000);
42
- return `Refresh (${ageSeconds}s old)`;
43
- }
44
- }
45
- return 'Refresh Data';
46
- };
47
- const getButtonStyle = () => {
48
- if (isFromCache && isStale) {
49
- return 'refresh-button stale';
50
- }
51
- else if (isFromCache) {
52
- return 'refresh-button cached';
53
- }
54
- return 'refresh-button fresh';
55
- };
56
- return (_jsx("button", { className: getButtonStyle(), onClick: handleRefresh, children: getButtonText() }));
57
- }
58
- // Example 5: Data source status in header
59
- export function HeaderWithDataSource() {
60
- const description = useDataSourceDescription();
61
- const { handleRefresh } = useScoutRefresh();
62
- return (_jsxs("header", { className: "app-header", children: [_jsx("h1", { children: "Scout Dashboard" }), _jsxs("div", { className: "header-controls", children: [_jsx("span", { className: "data-source-status", children: description }), _jsx("button", { onClick: handleRefresh, children: "Refresh" })] })] }));
63
- }
64
- // Example 6: Data source debugging component
65
- export function DataSourceDebugger() {
66
- const { dataSource, dataSourceInfo, isFromCache, isFromDatabase, isUnknown } = useDataSource();
67
- return (_jsxs("div", { className: "data-source-debugger", children: [_jsx("h3", { children: "Data Source Debug Info" }), _jsxs("div", { className: "debug-info", children: [_jsxs("p", { children: [_jsx("strong", { children: "Source:" }), " ", dataSource] }), _jsxs("p", { children: [_jsx("strong", { children: "From Cache:" }), " ", isFromCache ? 'Yes' : 'No'] }), _jsxs("p", { children: [_jsx("strong", { children: "From Database:" }), " ", isFromDatabase ? 'Yes' : 'No'] }), _jsxs("p", { children: [_jsx("strong", { children: "Unknown:" }), " ", isUnknown ? 'Yes' : 'No'] }), dataSourceInfo && (_jsxs("div", { className: "detailed-info", children: [_jsxs("p", { children: [_jsx("strong", { children: "Timestamp:" }), " ", new Date(dataSourceInfo.timestamp).toISOString()] }), dataSourceInfo.cacheAge && (_jsxs("p", { children: [_jsx("strong", { children: "Cache Age:" }), " ", Math.round(dataSourceInfo.cacheAge / 1000), "s"] })), typeof dataSourceInfo.isStale === 'boolean' && (_jsxs("p", { children: [_jsx("strong", { children: "Is Stale:" }), " ", dataSourceInfo.isStale ? 'Yes' : 'No'] }))] }))] })] }));
68
- }
@@ -1,43 +0,0 @@
1
- import { EnumDataSource, IDataSourceInfo } from "../types/data_source";
2
- /**
3
- * Hook to access data source information from the Redux store
4
- *
5
- * @returns Object containing:
6
- * - dataSource: The current data source (CACHE, DATABASE, or UNKNOWN)
7
- * - dataSourceInfo: Detailed information about the data source
8
- * - isFromCache: Boolean indicating if data is from cache
9
- * - isFromDatabase: Boolean indicating if data is from database
10
- * - cacheAge: Age of cached data in milliseconds (if from cache)
11
- * - isStale: Whether cached data is stale (if from cache)
12
- *
13
- * @example
14
- * ```tsx
15
- * function MyComponent() {
16
- * const { dataSource, isFromCache, cacheAge, isStale } = useDataSource();
17
- *
18
- * return (
19
- * <div>
20
- * <p>Data source: {dataSource}</p>
21
- * {isFromCache && (
22
- * <p>Cache age: {Math.round(cacheAge! / 1000)}s, Stale: {isStale ? 'Yes' : 'No'}</p>
23
- * )}
24
- * </div>
25
- * );
26
- * }
27
- * ```
28
- */
29
- export declare function useDataSource(): {
30
- dataSource: EnumDataSource;
31
- dataSourceInfo: IDataSourceInfo | null;
32
- isFromCache: boolean;
33
- isFromDatabase: boolean;
34
- isUnknown: boolean;
35
- cacheAge: number | undefined;
36
- isStale: boolean | undefined;
37
- };
38
- /**
39
- * Hook to get a human-readable description of the data source
40
- *
41
- * @returns String description of the current data source
42
- */
43
- export declare function useDataSourceDescription(): string;
@@ -1,63 +0,0 @@
1
- import { useSelector } from "react-redux";
2
- import { EnumDataSource } from "../types/data_source";
3
- /**
4
- * Hook to access data source information from the Redux store
5
- *
6
- * @returns Object containing:
7
- * - dataSource: The current data source (CACHE, DATABASE, or UNKNOWN)
8
- * - dataSourceInfo: Detailed information about the data source
9
- * - isFromCache: Boolean indicating if data is from cache
10
- * - isFromDatabase: Boolean indicating if data is from database
11
- * - cacheAge: Age of cached data in milliseconds (if from cache)
12
- * - isStale: Whether cached data is stale (if from cache)
13
- *
14
- * @example
15
- * ```tsx
16
- * function MyComponent() {
17
- * const { dataSource, isFromCache, cacheAge, isStale } = useDataSource();
18
- *
19
- * return (
20
- * <div>
21
- * <p>Data source: {dataSource}</p>
22
- * {isFromCache && (
23
- * <p>Cache age: {Math.round(cacheAge! / 1000)}s, Stale: {isStale ? 'Yes' : 'No'}</p>
24
- * )}
25
- * </div>
26
- * );
27
- * }
28
- * ```
29
- */
30
- export function useDataSource() {
31
- const dataSource = useSelector((state) => state.scout.data_source);
32
- const dataSourceInfo = useSelector((state) => state.scout.data_source_info);
33
- const isFromCache = dataSource === EnumDataSource.CACHE;
34
- const isFromDatabase = dataSource === EnumDataSource.DATABASE;
35
- const isUnknown = dataSource === EnumDataSource.UNKNOWN;
36
- return {
37
- dataSource,
38
- dataSourceInfo,
39
- isFromCache,
40
- isFromDatabase,
41
- isUnknown,
42
- cacheAge: dataSourceInfo?.cacheAge,
43
- isStale: dataSourceInfo?.isStale,
44
- };
45
- }
46
- /**
47
- * Hook to get a human-readable description of the data source
48
- *
49
- * @returns String description of the current data source
50
- */
51
- export function useDataSourceDescription() {
52
- const { dataSource, cacheAge, isStale } = useDataSource();
53
- switch (dataSource) {
54
- case EnumDataSource.CACHE:
55
- const ageSeconds = cacheAge ? Math.round(cacheAge / 1000) : 0;
56
- return `Loaded from cache (${ageSeconds}s old${isStale ? ', stale' : ', fresh'})`;
57
- case EnumDataSource.DATABASE:
58
- return 'Loaded from database (fresh data)';
59
- case EnumDataSource.UNKNOWN:
60
- default:
61
- return 'Data source unknown';
62
- }
63
- }