Files
2026-05-27 23:29:53 +01:00

91 lines
5.1 KiB
Markdown

# @suaveplan/api-events-worker-proxy - Worker-tier proxy over a main-process @suaveplan/events EventBus. The main side calls createEventBusProxyServer(port, bus) to expose the bus over a MessagePort via @suaveplan/api-worker-rpc; worker-tier plugins call createEventBusProxyClient(port) to obtain an EventBus-shaped surface that marshals on/once/off/emit/emitAsync across the port. Subscriptions become long-lived stream-* frames that deliver one stream-chunk per main-side event. Zod-validated payload codec rejects non-structured-clone-safe payloads with EVENTS_PROXY.UNSERIALISABLE_PAYLOAD.
Worker-tier proxy over a main-process `@suaveplan/events` `EventBus`.
The host (main process) owns one `EventBus<TMap>` instance. Worker-tier
plugins want to publish to and subscribe from the same bus without
running the bus in every worker. This package marshals every
`on` / `once` / `off` / `emit` / `emitAsync` call across a
`MessagePort` via `@suaveplan/api-worker-rpc`, so worker-tier plugin
code compiles unchanged against an `EventBus`-shaped proxy surface.
This is an adapter, not a new contract — the design doc (§5.2a) is
explicit that no abstract `api-events` contract package exists. The
host injects `@suaveplan/events` directly; this package is the
worker-side surface over that existing bus.
<!-- begin:auto-docs -->
## Documentation tree
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable string registry of `EVENTS_PROXY.*` error codes raised by every failure path in `@suaveplan/api-even…
- [error-codes](./src/error-codes/error-codes.md) — Defines the stable string registry of `EVENTS_PROXY.*` error codes raised by every failure path in `@suaveplan/api-even…
- [main-side](./src/main-side/main-side.md) — Mounts a main-process `@suaveplan/events` `EventBus` on a `MessagePort` via the `@suaveplan/api-worker-rpc` server so w…
- [main-side](./src/main-side/main-side.md) — Mounts a main-process `@suaveplan/events` `EventBus` on a `MessagePort` via the `@suaveplan/api-worker-rpc` server so w…
- [payload-codec](./src/payload-codec/payload-codec.md) — Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePor…
- [payload-codec](./src/payload-codec/payload-codec.md) — Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePor…
- [testing](./src/testing/testing.md) — Re-usable test fixtures for `@suaveplan/api-events-worker-proxy`. Builds a real `EventBus`, a real Node.js `MessageChan…
- [testing](./src/testing/testing.md) — Re-usable test fixtures for `@suaveplan/api-events-worker-proxy`. Builds a real `EventBus`, a real Node.js `MessageChan…
- [worker-side](./src/worker-side/worker-side.md) — Builds a worker-side proxy that exposes an `EventBus`-shaped surface backed by a `PortLike` connected to a main-process…
- [worker-side](./src/worker-side/worker-side.md) — Builds a worker-side proxy that exposes an `EventBus`-shaped surface backed by a `PortLike` connected to a main-process…
<!-- end:auto-docs -->
## Install
```bash
bun add @suaveplan/api-events-worker-proxy
```
## Main-side (host)
```ts
import { EventBus } from "@suaveplan/events";
import { createEventBusProxyServer } from "@suaveplan/api-events-worker-proxy/main-side";
import { createInProcessPortPair } from "@suaveplan/api-worker-rpc";
const bus = new EventBus<{ "billing.invoice.created": { id: string } }>();
const { clientPort, serverPort, close } = createInProcessPortPair();
const server = createEventBusProxyServer(serverPort, bus);
// Hand `clientPort` to a worker; tear down with `server.dispose()` + close().
```
## Worker-side
```ts
import { createEventBusProxyClient } from "@suaveplan/api-events-worker-proxy/worker-side";
type Map = { "billing.invoice.created": { id: string } };
const events = createEventBusProxyClient<Map>(port);
events.on("billing.invoice.created", ({ id }) => console.log("got", id));
const result = await events.emitAsync("billing.invoice.created", {
id: "i_1",
});
console.log(result.delivered);
```
## Exports
- `./main-side` — `createEventBusProxyServer(port, bus)`.
- `./worker-side` — `createEventBusProxyClient(port)`.
- `./payload-codec` — Zod schema + structured-clone probe.
- `./error-codes` — `EVENTS_PROXY.*` codes + `EventsProxyError`.
- `./testing` — `createProxyPair` + `waitFor` for downstream tests.
## Error codes
- `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD` — payload failed the
structured-clone safety probe (functions, class instances, cycles).
- `EVENTS_PROXY.SUBSCRIPTION_DROPPED` — subscription terminated
unexpectedly (server disposed, port closed mid-stream).
- `EVENTS_PROXY.BACKPRESSURE_EXCEEDED` — worker-side queue exceeded the
configured high-water mark.
- `EVENTS_PROXY.PROXY_DISPOSED` — method called after `dispose()`.
## Docs
- [`main-side`](./src/main-side/main-side.md)
- [`worker-side`](./src/worker-side/worker-side.md)
- [`payload-codec`](./src/payload-codec/payload-codec.md)
- [`error-codes`](./src/error-codes/error-codes.md)
- [`testing`](./src/testing/testing.md)