@ebca/ws-gateway
v0.0.11
Published
Universal WebSocket gateway adapter for EBCA component projection, mutation, and read queries.
Maintainers
Readme
@ebca/ws-gateway
Optional WebSocket gateway for EBCA component projection, mutation, requests, and read queries.
@ebca/ws-gateway connects Socket.IO/NestJS clients to the declarative surface provided by @ebca/core. It does not contain domain rules. It reads EBCA metadata, validates inbound component access, calls ComponentManager, and projects exposed lifecycle events to connected identities.
Install
npm install @ebca/ws-gatewayPeer dependencies include @ebca/core, NestJS, Socket.IO, TypeORM, and NestJS microservices.
What It Does
- Accepts generic component mutations from clients.
- Validates
ComponentOptions.inbound. - Supports component batch requests by entity or collection target.
- Projects lifecycle updates for components exposed through
ComponentOptions.projection. - Executes read queries declared with
@EbcaQuery(...); omit querygatesfor every query transport, usegates: ['ws']to narrow exposure, orgates: []for internal repository helpers. - Keeps auth, identity lookup, custom filtering, and domain policy in the consuming app.
ComponentOptions.websocket remains supported as a deprecated alias for older components. New components should use projection: { expose: true, gates: ['ws'], ... } or omit gates to expose to all realtime projection gates.
Basic Setup
import { EbcaWsGatewayModule } from '@ebca/ws-gateway';
EbcaWsGatewayModule.forRoot({
namespace: '/app',
identityField: 'accountId',
identityEntityName: 'AccountEntity',
defaultRoles: ['user'],
authAdapter: AppSocketAuthAdapter,
});identityId is the internal EBCA identity name. identityField controls the public envelope field, so a project can expose accountId, playerId, tenantId, or another domain-specific name without changing the gateway internals.
Client Events
| Event | Purpose |
| --- | --- |
| client.hello | Attach a socket to the authenticated identity room. |
| client.component | Add/update/upsert/remove an exposed inbound component. |
| client.component.request | Request exposed components for one entity or a collection. |
| client.query | Execute an EBCA read query exposed to the ws gate. |
| server.component | Receive projected component lifecycle updates. |
| server.query.result | Receive query results. |
| server.error | Receive transport-level protocol or validation errors. |
Generated WebSocket contracts infer WebsocketQueryResultByName from query method return annotations and exported declarations reachable from component/query imports. @EbcaQuery({ resultType }) remains an explicit override for unusual signatures; untyped results stay WebsocketJsonValue.
Command Mutations
Command components use the same ComponentManager path as other inbound writes. They stay transient unless core metadata sets transient: false; in that mode idempotent retries need a stable commandId in the inbound payload.
Extension Points
The consuming app can provide:
- auth adapters;
- inbound normalizers;
- projection policies;
- audience resolvers;
- custom identity field naming;
- default roles.
That keeps WebSocket code boring and domain logic explicit.
Why This Is Useful
Many realtime systems grow separate APIs for commands, snapshots, events, and read models. EBCA lets the WebSocket boundary stay generic:
- Commands are component mutations.
- Results are component lifecycle.
- Snapshots are component requests.
- Lists and dashboards are declared read queries.
- Client contracts can be generated from the same metadata.
This makes frontend/backend integration easier to inspect and easier for AI agents to update without inventing hidden transport-specific business logic.
License
Apache-2.0.
