@adventurelabs/scout-core 1.4.48 → 1.4.49

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.
@@ -1 +1,4 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { Database } from "../types/supabase";
1
3
  export declare function isEmailValidForLogin(email: string, approved_domains?: string[]): boolean;
4
+ export declare function isCurrentUserPlatformSuperadmin(client: SupabaseClient<Database>): Promise<boolean>;
@@ -6,3 +6,11 @@ export function isEmailValidForLogin(email, approved_domains = APPROVED_DOMAINS)
6
6
  function isEmailFromApprovedDomain(email, approved_domains = APPROVED_DOMAINS) {
7
7
  return approved_domains.filter((domain) => email.endsWith(domain)).length > 0;
8
8
  }
9
+ export async function isCurrentUserPlatformSuperadmin(client) {
10
+ const { data, error } = await client.rpc("is_platform_superadmin_current_user");
11
+ if (error) {
12
+ console.warn("[scout-core auth] Failed to check platform superadmin status:", error.message);
13
+ return false;
14
+ }
15
+ return data === true;
16
+ }
@@ -8,5 +8,7 @@ export { useScoutRealtimeSessions } from "./useScoutRealtimeSessions";
8
8
  export { useScoutRealtimePlans } from "./useScoutRealtimePlans";
9
9
  export { useScoutRealtimePins } from "./useScoutRealtimePins";
10
10
  export { useScoutRealtimeParts } from "./useScoutRealtimeParts";
11
+ export { useScoutRealtimeAnalysisJobs } from "./useScoutRealtimeAnalysisJobs";
12
+ export { useScoutRealtimeAnalysisTasks } from "./useScoutRealtimeAnalysisTasks";
11
13
  export { useInfiniteSessionsByHerd, useInfiniteSessionsByDevice, useInfiniteEventsByHerd, useInfiniteEventsByDevice, useInfiniteArtifactsByHerd, useInfiniteArtifactsByDevice, useInfiniteFeedByHerd, useInfiniteFeedByDevice, useInfiniteAnalysisJobs, useInfiniteAnalysisTasks, useIntersectionObserver, type UseInfiniteScrollOptions, type UseAnalysisJobsInfiniteOptions, type UseAnalysisTasksInfiniteOptions, } from "./useInfiniteQuery";
12
14
  export { useLoadingPerformance, useSessionSummariesByHerd, useHasSessionSummaries, } from "../store/hooks";
@@ -8,6 +8,8 @@ export { useScoutRealtimeSessions } from "./useScoutRealtimeSessions";
8
8
  export { useScoutRealtimePlans } from "./useScoutRealtimePlans";
9
9
  export { useScoutRealtimePins } from "./useScoutRealtimePins";
10
10
  export { useScoutRealtimeParts } from "./useScoutRealtimeParts";
11
+ export { useScoutRealtimeAnalysisJobs } from "./useScoutRealtimeAnalysisJobs";
12
+ export { useScoutRealtimeAnalysisTasks } from "./useScoutRealtimeAnalysisTasks";
11
13
  // RTK Query infinite scroll hooks
12
14
  export { useInfiniteSessionsByHerd, useInfiniteSessionsByDevice, useInfiniteEventsByHerd, useInfiniteEventsByDevice, useInfiniteArtifactsByHerd, useInfiniteArtifactsByDevice, useInfiniteFeedByHerd, useInfiniteFeedByDevice, useInfiniteAnalysisJobs, useInfiniteAnalysisTasks, useIntersectionObserver, } from "./useInfiniteQuery";
