From 38e23ba095145347851fb3a7832cc41cfd99c53f Mon Sep 17 00:00:00 2001 From: Pablo Baleztena Date: Tue, 15 Oct 2024 07:45:11 -0300 Subject: [PATCH] Refactor event interface to use VariantTag for event types --- packages/fabric/core/src/variant/variant.ts | 2 +- .../fabric/domain/src/events/event-store.ts | 14 +++++-- packages/fabric/domain/src/events/event.ts | 7 ++-- .../src/events/event-store.spec.ts | 8 ++-- .../sqlite-store/src/events/event-store.ts | 40 +++++++++++-------- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/packages/fabric/core/src/variant/variant.ts b/packages/fabric/core/src/variant/variant.ts index 12d5b47..928fdd4 100644 --- a/packages/fabric/core/src/variant/variant.ts +++ b/packages/fabric/core/src/variant/variant.ts @@ -7,7 +7,7 @@ export interface TaggedVariant { export type VariantFromTag< TVariant extends TaggedVariant, - TTag extends TVariant[typeof VariantTag], + TTag extends TVariant[VariantTag], > = Extract; export namespace Variant { diff --git a/packages/fabric/domain/src/events/event-store.ts b/packages/fabric/domain/src/events/event-store.ts index 549031f..62e09ee 100644 --- a/packages/fabric/domain/src/events/event-store.ts +++ b/packages/fabric/domain/src/events/event-store.ts @@ -1,7 +1,13 @@ -import { AsyncResult, MaybePromise, PosixDate } from "@fabric/core"; +import { + AsyncResult, + MaybePromise, + PosixDate, + VariantFromTag, + VariantTag, +} from "@fabric/core"; import { StoreQueryError } from "../errors/query-error.js"; import { UUID } from "../types/uuid.js"; -import { Event, EventFromKey } from "./event.js"; +import { Event } from "./event.js"; import { StoredEvent } from "./stored-event.js"; export interface EventStore { @@ -16,9 +22,9 @@ export interface EventStore { streamId: UUID, ): AsyncResult[], StoreQueryError>; - subscribe( + subscribe( events: TEventKey[], - subscriber: EventSubscriber>, + subscriber: EventSubscriber>, ): void; } diff --git a/packages/fabric/domain/src/events/event.ts b/packages/fabric/domain/src/events/event.ts index d71ef0a..8b8a417 100644 --- a/packages/fabric/domain/src/events/event.ts +++ b/packages/fabric/domain/src/events/event.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { VariantTag } from "@fabric/core"; import { UUID } from "../types/uuid.js"; /** * An event is a tagged variant with a payload and a timestamp. */ export interface Event { - readonly type: TTag; + readonly [VariantTag]: TTag; readonly id: UUID; readonly streamId: UUID; readonly payload: TPayload; @@ -13,5 +14,5 @@ export interface Event { export type EventFromKey< TEvents extends Event, - TKey extends TEvents["type"], -> = Extract; + TKey extends TEvents[VariantTag], +> = Extract; diff --git a/packages/fabric/sqlite-store/src/events/event-store.spec.ts b/packages/fabric/sqlite-store/src/events/event-store.spec.ts index 4ca0888..4093c78 100644 --- a/packages/fabric/sqlite-store/src/events/event-store.spec.ts +++ b/packages/fabric/sqlite-store/src/events/event-store.spec.ts @@ -26,7 +26,7 @@ describe("Event Store", () => { const newUUID = UUIDGeneratorMock.generate(); const userCreated: UserCreated = { - type: "UserCreated", + _tag: "UserCreated", id: newUUID, streamId: newUUID, payload: { name: "test" }, @@ -41,7 +41,7 @@ describe("Event Store", () => { expect(events[0]).toEqual({ id: newUUID, streamId: newUUID, - type: "UserCreated", + _tag: "UserCreated", version: BigInt(1), timestamp: expect.any(PosixDate), payload: { name: "test" }, @@ -52,7 +52,7 @@ describe("Event Store", () => { const newUUID = UUIDGeneratorMock.generate(); const userCreated: UserCreated = { - type: "UserCreated", + _tag: "UserCreated", id: newUUID, streamId: newUUID, payload: { name: "test" }, @@ -68,7 +68,7 @@ describe("Event Store", () => { expect(subscriber).toHaveBeenCalledWith({ id: newUUID, streamId: newUUID, - type: "UserCreated", + _tag: "UserCreated", version: BigInt(1), timestamp: expect.any(PosixDate), payload: { name: "test" }, diff --git a/packages/fabric/sqlite-store/src/events/event-store.ts b/packages/fabric/sqlite-store/src/events/event-store.ts index 8700f30..298a38d 100644 --- a/packages/fabric/sqlite-store/src/events/event-store.ts +++ b/packages/fabric/sqlite-store/src/events/event-store.ts @@ -1,4 +1,10 @@ -import { AsyncResult, MaybePromise, PosixDate, Run } from "@fabric/core"; +import { + AsyncResult, + MaybePromise, + PosixDate, + Run, + VariantTag, +} from "@fabric/core"; import { Event, EventFromKey, @@ -19,7 +25,7 @@ export class SQLiteEventStore private streamVersions = new Map(); private eventSubscribers = new Map< - TEvents["type"], + TEvents[VariantTag], EventSubscriber[] >(); @@ -34,7 +40,7 @@ export class SQLiteEventStore await this.db.run( `CREATE TABLE IF NOT EXISTS events ( id TEXT PRIMARY KEY, - type TEXT NOT NULL, + _tag TEXT NOT NULL, streamId TEXT NOT NULL, version INTEGER NOT NULL, timestamp NUMERIC NOT NULL, @@ -57,13 +63,13 @@ export class SQLiteEventStore { $id: streamId, }, - (event) => ({ - id: event.id, - streamId: event.streamId, - type: event.type, - version: BigInt(event.version), - timestamp: new PosixDate(event.timestamp), - payload: JSONUtils.parse(event.payload), + (e) => ({ + id: e.id, + streamId: e.streamId, + _tag: e._tag, + version: BigInt(e.version), + timestamp: new PosixDate(e.timestamp), + payload: JSONUtils.parse(e.payload), }), ); return events; @@ -95,7 +101,7 @@ export class SQLiteEventStore event: StoredEvent, ): AsyncResult { return AsyncResult.from(async () => { - const subscribers = this.eventSubscribers.get(event.type) || []; + const subscribers = this.eventSubscribers.get(event[VariantTag]) || []; await Promise.all(subscribers.map((subscriber) => subscriber(event))); }); } @@ -121,13 +127,13 @@ export class SQLiteEventStore ); } - subscribe( - events: TEventKey[], + subscribe( + eventNames: TEventKey[], subscriber: ( event: StoredEvent>, ) => MaybePromise, ): void { - events.forEach((event) => { + eventNames.forEach((event) => { const subscribers = this.eventSubscribers.get(event) || []; const newSubscribers = [ ...subscribers, @@ -157,12 +163,12 @@ export class SQLiteEventStore timestamp: new PosixDate(), }; await this.db.runPrepared( - `INSERT INTO events (id, streamId, type, version, timestamp, payload) - VALUES ($id, $streamId, $type, $version, $timestamp, $payload)`, + `INSERT INTO events (id, streamId, _tag, version, timestamp, payload) + VALUES ($id, $streamId, $_tag, $version, $timestamp, $payload)`, { $id: storedEvent.id, $streamId: streamId, - $type: storedEvent.type, + $_tag: storedEvent[VariantTag], $version: storedEvent.version.toString(), $timestamp: storedEvent.timestamp.timestamp, $payload: JSON.stringify(storedEvent.payload),