@meego-harness/event-relay
v0.9.0
Published
Public event relay for forwarding Meego webhooks to an internal gateway
Readme
@meego-harness/event-relay
event-relay provides a small public HTTP/websocket relay for deployments where Meego can reach a public server but the gateway runs inside a private network.
The relay receives webhook requests, queues them in memory, and forwards each event over authenticated websocket client connections. The internal gateway connects out to the relay through gateway.eventRelay.
Install
pnpm add @meego-harness/event-relayCLI
Run the relay on the public server:
pnpm exec meego-harness-event-relay run --config-file ./relay.config.jsonExample config:
{
"host": "127.0.0.1",
"port": 4100,
"webhookPath": "/public-webhook",
"websocketPath": "/relay-ws",
"routingMode": "single",
"clientToken": "change-me",
"maxQueuedEvents": 100,
"maxBodyBytes": 262144
}Use the printed webhookUrl as the Meego webhook callback URL.
routingMode defaults to single. In single mode, relay accepts POST /public-webhook and one websocket client at /relay-ws.
Use room mode when one relay process must forward events to multiple gateway clients:
{
"host": "127.0.0.1",
"port": 4100,
"webhookPath": "/public-webhook",
"websocketPath": "/relay-ws",
"routingMode": "room",
"clientToken": "change-me",
"maxQueuedEvents": 100,
"maxBodyBytes": 262144
}In room mode, configure Meego callback URLs as /public-webhook/<roomId>, and configure the gateway client with the same roomId. The roomId is a caller-chosen room name; it is not registered ahead of time and is not bound to clientToken.
Programmatic Usage
import { EventRelayServer } from '@meego-harness/event-relay'
const relay = new EventRelayServer({
port: 4100,
webhookPath: '/public-webhook',
websocketPath: '/relay-ws',
routingMode: 'room',
clientToken: process.env.RELAY_CLIENT_TOKEN!,
maxQueuedEvents: 100,
maxBodyBytes: 262144,
})
await relay.start()Internal consumers can use EventRelayClient directly when not relying on gateway config:
import { EventRelayClient } from '@meego-harness/event-relay'
const client = new EventRelayClient({
serverUrl: 'ws://relay.example.com/relay-ws',
clientToken: process.env.RELAY_CLIENT_TOKEN!,
roomId: 'workspace-alpha',
async handleEvent(event) {
const response = await fetch('http://127.0.0.1:3000/webhook', {
method: 'POST',
body: event.rawBody,
})
return { ok: response.ok, status: response.status }
},
})
await client.start()Operational Notes
- Queue state is in memory; if the relay process exits, queued events are lost.
- In
singlemode, only one websocket client is active at a time. - In
roommode, each room has an independent queue and active websocket client. A new connection replaces the previous connection in the same room only. - Events are acknowledged after the client reports a successful local handler result.
maxBodyBytesrejects oversized webhook bodies before they enter the queue.maxQueuedEventsis the queue limit for each room. Insinglemode, the single relay connection uses one room internally.clientTokenprotects the websocket relay channel; do not reuse it as a Meego webhook token, and do not treatroomIdas a secret.
