@adventurelabs/scout-core 1.0.79 → 1.0.82

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.
@@ -62,3 +62,5 @@ export interface IApiKeyScout {
62
62
  }
63
63
  export type Tag = ITag;
64
64
  export type TagClassName = string;
65
+ export type DeviceInsert = Database["public"]["Tables"]["devices"]["Insert"];
66
+ export type DeviceUpdate = Database["public"]["Tables"]["devices"]["Update"];
@@ -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: {
@@ -427,9 +427,9 @@ export type Database = {
427
427
  earthranger_url: string | null;
428
428
  id: number;
429
429
  inserted_at: string;
430
- locations: unknown;
430
+ locations: unknown | null;
431
431
  software_version: string;
432
- timestamp_end: string;
432
+ timestamp_end: string | null;
433
433
  timestamp_start: string;
434
434
  velocity_average: number;
435
435
  velocity_max: number;
@@ -445,9 +445,9 @@ export type Database = {
445
445
  earthranger_url?: string | null;
446
446
  id?: number;
447
447
  inserted_at?: string;
448
- locations: unknown;
448
+ locations?: unknown | null;
449
449
  software_version: string;
450
- timestamp_end: string;
450
+ timestamp_end?: string | null;
451
451
  timestamp_start: string;
452
452
  velocity_average: number;
453
453
  velocity_max: number;
@@ -463,9 +463,9 @@ export type Database = {
463
463
  earthranger_url?: string | null;
464
464
  id?: number;
465
465
  inserted_at?: string;
466
- locations?: unknown;
466
+ locations?: unknown | null;
467
467
  software_version?: string;
468
- timestamp_end?: string;
468
+ timestamp_end?: string | null;
469
469
  timestamp_start?: string;
470
470
  velocity_average?: number;
471
471
  velocity_max?: number;
@@ -869,7 +869,7 @@ export type Database = {
869
869
  device_type: "trail_camera" | "drone_fixed_wing" | "drone_quad" | "gps_tracker" | "sentry_tower" | "smart_buoy" | "radio_mesh_base_station" | "radio_mesh_repeater" | "unknown";
870
870
  media_type: "image" | "video" | "audio" | "text";
871
871
  plan_type: "mission" | "fence" | "rally" | "markov";
872
- role: "admin" | "viewer" | "editor";
872
+ role: "admin" | "viewer" | "editor" | "operator";
873
873
  tag_observation_type: "manual" | "auto";
874
874
  user_status: "ONLINE" | "OFFLINE";
875
875
  };
@@ -1068,7 +1068,7 @@ export declare const Constants: {
1068
1068
  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
1069
  readonly media_type: readonly ["image", "video", "audio", "text"];
1070
1070
  readonly plan_type: readonly ["mission", "fence", "rally", "markov"];
1071
- readonly role: readonly ["admin", "viewer", "editor"];
1071
+ readonly role: readonly ["admin", "viewer", "editor", "operator"];
1072
1072
  readonly tag_observation_type: readonly ["manual", "auto"];
1073
1073
  readonly user_status: readonly ["ONLINE", "OFFLINE"];
1074
1074
  };
@@ -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.79",
3
+ "version": "1.0.82",
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
- }