Get Started with EdgeStream

EdgeStream is a pure TypeScript library with zero external runtime dependencies. Install the core package, create an EdgeStream instance, connect to your SignalR hub, and start publishing and subscribing in under ten minutes.

Installation

1
Install the core package

The main edge-stream-js package is the foundation. Add observability and React packages as needed.

pnpm add edge-stream-js # Optional: observability pnpm add @edge-stream/observability-core pnpm add @edge-stream/observability-hooks-js # Optional: React integration pnpm add @edge-stream/react-hooks
2
Add the React Native package (mobile only)

For React Native applications, install the mobile-specific adapter. The same API surface as the web package — only the transport layer differs.

pnpm add edge-stream-js-react-native

Create and connect

3
Initialise EdgeStream with a SignalR server

EdgeStream is the main facade. Pass it a HubServer configured with your SignalR endpoint. Start the connection — EdgeStream manages reconnection automatically.

import { EdgeStream, HubServer } from 'edge-stream-js'; // 1. Create the server adapter const server = new HubServer({ url: 'https://your-api.example.com/chat-hub', reconnect: true, reconnectIntervals: [0, 2000, 5000, 10000] }); // 2. Create EdgeStream and register the server const edgeStream = new EdgeStream(); edgeStream.registerServer(server); // 3. Start the connection await edgeStream.start(); console.log('EdgeStream connected');
EdgeStream supports multiple concurrent servers. Register a WebSocketServer alongside a HubServer and EdgeStream manages both connections independently.
4
Listen for connection events

EdgeStream emits lifecycle events for connection state changes, reconnections, and errors. Subscribe to stay in sync with the connection.

edgeStream.on('connected', () => { console.log('Connected to EdgeStream hub'); updateUI({ status: 'connected' }); }); edgeStream.on('disconnected', ({ reason }) => { console.warn('Disconnected:', reason); updateUI({ status: 'disconnected' }); }); edgeStream.on('reconnecting', ({ attempt }) => { console.log(`Reconnecting (attempt ${attempt})...`); });

Register hooks

5
Register an incoming hook

Hooks intercept every message in the pipeline. Register them before starting the connection. Lower priority numbers run first — the system executes hooks in order.

import type { IHook, IEnvelope } from 'edge-stream-js'; class ValidationHook implements IHook { name = 'validation-hook'; priority = 10; async execute(envelope: IEnvelope): Promise<IEnvelope> { if (!envelope.body?.text) { throw new Error('Message body is required'); } return envelope; } } class LogHook implements IHook { name = 'log-hook'; priority = 50; async execute(envelope: IEnvelope): Promise<IEnvelope> { console.log('[EdgeStream]', envelope.meta.messageId, envelope.body?.text); return envelope; } } // Register on the incoming pipeline edgeStream.registerIncomingHook(new ValidationHook()); edgeStream.registerIncomingHook(new LogHook());

Subscribe and publish

6
Subscribe to a topic

Topics are dot-separated strings. Use * as a wildcard segment. The callback receives the full IEnvelope including message body, metadata, and routing context.

// Exact topic match const sub1 = edgeStream.subscribe( 'messages:conversation:conv-123', (envelope) => { console.log('New message:', envelope.body.text); console.log('Message ID:', envelope.meta.messageId); console.log('Source:', envelope.meta.source); } ); // Wildcard: all messages for a user const sub2 = edgeStream.subscribe( 'user:sarah-123:*', (envelope) => { handleUserEvent(envelope); } ); // Wildcard: all order status changes const sub3 = edgeStream.subscribe( 'order:*:status', (envelope) => { updateOrderStatus(envelope.body.orderId, envelope.body.status); } ); // Later: unsubscribe sub1.unsubscribe(); sub2.unsubscribe();
7
Publish a message

Publish sends a message through the outgoing pipeline (hooks fire in order) before transmitting to the server. The server processes and distributes to matching subscribers.

// Publish a message — hooks run before transmission await edgeStream.publish({ topic: 'messages:conversation:conv-123', body: { text: 'Hello from EdgeStream', type: 'user', timestamp: new Date().toISOString() }, meta: { source: 'web-client', conversationId: 'conv-123', userId: 'user-sarah-123' } }); // Batch publish — multiple messages in one call await edgeStream.publishBatch([ { topic: 'metrics:page:view', body: { page: '/dashboard' } }, { topic: 'metrics:session:active', body: { duration: 42 } } ]);
Messages pass through the outgoing pipeline before leaving the client. Your validation, logging, and retry hooks fire on every publish — no boilerplate required at each call site.

React integration

8
Wrap your app in EdgeStreamProvider

The React package provides a context provider and hooks. Wrap once at the app root and use hooks anywhere in the component tree — no prop drilling.

// App.tsx import { EdgeStreamProvider } from '@edge-stream/react-hooks'; import { EdgeStream, HubServer } from 'edge-stream-js'; const edgeStream = new EdgeStream(); edgeStream.registerServer(new HubServer({ url: '/chat-hub' })); export function App() { return ( <EdgeStreamProvider edgeStream={edgeStream}> <Dashboard /> </EdgeStreamProvider> ); } // Dashboard.tsx import { useEdgeStream, useSubscription } from '@edge-stream/react-hooks'; function Dashboard() { const { status } = useEdgeStream(); const [messages, setMessages] = useState([]); useSubscription('messages:dashboard:*', (envelope) => { setMessages(prev => [...prev, envelope.body]); }); return ( <div> <span>Status: {status}</span> {messages.map(m => <div key={m.id}>{m.text}</div>)} </div> ); }

Need help getting set up?

Explore the architecture or join the EdgeStream community.