@codeforbreakfast/eventsourcing-websocket
v0.3.17
Published
Batteries-included WebSocket event sourcing package - Complete WebSocket transport with default protocol for rapid event sourcing development
Maintainers
Readme
@codeforbreakfast/eventsourcing-websocket
WebSocket transport layer setup for event sourcing clients.
Purpose
This package provides the WebSocket transport implementation for connecting to event sourcing servers. Use this package ONLY for creating your Effect Layer - all application logic should use @codeforbreakfast/eventsourcing-protocol.
Key principle: Your application code shouldn't know it's using WebSocket. This is a deployment detail configured once when setting up layers.
Installation
bun add @codeforbreakfast/eventsourcing-websocket
bun add @codeforbreakfast/eventsourcing-protocol
bun add @codeforbreakfast/eventsourcing-commandsLayer Setup
Recommended: Layer-based Setup
import { makeWebSocketProtocolLayer } from '@codeforbreakfast/eventsourcing-websocket';
import { sendWireCommand, subscribe } from '@codeforbreakfast/eventsourcing-protocol';
import { Effect, Stream, pipe } from 'effect';
interface WireCommand {
id: string;
target: string;
name: string;
payload: unknown;
}
const sendCommand = (command: WireCommand) =>
pipe(
sendWireCommand(command),
Effect.flatMap(() => subscribe('user-123')),
Effect.flatMap((events) =>
Stream.runForEach(events, (event) => Effect.sync(() => console.log('Event:', event.type)))
)
);
const myApplication = sendCommand({
id: crypto.randomUUID(),
target: 'user-123',
name: 'CreateUser',
payload: { name: 'Alice', email: '[email protected]' },
});
const layer = makeWebSocketProtocolLayer('ws://localhost:8080');
await Effect.runPromise(pipe(myApplication, Effect.provide(layer), Effect.scoped));To switch transports (e.g., to HTTP), you'd only change the layer - application code stays the same.
Convenience: Direct Connection
For quick prototypes or scripts, you can use the makeWebSocketProtocolLayer directly with Effect.scoped:
import { makeWebSocketProtocolLayer } from '@codeforbreakfast/eventsourcing-websocket';
import { sendWireCommand } from '@codeforbreakfast/eventsourcing-protocol';
import { Effect, pipe } from 'effect';
const sendCommand = pipe(
sendWireCommand({
id: crypto.randomUUID(),
target: 'user-123',
name: 'CreateUser',
payload: { name: 'Alice' },
}),
Effect.provide(makeWebSocketProtocolLayer('ws://localhost:8080')),
Effect.scoped
);
Effect.runPromise(sendCommand);Note: The layer-based approach is preferred for production applications as it supports dependency injection and testing.
API Reference
makeWebSocketProtocolLayer
import { Layer, Scope } from 'effect';
import { Protocol } from '@codeforbreakfast/eventsourcing-protocol';
import { TransportError, ConnectionError } from '@codeforbreakfast/eventsourcing-transport';
declare const makeWebSocketProtocolLayer: (
url: string
) => Layer.Layer<Protocol, TransportError | ConnectionError, Scope.Scope>;Creates an Effect Layer that provides the Protocol service over WebSocket.
Parameters:
url: string- WebSocket server URL (e.g.,ws://localhost:8080)
Returns: Layer that can be provided to your application
Example:
import { Effect, pipe } from 'effect';
import { makeWebSocketProtocolLayer } from '@codeforbreakfast/eventsourcing-websocket';
declare const myApp: Effect.Effect<void, never, never>;
const runApp = pipe(
myApp,
Effect.provide(makeWebSocketProtocolLayer('ws://localhost:8080')),
Effect.scoped
);
Effect.runPromise(runApp);connect
import { Effect, Scope } from 'effect';
import { Protocol } from '@codeforbreakfast/eventsourcing-protocol';
import { TransportError, ConnectionError } from '@codeforbreakfast/eventsourcing-transport';
declare const connect: (
url: string
) => Effect.Effect<Protocol, TransportError | ConnectionError, Protocol | Scope.Scope>;Convenience function that connects and returns the Protocol service directly.
Parameters:
url: string- WebSocket server URL
Returns: Effect providing Protocol service (must be run in scoped context)
Example:
import { Effect, pipe } from 'effect';
import { connect } from '@codeforbreakfast/eventsourcing-websocket';
const program = pipe(
connect('ws://localhost:8080'),
Effect.flatMap((protocol) => Effect.succeed(protocol)), // use protocol...
Effect.scoped
);Next Steps
Once you've set up your WebSocket layer, see the following packages for building your application:
- @codeforbreakfast/eventsourcing-protocol - Send commands and subscribe to events (your main application API)
- @codeforbreakfast/eventsourcing-commands - WireCommand and CommandResult types
- @codeforbreakfast/eventsourcing-store - Event types and event store contracts
Advanced: Low-Level Transport
If you need access to the raw WebSocket transport (for advanced use cases), see:
- @codeforbreakfast/eventsourcing-transport-websocket - Low-level WebSocket transport implementation
Contributing
This package is part of the @codeforbreakfast/eventsourcing monorepo. See the main repository for contribution guidelines.
License
MIT