13
15
  // Session summaries and performance hooks
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { Database } from "../types/supabase";
3
+ import { IAnalysisJob } from "../types/db";
4
+ import { RealtimeData } from "../types/realtime";
5
+ export declare function useScoutRealtimeAnalysisJobs(scoutSupabase: SupabaseClient<Database>): [RealtimeData<IAnalysisJob> | null, () => void];
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { useEffect, useRef, useCallback, useState } from "react";
3
+ import { EnumRealtimeOperation } from "../types/realtime";
4
+ export function useScoutRealtimeAnalysisJobs(scoutSupabase) {
5
+ const channels = useRef([]);
6
+ const [latestJobUpdate, setLatestJobUpdate] = useState(null);
7
+ const handleAnalysisJobBroadcast = useCallback((payload) => {
8
+ const { payload: data } = payload;
9
+ const jobData = data.record || data.old_record;
10
+ if (!jobData) {
11
+ return;
12
+ }
13
+ let operation;
14
+ switch (data.operation) {
15
+ case "INSERT":
16
+ operation = EnumRealtimeOperation.INSERT;
17
+ break;
18
+ case "UPDATE":
19
+ operation = EnumRealtimeOperation.UPDATE;
20
+ break;
21
+ case "DELETE":
22
+ operation = EnumRealtimeOperation.DELETE;
23
+ break;
24
+ default:
25
+ return;
26
+ }
27
+ console.log(`[scout-core realtime] ANALYSIS_JOB ${data.operation} received for job ${jobData.id}:`, JSON.stringify(jobData));
28
+ const realtimeData = {
29
+ data: jobData,
30
+ operation,
31
+ };
32
+ setLatestJobUpdate(realtimeData);
33
+ }, []);
34
+ const clearLatestUpdate = useCallback(() => {
35
+ setLatestJobUpdate(null);
36
+ }, []);
37
+ useEffect(() => {
38
+ if (!scoutSupabase)
39
+ return;
40
+ channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
41
+ channels.current = [];
42
+ clearLatestUpdate();
43
+ const channel = scoutSupabase
44
+ .channel("analysis_jobs_changes", { config: { private: true } })
45
+ .on("broadcast", { event: "*" }, handleAnalysisJobBroadcast)
46
+ .subscribe((status) => {
47
+ if (status === "SUBSCRIBED") {
48
+ console.log("[ANALYSIS_JOBS] ✅ Connected to analysis jobs broadcasts");
49
+ }
50
+ else if (status === "CHANNEL_ERROR") {
51
+ console.warn("[ANALYSIS_JOBS] 🟡 Failed to connect to analysis jobs broadcasts");
52
+ }
53
+ });
54
+ channels.current.push(channel);
55
+ return () => {
56
+ channels.current.forEach((ch) => scoutSupabase.removeChannel(ch));
57
+ channels.current = [];
58
+ };
59
+ }, [scoutSupabase, handleAnalysisJobBroadcast, clearLatestUpdate]);
60
+ return [latestJobUpdate, clearLatestUpdate];
61
+ }
@@ -0,0 +1,5 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { Database } from "../types/supabase";
3
+ import { IAnalysisTask } from "../types/db";
4
+ import { RealtimeData } from "../types/realtime";
5
+ export declare function useScoutRealtimeAnalysisTasks(scoutSupabase: SupabaseClient<Database>): [RealtimeData<IAnalysisTask> | null, () => void];
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { useEffect, useRef, useCallback, useState } from "react";
3
+ import { EnumRealtimeOperation } from "../types/realtime";
4
+ export function useScoutRealtimeAnalysisTasks(scoutSupabase) {
5
+ const channels = useRef([]);
6
+ const [latestTaskUpdate, setLatestTaskUpdate] = useState(null);
7
+ const handleAnalysisTaskBroadcast = useCallback((payload) => {
8
+ const { payload: data } = payload;
9
+ const taskData = data.record || data.old_record;
10
+ if (!taskData) {
11
+ return;
12
+ }
13
+ let operation;
14
+ switch (data.operation) {
15
+ case "INSERT":
16
+ operation = EnumRealtimeOperation.INSERT;
17
+ break;
18
+ case "UPDATE":
19
+ operation = EnumRealtimeOperation.UPDATE;
20
+ break;
21
+ case "DELETE":
22
+ operation = EnumRealtimeOperation.DELETE;
23
+ break;
24
+ default:
25
+ return;
26
+ }
27
+ console.log(`[scout-core realtime] ANALYSIS_TASK ${data.operation} received for task ${taskData.id} (job ${taskData.job_id}):`, JSON.stringify(taskData));
28
+ const realtimeData = {
29
+ data: taskData,
30
+ operation,
31
+ };
32
+ setLatestTaskUpdate(realtimeData);
33
+ }, []);
34
+ const clearLatestUpdate = useCallback(() => {
35
+ setLatestTaskUpdate(null);
36
+ }, []);
37
+ useEffect(() => {
38
+ if (!scoutSupabase)
39
+ return;
40
+ channels.current.forEach((channel) => scoutSupabase.removeChannel(channel));
41
+ channels.current = [];
42
+ clearLatestUpdate();
43
+ const channel = scoutSupabase
44
+ .channel("analysis_tasks_changes", { config: { private: true } })
45
+ .on("broadcast", { event: "*" }, handleAnalysisTaskBroadcast)
46
+ .subscribe((status) => {
47
+ if (status === "SUBSCRIBED") {
48
+ console.log("[ANALYSIS_TASKS] ✅ Connected to analysis tasks broadcasts");
49
+ }
50
+ else if (status === "CHANNEL_ERROR") {
51
+ console.warn("[ANALYSIS_TASKS] 🟡 Failed to connect to analysis tasks broadcasts");
52
+ }
53
+ });
54
+ channels.current.push(channel);
55
+ return () => {
56
+ channels.current.forEach((ch) => scoutSupabase.removeChannel(ch));
57
+ channels.current = [];
58
+ };
59
+ }, [scoutSupabase, handleAnalysisTaskBroadcast, clearLatestUpdate]);
60
+ return [latestTaskUpdate, clearLatestUpdate];
61
+ }
package/dist/index.d.ts CHANGED
@@ -55,6 +55,8 @@ export * from "./hooks/useScoutRealtimeSessions";
55
55
  export * from "./hooks/useScoutRealtimeParts";
