@aidex/admin-react
v1.0.1
Published
Aidex Admin React adapter — useAdmin(controller) plus a small set of headless, unstyled Admin components (AdminOverview, AIControl, ConnectionList, ObservabilitySummary) over @aidex/admin's AdminController. No business logic — React is the entire concern
Readme
@aidex/admin-react
Installation
pnpm add @aidex/admin-react @aidex/admin reactnpm install @aidex/admin-react @aidex/admin reactA single hook, useAdmin(controller), adapting @aidex/admin's
AdminController to React. No business logic lives here — every read and
command still goes through the same AdminController your application
already constructed; this package only translates its existing
subscribe()/getSnapshot() into React's external-store contract via
useSyncExternalStore.
Usage
import { AdminController } from '@aidex/admin';
import { useAdmin } from '@aidex/admin-react';
// 1. Create/configure AdminController exactly as in @aidex/admin's own
// docs — the same connectionManager/aiControl instances your app
// already wired into Aidex.
const admin = new AdminController({ connectionManager, aiControl, observability });
function AdminPanel() {
// 2. Pass it to useAdmin(controller)
const snapshot = useAdmin(admin);
// 3. Read the snapshot
return (
<div>
<p>Health: {snapshot.health}</p>
<p>AI enabled: {String(snapshot.aiControl.enabled)}</p>
<p>Connections: {snapshot.connections.length}</p>
{/* 4. Continue using controller commands directly — no wrapped
command API, no dispatch layer. */}
<button onClick={() => admin.setAIEnabled(!snapshot.aiControl.enabled)}>
Toggle AI
</button>
</div>
);
}Design notes
- No
AdminProvider, no React Context.adminis passed touseAdminas a plain argument, the same way you'd pass any object to a hook — there is no ambient/global Admin state to provide.AdminControlleritself remains the single source of truth; this hook never caches or copies its state. - Pass the same
controllerreference across renders (construct it once — module scope, a ref, oruseMemo) so the subscription stays stable; a newcontrolleridentity on every render would resubscribe on every render, which is correct behavior for "the controller actually changed" but wasteful if unintended. - SSR-safe.
AdminController.getSnapshot()is a synchronous in-memory read with nowindow/documentaccess, so the hook's server snapshot is identical to its client one — no hydration mismatch, no extra code. - New
AdminSnapshotfields need no adapter change.useAdmin()hands back the whole snapshot generically —snapshot.providers(capability discovery) andsnapshot.executions(requested-vs-actual, tokens, cost, duration, success/error) are already available with zero changes to this package. See@aidex/admin's own README for their shape.
