// Main app: backend data loading + layout + page routing.
const { useState, useReducer, useEffect, useCallback } = React;
const { ToastProvider, useToast } = window.UI;
const EMPTY_TRAFFIC = {
metrics: {},
requests: [],
series: Array.from({ length: 60 }, (_, t) => ({ t, total: 0, success: 0, errors: 0, p95: 0 })),
};
function emptyState() {
return {
pools: [],
fingerprints: [],
regionGroups: [],
traffic: EMPTY_TRAFFIC,
stats: null,
auth: window.PG_API.getTokenMeta(),
loading: true,
booted: false,
authRequired: false,
error: "",
};
}
function rebuildRegionGroups(pools) {
return window.PG.buildRegionGroups(pools || []);
}
function reducer(state, action) {
switch (action.type) {
case "setData":
return {
...state,
...action.data,
regionGroups: action.data.regionGroups || rebuildRegionGroups(action.data.pools),
loading: false,
booted: true,
authRequired: false,
error: "",
};
case "setTraffic":
return { ...state, traffic: action.traffic || EMPTY_TRAFFIC };
case "setLoading":
return { ...state, loading: action.loading, error: action.error || state.error };
case "setError":
return { ...state, loading: false, error: action.error || "" };
case "setAuthRequired":
return {
...state,
loading: false,
authRequired: true,
auth: null,
error: action.error || "",
};
case "setLoggedOut":
return { ...emptyState(), loading: false, authRequired: true };
case "toggleNodeLocal": {
const pools = state.pools.map(p => ({
...p,
nodes: (p.nodes || []).map(n => n.id === action.id ? { ...n, enabled: action.enabled } : n),
}));
return { ...state, pools, regionGroups: rebuildRegionGroups(pools) };
}
case "togglePoolLocal": {
const pools = state.pools.map(p => p.name === action.name ? { ...p, enabled: action.enabled } : p);
return { ...state, pools, regionGroups: rebuildRegionGroups(pools) };
}
default:
return state;
}
}
function findPool(pools, name) {
return (pools || []).find(p => p.name === name);
}
function findNodeById(pools, id) {
for (const pool of pools || []) {
for (const node of pool.nodes || []) {
if (node.id === id) return { pool, node };
}
}
return null;
}
const NAV = [
{ id: "overview", label: "Overview", icon: "dashboard" },
{ id: "egress", label: "Egress", icon: "globe" },
{ id: "subscriptions", label: "Subscriptions", icon: "rss" },
{ id: "templates", label: "Templates", icon: "tpl" },
{ id: "tls", label: "TLS Profiles", icon: "shield" },
{ id: "traffic", label: "Traffic", icon: "activity" },
{ id: "system", label: "System", icon: "cog" },
];
function pageFromPath(pathname) {
const slug = String(pathname || "/").replace(/^\/+|\/+$/g, "");
if (!slug || slug === "login") return slug === "login" ? null : "overview";
return NAV.some(item => item.id === slug) ? slug : "overview";
}
function pathForPage(page) {
return page === "overview" ? "/" : `/${page}`;
}
function replacePath(path) {
if (window.location.pathname !== path) {
window.history.replaceState({}, "", path);
}
}
function Sidebar({ page, setPage, state }) {
const counts = {
egress: state.pools.flatMap(p => p.nodes || []).length,
subscriptions: state.pools.filter(p => p.source === "subscription").length,
templates: state.pools.filter(p => p.source === "template").length,
tls: state.fingerprints.length,
traffic: state.traffic.requests.length,
};
return (
Console
{NAV.map(n => {
const Icon = window.Ic[n.icon];
return (
setPage(n.id)}>
{n.label}
{counts[n.id] != null && {counts[n.id]}}
);
})}
Admin API
{state.error ? "attention required" : "connected"}
);
}
function fmtToken(seconds) {
if (!seconds) return "JWT";
if (seconds < 60) return `JWT · ${seconds}s`;
if (seconds < 3600) return `JWT · ${Math.round(seconds / 60)}m`;
return `JWT · ${Math.round(seconds / 3600)}h`;
}
function Topbar({ page, state, onRefresh, onLogout, busy }) {
const label = NAV.find(n => n.id === page)?.label || "";
return (
Console/
{label}
/api/{page === "overview" ? "stats" : page}
AD
admin
{fmtToken(state.auth?.seconds)}
);
}
function ShellMessage({ title, message, action }) {
return (
{title}
{message &&
{message}
}
{action}
);
}
function LoginScreen({ onLogin, error }) {
const [password, setPassword] = useState("");
const [busy, setBusy] = useState(false);
const [localError, setLocalError] = useState("");
const submit = async (event) => {
event.preventDefault();
setBusy(true);
setLocalError("");
const ok = await onLogin(password);
if (!ok) setLocalError("Login failed");
setBusy(false);
};
return (
);
}
function App() {
const [state, baseDispatch] = useReducer(reducer, null, emptyState);
const [page, setPageState] = useState(() => pageFromPath(window.location.pathname) || "overview");
const [trafficLimit, setTrafficLimit] = useState(200);
const [busy, setBusy] = useState(false);
const toast = useToast();
const setPage = useCallback((nextPage) => {
setPageState(nextPage);
const nextPath = pathForPage(nextPage);
if (window.location.pathname !== nextPath) {
window.history.pushState({ page: nextPage }, "", nextPath);
}
}, []);
const refreshData = useCallback(async (quiet = true) => {
try {
const next = await window.PG_API.loadState({ trafficLimit });
baseDispatch({ type: "setData", data: next });
if (!quiet) toast("Data refreshed");
return next;
} catch (err) {
if (err.authRequired || err.status === 401) {
baseDispatch({ type: "setAuthRequired", error: err.message });
} else {
baseDispatch({ type: "setError", error: err.message });
}
return null;
}
}, [toast, trafficLimit]);
useEffect(() => {
refreshData(true);
}, [refreshData]);
useEffect(() => {
const onPopState = () => {
const nextPage = pageFromPath(window.location.pathname);
if (nextPage) setPageState(nextPage);
};
window.addEventListener("popstate", onPopState);
return () => window.removeEventListener("popstate", onPopState);
}, []);
useEffect(() => {
if (state.authRequired || !state.booted) return undefined;
const timer = setInterval(() => refreshData(true), 10000);
return () => clearInterval(timer);
}, [state.authRequired, state.booted, refreshData]);
useEffect(() => {
if (state.authRequired) {
replacePath("/login");
return;
}
if (state.booted && window.location.pathname === "/login") {
replacePath(pathForPage(page));
}
}, [state.authRequired, state.booted, page]);
const dispatch = useCallback(async (action) => {
const api = window.PG_API;
setBusy(true);
try {
switch (action.type) {
case "refreshData":
return await refreshData(false);
case "toggleNode": {
const found = findNodeById(state.pools, action.id);
if (!found) throw new Error("node not found");
const enabled = !found.node.enabled;
baseDispatch({ type: "toggleNodeLocal", id: action.id, enabled });
const result = await api.setNodeEnabled({ pool: found.pool.name, node: found.node.name, enabled });
await refreshData(true);
toast(enabled ? `Enabled ${found.node.name}` : `Disabled ${found.node.name}`);
return result;
}
case "togglePool": {
const pool = findPool(state.pools, action.name);
if (!pool) throw new Error("pool not found");
const enabled = !pool.enabled;
baseDispatch({ type: "togglePoolLocal", name: action.name, enabled });
const result = await api.setPoolEnabled(pool, enabled);
await refreshData(true);
toast(enabled ? `Enabled ${pool.name}` : `Disabled ${pool.name}`);
return result;
}
case "addStaticNode": {
const pool = findPool(state.pools, action.pool);
if (!pool) throw new Error("static pool not found");
const result = await api.addStaticNode(pool, action.node);
await refreshData(true);
toast(`Added ${action.node.name}`);
return result;
}
case "deleteNode": {
const result = await api.deleteNode({ pool: action.pool, node: action.node });
await refreshData(true);
toast(`Deleted ${action.node}`);
return result;
}
case "refreshSub": {
const result = await api.refreshSubscription(action.name);
await refreshData(true);
toast(`Refreshed ${action.name}`);
return result;
}
case "addPool": {
const result = await api.addPool(action.name, action.config);
await refreshData(true);
toast(`Created ${action.name}`);
return result;
}
case "updatePoolConfig": {
const pool = findPool(state.pools, action.pool);
if (!pool) throw new Error("pool not found");
const result = await api.updatePoolConfig(pool, action.patch, action.newName);
await refreshData(true);
toast(`Saved ${action.newName || action.pool}`);
return result;
}
case "deletePool": {
const result = await api.deletePool(action.pool);
await refreshData(true);
toast(`Deleted ${action.pool}`);
return result;
}
case "updateSubscriptionNode": {
const result = await api.updateSubscriptionNode(action.payload);
await refreshData(true);
toast(`Saved ${action.payload.node}`);
return result;
}
case "updateStaticNode": {
const result = await api.updateStaticNode({
pool: action.pool,
node: action.node,
updatedNode: action.updatedNode,
});
await refreshData(true);
toast(`Saved ${action.updatedNode.name}`);
return result;
}
case "testNode": {
const result = await api.testNode({ pool: action.pool, node: action.node });
await refreshData(true);
return result;
}
case "testTemplate":
return await api.testTemplate({ pool: action.pool, region: action.region, url: action.url });
case "loadMoreTraffic": {
const nextLimit = Math.min(1000, Math.max(200, trafficLimit + 200));
const traffic = await api.getTraffic(nextLimit);
setTrafficLimit(nextLimit);
baseDispatch({ type: "setTraffic", traffic });
return traffic;
}
case "addFingerprint": {
const result = await api.addFingerprint({ name: action.name, config: action.config, configText: action.configText });
await refreshData(true);
toast(`Created ${action.name}`);
return result;
}
case "deleteFingerprint": {
const result = await api.deleteFingerprint(action.name);
await refreshData(true);
toast(`Deleted ${action.name}`);
return result;
}
case "testFingerprint":
return await api.testFingerprint({ fingerprint: action.fingerprint, url: action.url });
case "reload": {
const result = await api.reload();
await refreshData(true);
toast("Config reloaded");
return result;
}
default:
return null;
}
} catch (err) {
if (err.status === 401) {
baseDispatch({ type: "setAuthRequired", error: err.message });
} else {
baseDispatch({ type: "setError", error: err.message });
}
toast(err.message);
await refreshData(true);
return null;
} finally {
setBusy(false);
}
}, [state.pools, trafficLimit, refreshData, toast]);
const login = async (password) => {
try {
await window.PG_API.login(password);
await refreshData(true);
replacePath(pathForPage(page));
toast("Signed in");
return true;
} catch (err) {
baseDispatch({ type: "setAuthRequired", error: err.message });
return false;
}
};
const logout = () => {
window.PG_API.logout();
replacePath("/login");
baseDispatch({ type: "setLoggedOut" });
};
if (state.authRequired) {
return ;
}
if (state.loading && !state.booted) {
return ;
}
if (!state.booted && state.error) {
return refreshData(false)}> Retry} />;
}
return (
dispatch({ type: "refreshData" })} onLogout={logout} busy={busy} />
{state.error && {state.error}
}
{page === "overview" && }
{page === "egress" && }
{page === "subscriptions" && }
{page === "templates" && }
{page === "tls" && }
{page === "traffic" && }
{page === "system" && }
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render();