56
56
  export * from "./hooks/useScoutRealtimePlans";
57
57
  export * from "./hooks/useScoutRealtimePins";
58
+ export * from "./hooks/useScoutRealtimeAnalysisJobs";
59
+ export * from "./hooks/useScoutRealtimeAnalysisTasks";
58
60
  export * from "./hooks/useScoutRefresh";
59
61
  export * from "./hooks/useInfiniteQuery";
60
62
  export * from "./providers";
package/dist/index.js CHANGED
@@ -59,6 +59,8 @@ export * from "./hooks/useScoutRealtimeSessions";
59
59
  export * from "./hooks/useScoutRealtimeParts";
60
60
  export * from "./hooks/useScoutRealtimePlans";
61
61
  export * from "./hooks/useScoutRealtimePins";
62
+ export * from "./hooks/useScoutRealtimeAnalysisJobs";
63
+ export * from "./hooks/useScoutRealtimeAnalysisTasks";
62
64
  export * from "./hooks/useScoutRefresh";
63
65
  export * from "./hooks/useInfiniteQuery";
64
66
  // Providers
@@ -2620,6 +2620,10 @@ export declare function useSupabase(): SupabaseClient<Database, "public", "publi
2620
2620
  isSetofReturn: true;
2621
2621
  };
2622
2622
  };
2623
+ is_platform_superadmin_current_user: {
2624
+ Args: never;
2625
+ Returns: boolean;
2626
+ };
2623
2627
  load_api_keys: {
2624
2628
  Args: {
2625
2629
  id_of_device: number;
@@ -2705,6 +2705,10 @@ export type Database = {
2705
2705
  isSetofReturn: true;
2706
2706
  };
2707
2707
  };
2708
+ is_platform_superadmin_current_user: {
2709
+ Args: never;
2710
+ Returns: boolean;
2711
+ };
2708
2712
  load_api_keys: {
2709
2713
  Args: {
2710
2714
  id_of_device: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adventurelabs/scout-core",
3
- "version": "1.4.48",
3
+ "version": "1.4.49",
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",