This repository was archived by the owner on Mar 24, 2026. It is now read-only.
forked from Synapsr/Vexa-Dashboard
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathuse-runtime-config.ts
More file actions
109 lines (96 loc) · 2.8 KB
/
use-runtime-config.ts
File metadata and controls
109 lines (96 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"use client";
import { useState, useEffect } from "react";
interface RuntimeConfig {
wsUrl: string;
apiUrl: string;
decisionListenerUrl: string;
defaultBotName: string | null;
}
// Global cache to avoid refetching on every component mount
let cachedConfig: RuntimeConfig | null = null;
let configPromise: Promise<RuntimeConfig> | null = null;
async function fetchConfig(): Promise<RuntimeConfig> {
const response = await fetch("/api/config");
if (!response.ok) {
throw new Error("Failed to fetch runtime config");
}
return response.json();
}
/**
* Hook to get runtime configuration (WebSocket URL, etc.)
* This solves the Next.js limitation where NEXT_PUBLIC_* vars are only available at build time.
*/
export function useRuntimeConfig() {
const [config, setConfig] = useState<RuntimeConfig | null>(cachedConfig);
const [isLoading, setIsLoading] = useState(!cachedConfig);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (cachedConfig) {
setConfig(cachedConfig);
setIsLoading(false);
return;
}
if (!configPromise) {
configPromise = fetchConfig();
}
configPromise
.then((cfg) => {
cachedConfig = cfg;
setConfig(cfg);
setIsLoading(false);
})
.catch((err) => {
setError(err.message);
setIsLoading(false);
// Reset promise to allow retry
configPromise = null;
});
}, []);
return { config, isLoading, error };
}
/**
* Get the WebSocket URL synchronously (returns cached value or fallback)
* For use in non-hook contexts or when you need immediate access
*/
export function getWsUrl(): string {
if (cachedConfig) {
return cachedConfig.wsUrl;
}
// Fallback to default (runtime config should always be available)
return "ws://localhost:18056/ws";
}
/**
* Get the decision listener URL synchronously (returns cached value or fallback)
* For use in non-hook contexts or when you need immediate access
*/
export function getDecisionListenerUrl(): string {
if (cachedConfig?.decisionListenerUrl) {
return cachedConfig.decisionListenerUrl;
}
// Fallback to default
return "http://localhost:8765";
}
/**
* Get the default bot name synchronously (returns cached value or fallback)
* For use in non-hook contexts or when you need immediate access
*/
export function getDefaultBotName(): string {
if (cachedConfig?.defaultBotName) {
return cachedConfig.defaultBotName;
}
// Fallback to default
return "Vexa - Open Source Bot";
}
/**
* Prefetch config - call this early in app initialization
*/
export async function prefetchConfig(): Promise<RuntimeConfig> {
if (cachedConfig) {
return cachedConfig;
}
if (!configPromise) {
configPromise = fetchConfig();
}
cachedConfig = await configPromise;
return cachedConfig;
}