xTaskjs 1.0 ya está disponible: cuentas por rol, documentación y una interfaz personalizable.

Paquetes

@xtaskjs/event-source

Event-sourced aggregates, optimistic stream persistence, stored-event subscribers, and optional queue publication.

npm install @xtaskjs/event-source reflect-metadata Ruta del paquete: packages/event-source

Resumen

Qué controla este paquete en el runtime

Event source adds aggregate rehydration, stream persistence, optimistic concurrency checks, and stored-event publication to xtaskjs. It keeps event application inside aggregate roots while exposing repositories, stores, publishers, and subscribers through the same DI lifecycle used by the rest of the framework.

Qué ofrece

  • EventSourcedAggregate() and ApplyEvent() let aggregates raise and replay domain events with explicit appliers.
  • EventSourceRepository is registered in the container and supports create(), load(), loadOrCreate(), and save() with optimistic stream appends.
  • InMemoryEventStore works by default, while createTypeOrmEventStore() adds durable event-stream persistence.
  • createQueueEventPublisher() and EventSourceSubscriber() connect stored events to queues, projections, and side-effect handlers without replacing CQRS buses.

Cómo encaja

  • Configured through @EventSource(...) or configureEventSource() before CreateApplication() so store and publisher bindings are ready during bootstrap.
  • Pairs naturally with @xtaskjs/typeorm for durable event storage and with @xtaskjs/queues for broker-backed event publication.
  • Works beside @xtaskjs/cqrs when commands load aggregates through repositories and downstream read models react to stored events.

Mapa de uso

Qué peso tiene este paquete dentro del runtime

Arranque

4/5

Inyección de dependencias

4/5

Persistencia

5/5

Mensajería

4/5

Domain Modeling

5/5

Flujo del paquete

Cómo atraviesa este paquete las fases del runtime de xtaskjs

Antes del arranque

Configure the package with @EventSource(...) or configureEventSource(), then decorate aggregates and subscribers so metadata exists before the container is scanned.

Durante CreateApplication()

The lifecycle manager resolves the configured event store and publisher, registers aggregate repositories and tokens in the container, and wires stored-event subscribers from DI-managed services.

Durante app.close()

Configured stores and publishers are destroyed automatically so in-memory, TypeORM-backed, and queue-backed event infrastructure shuts down with the application.

Superficie API

Exports representativos del paquete original

Configuration and publishers

  • EventSource
  • configureEventSource
  • createQueueEventPublisher
  • QueueEventPublisher
  • createTypeOrmEventStore
  • TypeOrmEventStore

Aggregates and repositories

  • EventSourcedAggregate
  • ApplyEvent
  • EventSourcedAggregateRoot
  • EventSourceRepository
  • InjectEventSourceRepository

Subscribers and lifecycle

  • EventSourceSubscriber
  • StoredEventSubscriber
  • InjectEventStore
  • InjectEventSourceBus
  • InjectEventPublisher
  • InjectEventSourceLifecycleManager
  • EventSourceLifecycleManager
  • initializeEventSourceIntegration
  • shutdownEventSourceIntegration
  • getEventSourceLifecycleManager
  • InMemoryEventStore
  • EventSourceBus

Uso

Flujo típico de adopción

1. Configure storage and publication

Start with the default in-memory store for tests and local workflows, or plug in createTypeOrmEventStore() and createQueueEventPublisher() when streams must be durable and publish outside the process.

2. Model aggregates around raised events

Decorate aggregate roots with EventSourcedAggregate(), raise domain events from command methods, and use ApplyEvent() handlers to mutate state during live execution and historical rehydration.

3. Save through repositories and react with subscribers

Inject EventSourceRepository into services or command handlers, save aggregates to append stored events, and attach EventSourceSubscriber() listeners for projections, integrations, or side effects.

Ejemplo

Fragmento de referencia

Aggregate registration with durable event storage
import { Service } from "@xtaskjs/core";
import {
  ApplyEvent,
  EventSource,
  EventSourcedAggregate,
  EventSourcedAggregateRoot,
  EventSourceRepository,
  InjectEventSourceRepository,
  createTypeOrmEventStore,
} from "@xtaskjs/event-source";

@EventSource({
  store: createTypeOrmEventStore({ dataSourceName: "write-db", tableName: "event_store" }),
})
class EventSourceConfiguration {}

class UserRegisteredEvent {
  constructor(public readonly id: string, public readonly email: string) {}
}

@EventSourcedAggregate({ stream: "users" })
class UserAggregate extends EventSourcedAggregateRoot {
  public email?: string;

  register(id: string, email: string) {
    this.assignStreamId(id);
    this.raiseEvent(new UserRegisteredEvent(id, email));
  }

  @ApplyEvent(UserRegisteredEvent)
  onRegistered(event: UserRegisteredEvent) {
    this.email = event.email;
  }
}

@Service()
export class UserRegistrationService {
  constructor(
    @InjectEventSourceRepository(UserAggregate)
    private readonly users: EventSourceRepository<UserAggregate>
  ) {}

  async register(id: string, email: string) {
    const user = this.users.create(id);
    user.register(id, email);
    await this.users.save(user);
  }
}

Ejemplos

Ejemplos oficiales para revisar después

Ejemplos de referencia: 21-event_source_rabbitmq_app and 22-event_source_cqrs_app

Relacionados

Paquetes que suelen usarse junto a este