UNPKG

@codeforbreakfast/eventsourcing-websocket

Version:

Batteries-included WebSocket event sourcing package - Complete WebSocket transport with default protocol for rapid event sourcing development

176 lines (121 loc) 5.32 kB
# @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 ```bash bun add @codeforbreakfast/eventsourcing-websocket bun add @codeforbreakfast/eventsourcing-protocol bun add @codeforbreakfast/eventsourcing-commands ``` ## Layer Setup ### Recommended: Layer-based Setup ```typescript 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: 'alice@example.com' }, }); 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: ```typescript 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` ```typescript 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:** ```typescript 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` ```typescript 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:** ```typescript 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](../eventsourcing-protocol)** - Send commands and subscribe to events (your main application API) - **[@codeforbreakfast/eventsourcing-commands](../eventsourcing-commands)** - WireCommand and CommandResult types - **[@codeforbreakfast/eventsourcing-store](../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](../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