{"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett/dist/index.cjs","../src/typing/command.ts","../src/typing/event.ts","../src/typing/message.ts","../src/typing/workflow.ts","../src/eventStore/afterCommit/afterEventStoreCommitHandler.ts","../src/eventStore/afterCommit/forwardToMessageBus.ts","../src/eventStore/events/index.ts","../src/eventStore/eventStore.ts","../src/eventStore/expectedVersion.ts","../src/eventStore/inMemoryEventStore.ts","../src/database/inMemoryDatabase.ts","../src/utils/collections/duplicates.ts","../src/utils/collections/merge.ts","../src/utils/collections/index.ts","../src/utils/deepEquals.ts","../src/utils/iterators.ts","../src/taskProcessing/taskProcessor.ts","../src/utils/locking/index.ts","../src/utils/promises.ts","../src/utils/retry.ts","../src/serialization/json/JSONParser.ts","../src/database/utils.ts","../src/eventStore/projections/inMemory/inMemoryProjection.ts","../src/eventStore/projections/inMemory/inMemoryProjectionSpec.ts","../src/testing/assertions.ts","../src/testing/deciderSpecification.ts","../src/testing/wrapEventStore.ts","../src/eventStore/subscriptions/caughtUpTransformStream.ts","../src/eventStore/subscriptions/streamingCoordinator.ts","../src/streaming/transformations/notifyAboutNoActiveReaders.ts","../src/streaming/writers/writeToStream.ts","../src/commandHandling/handleCommand.ts","../src/commandHandling/handleCommandWithDecider.ts","../src/messageBus/index.ts","../src/processors/processors.ts","../src/processors/inMemoryProcessors.ts","../src/projections/index.ts","../src/streaming/binaryArrays.ts","../src/streaming/collectors/collect.ts","../src/streaming/decoders/binary.ts","../src/streaming/decoders/string.ts","../src/streaming/decoders/json.ts","../src/streaming/decoders/object.ts","../src/streaming/decoders/composite.ts","../src/streaming/generators/fromArray.ts","../src/streaming/generators/index.ts","../src/streaming/restream.ts","../src/streaming/transformations/filter.ts","../src/streaming/transformations/map.ts","../src/streaming/transformations/reduce.ts","../src/streaming/transformations/retry.ts","../src/streaming/transformations/skip.ts","../src/streaming/transformations/stopAfter.ts","../src/streaming/transformations/stopOn.ts","../src/streaming/transformations/take.ts","../src/streaming/transformations/waitAtMost.ts","../src/streaming/transformations/index.ts"],"names":["message","error","event","map","result","sum","item","operationResult","newCollection","projections","projection","options","uuid","TransformStream","inlineProjections","command","skip"],"mappings":"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6B,EAAA;AACH,IAAA;AAC1B,EAAA;AACD;AxD4uE6B;AACA;AyDnvEK;AACnC,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACO,EAAA;AACP,EAAA;AACA,EAAA;AACA,EAAA;AACF;AzDqvEgC;AACA;A+CzwEd;AAOhB;AAW+C;AAQjB,EAAA;AAET,EAAA;AAEK,EAAA;AAEI,EAAA;AAC9B;AAGA;AAII,EAAA;AACsB,IAAA;AACV,IAAA;AAEM,IAAA;AACD,IAAA;AACL,EAAA;AACa,IAAA;AAC7B,EAAA;AACF;A/C2uEgC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/emmett/emmett/src/packages/emmett/dist/index.cjs","sourcesContent":[null,"import type { DefaultRecord } from './';\n\nexport type Command<\n  CommandType extends string = string,\n  CommandData extends DefaultRecord = DefaultRecord,\n  CommandMetaData extends DefaultRecord | undefined = undefined,\n> = Readonly<\n  CommandMetaData extends undefined\n    ? {\n        type: CommandType;\n        data: Readonly<CommandData>;\n        metadata?: DefaultCommandMetadata | undefined;\n      }\n    : {\n        type: CommandType;\n        data: CommandData;\n        metadata: CommandMetaData;\n      }\n> & { readonly kind?: 'Command' };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyCommand = Command<any, any, any>;\n\nexport type CommandTypeOf<T extends Command> = T['type'];\nexport type CommandDataOf<T extends Command> = T['data'];\nexport type CommandMetaDataOf<T extends Command> = T extends {\n  metadata: infer M;\n}\n  ? M\n  : undefined;\n\nexport type CreateCommandType<\n  CommandType extends string,\n  CommandData extends DefaultRecord,\n  CommandMetaData extends DefaultRecord | undefined = undefined,\n> = Readonly<\n  CommandMetaData extends undefined\n    ? {\n        type: CommandType;\n        data: CommandData;\n        metadata?: DefaultCommandMetadata | undefined;\n      }\n    : {\n        type: CommandType;\n        data: CommandData;\n        metadata: CommandMetaData;\n      }\n> & { readonly kind?: 'Command' };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const command = <CommandType extends Command<string, any, any>>(\n  ...args: CommandMetaDataOf<CommandType> extends undefined\n    ? [\n        type: CommandTypeOf<CommandType>,\n        data: CommandDataOf<CommandType>,\n        metadata?: DefaultCommandMetadata | undefined,\n      ]\n    : [\n        type: CommandTypeOf<CommandType>,\n        data: CommandDataOf<CommandType>,\n        metadata: CommandMetaDataOf<CommandType>,\n      ]\n): CommandType => {\n  const [type, data, metadata] = args;\n\n  return metadata !== undefined\n    ? ({ type, data, metadata, kind: 'Command' } as CommandType)\n    : ({ type, data, kind: 'Command' } as CommandType);\n};\n\nexport type DefaultCommandMetadata = { now: Date };\n","import type { DefaultRecord } from './';\nimport type {\n  AnyRecordedMessageMetadata,\n  CombinedMessageMetadata,\n  CommonRecordedMessageMetadata,\n  GlobalPositionTypeOfRecordedMessageMetadata,\n  RecordedMessage,\n  RecordedMessageMetadata,\n  RecordedMessageMetadataWithGlobalPosition,\n  RecordedMessageMetadataWithoutGlobalPosition,\n  StreamPositionTypeOfRecordedMessageMetadata,\n} from './message';\n\nexport type BigIntStreamPosition = bigint;\nexport type BigIntGlobalPosition = bigint;\n\nexport type Event<\n  EventType extends string = string,\n  EventData extends DefaultRecord = DefaultRecord,\n  EventMetaData extends DefaultRecord | undefined = undefined,\n> = Readonly<\n  EventMetaData extends undefined\n    ? {\n        type: EventType;\n        data: EventData;\n      }\n    : {\n        type: EventType;\n        data: EventData;\n        metadata: EventMetaData;\n      }\n> & { readonly kind?: 'Event' };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyEvent = Event<any, any, any>;\n\nexport type EventTypeOf<T extends Event> = T['type'];\nexport type EventDataOf<T extends Event> = T['data'];\nexport type EventMetaDataOf<T extends Event> = T extends { metadata: infer M }\n  ? M\n  : undefined;\n\nexport type CreateEventType<\n  EventType extends string,\n  EventData extends DefaultRecord,\n  EventMetaData extends DefaultRecord | undefined = undefined,\n> = Readonly<\n  EventMetaData extends undefined\n    ? {\n        type: EventType;\n        data: EventData;\n      }\n    : {\n        type: EventType;\n        data: EventData;\n        metadata: EventMetaData;\n      }\n> & { readonly kind?: 'Event' };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const event = <EventType extends Event<string, any, any>>(\n  ...args: EventMetaDataOf<EventType> extends undefined\n    ? [type: EventTypeOf<EventType>, data: EventDataOf<EventType>]\n    : [\n        type: EventTypeOf<EventType>,\n        data: EventDataOf<EventType>,\n        metadata: EventMetaDataOf<EventType>,\n      ]\n): EventType => {\n  const [type, data, metadata] = args;\n\n  return metadata !== undefined\n    ? ({ type, data, metadata, kind: 'Event' } as EventType)\n    : ({ type, data, kind: 'Event' } as EventType);\n};\n\nexport type CombinedReadEventMetadata<\n  EventType extends Event = Event,\n  EventMetaDataType extends\n    AnyRecordedMessageMetadata = AnyRecordedMessageMetadata,\n> = CombinedMessageMetadata<EventType, EventMetaDataType>;\n\nexport type ReadEvent<\n  EventType extends Event = Event,\n  EventMetaDataType extends\n    AnyRecordedMessageMetadata = AnyRecordedMessageMetadata,\n> = RecordedMessage<EventType, EventMetaDataType>;\n\nexport type AnyReadEvent<\n  EventMetaDataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n> = ReadEvent<AnyEvent, EventMetaDataType>;\n\nexport type CommonReadEventMetadata<StreamPosition = BigIntStreamPosition> =\n  CommonRecordedMessageMetadata<StreamPosition>;\n\nexport type ReadEventMetadata<\n  GlobalPosition = undefined,\n  StreamPosition = BigIntStreamPosition,\n> = RecordedMessageMetadata<GlobalPosition, StreamPosition>;\n\nexport type AnyReadEventMetadata = AnyRecordedMessageMetadata;\n\nexport type ReadEventMetadataWithGlobalPosition<\n  GlobalPosition = BigIntGlobalPosition,\n> = RecordedMessageMetadataWithGlobalPosition<GlobalPosition>;\n\nexport type ReadEventMetadataWithoutGlobalPosition<\n  StreamPosition = BigIntStreamPosition,\n> = RecordedMessageMetadataWithoutGlobalPosition<StreamPosition>;\n\nexport type GlobalPositionTypeOfReadEventMetadata<ReadEventMetadataType> =\n  GlobalPositionTypeOfRecordedMessageMetadata<ReadEventMetadataType>;\n\nexport type StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType> =\n  StreamPositionTypeOfRecordedMessageMetadata<ReadEventMetadataType>;\n","import type {\n  AnyCommand,\n  AnyEvent,\n  BigIntGlobalPosition,\n  BigIntStreamPosition,\n  Command,\n  DefaultRecord,\n  Event,\n} from '.';\n\nexport type Message<\n  Type extends string = string,\n  Data extends DefaultRecord = DefaultRecord,\n  MetaData extends DefaultRecord | undefined = undefined,\n> = Command<Type, Data, MetaData> | Event<Type, Data, MetaData>;\n\nexport type AnyMessage = AnyEvent | AnyCommand;\n\nexport type MessageKindOf<T extends Message> = T['kind'];\nexport type MessageTypeOf<T extends Message> = T['type'];\nexport type MessageDataOf<T extends Message> = T['data'];\nexport type MessageMetaDataOf<T extends Message> = T extends {\n  metadata: infer M;\n}\n  ? M\n  : undefined;\n\nexport type CanHandle<T extends Message> = MessageTypeOf<T>[];\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const message = <MessageType extends Message<string, any, any>>(\n  ...args: MessageMetaDataOf<MessageType> extends undefined\n    ? [\n        kind: MessageKindOf<MessageType>,\n        type: MessageTypeOf<MessageType>,\n        data: MessageDataOf<MessageType>,\n      ]\n    : [\n        kind: MessageKindOf<MessageType>,\n        type: MessageTypeOf<MessageType>,\n        data: MessageDataOf<MessageType>,\n        metadata: MessageMetaDataOf<MessageType>,\n      ]\n): MessageType => {\n  const [kind, type, data, metadata] = args;\n\n  return metadata !== undefined\n    ? ({ type, data, metadata, kind } as MessageType)\n    : ({ type, data, kind } as MessageType);\n};\n\nexport type CombinedMessageMetadata<\n  MessageType extends Message = Message,\n  MessageMetaDataType extends DefaultRecord = DefaultRecord,\n> =\n  MessageMetaDataOf<MessageType> extends undefined\n    ? MessageMetaDataType\n    : MessageMetaDataOf<MessageType> & MessageMetaDataType;\n\nexport type CombineMetadata<\n  MessageType extends Message = Message,\n  MessageMetaDataType extends DefaultRecord = DefaultRecord,\n> = MessageType & {\n  metadata: CombinedMessageMetadata<MessageType, MessageMetaDataType>;\n};\n\nexport type RecordedMessage<\n  MessageType extends Message = Message,\n  MessageMetaDataType extends\n    AnyRecordedMessageMetadata = AnyRecordedMessageMetadata,\n> = CombineMetadata<MessageType, MessageMetaDataType> & {\n  kind: NonNullable<MessageKindOf<Message>>;\n};\n\nexport type CommonRecordedMessageMetadata<\n  StreamPosition = BigIntStreamPosition,\n> = Readonly<{\n  messageId: string;\n  streamPosition: StreamPosition;\n  streamName: string;\n}>;\n\nexport type WithGlobalPosition<GlobalPosition> = Readonly<{\n  globalPosition: GlobalPosition;\n}>;\n\nexport type RecordedMessageMetadata<\n  GlobalPosition = undefined,\n  StreamPosition = BigIntStreamPosition,\n> = CommonRecordedMessageMetadata<StreamPosition> &\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n  (GlobalPosition extends undefined ? {} : WithGlobalPosition<GlobalPosition>);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyRecordedMessageMetadata = RecordedMessageMetadata<any, any>;\n\nexport type RecordedMessageMetadataWithGlobalPosition<\n  GlobalPosition = BigIntGlobalPosition,\n> = RecordedMessageMetadata<GlobalPosition>;\n\nexport type RecordedMessageMetadataWithoutGlobalPosition<\n  StreamPosition = BigIntStreamPosition,\n> = RecordedMessageMetadata<undefined, StreamPosition>;\n\nexport type GlobalPositionTypeOfRecordedMessageMetadata<\n  RecordedMessageMetadataType,\n> =\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  RecordedMessageMetadataType extends RecordedMessageMetadata<infer GP, any>\n    ? GP\n    : never;\n\nexport type StreamPositionTypeOfRecordedMessageMetadata<\n  RecordedMessageMetadataType,\n> =\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  RecordedMessageMetadataType extends RecordedMessageMetadata<any, infer SV>\n    ? SV\n    : never;\n","import type { AnyCommand } from './command';\nimport type { AnyEvent } from './event';\n\n/// Inspired by https://blog.bittacklr.be/the-workflow-pattern.html\n\nexport type Workflow<\n  Input extends AnyEvent | AnyCommand,\n  State,\n  Output extends AnyEvent | AnyCommand,\n> = {\n  decide: (command: Input, state: State) => WorkflowOutput<Output>[];\n  evolve: (currentState: State, event: WorkflowEvent<Output>) => State;\n  initialState: () => State;\n};\n\nexport type WorkflowEvent<Output extends AnyEvent | AnyCommand> = Extract<\n  Output,\n  { kind?: 'Event' }\n>;\n\nexport type WorkflowCommand<Output extends AnyEvent | AnyCommand> = Extract<\n  Output,\n  { kind?: 'Command' }\n>;\n\nexport type WorkflowOutput<TOutput extends AnyEvent | AnyCommand> =\n  | { action: 'Reply'; message: TOutput }\n  | { action: 'Send'; message: WorkflowCommand<TOutput> }\n  | { action: 'Publish'; message: WorkflowEvent<TOutput> }\n  | {\n      action: 'Schedule';\n      message: TOutput;\n      when: { afterInMs: number } | { at: Date };\n    }\n  | { action: 'Complete' }\n  | { action: 'Accept' }\n  | { action: 'Ignore'; reason: string }\n  | { action: 'Error'; reason: string };\n\nexport const reply = <TOutput extends AnyEvent | AnyCommand>(\n  message: TOutput,\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Reply',\n    message,\n  };\n};\n\nexport const send = <TOutput extends AnyEvent | AnyCommand>(\n  message: WorkflowCommand<TOutput>,\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Send',\n    message,\n  };\n};\n\nexport const publish = <TOutput extends AnyEvent | AnyCommand>(\n  message: WorkflowEvent<TOutput>,\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Publish',\n    message,\n  };\n};\n\nexport const schedule = <TOutput extends AnyEvent | AnyCommand>(\n  message: TOutput,\n  when: { afterInMs: number } | { at: Date },\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Schedule',\n    message,\n    when,\n  };\n};\n\nexport const complete = <\n  TOutput extends AnyEvent | AnyCommand,\n>(): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Complete',\n  };\n};\n\nexport const ignore = <TOutput extends AnyEvent | AnyCommand>(\n  reason: string,\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Ignore',\n    reason,\n  };\n};\n\nexport const error = <TOutput extends AnyEvent | AnyCommand>(\n  reason: string,\n): WorkflowOutput<TOutput> => {\n  return {\n    action: 'Error',\n    reason,\n  };\n};\n\nexport const accept = <\n  TOutput extends AnyEvent | AnyCommand,\n>(): WorkflowOutput<TOutput> => {\n  return { action: 'Accept' };\n};\n","import {\n  type BatchRecordedMessageHandlerWithContext,\n  type BatchRecordedMessageHandlerWithoutContext,\n  type DefaultRecord,\n  type Event,\n  type ReadEvent,\n} from '../../typing';\nimport type { EventStore, EventStoreReadEventMetadata } from '../eventStore';\n\nexport type AfterEventStoreCommitHandler<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> = HandlerContext extends undefined\n  ? BatchRecordedMessageHandlerWithoutContext<\n      Event,\n      EventStoreReadEventMetadata<Store>\n    >\n  : BatchRecordedMessageHandlerWithContext<\n      Event,\n      EventStoreReadEventMetadata<Store>,\n      NonNullable<HandlerContext>\n    >;\n\nexport type BeforeEventStoreCommitHandler<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> = HandlerContext extends undefined\n  ? BatchRecordedMessageHandlerWithoutContext<\n      Event,\n      EventStoreReadEventMetadata<Store>\n    >\n  : BatchRecordedMessageHandlerWithContext<\n      Event,\n      EventStoreReadEventMetadata<Store>,\n      NonNullable<HandlerContext>\n    >;\n\ntype TryPublishMessagesAfterCommitOptions<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> = {\n  onAfterCommit?: AfterEventStoreCommitHandler<Store, HandlerContext>;\n};\n\nexport async function tryPublishMessagesAfterCommit<Store extends EventStore>(\n  messages: ReadEvent<Event, EventStoreReadEventMetadata<Store>>[],\n  options: TryPublishMessagesAfterCommitOptions<Store, undefined> | undefined,\n): Promise<boolean>;\nexport async function tryPublishMessagesAfterCommit<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n>(\n  messages: ReadEvent<Event, EventStoreReadEventMetadata<Store>>[],\n  options:\n    | TryPublishMessagesAfterCommitOptions<Store, HandlerContext>\n    | undefined,\n  context: HandlerContext,\n): Promise<boolean>;\nexport async function tryPublishMessagesAfterCommit<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n>(\n  messages: ReadEvent<Event, EventStoreReadEventMetadata<Store>>[],\n  options:\n    | TryPublishMessagesAfterCommitOptions<Store, HandlerContext>\n    | undefined,\n  context?: HandlerContext,\n): Promise<boolean> {\n  if (options?.onAfterCommit === undefined) return false;\n\n  try {\n    await options?.onAfterCommit(messages, context!);\n    return true;\n  } catch (error) {\n    // TODO: enhance with tracing\n    console.error(`Error in on after commit hook`, error);\n    return false;\n  }\n}\n","import type { EventsPublisher } from '../../messageBus';\nimport type { DefaultRecord, Event, ReadEvent } from '../../typing';\nimport type { EventStore, EventStoreReadEventMetadata } from '../eventStore';\nimport type { AfterEventStoreCommitHandler } from './afterEventStoreCommitHandler';\n\nexport const forwardToMessageBus = <\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n>(\n  eventPublisher: EventsPublisher,\n): AfterEventStoreCommitHandler<Store, HandlerContext> =>\n  (async (\n    messages: ReadEvent<Event, EventStoreReadEventMetadata<Store>>[],\n  ): Promise<void> => {\n    for (const message of messages) {\n      await eventPublisher.publish(message);\n    }\n  }) as AfterEventStoreCommitHandler<Store, HandlerContext>;\n","import {\n  event,\n  type Event,\n  type EventDataOf,\n  type ReadEvent,\n  type ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\n\nexport const GlobalStreamCaughtUpType = '__emt:GlobalStreamCaughtUp';\n\nexport type GlobalStreamCaughtUp = Event<\n  '__emt:GlobalStreamCaughtUp',\n  { globalPosition: bigint },\n  { globalPosition: bigint }\n>;\n\nexport const isGlobalStreamCaughtUp = (\n  event: Event,\n): event is GlobalStreamCaughtUp => event.type === GlobalStreamCaughtUpType;\n\nexport const caughtUpEventFrom =\n  (position: bigint) =>\n  (\n    event: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>,\n  ): event is ReadEvent<\n    GlobalStreamCaughtUp,\n    ReadEventMetadataWithGlobalPosition\n  > =>\n    event.type === GlobalStreamCaughtUpType &&\n    event.metadata?.globalPosition >= position;\n\nexport const globalStreamCaughtUp = (\n  data: EventDataOf<GlobalStreamCaughtUp>,\n): GlobalStreamCaughtUp =>\n  event<GlobalStreamCaughtUp>(GlobalStreamCaughtUpType, data, {\n    globalPosition: data.globalPosition,\n  });\n\nexport const isSubscriptionEvent = (\n  event: Event,\n): event is GlobalSubscriptionEvent => isGlobalStreamCaughtUp(event);\n\nexport const isNotInternalEvent = (event: Event): boolean =>\n  !isGlobalStreamCaughtUp(event);\n\nexport type GlobalSubscriptionEvent = GlobalStreamCaughtUp;\n","//import type { ReadableStream } from 'web-streams-polyfill';\nimport type {\n  AnyReadEventMetadata,\n  BigIntGlobalPosition,\n  BigIntStreamPosition,\n  CommonReadEventMetadata,\n  DefaultRecord,\n  Event,\n  GlobalPositionTypeOfReadEventMetadata,\n  ReadEvent,\n  ReadEventMetadata,\n  StreamPositionTypeOfReadEventMetadata,\n  WithGlobalPosition,\n} from '../typing';\nimport type { AfterEventStoreCommitHandler } from './afterCommit';\n//import type { GlobalSubscriptionEvent } from './events';\nimport type { ExpectedStreamVersion } from './expectedVersion';\n\n// #region event-store\nexport interface EventStore<\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n> {\n  aggregateStream<State, EventType extends Event>(\n    streamName: string,\n    options: AggregateStreamOptions<State, EventType, ReadEventMetadataType>,\n  ): Promise<\n    AggregateStreamResult<\n      State,\n      StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>\n    >\n  >;\n\n  readStream<EventType extends Event>(\n    streamName: string,\n    options?: ReadStreamOptions<\n      StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>\n    >,\n  ): Promise<ReadStreamResult<EventType, ReadEventMetadataType>>;\n\n  appendToStream<EventType extends Event>(\n    streamName: string,\n    events: EventType[],\n    options?: AppendToStreamOptions<\n      StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>\n    >,\n  ): Promise<\n    AppendToStreamResult<\n      StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>\n    >\n  >;\n\n  // streamEvents(): ReadableStream<\n  //   ReadEvent<Event, ReadEventMetadataType> | GlobalSubscriptionEvent\n  // >;\n}\n\nexport type EventStoreReadEventMetadata<Store extends EventStore> =\n  Store extends EventStore<infer T>\n    ? T extends CommonReadEventMetadata<infer SP>\n      ? T extends WithGlobalPosition<infer GP>\n        ? ReadEventMetadata<GP, SP> & T\n        : ReadEventMetadata<undefined, SP> & T\n      : never\n    : never;\n\nexport type GlobalPositionTypeOfEventStore<Store extends EventStore> =\n  GlobalPositionTypeOfReadEventMetadata<EventStoreReadEventMetadata<Store>>;\n\nexport type StreamPositionTypeOfEventStore<Store extends EventStore> =\n  StreamPositionTypeOfReadEventMetadata<EventStoreReadEventMetadata<Store>>;\n\nexport type EventStoreSession<EventStoreType extends EventStore> = {\n  eventStore: EventStoreType;\n  close: () => Promise<void>;\n};\n\nexport interface EventStoreSessionFactory<EventStoreType extends EventStore> {\n  withSession<T = unknown>(\n    callback: (session: EventStoreSession<EventStoreType>) => Promise<T>,\n  ): Promise<T>;\n}\n// #endregion event-store\n\nexport const canCreateEventStoreSession = <Store extends EventStore>(\n  eventStore: Store | EventStoreSessionFactory<Store>,\n): eventStore is EventStoreSessionFactory<Store> => 'withSession' in eventStore;\n\nexport const nulloSessionFactory = <EventStoreType extends EventStore>(\n  eventStore: EventStoreType,\n): EventStoreSessionFactory<EventStoreType> => ({\n  withSession: (callback) => {\n    const nulloSession: EventStoreSession<EventStoreType> = {\n      eventStore,\n      close: () => Promise.resolve(),\n    };\n\n    return callback(nulloSession);\n  },\n});\n\n////////////////////////////////////////////////////////////////////\n/// ReadStream types\n////////////////////////////////////////////////////////////////////\n\nexport type ReadStreamOptions<StreamVersion = BigIntStreamPosition> = (\n  | {\n      from: StreamVersion;\n    }\n  | { to: StreamVersion }\n  | { from: StreamVersion; maxCount?: bigint }\n  | {\n      expectedStreamVersion: ExpectedStreamVersion<StreamVersion>;\n    }\n) & {\n  expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n};\n\nexport type ReadStreamResult<\n  EventType extends Event,\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n> = {\n  currentStreamVersion: StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>;\n  events: ReadEvent<EventType, ReadEventMetadataType>[];\n  streamExists: boolean;\n};\n\n////////////////////////////////////////////////////////////////////\n/// AggregateStream types\n////////////////////////////////////////////////////////////////////\n\ntype Evolve<\n  State,\n  EventType extends Event,\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n> =\n  | ((currentState: State, event: EventType) => State)\n  | ((\n      currentState: State,\n      event: ReadEvent<EventType, ReadEventMetadataType>,\n    ) => State)\n  | ((currentState: State, event: ReadEvent<EventType>) => State);\n\nexport type AggregateStreamOptions<\n  State,\n  EventType extends Event,\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n> = {\n  evolve: Evolve<State, EventType, ReadEventMetadataType>;\n  initialState: () => State;\n  read?: ReadStreamOptions<\n    StreamPositionTypeOfReadEventMetadata<ReadEventMetadataType>\n  >;\n};\n\nexport type AggregateStreamResult<\n  State,\n  StreamPosition = BigIntStreamPosition,\n> = {\n  currentStreamVersion: StreamPosition;\n  state: State;\n  streamExists: boolean;\n};\n\nexport type AggregateStreamResultWithGlobalPosition<\n  State,\n  StreamPosition = BigIntStreamPosition,\n  GlobalPosition = BigIntGlobalPosition,\n> =\n  | (AggregateStreamResult<State, StreamPosition> & {\n      streamExists: true;\n      lastEventGlobalPosition: GlobalPosition;\n    })\n  | (AggregateStreamResult<State, StreamPosition> & {\n      streamExists: false;\n    });\n\nexport type AggregateStreamResultOfEventStore<Store extends EventStore> =\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  Store['aggregateStream'] extends (...args: any[]) => Promise<infer R>\n    ? R\n    : never;\n\n////////////////////////////////////////////////////////////////////\n/// AppendToStream types\n////////////////////////////////////////////////////////////////////\n\nexport type AppendToStreamOptions<StreamVersion = BigIntStreamPosition> = {\n  expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n};\n\nexport type AppendToStreamResult<StreamVersion = BigIntStreamPosition> = {\n  nextExpectedStreamVersion: StreamVersion;\n  createdNewStream: boolean;\n};\n\nexport type AppendToStreamResultWithGlobalPosition<\n  StreamVersion = BigIntStreamPosition,\n  GlobalPosition = BigIntGlobalPosition,\n> = AppendToStreamResult<StreamVersion> & {\n  lastEventGlobalPosition: GlobalPosition;\n};\n\nexport type AppendStreamResultOfEventStore<Store extends EventStore> =\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  Store['appendToStream'] extends (...args: any[]) => Promise<infer R>\n    ? R\n    : never;\n\n////////////////////////////////////////////////////////////////////\n/// DefaultEventStoreOptions\n////////////////////////////////////////////////////////////////////\n\nexport type DefaultEventStoreOptions<\n  Store extends EventStore,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> = {\n  /**\n   * Pluggable set of hooks informing about the event store internal behaviour.\n   */\n  hooks?: {\n    /**\n     * This hook will be called **AFTER** events were stored in the event store.\n     * It's designed to handle scenarios where delivery and ordering guarantees do not matter much.\n     *\n     * **WARNINGS:**\n     *\n     *  1. It will be called **EXACTLY ONCE** if append succeded.\n     *  2. If the hook fails, its append **will still silently succeed**, and no error will be thrown.\n     *  3. Wen process crashes after events were committed, but before the hook was called, delivery won't be retried.\n     * That can lead to state inconsistencies.\n     *  4. In the case of high concurrent traffic, **race conditions may cause ordering issues**.\n     * For instance, where the second hook takes longer to process than the first one, ordering won't be guaranteed.\n     *\n     * @type {AfterEventStoreCommitHandler<Store, HandlerContext>}\n     */\n    onAfterCommit?: AfterEventStoreCommitHandler<Store, HandlerContext>;\n  };\n};\n","import { ConcurrencyError } from '../errors';\nimport type { BigIntStreamPosition, Flavour } from '../typing';\n\nexport type ExpectedStreamVersion<VersionType = BigIntStreamPosition> =\n  | ExpectedStreamVersionWithValue<VersionType>\n  | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<VersionType = BigIntStreamPosition> =\n  Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n  'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n  'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n  'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n  'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <StreamVersion = BigIntStreamPosition>(\n  current: StreamVersion | undefined,\n  expected: ExpectedStreamVersion<StreamVersion>,\n  defaultVersion: StreamVersion,\n): boolean => {\n  if (expected === NO_CONCURRENCY_CHECK) return true;\n\n  if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;\n\n  if (expected == STREAM_EXISTS) return current !== defaultVersion;\n\n  return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n  StreamVersion = BigIntStreamPosition,\n>(\n  current: StreamVersion,\n  expected: ExpectedStreamVersion<StreamVersion> | undefined,\n  defaultVersion: StreamVersion,\n): void => {\n  expected ??= NO_CONCURRENCY_CHECK;\n\n  if (!matchesExpectedVersion(current, expected, defaultVersion))\n    throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n  VersionType = BigIntStreamPosition,\n> extends ConcurrencyError {\n  constructor(\n    current: VersionType,\n    expected: ExpectedStreamVersion<VersionType>,\n  ) {\n    super(current?.toString(), expected?.toString());\n\n    // 👇️ because we are extending a built-in class\n    Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n  }\n}\n\nexport const isExpectedVersionConflictError = (\n  error: unknown,\n): error is ExpectedVersionConflictError =>\n  error instanceof ExpectedVersionConflictError;\n","import { v4 as uuid } from 'uuid';\nimport {\n  getInMemoryDatabase,\n  type InMemoryDatabase,\n} from '../database/inMemoryDatabase';\nimport type { ProjectionRegistration } from '../projections';\nimport type {\n  BigIntStreamPosition,\n  CombinedReadEventMetadata,\n  Event,\n  ReadEvent,\n  ReadEventMetadataWithGlobalPosition,\n} from '../typing';\nimport { tryPublishMessagesAfterCommit } from './afterCommit';\nimport {\n  type AggregateStreamOptions,\n  type AggregateStreamResult,\n  type AppendToStreamOptions,\n  type AppendToStreamResult,\n  type DefaultEventStoreOptions,\n  type EventStore,\n  type ReadStreamOptions,\n  type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\nimport { handleInMemoryProjections } from './projections/inMemory';\nimport { StreamingCoordinator } from './subscriptions';\n\nexport const InMemoryEventStoreDefaultStreamVersion = 0n;\n\nexport type InMemoryEventStore =\n  EventStore<ReadEventMetadataWithGlobalPosition> & {\n    database: InMemoryDatabase;\n  };\n\nexport type InMemoryReadEventMetadata = ReadEventMetadataWithGlobalPosition;\n\nexport type InMemoryProjectionHandlerContext = {\n  eventStore?: InMemoryEventStore;\n  database?: InMemoryDatabase;\n};\n\nexport type InMemoryEventStoreOptions =\n  DefaultEventStoreOptions<InMemoryEventStore> & {\n    projections?: ProjectionRegistration<\n      'inline',\n      InMemoryReadEventMetadata,\n      InMemoryProjectionHandlerContext\n    >[];\n    database?: InMemoryDatabase;\n  };\n\nexport type InMemoryReadEvent<EventType extends Event = Event> = ReadEvent<\n  EventType,\n  ReadEventMetadataWithGlobalPosition\n>;\n\nexport const getInMemoryEventStore = (\n  eventStoreOptions?: InMemoryEventStoreOptions,\n): InMemoryEventStore => {\n  const streams = new Map<\n    string,\n    ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]\n  >();\n  const streamingCoordinator = StreamingCoordinator();\n\n  const getAllEventsCount = () => {\n    return Array.from<ReadEvent[]>(streams.values())\n      .map((s) => s.length)\n      .reduce((p, c) => p + c, 0);\n  };\n\n  // Get the database instance to be used for projections\n  const database = eventStoreOptions?.database || getInMemoryDatabase();\n\n  // Extract inline projections from options\n  const inlineProjections = (eventStoreOptions?.projections ?? [])\n    .filter(({ type }) => type === 'inline')\n    .map(({ projection }) => projection);\n\n  // Create the event store object\n  const eventStore: InMemoryEventStore = {\n    database,\n    async aggregateStream<State, EventType extends Event>(\n      streamName: string,\n      options: AggregateStreamOptions<\n        State,\n        EventType,\n        ReadEventMetadataWithGlobalPosition\n      >,\n    ): Promise<AggregateStreamResult<State>> {\n      const { evolve, initialState, read } = options;\n\n      const result = await this.readStream<EventType>(streamName, read);\n\n      const events = result?.events ?? [];\n\n      return {\n        currentStreamVersion: BigInt(events.length),\n        state: events.reduce(evolve, initialState()),\n        streamExists: result.streamExists,\n      };\n    },\n\n    readStream: <EventType extends Event>(\n      streamName: string,\n      options?: ReadStreamOptions<BigIntStreamPosition>,\n    ): Promise<\n      ReadStreamResult<EventType, ReadEventMetadataWithGlobalPosition>\n    > => {\n      const events = streams.get(streamName);\n      const currentStreamVersion = events\n        ? BigInt(events.length)\n        : InMemoryEventStoreDefaultStreamVersion;\n\n      assertExpectedVersionMatchesCurrent(\n        currentStreamVersion,\n        options?.expectedStreamVersion,\n        InMemoryEventStoreDefaultStreamVersion,\n      );\n\n      const from = Number(options && 'from' in options ? options.from : 0);\n      const to = Number(\n        options && 'to' in options\n          ? options.to\n          : options && 'maxCount' in options && options.maxCount\n            ? options.from + options.maxCount\n            : (events?.length ?? 1),\n      );\n\n      const resultEvents =\n        events !== undefined && events.length > 0\n          ? events\n              .map(\n                (e) =>\n                  e as ReadEvent<\n                    EventType,\n                    ReadEventMetadataWithGlobalPosition\n                  >,\n              )\n              .slice(from, to)\n          : [];\n\n      const result: ReadStreamResult<\n        EventType,\n        ReadEventMetadataWithGlobalPosition\n      > = {\n        currentStreamVersion,\n        events: resultEvents,\n        streamExists: events !== undefined && events.length > 0,\n      };\n\n      return Promise.resolve(result);\n    },\n\n    appendToStream: async <EventType extends Event>(\n      streamName: string,\n      events: EventType[],\n      options?: AppendToStreamOptions,\n    ): Promise<AppendToStreamResult> => {\n      const currentEvents = streams.get(streamName) ?? [];\n      const currentStreamVersion =\n        currentEvents.length > 0\n          ? BigInt(currentEvents.length)\n          : InMemoryEventStoreDefaultStreamVersion;\n\n      assertExpectedVersionMatchesCurrent(\n        currentStreamVersion,\n        options?.expectedStreamVersion,\n        InMemoryEventStoreDefaultStreamVersion,\n      );\n\n      const newEvents: ReadEvent<\n        EventType,\n        ReadEventMetadataWithGlobalPosition\n      >[] = events.map((event, index) => {\n        const metadata: ReadEventMetadataWithGlobalPosition = {\n          streamName,\n          messageId: uuid(),\n          streamPosition: BigInt(currentEvents.length + index + 1),\n          globalPosition: BigInt(getAllEventsCount() + index + 1),\n        };\n        return {\n          ...event,\n          kind: event.kind ?? 'Event',\n          metadata: {\n            ...('metadata' in event ? (event.metadata ?? {}) : {}),\n            ...metadata,\n          } as CombinedReadEventMetadata<\n            EventType,\n            ReadEventMetadataWithGlobalPosition\n          >,\n        };\n      });\n\n      const positionOfLastEventInTheStream = BigInt(\n        newEvents.slice(-1)[0]!.metadata.streamPosition,\n      );\n\n      streams.set(streamName, [...currentEvents, ...newEvents]);\n      await streamingCoordinator.notify(newEvents);\n\n      // Process projections if there are any registered\n      if (inlineProjections.length > 0) {\n        await handleInMemoryProjections({\n          projections: inlineProjections,\n          events: newEvents,\n          database: eventStore.database,\n          eventStore,\n        });\n      }\n\n      const result: AppendToStreamResult = {\n        nextExpectedStreamVersion: positionOfLastEventInTheStream,\n        createdNewStream:\n          currentStreamVersion === InMemoryEventStoreDefaultStreamVersion,\n      };\n\n      await tryPublishMessagesAfterCommit<InMemoryEventStore>(\n        newEvents,\n        eventStoreOptions?.hooks,\n      );\n\n      return result;\n    },\n\n    //streamEvents: streamingCoordinator.stream,\n  };\n\n  return eventStore;\n};\n","import { v7 as uuid } from 'uuid';\nimport { deepEquals } from '../utils';\nimport {\n  type DatabaseHandleOptionErrors,\n  type DatabaseHandleOptions,\n  type DatabaseHandleResult,\n  type DeleteResult,\n  type Document,\n  type DocumentHandler,\n  type InsertOneResult,\n  type OptionalUnlessRequiredIdAndVersion,\n  type ReplaceOneOptions,\n  type UpdateResult,\n  type WithIdAndVersion,\n  type WithoutId,\n} from './types';\nimport { expectedVersionValue, operationResult } from './utils';\n\nexport interface InMemoryDocumentsCollection<T extends Document> {\n  handle: (\n    id: string,\n    handle: DocumentHandler<T>,\n    options?: DatabaseHandleOptions,\n  ) => Promise<DatabaseHandleResult<T>>;\n  findOne: (predicate?: Predicate<T>) => Promise<T | null>;\n  find: (predicate?: Predicate<T>) => Promise<T[]>;\n  insertOne: (\n    document: OptionalUnlessRequiredIdAndVersion<T>,\n  ) => Promise<InsertOneResult>;\n  deleteOne: (predicate?: Predicate<T>) => Promise<DeleteResult>;\n  replaceOne: (\n    predicate: Predicate<T>,\n    document: WithoutId<T>,\n    options?: ReplaceOneOptions,\n  ) => Promise<UpdateResult>;\n}\n\nexport interface InMemoryDatabase {\n  collection: <T extends Document>(\n    name: string,\n  ) => InMemoryDocumentsCollection<T>;\n}\n\ntype Predicate<T> = (item: T) => boolean;\ntype CollectionName = string;\n\nexport const getInMemoryDatabase = (): InMemoryDatabase => {\n  const storage = new Map<CollectionName, WithIdAndVersion<Document>[]>();\n\n  return {\n    collection: <T extends Document, CollectionName extends string>(\n      collectionName: CollectionName,\n      collectionOptions: {\n        errors?: DatabaseHandleOptionErrors;\n      } = {},\n    ): InMemoryDocumentsCollection<T> => {\n      const ensureCollectionCreated = () => {\n        if (!storage.has(collectionName)) storage.set(collectionName, []);\n      };\n\n      const errors = collectionOptions.errors;\n\n      const collection = {\n        collectionName,\n        insertOne: async (\n          document: OptionalUnlessRequiredIdAndVersion<T>,\n        ): Promise<InsertOneResult> => {\n          ensureCollectionCreated();\n\n          const _id = (document._id as string | undefined | null) ?? uuid();\n          const _version = document._version ?? 1n;\n\n          const existing = await collection.findOne((c) => c._id === _id);\n\n          if (existing) {\n            return operationResult<InsertOneResult>(\n              {\n                successful: false,\n                insertedId: null,\n                nextExpectedVersion: _version,\n              },\n              { operationName: 'insertOne', collectionName, errors },\n            );\n          }\n\n          const documentsInCollection = storage.get(collectionName)!;\n          const newDocument = { ...document, _id, _version };\n          const newCollection = [...documentsInCollection, newDocument];\n          storage.set(collectionName, newCollection);\n\n          return operationResult<InsertOneResult>(\n            {\n              successful: true,\n              insertedId: _id,\n              nextExpectedVersion: _version,\n            },\n            { operationName: 'insertOne', collectionName, errors },\n          );\n        },\n        findOne: (predicate?: Predicate<T>): Promise<T | null> => {\n          ensureCollectionCreated();\n\n          const documentsInCollection = storage.get(collectionName);\n          const filteredDocuments = predicate\n            ? documentsInCollection?.filter((doc) => predicate(doc as T))\n            : documentsInCollection;\n\n          const firstOne = filteredDocuments?.[0] ?? null;\n\n          return Promise.resolve(firstOne as T | null);\n        },\n        find: (predicate?: Predicate<T>): Promise<T[]> => {\n          ensureCollectionCreated();\n\n          const documentsInCollection = storage.get(collectionName);\n          const filteredDocuments = predicate\n            ? documentsInCollection?.filter((doc) => predicate(doc as T))\n            : documentsInCollection;\n\n          return Promise.resolve(filteredDocuments as T[]);\n        },\n        deleteOne: (predicate?: Predicate<T>): Promise<DeleteResult> => {\n          ensureCollectionCreated();\n\n          const documentsInCollection = storage.get(collectionName)!;\n\n          if (predicate) {\n            const foundIndex = documentsInCollection.findIndex((doc) =>\n              predicate(doc as T),\n            );\n\n            if (foundIndex === -1) {\n              return Promise.resolve(\n                operationResult<DeleteResult>(\n                  {\n                    successful: false,\n                    matchedCount: 0,\n                    deletedCount: 0,\n                  },\n                  { operationName: 'deleteOne', collectionName, errors },\n                ),\n              );\n            } else {\n              const newCollection = documentsInCollection.toSpliced(\n                foundIndex,\n                1,\n              );\n\n              storage.set(collectionName, newCollection);\n\n              return Promise.resolve(\n                operationResult<DeleteResult>(\n                  {\n                    successful: true,\n                    matchedCount: 1,\n                    deletedCount: 1,\n                  },\n                  { operationName: 'deleteOne', collectionName, errors },\n                ),\n              );\n            }\n          }\n\n          const newCollection = documentsInCollection.slice(1);\n\n          storage.set(collectionName, newCollection);\n\n          return Promise.resolve(\n            operationResult<DeleteResult>(\n              {\n                successful: true,\n                matchedCount: 1,\n                deletedCount: 1,\n              },\n              { operationName: 'deleteOne', collectionName, errors },\n            ),\n          );\n        },\n        replaceOne: (\n          predicate: Predicate<T>,\n          document: WithoutId<T>,\n          options?: ReplaceOneOptions,\n        ): Promise<UpdateResult> => {\n          ensureCollectionCreated();\n\n          const documentsInCollection = storage.get(collectionName)!;\n\n          const firstIndex = documentsInCollection.findIndex((doc) =>\n            predicate(doc as T),\n          );\n\n          if (firstIndex === undefined || firstIndex === -1) {\n            return Promise.resolve(\n              operationResult<UpdateResult>(\n                {\n                  successful: false,\n                  matchedCount: 0,\n                  modifiedCount: 0,\n                  nextExpectedVersion: 0n,\n                },\n                { operationName: 'replaceOne', collectionName, errors },\n              ),\n            );\n          }\n\n          const existing = documentsInCollection[firstIndex]!;\n\n          if (\n            typeof options?.expectedVersion === 'bigint' &&\n            existing._version !== options.expectedVersion\n          ) {\n            return Promise.resolve(\n              operationResult<UpdateResult>(\n                {\n                  successful: false,\n                  matchedCount: 1,\n                  modifiedCount: 0,\n                  nextExpectedVersion: existing._version,\n                },\n                { operationName: 'replaceOne', collectionName, errors },\n              ),\n            );\n          }\n\n          const newVersion = existing._version + 1n;\n\n          const newCollection = documentsInCollection.with(firstIndex, {\n            _id: existing._id,\n            ...document,\n            _version: newVersion,\n          });\n\n          storage.set(collectionName, newCollection);\n\n          return Promise.resolve(\n            operationResult<UpdateResult>(\n              {\n                successful: true,\n                modifiedCount: 1,\n                matchedCount: firstIndex,\n                nextExpectedVersion: newVersion,\n              },\n              { operationName: 'replaceOne', collectionName, errors },\n            ),\n          );\n        },\n        handle: async (\n          id: string,\n          handle: DocumentHandler<T>,\n          options?: DatabaseHandleOptions,\n        ): Promise<DatabaseHandleResult<T>> => {\n          const { expectedVersion: version, ...operationOptions } =\n            options ?? {};\n          ensureCollectionCreated();\n          const existing = await collection.findOne(({ _id }) => _id === id);\n\n          const expectedVersion = expectedVersionValue(version);\n\n          if (\n            (existing == null && version === 'DOCUMENT_EXISTS') ||\n            (existing == null && expectedVersion != null) ||\n            (existing != null && version === 'DOCUMENT_DOES_NOT_EXIST') ||\n            (existing != null &&\n              expectedVersion !== null &&\n              existing._version !== expectedVersion)\n          ) {\n            return operationResult<DatabaseHandleResult<T>>(\n              {\n                successful: false,\n                document: existing as WithIdAndVersion<T>,\n              },\n              { operationName: 'handle', collectionName, errors },\n            );\n          }\n\n          const result = handle(existing !== null ? { ...existing } : null);\n\n          if (deepEquals(existing, result))\n            return operationResult<DatabaseHandleResult<T>>(\n              {\n                successful: true,\n                document: existing as WithIdAndVersion<T>,\n              },\n              { operationName: 'handle', collectionName, errors },\n            );\n\n          if (!existing && result) {\n            const newDoc = { ...result, _id: id };\n            const insertResult = await collection.insertOne({\n              ...newDoc,\n              _id: id,\n            } as OptionalUnlessRequiredIdAndVersion<T>);\n            return {\n              ...insertResult,\n              document: {\n                ...newDoc,\n                _version: insertResult.nextExpectedVersion,\n              } as unknown as WithIdAndVersion<T>,\n            };\n          }\n\n          if (existing && !result) {\n            const deleteResult = await collection.deleteOne(\n              ({ _id }) => id === _id,\n            );\n            return { ...deleteResult, document: null };\n          }\n\n          if (existing && result) {\n            const replaceResult = await collection.replaceOne(\n              ({ _id }) => id === _id,\n              result,\n              {\n                ...operationOptions,\n                expectedVersion: expectedVersion ?? 'DOCUMENT_EXISTS',\n              },\n            );\n            return {\n              ...replaceResult,\n              document: {\n                ...result,\n                _version: replaceResult.nextExpectedVersion,\n              } as unknown as WithIdAndVersion<T>,\n            };\n          }\n\n          return operationResult<DatabaseHandleResult<T>>(\n            {\n              successful: true,\n              document: existing as WithIdAndVersion<T>,\n            },\n            { operationName: 'handle', collectionName, errors },\n          );\n        },\n      };\n\n      return collection;\n    },\n  };\n};\n","export const hasDuplicates = <ArrayItem, Mapped>(\n  array: ArrayItem[],\n  predicate: (value: ArrayItem, index: number, array: ArrayItem[]) => Mapped,\n) => {\n  const mapped = array.map(predicate);\n  const uniqueValues = new Set(mapped);\n\n  return uniqueValues.size < mapped.length;\n};\n\nexport const getDuplicates = <ArrayItem, Mapped>(\n  array: ArrayItem[],\n  predicate: (value: ArrayItem, index: number, array: ArrayItem[]) => Mapped,\n): ArrayItem[] => {\n  const map = new Map<Mapped, ArrayItem[]>();\n\n  for (let i = 0; i < array.length; i++) {\n    const item = array[i]!;\n    const key = predicate(item, i, array);\n    if (!map.has(key)) {\n      map.set(key, []);\n    }\n    map.get(key)!.push(item);\n  }\n\n  return Array.from(map.values())\n    .filter((group) => group.length > 1)\n    .flat();\n};\n","export const merge = <T>(\n  array: T[],\n  item: T,\n  where: (current: T) => boolean,\n  onExisting: (current: T) => T,\n  onNotFound: () => T | undefined = () => undefined,\n) => {\n  let wasFound = false;\n\n  const result = array\n    // merge the existing item if matches condition\n    .map((p: T) => {\n      if (!where(p)) return p;\n\n      wasFound = true;\n      return onExisting(p);\n    })\n    // filter out item if undefined was returned\n    // for cases of removal\n    .filter((p) => p !== undefined)\n    // make TypeScript happy\n    .map((p) => {\n      if (!p) throw Error('That should not happen');\n\n      return p;\n    });\n\n  // if item was not found and onNotFound action is defined\n  // try to generate new item\n  if (!wasFound) {\n    const result = onNotFound();\n\n    if (result !== undefined) return [...array, item];\n  }\n\n  return result;\n};\n","import { getDuplicates, hasDuplicates } from './duplicates';\nimport { merge } from './merge';\n\nexport * from './merge';\n\nexport const arrayUtils = {\n  merge,\n  hasDuplicates,\n  getDuplicates,\n};\n","export const deepEquals = <T>(left: T, right: T): boolean => {\n  if (isEquatable(left)) {\n    return left.equals(right);\n  }\n\n  if (Array.isArray(left)) {\n    return (\n      Array.isArray(right) &&\n      left.length === right.length &&\n      left.every((val, index) => deepEquals(val, right[index]))\n    );\n  }\n\n  if (\n    typeof left !== 'object' ||\n    typeof right !== 'object' ||\n    left === null ||\n    right === null\n  ) {\n    return left === right;\n  }\n\n  if (Array.isArray(right)) return false;\n\n  const keys1 = Object.keys(left);\n  const keys2 = Object.keys(right);\n\n  if (\n    keys1.length !== keys2.length ||\n    !keys1.every((key) => keys2.includes(key))\n  )\n    return false;\n\n  for (const key in left) {\n    if (left[key] instanceof Function && right[key] instanceof Function)\n      continue;\n\n    const isEqual = deepEquals(left[key], right[key]);\n    if (!isEqual) {\n      return false;\n    }\n  }\n\n  return true;\n};\n\nexport type Equatable<T> = { equals: (right: T) => boolean } & T;\n\nexport const isEquatable = <T>(left: T): left is Equatable<T> => {\n  return (\n    left &&\n    typeof left === 'object' &&\n    'equals' in left &&\n    typeof left['equals'] === 'function'\n  );\n};\n","export const sum = (\n  iterator: Iterator<number, number, number> | Iterator<number>,\n) => {\n  let value,\n    done: boolean | undefined,\n    sum = 0;\n  do {\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n    ({ value, done } = iterator.next());\n    sum += value || 0;\n  } while (!done);\n  return sum;\n};\n","import { EmmettError } from '../errors';\n\nexport type TaskQueue = TaskQueueItem[];\n\nexport type TaskQueueItem = {\n  task: () => Promise<void>;\n  options?: EnqueueTaskOptions;\n};\n\nexport type TaskProcessorOptions = {\n  maxActiveTasks: number;\n  maxQueueSize: number;\n  maxTaskIdleTime?: number;\n};\n\nexport type Task<T> = (context: TaskContext) => Promise<T>;\n\nexport type TaskContext = {\n  ack: () => void;\n};\n\nexport type EnqueueTaskOptions = { taskGroupId?: string };\n\nexport class TaskProcessor {\n  private queue: TaskQueue = [];\n  private isProcessing = false;\n  private activeTasks = 0;\n  private activeGroups: Set<string> = new Set();\n\n  constructor(private options: TaskProcessorOptions) {}\n\n  enqueue<T>(task: Task<T>, options?: EnqueueTaskOptions): Promise<T> {\n    if (this.queue.length >= this.options.maxQueueSize) {\n      return Promise.reject(\n        new EmmettError(\n          'Too many pending connections. Please try again later.',\n        ),\n      );\n    }\n\n    return this.schedule(task, options);\n  }\n\n  waitForEndOfProcessing(): Promise<void> {\n    return this.schedule(({ ack }) => Promise.resolve(ack()));\n  }\n\n  private schedule<T>(task: Task<T>, options?: EnqueueTaskOptions): Promise<T> {\n    return promiseWithDeadline(\n      (resolve, reject) => {\n        const taskWithContext = () => {\n          return new Promise<void>((resolveTask, failTask) => {\n            const taskPromise = task({\n              ack: resolveTask,\n            });\n\n            taskPromise.then(resolve).catch((err) => {\n              // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n              failTask(err);\n              reject(err);\n            });\n          });\n        };\n\n        this.queue.push({ task: taskWithContext, options });\n        if (!this.isProcessing) {\n          this.ensureProcessing();\n        }\n      },\n      { deadline: this.options.maxTaskIdleTime },\n    );\n  }\n\n  private ensureProcessing(): void {\n    if (this.isProcessing) return;\n    this.isProcessing = true;\n    this.processQueue();\n  }\n\n  private processQueue(): void {\n    try {\n      while (\n        this.activeTasks < this.options.maxActiveTasks &&\n        this.queue.length > 0\n      ) {\n        const item = this.takeFirstAvailableItem();\n\n        if (item === null) return;\n\n        const groupId = item.options?.taskGroupId;\n\n        if (groupId) {\n          // Mark the group as active\n          this.activeGroups.add(groupId);\n        }\n\n        this.activeTasks++;\n        void this.executeItem(item);\n      }\n    } catch (error) {\n      console.error(error);\n      throw error;\n    } finally {\n      this.isProcessing = false;\n      if (\n        this.hasItemsToProcess() &&\n        this.activeTasks < this.options.maxActiveTasks\n      ) {\n        this.ensureProcessing();\n      }\n    }\n  }\n\n  private async executeItem({ task, options }: TaskQueueItem): Promise<void> {\n    try {\n      await task();\n    } finally {\n      this.activeTasks--;\n\n      // Mark the group as inactive after task completion\n      if (options && options.taskGroupId) {\n        this.activeGroups.delete(options.taskGroupId);\n      }\n\n      this.ensureProcessing();\n    }\n  }\n\n  private takeFirstAvailableItem = (): TaskQueueItem | null => {\n    const taskIndex = this.queue.findIndex(\n      (item) =>\n        !item.options?.taskGroupId ||\n        !this.activeGroups.has(item.options.taskGroupId),\n    );\n\n    if (taskIndex === -1) {\n      // All remaining tasks are blocked by active groups\n      return null;\n    }\n\n    // Remove the task from the queue\n    const [item] = this.queue.splice(taskIndex, 1);\n\n    return item ?? null;\n  };\n\n  private hasItemsToProcess = (): boolean =>\n    this.queue.findIndex(\n      (item) =>\n        !item.options?.taskGroupId ||\n        !this.activeGroups.has(item.options.taskGroupId),\n    ) !== -1;\n}\n\nconst DEFAULT_PROMISE_DEADLINE = 2147483647;\n\nconst promiseWithDeadline = <T>(\n  executor: (\n    resolve: (value: T | PromiseLike<T>) => void,\n    reject: (reason?: unknown) => void,\n  ) => void,\n  options: { deadline?: number },\n) => {\n  return new Promise<T>((resolve, reject) => {\n    let taskStarted = false;\n\n    const maxWaitingTime = options.deadline || DEFAULT_PROMISE_DEADLINE;\n\n    let timeoutId: NodeJS.Timeout | null = setTimeout(() => {\n      if (!taskStarted) {\n        reject(\n          new Error('Task was not started within the maximum waiting time'),\n        );\n      }\n    }, maxWaitingTime);\n\n    executor((value) => {\n      taskStarted = true;\n      if (timeoutId) {\n        clearTimeout(timeoutId);\n      }\n      timeoutId = null;\n      resolve(value);\n    }, reject);\n  });\n};\n","import { TaskProcessor } from '../../taskProcessing';\n\nexport type LockOptions = { lockId: number };\n\nexport type AcquireLockOptions = { lockId: string };\nexport type ReleaseLockOptions = { lockId: string };\n\nexport type Lock = {\n  acquire(options: AcquireLockOptions): Promise<void>;\n  tryAcquire(options: AcquireLockOptions): Promise<boolean>;\n  release(options: ReleaseLockOptions): Promise<boolean>;\n  withAcquire: <Result = unknown>(\n    handle: () => Promise<Result>,\n    options: AcquireLockOptions,\n  ) => Promise<Result>;\n};\n\nexport const InProcessLock = (): Lock => {\n  const taskProcessor = new TaskProcessor({\n    maxActiveTasks: Number.MAX_VALUE,\n    maxQueueSize: Number.MAX_VALUE,\n  });\n\n  // Map to store ack functions of currently held locks: lockId -> ack()\n  const locks = new Map<string, () => void>();\n\n  return {\n    async acquire({ lockId }: AcquireLockOptions): Promise<void> {\n      // If the lock is already held, we just queue up another task in the same group.\n      // TaskProcessor ensures tasks in the same group run one at a time.\n      await new Promise<void>((resolve, reject) => {\n        taskProcessor\n          .enqueue(\n            ({ ack }) => {\n              // When this task starts, it means the previous lock (if any) was released\n              // and now we have exclusive access.\n              locks.set(lockId, ack);\n              // We do NOT call ack() here. We hold onto the lock.\n              resolve();\n              return Promise.resolve();\n            },\n            { taskGroupId: lockId },\n          )\n          .catch(reject);\n      });\n    },\n\n    async tryAcquire({ lockId }: AcquireLockOptions): Promise<boolean> {\n      // If lock is already held, fail immediately\n      if (locks.has(lockId)) {\n        return false;\n      }\n\n      // TODO: Check pending queue\n      await this.acquire({ lockId });\n\n      return true;\n    },\n\n    release({ lockId }: ReleaseLockOptions): Promise<boolean> {\n      const ack = locks.get(lockId);\n      if (ack === undefined) {\n        return Promise.resolve(true);\n      }\n      locks.delete(lockId);\n      ack();\n      return Promise.resolve(true);\n    },\n\n    async withAcquire<Result = unknown>(\n      handle: () => Promise<Result>,\n      { lockId }: AcquireLockOptions,\n    ): Promise<Result> {\n      return taskProcessor.enqueue(\n        async ({ ack }) => {\n          // When this task starts, it means the previous lock (if any) was released\n          // and now we have exclusive access.\n          locks.set(lockId, ack);\n\n          // We do NOT call ack() here. We hold onto the lock.\n          try {\n            return await handle();\n          } finally {\n            locks.delete(lockId);\n            ack();\n          }\n        },\n        { taskGroupId: lockId },\n      );\n    },\n  };\n};\n","export const delay = (ms: number): Promise<void> => {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n};\n\nexport type AsyncAwaiter<T = void> = {\n  wait: Promise<T>;\n  resolve: (value: T | PromiseLike<T>) => void;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  reject: (reason?: any) => void;\n  reset: () => void;\n};\n\n// TODO: Remove this after migrating to Node 22\nexport const asyncAwaiter = <T = void>(): AsyncAwaiter<T> => {\n  const result: AsyncAwaiter<T> = {} as AsyncAwaiter<T>;\n\n  (result.reset = () => {\n    result.wait = new Promise<T>((res, rej) => {\n      result.resolve = res;\n      result.reject = rej;\n    });\n  })();\n\n  return result;\n};\n","import retry from 'async-retry';\nimport { EmmettError } from '../errors';\nimport { JSONParser } from '../serialization';\n\nexport type AsyncRetryOptions<T = unknown> = retry.Options & {\n  shouldRetryResult?: (result: T) => boolean;\n  shouldRetryError?: (error?: unknown) => boolean;\n};\n\nexport const NoRetries: AsyncRetryOptions = { retries: 0 };\n\nexport const asyncRetry = async <T>(\n  fn: () => Promise<T>,\n  opts?: AsyncRetryOptions<T>,\n): Promise<T> => {\n  if (opts === undefined || opts.retries === 0) return fn();\n\n  return retry(\n    async (bail) => {\n      try {\n        const result = await fn();\n\n        if (opts?.shouldRetryResult && opts.shouldRetryResult(result)) {\n          throw new EmmettError(\n            `Retrying because of result: ${JSONParser.stringify(result)}`,\n          );\n        }\n        return result;\n      } catch (error) {\n        if (opts?.shouldRetryError && !opts.shouldRetryError(error)) {\n          bail(error as Error);\n          return undefined as unknown as T;\n        }\n        throw error;\n      }\n    },\n    opts ?? { retries: 0 },\n  );\n};\n","export class ParseError extends Error {\n  constructor(text: string) {\n    super(`Cannot parse! ${text}`);\n  }\n}\n\nexport type Mapper<From, To = From> =\n  | ((value: unknown) => To)\n  | ((value: Partial<From>) => To)\n  | ((value: From) => To)\n  | ((value: Partial<To>) => To)\n  | ((value: To) => To)\n  | ((value: Partial<To | From>) => To)\n  | ((value: To | From) => To);\n\nexport type MapperArgs<From, To = From> = Partial<From> &\n  From &\n  Partial<To> &\n  To;\n\nexport type ParseOptions<From, To = From> = {\n  reviver?: (key: string, value: unknown) => unknown;\n  map?: Mapper<From, To>;\n  typeCheck?: <To>(value: unknown) => value is To;\n};\n\nexport type StringifyOptions<From, To = From> = {\n  map?: Mapper<From, To>;\n};\n\nexport const JSONParser = {\n  stringify: <From, To = From>(\n    value: From,\n    options?: StringifyOptions<From, To>,\n  ) => {\n    return JSON.stringify(\n      options?.map ? options.map(value as MapperArgs<From, To>) : value,\n      //TODO: Consider adding support to DateTime and adding specific format to mark that's a bigint\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n      (_, v) => (typeof v === 'bigint' ? v.toString() : v),\n    );\n  },\n  parse: <From, To = From>(\n    text: string,\n    options?: ParseOptions<From, To>,\n  ): To | undefined => {\n    const parsed: unknown = JSON.parse(text, options?.reviver);\n\n    if (options?.typeCheck && !options?.typeCheck<To>(parsed))\n      throw new ParseError(text);\n\n    return options?.map\n      ? options.map(parsed as MapperArgs<From, To>)\n      : (parsed as To | undefined);\n  },\n};\n","import { ConcurrencyInMemoryDatabaseError } from '../errors';\nimport { JSONParser } from '../serialization';\nimport type {\n  DatabaseHandleOptionErrors,\n  ExpectedDocumentVersion,\n  ExpectedDocumentVersionGeneral,\n  ExpectedDocumentVersionValue,\n  OperationResult,\n} from './types';\n\nexport const isGeneralExpectedDocumentVersion = (\n  version: ExpectedDocumentVersion | undefined,\n): version is ExpectedDocumentVersionGeneral => {\n  return (\n    version === 'DOCUMENT_DOES_NOT_EXIST' ||\n    version === 'DOCUMENT_EXISTS' ||\n    version === 'NO_CONCURRENCY_CHECK'\n  );\n};\n\nexport const expectedVersionValue = (\n  version: ExpectedDocumentVersion | undefined,\n): ExpectedDocumentVersionValue | null =>\n  version === undefined || isGeneralExpectedDocumentVersion(version)\n    ? null\n    : version;\n\nexport const operationResult = <T extends OperationResult>(\n  result: Omit<T, 'assertSuccess' | 'acknowledged' | 'assertSuccessful'>,\n  options: {\n    operationName: string;\n    collectionName: string;\n    errors?: DatabaseHandleOptionErrors;\n  },\n): T => {\n  const operationResult: T = {\n    ...result,\n    acknowledged: true,\n    successful: result.successful,\n    assertSuccessful: (errorMessage?: string) => {\n      const { successful } = result;\n      const { operationName, collectionName } = options;\n\n      if (!successful)\n        throw new ConcurrencyInMemoryDatabaseError(\n          errorMessage ??\n            `${operationName} on ${collectionName} failed. Expected document state does not match current one! Result: ${JSONParser.stringify(result)}!`,\n        );\n    },\n  } as T;\n\n  if (options.errors?.throwOnOperationFailures)\n    operationResult.assertSuccessful();\n\n  return operationResult;\n};\n","import type { InMemoryDatabase } from '../../../database/inMemoryDatabase';\nimport type {\n  ProjectionDefinition,\n  TruncateProjection,\n} from '../../../projections';\nimport type { CanHandle, Event, ReadEvent } from '../../../typing';\nimport {\n  type InMemoryProjectionHandlerContext,\n  type InMemoryReadEventMetadata,\n} from '../../inMemoryEventStore';\n\nexport const DATABASE_REQUIRED_ERROR_MESSAGE =\n  'Database is required in context for InMemory projections';\n\nexport type InMemoryProjectionDefinition<EventType extends Event> =\n  ProjectionDefinition<\n    EventType,\n    InMemoryReadEventMetadata,\n    InMemoryProjectionHandlerContext\n  >;\n\nexport type InMemoryProjectionHandlerOptions<EventType extends Event = Event> =\n  {\n    projections: InMemoryProjectionDefinition<EventType>[];\n    events: ReadEvent<EventType, InMemoryReadEventMetadata>[];\n    database: InMemoryDatabase;\n    eventStore?: InMemoryProjectionHandlerContext['eventStore'];\n  };\n\n/**\n * Handles projections for the InMemoryEventStore\n * Similar to the PostgreSQL implementation, this processes events through projections\n */\nexport const handleInMemoryProjections = async <\n  EventType extends Event = Event,\n>(\n  options: InMemoryProjectionHandlerOptions<EventType>,\n): Promise<void> => {\n  const { projections, events, database, eventStore } = options;\n\n  // Get all event types from the events batch to filter projections\n  const eventTypes = events.map((e) => e.type);\n\n  // Filter projections that can handle these event types\n  const relevantProjections = projections.filter((p) =>\n    p.canHandle.some((type) => eventTypes.includes(type)),\n  );\n\n  // Process each projection\n  for (const projection of relevantProjections) {\n    await projection.handle(events, {\n      eventStore,\n      database,\n    });\n  }\n};\n\nexport type InMemoryWithNotNullDocumentEvolve<\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n> = (\n  document: DocumentType,\n  event: ReadEvent<EventType, InMemoryReadEventMetadata>,\n) => DocumentType | null;\n\nexport type InMemoryWithNullableDocumentEvolve<\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n> = (\n  document: DocumentType | null,\n  event: ReadEvent<EventType, InMemoryReadEventMetadata>,\n) => DocumentType | null;\n\nexport type InMemoryDocumentEvolve<\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n> =\n  | InMemoryWithNotNullDocumentEvolve<DocumentType, EventType>\n  | InMemoryWithNullableDocumentEvolve<DocumentType, EventType>;\n\nexport type InMemoryProjectionOptions<EventType extends Event> = {\n  handle: (\n    events: ReadEvent<EventType, InMemoryReadEventMetadata>[],\n    context: InMemoryProjectionHandlerContext & { database: InMemoryDatabase },\n  ) => Promise<void>;\n  canHandle: CanHandle<EventType>;\n  truncate?: TruncateProjection<\n    InMemoryProjectionHandlerContext & { database: InMemoryDatabase }\n  >;\n};\n\n/**\n * Creates an InMemory projection\n */\nexport const inMemoryProjection = <EventType extends Event>({\n  truncate,\n  handle,\n  canHandle,\n}: InMemoryProjectionOptions<EventType>): InMemoryProjectionDefinition<EventType> => ({\n  canHandle,\n  handle: async (events, context) => {\n    if (!context.database) {\n      throw new Error(DATABASE_REQUIRED_ERROR_MESSAGE);\n    }\n    await handle(events, {\n      ...context,\n      database: context.database,\n    });\n  },\n  truncate: truncate\n    ? (context) => {\n        if (!context.database) {\n          throw new Error(DATABASE_REQUIRED_ERROR_MESSAGE);\n        }\n        return truncate({\n          ...context,\n          database: context.database,\n        });\n      }\n    : undefined,\n});\n\n/**\n * Creates a multi-stream projection for InMemoryDatabase\n */\nexport type InMemoryMultiStreamProjectionOptions<\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n> = {\n  canHandle: CanHandle<EventType>;\n  collectionName: string;\n  getDocumentId: (event: ReadEvent<EventType>) => string;\n} & (\n  | {\n      evolve: InMemoryWithNullableDocumentEvolve<DocumentType, EventType>;\n    }\n  | {\n      evolve: InMemoryWithNotNullDocumentEvolve<DocumentType, EventType>;\n      initialState: () => DocumentType;\n    }\n);\n\n/**\n * Creates a projection that handles events across multiple streams\n */\nexport const inMemoryMultiStreamProjection = <\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n>(\n  options: InMemoryMultiStreamProjectionOptions<DocumentType, EventType>,\n): InMemoryProjectionDefinition<EventType> => {\n  const { collectionName, getDocumentId, canHandle } = options;\n\n  return inMemoryProjection({\n    handle: async (\n      events: ReadEvent<EventType, InMemoryReadEventMetadata>[],\n      { database },\n    ) => {\n      const collection = database.collection<DocumentType>(collectionName);\n\n      for (const event of events) {\n        await collection.handle(getDocumentId(event), (document) => {\n          if ('initialState' in options) {\n            return options.evolve(document ?? options.initialState(), event);\n          } else {\n            return options.evolve(document, event);\n          }\n        });\n      }\n    },\n    canHandle,\n    truncate: async ({\n      database,\n    }: InMemoryProjectionHandlerContext & { database: InMemoryDatabase }) => {\n      // For InMemory database, we can't directly truncate a collection\n      // So we'll delete all documents from the collection\n      const collection = database.collection<DocumentType>(collectionName);\n      const documents = await collection.find();\n\n      for (const doc of documents) {\n        if (doc && '_id' in doc) {\n          const id = doc._id;\n          await collection.deleteOne((d) => d._id === id);\n        }\n      }\n    },\n  });\n};\n\n/**\n * Creates a single-stream projection for InMemoryDatabase\n */\nexport type InMemorySingleStreamProjectionOptions<\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n> = {\n  canHandle: CanHandle<EventType>;\n  getDocumentId?: (event: ReadEvent<EventType>) => string;\n  collectionName: string;\n} & (\n  | {\n      evolve: InMemoryWithNullableDocumentEvolve<DocumentType, EventType>;\n    }\n  | {\n      evolve: InMemoryWithNotNullDocumentEvolve<DocumentType, EventType>;\n      initialState: () => DocumentType;\n    }\n);\n\n/**\n * Creates a projection that handles events from a single stream\n */\nexport const inMemorySingleStreamProjection = <\n  DocumentType extends Record<string, unknown>,\n  EventType extends Event,\n>(\n  options: InMemorySingleStreamProjectionOptions<DocumentType, EventType>,\n): InMemoryProjectionDefinition<EventType> => {\n  return inMemoryMultiStreamProjection<DocumentType, EventType>({\n    ...options,\n    getDocumentId:\n      options.getDocumentId ?? ((event) => event.metadata.streamName),\n  });\n};\n","import { v4 as uuid } from 'uuid';\nimport {\n  handleInMemoryProjections,\n  type InMemoryProjectionDefinition,\n} from '.';\nimport {\n  getInMemoryDatabase,\n  type Document,\n  type InMemoryDatabase,\n} from '../../../database';\nimport { isErrorConstructor } from '../../../errors';\nimport { JSONParser } from '../../../serialization';\nimport {\n  assertFails,\n  AssertionError,\n  assertTrue,\n  type ThenThrows,\n} from '../../../testing';\nimport type { CombinedReadEventMetadata, ReadEvent } from '../../../typing';\nimport { type Event } from '../../../typing';\nimport type {\n  InMemoryEventStore,\n  InMemoryReadEventMetadata,\n} from '../../inMemoryEventStore';\n\n// Define a more specific type for T that extends Document\ntype DocumentWithId = Document & { _id?: string | number };\n\nexport type InMemoryProjectionSpecEvent<\n  EventType extends Event,\n  EventMetaDataType extends\n    InMemoryReadEventMetadata = InMemoryReadEventMetadata,\n> = EventType & {\n  metadata?: Partial<EventMetaDataType>;\n};\n\nexport type InMemoryProjectionSpecWhenOptions = { numberOfTimes: number };\n\nexport type InMemoryProjectionSpec<EventType extends Event> = (\n  givenEvents: InMemoryProjectionSpecEvent<EventType>[],\n) => {\n  when: (\n    events: InMemoryProjectionSpecEvent<EventType>[],\n    options?: InMemoryProjectionSpecWhenOptions,\n  ) => {\n    then: (assert: InMemoryProjectionAssert, message?: string) => Promise<void>;\n    thenThrows: <ErrorType extends Error = Error>(\n      ...args: Parameters<ThenThrows<ErrorType>>\n    ) => Promise<void>;\n  };\n};\n\nexport type InMemoryProjectionAssert = (options: {\n  database: InMemoryDatabase;\n}) => Promise<void | boolean>;\n\nexport type InMemoryProjectionSpecOptions<EventType extends Event> = {\n  projection: InMemoryProjectionDefinition<EventType>;\n};\n\nexport const InMemoryProjectionSpec = {\n  for: <EventType extends Event>(\n    options: InMemoryProjectionSpecOptions<EventType>,\n  ): InMemoryProjectionSpec<EventType> => {\n    const { projection } = options;\n\n    return (givenEvents: InMemoryProjectionSpecEvent<EventType>[]) => {\n      return {\n        when: (\n          events: InMemoryProjectionSpecEvent<EventType>[],\n          options?: InMemoryProjectionSpecWhenOptions,\n        ) => {\n          const allEvents: ReadEvent<EventType, InMemoryReadEventMetadata>[] =\n            [];\n\n          const run = async (database: InMemoryDatabase) => {\n            let globalPosition = 0n;\n            const numberOfTimes = options?.numberOfTimes ?? 1;\n\n            for (const event of [\n              ...givenEvents,\n              ...Array.from({ length: numberOfTimes }).flatMap(() => events),\n            ]) {\n              const metadata: InMemoryReadEventMetadata = {\n                globalPosition: ++globalPosition,\n                streamPosition: globalPosition,\n                streamName: event.metadata?.streamName ?? `test-${uuid()}`,\n                messageId: uuid(),\n              };\n\n              allEvents.push({\n                ...event,\n                kind: 'Event',\n                metadata: {\n                  ...metadata,\n                  ...('metadata' in event ? (event.metadata ?? {}) : {}),\n                } as CombinedReadEventMetadata<\n                  EventType,\n                  InMemoryReadEventMetadata\n                >,\n              });\n            }\n\n            // Create a minimal mock EventStore implementation\n            const mockEventStore = {\n              database,\n              aggregateStream: async () => {\n                return Promise.resolve({\n                  state: {},\n                  currentStreamVersion: 0n,\n                  streamExists: false,\n                });\n              },\n              readStream: async () => {\n                return Promise.resolve({\n                  events: [],\n                  currentStreamVersion: 0n,\n                  streamExists: false,\n                });\n              },\n              appendToStream: async () => {\n                return Promise.resolve({\n                  nextExpectedStreamVersion: 0n,\n                  createdNewStream: false,\n                });\n              },\n            } as InMemoryEventStore;\n\n            await handleInMemoryProjections({\n              events: allEvents,\n              projections: [projection],\n              database,\n              eventStore: mockEventStore,\n            });\n          };\n\n          return {\n            then: async (\n              assertFn: InMemoryProjectionAssert,\n              message?: string,\n            ): Promise<void> => {\n              const database = getInMemoryDatabase();\n              await run(database);\n\n              const succeeded = await assertFn({ database });\n\n              if (succeeded !== undefined && succeeded === false) {\n                assertFails(\n                  message ??\n                    \"Projection specification didn't match the criteria\",\n                );\n              }\n            },\n            thenThrows: async <ErrorType extends Error = Error>(\n              ...args: Parameters<ThenThrows<ErrorType>>\n            ): Promise<void> => {\n              const database = getInMemoryDatabase();\n              try {\n                await run(database);\n                throw new AssertionError('Handler did not fail as expected');\n              } catch (error) {\n                if (error instanceof AssertionError) throw error;\n\n                if (args.length === 0) return;\n\n                if (!isErrorConstructor(args[0])) {\n                  assertTrue(\n                    args[0](error as ErrorType),\n                    `Error didn't match the error condition: ${error?.toString()}`,\n                  );\n                  return;\n                }\n\n                assertTrue(\n                  error instanceof args[0],\n                  `Caught error is not an instance of the expected type: ${error?.toString()}`,\n                );\n\n                if (args[1]) {\n                  assertTrue(\n                    args[1](error as ErrorType),\n                    `Error didn't match the error condition: ${error?.toString()}`,\n                  );\n                }\n              }\n            },\n          };\n        },\n      };\n    };\n  },\n};\n\n// Helper functions for creating events in stream\nexport const eventInStream = <\n  EventType extends Event = Event,\n  EventMetaDataType extends\n    InMemoryReadEventMetadata = InMemoryReadEventMetadata,\n>(\n  streamName: string,\n  event: InMemoryProjectionSpecEvent<EventType, EventMetaDataType>,\n): InMemoryProjectionSpecEvent<EventType, EventMetaDataType> => {\n  return {\n    ...event,\n    metadata: {\n      ...(event.metadata ?? {}),\n      streamName: event.metadata?.streamName ?? streamName,\n    } as Partial<EventMetaDataType>,\n  };\n};\n\nexport const eventsInStream = <\n  EventType extends Event = Event,\n  EventMetaDataType extends\n    InMemoryReadEventMetadata = InMemoryReadEventMetadata,\n>(\n  streamName: string,\n  events: InMemoryProjectionSpecEvent<EventType, EventMetaDataType>[],\n): InMemoryProjectionSpecEvent<EventType, EventMetaDataType>[] => {\n  return events.map((e) => eventInStream(streamName, e));\n};\n\nexport const newEventsInStream = eventsInStream;\n\n// Assertion helpers for checking documents\nexport function documentExists<T extends DocumentWithId>(\n  expected: Partial<T>,\n  options: { inCollection: string; withId: string | number },\n): InMemoryProjectionAssert {\n  return async ({ database }) => {\n    const collection = database.collection<T>(options.inCollection);\n\n    const document = await collection.findOne((doc) => {\n      // Handle both string IDs and numeric IDs in a type-safe way\n      const docId = '_id' in doc ? doc._id : undefined;\n      return docId === options.withId;\n    });\n\n    if (!document) {\n      assertFails(\n        `Document with ID ${options.withId} does not exist in collection ${options.inCollection}`,\n      );\n      return Promise.resolve(false);\n    }\n\n    // Check that all expected properties exist with expected values\n    for (const [key, value] of Object.entries(expected)) {\n      const propKey = key as keyof typeof document;\n      if (\n        !(key in document) ||\n        JSONParser.stringify(document[propKey]) !== JSONParser.stringify(value)\n      ) {\n        assertFails(`Property ${key} doesn't match the expected value`);\n        return Promise.resolve(false);\n      }\n    }\n\n    return Promise.resolve(true);\n  };\n}\n\n// Helper for checking document contents\nexport const expectInMemoryDocuments = {\n  fromCollection: <T extends DocumentWithId>(collectionName: string) => ({\n    withId: (id: string | number) => ({\n      toBeEqual: (expected: Partial<T>): InMemoryProjectionAssert =>\n        documentExists<T>(expected, {\n          inCollection: collectionName,\n          withId: id,\n        }),\n    }),\n  }),\n};\n","import { JSONParser } from '../serialization';\nimport type { DefaultRecord } from '../typing';\nimport { deepEquals } from '../utils';\n\nexport class AssertionError extends Error {\n  constructor(message: string) {\n    super(message);\n  }\n}\n\nexport const isSubset = (superObj: unknown, subObj: unknown): boolean => {\n  const sup = superObj as DefaultRecord;\n  const sub = subObj as DefaultRecord;\n\n  assertOk(sup);\n  assertOk(sub);\n\n  return Object.keys(sub).every((ele: string) => {\n    if (typeof sub[ele] == 'object') {\n      return isSubset(sup[ele], sub[ele]);\n    }\n    return sub[ele] === sup[ele];\n  });\n};\n\nexport const assertFails = (message?: string) => {\n  throw new AssertionError(message ?? 'That should not ever happened, right?');\n};\n\nexport const assertThrowsAsync = async <TError extends Error>(\n  fun: () => Promise<void>,\n  errorCheck?: (error: Error) => boolean,\n): Promise<TError> => {\n  try {\n    await fun();\n  } catch (error) {\n    const typedError = error as TError;\n    if (typedError instanceof AssertionError || !errorCheck) {\n      assertFalse(\n        typedError instanceof AssertionError,\n        \"Function didn't throw expected error\",\n      );\n      return typedError;\n    }\n\n    assertTrue(\n      errorCheck(typedError),\n      `Error doesn't match the expected condition: ${JSONParser.stringify(error)}`,\n    );\n\n    return typedError;\n  }\n  throw new AssertionError(\"Function didn't throw expected error\");\n};\n\nexport const assertThrows = <TError extends Error>(\n  fun: () => void,\n  errorCheck?: (error: Error) => boolean,\n): TError => {\n  try {\n    fun();\n  } catch (error) {\n    const typedError = error as TError;\n\n    if (errorCheck) {\n      assertTrue(\n        errorCheck(typedError),\n        `Error doesn't match the expected condition: ${JSONParser.stringify(error)}`,\n      );\n    } else if (typedError instanceof AssertionError) {\n      assertFalse(\n        typedError instanceof AssertionError,\n        \"Function didn't throw expected error\",\n      );\n    }\n\n    return typedError;\n  }\n  throw new AssertionError(\"Function didn't throw expected error\");\n};\n\nexport const assertDoesNotThrow = <TError extends Error>(\n  fun: () => void,\n  errorCheck?: (error: Error) => boolean,\n): TError | null => {\n  try {\n    fun();\n    return null;\n  } catch (error) {\n    const typedError = error as TError;\n\n    if (errorCheck) {\n      assertFalse(\n        errorCheck(typedError),\n        `Error matching the expected condition was thrown!: ${JSONParser.stringify(error)}`,\n      );\n    } else {\n      assertFails(`Function threw an error: ${JSONParser.stringify(error)}`);\n    }\n\n    return typedError;\n  }\n};\n\nexport const assertRejects = async <T, TError extends Error = Error>(\n  promise: Promise<T>,\n  errorCheck?: ((error: TError) => boolean) | TError,\n) => {\n  try {\n    await promise;\n    throw new AssertionError(\"Function didn't throw expected error\");\n  } catch (error) {\n    if (!errorCheck) return;\n\n    if (errorCheck instanceof Error) assertDeepEqual(error, errorCheck);\n    else assertTrue(errorCheck(error as TError));\n  }\n};\n\nexport const assertMatches = (\n  actual: unknown,\n  expected: unknown,\n  message?: string,\n) => {\n  if (!isSubset(actual, expected))\n    throw new AssertionError(\n      message ??\n        `subObj:\\n${JSONParser.stringify(expected)}\\nis not subset of\\n${JSONParser.stringify(actual)}`,\n    );\n};\n\nexport const assertDeepEqual = <T = unknown>(\n  actual: T,\n  expected: T,\n  message?: string,\n) => {\n  if (!deepEquals(actual, expected))\n    throw new AssertionError(\n      message ??\n        `subObj:\\n${JSONParser.stringify(expected)}\\nis not equal to\\n${JSONParser.stringify(actual)}`,\n    );\n};\n\nexport const assertNotDeepEqual = <T = unknown>(\n  actual: T,\n  expected: T,\n  message?: string,\n) => {\n  if (deepEquals(actual, expected))\n    throw new AssertionError(\n      message ??\n        `subObj:\\n${JSONParser.stringify(expected)}\\nis equals to\\n${JSONParser.stringify(actual)}`,\n    );\n};\n\nexport const assertThat = <T>(item: T) => {\n  return {\n    isEqualTo: (other: T) => assertTrue(deepEquals(item, other)),\n  };\n};\n\nexport function assertFalse(\n  condition: boolean,\n  message?: string,\n): asserts condition is false {\n  if (condition !== false)\n    throw new AssertionError(message ?? `Condition is true`);\n}\n\nexport function assertTrue(\n  condition: boolean,\n  message?: string,\n): asserts condition is true {\n  if (condition !== true)\n    throw new AssertionError(message ?? `Condition is false`);\n}\n\nexport function assertOk<T>(\n  obj: T | null | undefined,\n  message?: string,\n): asserts obj is T {\n  if (!obj) throw new AssertionError(message ?? `Condition is not truthy`);\n}\n\nexport function assertEqual<T>(\n  expected: T | null | undefined,\n  actual: T | null | undefined,\n  message?: string,\n): void {\n  if (expected !== actual)\n    throw new AssertionError(\n      `${message ?? 'Objects are not equal'}:\\nExpected: ${JSONParser.stringify(expected)}\\nActual: ${JSONParser.stringify(actual)}`,\n    );\n}\n\nexport function assertNotEqual<T>(\n  obj: T | null | undefined,\n  other: T | null | undefined,\n  message?: string,\n): void {\n  if (obj === other)\n    throw new AssertionError(\n      message ?? `Objects are equal: ${JSONParser.stringify(obj)}`,\n    );\n}\n\nexport function assertIsNotNull<T extends object | bigint>(\n  result: T | null,\n): asserts result is T {\n  assertNotEqual(result, null);\n  assertOk(result);\n}\n\nexport function assertIsNull<T extends object>(\n  result: T | null,\n): asserts result is null {\n  assertEqual(result, null);\n}\n\ntype Call = {\n  arguments: unknown[];\n  result: unknown;\n  target: unknown;\n  this: unknown;\n};\n\nexport type ArgumentMatcher = (arg: unknown) => boolean;\n\nexport const argValue =\n  <T>(value: T): ArgumentMatcher =>\n  (arg) =>\n    deepEquals(arg, value);\n\nexport const argMatches =\n  <T>(matches: (arg: T) => boolean): ArgumentMatcher =>\n  (arg) =>\n    matches(arg as T);\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport type MockedFunction = Function & { mock?: { calls: Call[] } };\n\nexport function verifyThat(fn: MockedFunction) {\n  return {\n    calledTimes: (times: number) => {\n      assertEqual(fn.mock?.calls?.length, times);\n    },\n    notCalled: () => {\n      assertEqual(fn?.mock?.calls?.length, 0);\n    },\n    called: () => {\n      assertTrue(\n        fn.mock?.calls.length !== undefined && fn.mock.calls.length > 0,\n      );\n    },\n    calledWith: (...args: unknown[]) => {\n      assertTrue(\n        fn.mock?.calls.length !== undefined &&\n          fn.mock.calls.length >= 1 &&\n          fn.mock.calls.some((call) => deepEquals(call.arguments, args)),\n      );\n    },\n    calledOnceWith: (...args: unknown[]) => {\n      assertTrue(\n        fn.mock?.calls.length !== undefined &&\n          fn.mock.calls.length === 1 &&\n          fn.mock.calls.some((call) => deepEquals(call.arguments, args)),\n      );\n    },\n    calledWithArgumentMatching: (...matches: ArgumentMatcher[]) => {\n      assertTrue(\n        fn.mock?.calls.length !== undefined && fn.mock.calls.length >= 1,\n      );\n      assertTrue(\n        fn.mock?.calls.length !== undefined &&\n          fn.mock.calls.length >= 1 &&\n          fn.mock.calls.some(\n            (call) =>\n              call.arguments &&\n              call.arguments.length >= matches.length &&\n              matches.every((match, index) => match(call.arguments[index])),\n          ),\n      );\n    },\n    notCalledWithArgumentMatching: (...matches: ArgumentMatcher[]) => {\n      assertFalse(\n        fn.mock?.calls.length !== undefined &&\n          fn.mock.calls.length >= 1 &&\n          fn.mock.calls[0]!.arguments &&\n          fn.mock.calls[0]!.arguments.length >= matches.length &&\n          matches.every((match, index) =>\n            match(fn.mock!.calls[0]!.arguments[index]),\n          ),\n      );\n    },\n  };\n}\n\nexport const assertThatArray = <T>(array: T[]) => {\n  return {\n    isEmpty: () =>\n      assertEqual(\n        array.length,\n        0,\n        `Array is not empty ${JSONParser.stringify(array)}`,\n      ),\n    isNotEmpty: () => assertNotEqual(array.length, 0, `Array is empty`),\n    hasSize: (length: number) => assertEqual(array.length, length),\n    containsElements: (other: T[]) => {\n      assertTrue(other.every((ts) => array.some((o) => deepEquals(ts, o))));\n    },\n    containsElementsMatching: (other: T[]) => {\n      assertTrue(other.every((ts) => array.some((o) => isSubset(o, ts))));\n    },\n    containsOnlyElementsMatching: (other: T[]) => {\n      assertEqual(array.length, other.length, `Arrays lengths don't match`);\n      assertTrue(other.every((ts) => array.some((o) => isSubset(o, ts))));\n    },\n    containsExactlyInAnyOrder: (other: T[]) => {\n      assertEqual(array.length, other.length);\n      assertTrue(array.every((ts) => other.some((o) => deepEquals(ts, o))));\n    },\n    containsExactlyInAnyOrderElementsOf: (other: T[]) => {\n      assertEqual(array.length, other.length);\n      assertTrue(array.every((ts) => other.some((o) => deepEquals(ts, o))));\n    },\n    containsExactlyElementsOf: (other: T[]) => {\n      assertEqual(array.length, other.length);\n      for (let i = 0; i < array.length; i++) {\n        assertTrue(deepEquals(array[i], other[i]));\n      }\n    },\n    containsExactly: (elem: T) => {\n      assertEqual(array.length, 1);\n      assertTrue(deepEquals(array[0], elem));\n    },\n    contains: (elem: T) => {\n      assertTrue(array.some((a) => deepEquals(a, elem)));\n    },\n    containsOnlyOnceElementsOf: (other: T[]) => {\n      assertTrue(\n        other\n          .map((o) => array.filter((a) => deepEquals(a, o)).length)\n          .filter((a) => a === 1).length === other.length,\n      );\n    },\n    containsAnyOf: (other: T[]) => {\n      assertTrue(array.some((a) => other.some((o) => deepEquals(a, o))));\n    },\n    allMatch: (matches: (item: T) => boolean) => {\n      assertTrue(array.every(matches));\n    },\n    anyMatches: (matches: (item: T) => boolean) => {\n      assertTrue(array.some(matches));\n    },\n    allMatchAsync: async (\n      matches: (item: T) => Promise<boolean>,\n    ): Promise<void> => {\n      for (const item of array) {\n        assertTrue(await matches(item));\n      }\n    },\n  };\n};\n","import { isErrorConstructor, type ErrorConstructor } from '../errors';\nimport { AssertionError, assertThatArray, assertTrue } from './assertions';\n\ntype ErrorCheck<ErrorType> = (error: ErrorType) => boolean;\n\nexport type ThenThrows<ErrorType extends Error> =\n  | (() => void)\n  | ((errorConstructor: ErrorConstructor<ErrorType>) => void)\n  | ((errorCheck: ErrorCheck<ErrorType>) => void)\n  | ((\n      errorConstructor: ErrorConstructor<ErrorType>,\n      errorCheck?: ErrorCheck<ErrorType>,\n    ) => void);\n\nexport type DeciderSpecification<Command, Event> = (\n  givenEvents: Event | Event[],\n) => {\n  when: (command: Command) => {\n    then: (expectedEvents: Event | Event[]) => void;\n    thenNothingHappened: () => void;\n    thenThrows: <ErrorType extends Error = Error>(\n      ...args: Parameters<ThenThrows<ErrorType>>\n    ) => void;\n  };\n};\nexport type AsyncDeciderSpecification<Command, Event> = (\n  givenEvents: Event | Event[],\n) => {\n  when: (command: Command) => {\n    then: (expectedEvents: Event | Event[]) => Promise<void>;\n    thenNothingHappened: () => Promise<void>;\n    thenThrows: <ErrorType extends Error = Error>(\n      ...args: Parameters<ThenThrows<ErrorType>>\n    ) => Promise<void>;\n  };\n};\n\nexport const DeciderSpecification = {\n  for: deciderSpecificationFor,\n};\n\nfunction deciderSpecificationFor<Command, Event, State>(decider: {\n  decide: (command: Command, state: State) => Event | Event[];\n  evolve: (state: State, event: Event) => State;\n  initialState: () => State;\n}): DeciderSpecification<Command, Event>;\nfunction deciderSpecificationFor<Command, Event, State>(decider: {\n  decide: (command: Command, state: State) => Promise<Event | Event[]>;\n  evolve: (state: State, event: Event) => State;\n  initialState: () => State;\n}): AsyncDeciderSpecification<Command, Event>;\nfunction deciderSpecificationFor<Command, Event, State>(decider: {\n  decide: (\n    command: Command,\n    state: State,\n  ) => Event | Event[] | Promise<Event | Event[]>;\n  evolve: (state: State, event: Event) => State;\n  initialState: () => State;\n}):\n  | DeciderSpecification<Command, Event>\n  | AsyncDeciderSpecification<Command, Event> {\n  {\n    return (givenEvents: Event | Event[]) => {\n      return {\n        when: (command: Command) => {\n          const handle = () => {\n            const existingEvents = Array.isArray(givenEvents)\n              ? givenEvents\n              : [givenEvents];\n\n            const currentState = existingEvents.reduce<State>(\n              decider.evolve,\n              decider.initialState(),\n            );\n\n            return decider.decide(command, currentState);\n          };\n\n          return {\n            then: (expectedEvents: Event | Event[]): void | Promise<void> => {\n              const resultEvents = handle();\n\n              if (resultEvents instanceof Promise) {\n                return resultEvents.then((events) => {\n                  thenHandler(events, expectedEvents);\n                });\n              }\n\n              thenHandler(resultEvents, expectedEvents);\n            },\n            thenNothingHappened: (): void | Promise<void> => {\n              const resultEvents = handle();\n\n              if (resultEvents instanceof Promise) {\n                return resultEvents.then((events) => {\n                  thenNothingHappensHandler(events);\n                });\n              }\n\n              thenNothingHappensHandler(resultEvents);\n            },\n            thenThrows: <ErrorType extends Error>(\n              ...args: Parameters<ThenThrows<ErrorType>>\n            ): void | Promise<void> => {\n              try {\n                const result = handle();\n                if (result instanceof Promise) {\n                  return result\n                    .then(() => {\n                      throw new AssertionError(\n                        'Handler did not fail as expected',\n                      );\n                    })\n                    .catch((error) => {\n                      thenThrowsErrorHandler(error, args);\n                    });\n                }\n                throw new AssertionError('Handler did not fail as expected');\n              } catch (error) {\n                thenThrowsErrorHandler(error, args);\n              }\n            },\n          };\n        },\n      };\n    };\n  }\n}\n\nfunction thenHandler<Event>(\n  events: Event | Event[],\n  expectedEvents: Event | Event[],\n): void {\n  const resultEventsArray = Array.isArray(events) ? events : [events];\n\n  const expectedEventsArray = Array.isArray(expectedEvents)\n    ? expectedEvents\n    : [expectedEvents];\n\n  assertThatArray(resultEventsArray).containsOnlyElementsMatching(\n    expectedEventsArray,\n  );\n}\n\nfunction thenNothingHappensHandler<Event>(events: Event | Event[]): void {\n  const resultEventsArray = Array.isArray(events) ? events : [events];\n  assertThatArray(resultEventsArray).isEmpty();\n}\n\nfunction thenThrowsErrorHandler<ErrorType extends Error>(\n  error: unknown,\n  args: Parameters<ThenThrows<ErrorType>>,\n): void {\n  if (error instanceof AssertionError) throw error;\n\n  if (args.length === 0) return;\n\n  if (!isErrorConstructor(args[0])) {\n    assertTrue(\n      args[0](error as ErrorType),\n      `Error didn't match the error condition: ${error?.toString()}`,\n    );\n    return;\n  }\n\n  assertTrue(\n    error instanceof args[0],\n    `Caught error is not an instance of the expected type: ${error?.toString()}`,\n  );\n\n  if (args[1]) {\n    assertTrue(\n      args[1](error as ErrorType),\n      `Error didn't match the error condition: ${error?.toString()}`,\n    );\n  }\n}\n","import type {\n  AggregateStreamOptions,\n  AggregateStreamResult,\n  AppendToStreamOptions,\n  AppendToStreamResult,\n  EventStore,\n  EventStoreReadEventMetadata,\n  ReadStreamOptions,\n  ReadStreamResult,\n  StreamPositionTypeOfEventStore,\n} from '../eventStore';\nimport { type Event, type EventMetaDataOf } from '../typing';\n\nexport type TestEventStream<EventType extends Event = Event> = [\n  string,\n  EventType[],\n];\n\nexport type EventStoreWrapper<Store extends EventStore> = Store & {\n  appendedEvents: Map<string, TestEventStream>;\n  setup<EventType extends Event>(\n    streamName: string,\n    events: EventType[],\n  ): Promise<AppendToStreamResult<StreamPositionTypeOfEventStore<Store>>>;\n};\n\nexport const WrapEventStore = <Store extends EventStore>(\n  eventStore: Store,\n): EventStoreWrapper<Store> => {\n  const appendedEvents = new Map<string, TestEventStream>();\n\n  const wrapped = {\n    ...eventStore,\n    aggregateStream<State, EventType extends Event>(\n      streamName: string,\n      options: AggregateStreamOptions<State, EventType>,\n    ): Promise<\n      AggregateStreamResult<State, StreamPositionTypeOfEventStore<Store>>\n    > {\n      return eventStore.aggregateStream(streamName, options);\n    },\n\n    async readStream<EventType extends Event>(\n      streamName: string,\n      options?: ReadStreamOptions<StreamPositionTypeOfEventStore<Store>>,\n    ): Promise<\n      ReadStreamResult<\n        EventType,\n        EventStoreReadEventMetadata<Store> & EventMetaDataOf<EventType>\n      >\n    > {\n      return (await eventStore.readStream(\n        streamName,\n        options,\n      )) as ReadStreamResult<\n        EventType,\n        EventStoreReadEventMetadata<Store> & EventMetaDataOf<EventType>\n      >;\n    },\n\n    appendToStream: async <EventType extends Event>(\n      streamName: string,\n      events: EventType[],\n      options?: AppendToStreamOptions<StreamPositionTypeOfEventStore<Store>>,\n    ): Promise<AppendToStreamResult<StreamPositionTypeOfEventStore<Store>>> => {\n      const result = await eventStore.appendToStream(\n        streamName,\n        events,\n        options,\n      );\n\n      const currentStream = appendedEvents.get(streamName) ?? [streamName, []];\n\n      appendedEvents.set(streamName, [\n        streamName,\n        [...currentStream[1], ...events],\n      ]);\n\n      return result;\n    },\n\n    appendedEvents,\n\n    setup: async <EventType extends Event>(\n      streamName: string,\n      events: EventType[],\n    ): Promise<AppendToStreamResult<StreamPositionTypeOfEventStore<Store>>> => {\n      return eventStore.appendToStream(streamName, events);\n    },\n\n    // streamEvents: (): ReadableStream<\n    //   // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n    //   ReadEvent<Event, ReadEventMetadataType> | GlobalSubscriptionEvent\n    // > => {\n    //   return eventStore.streamEvents();\n    // },\n  };\n\n  return wrapped as EventStoreWrapper<Store>;\n};\n","import { TransformStream } from 'web-streams-polyfill';\nimport type {\n  Event,\n  ReadEvent,\n  ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport { globalStreamCaughtUp, type GlobalSubscriptionEvent } from '../events';\n\nexport const streamTrackingGlobalPosition = (\n  currentEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n) => new CaughtUpTransformStream(currentEvents);\n\nexport class CaughtUpTransformStream extends TransformStream<\n  ReadEvent<Event, ReadEventMetadataWithGlobalPosition>,\n  | ReadEvent<Event, ReadEventMetadataWithGlobalPosition>\n  | GlobalSubscriptionEvent\n> {\n  private _currentPosition: bigint;\n  private _logPosition: bigint;\n\n  constructor(events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]) {\n    super({\n      start: (controller) => {\n        let globalPosition = 0n;\n        for (const event of events) {\n          controller.enqueue(event);\n          globalPosition = event.metadata.globalPosition;\n        }\n        controller.enqueue(globalStreamCaughtUp({ globalPosition }));\n      },\n      transform: (event, controller) => {\n        this._currentPosition = event.metadata.globalPosition;\n        controller.enqueue(event);\n\n        if (this._currentPosition < this._logPosition) return;\n\n        controller.enqueue(\n          globalStreamCaughtUp({ globalPosition: this._currentPosition }),\n        );\n      },\n    });\n\n    this._currentPosition = this._logPosition =\n      events.length > 0\n        ? events[events.length - 1]!.metadata.globalPosition\n        : 0n;\n  }\n\n  public set logPosition(value: bigint) {\n    this._logPosition = value;\n  }\n}\n","import { v4 as uuid } from 'uuid';\nimport { notifyAboutNoActiveReadersStream } from '../../streaming/transformations/notifyAboutNoActiveReaders';\nimport { writeToStream } from '../../streaming/writers';\nimport type {\n  Event,\n  ReadEvent,\n  ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport {\n  CaughtUpTransformStream,\n  streamTrackingGlobalPosition,\n} from './caughtUpTransformStream';\n\nexport const StreamingCoordinator = () => {\n  const allEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[] = [];\n  const listeners = new Map<string, CaughtUpTransformStream>();\n\n  return {\n    notify: async (\n      events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n    ) => {\n      if (events.length === 0) return;\n\n      allEvents.push(...events);\n\n      for (const listener of listeners.values()) {\n        listener.logPosition =\n          events[events.length - 1]!.metadata.globalPosition;\n\n        await writeToStream(listener, events);\n      }\n    },\n\n    stream: () => {\n      const streamId = uuid();\n      const transformStream = streamTrackingGlobalPosition(allEvents);\n\n      listeners.set(streamId, transformStream);\n      return transformStream.readable.pipeThrough(\n        notifyAboutNoActiveReadersStream(\n          (stream) => {\n            if (listeners.has(stream.streamId))\n              listeners.delete(stream.streamId);\n          },\n          { streamId },\n        ),\n      );\n    },\n  };\n};\n","import { v4 as uuid } from 'uuid';\nimport { TransformStream } from 'web-streams-polyfill';\n\nexport const notifyAboutNoActiveReadersStream = <Item>(\n  onNoActiveReaderCallback: (\n    stream: NotifyAboutNoActiveReadersStream<Item>,\n  ) => void,\n  options: { streamId?: string; intervalCheckInMs?: number } = {},\n) => new NotifyAboutNoActiveReadersStream(onNoActiveReaderCallback, options);\n\nexport class NotifyAboutNoActiveReadersStream<Item> extends TransformStream<\n  Item,\n  Item\n> {\n  private checkInterval: NodeJS.Timeout | null = null;\n  public readonly streamId: string;\n  private _isStopped: boolean = false;\n  public get hasActiveSubscribers() {\n    return !this._isStopped;\n  }\n\n  constructor(\n    private onNoActiveReaderCallback: (\n      stream: NotifyAboutNoActiveReadersStream<Item>,\n    ) => void,\n    options: { streamId?: string; intervalCheckInMs?: number } = {},\n  ) {\n    super({\n      cancel: (reason) => {\n        console.log('Stream was canceled. Reason:', reason);\n        this.stopChecking();\n      },\n    });\n    this.streamId = options?.streamId ?? uuid();\n\n    this.onNoActiveReaderCallback = onNoActiveReaderCallback;\n\n    this.startChecking(options?.intervalCheckInMs ?? 20);\n  }\n\n  private startChecking(interval: number) {\n    this.checkInterval = setInterval(() => {\n      this.checkNoActiveReader();\n    }, interval);\n  }\n\n  private stopChecking() {\n    if (!this.checkInterval) return;\n\n    clearInterval(this.checkInterval);\n    this.checkInterval = null;\n    this._isStopped = true;\n    this.onNoActiveReaderCallback(this);\n  }\n\n  private checkNoActiveReader() {\n    if (!this.readable.locked && !this._isStopped) {\n      this.stopChecking();\n    }\n  }\n}\n","import type { ReadableStream, TransformStream } from 'web-streams-polyfill';\nimport { noMoreWritingOn } from './noMoreWritingOn';\n\nexport const writeToStream = async <In, Out = In>(\n  stream: TransformStream<In, Out>,\n  items: In[],\n): Promise<boolean> => {\n  if (stream.writable.locked) return false;\n\n  const writer = stream.writable.getWriter();\n  await writer.ready;\n\n  if (!stream.readable.locked) return false;\n\n  try {\n    for (const item of items) {\n      await writer.write(item);\n    }\n  } catch (error) {\n    console.log(error);\n  } finally {\n    await writer.close();\n  }\n  return true;\n};\n\nexport const writeToStreamAndStop = async <In, Out>(\n  stream: TransformStream<In, Out>,\n  items: In[],\n): Promise<ReadableStream<Out>> => {\n  await writeToStream(stream, items);\n  return await noMoreWritingOn(stream);\n};\n","import {\n  canCreateEventStoreSession,\n  isExpectedVersionConflictError,\n  NO_CONCURRENCY_CHECK,\n  nulloSessionFactory,\n  STREAM_DOES_NOT_EXIST,\n  type AppendStreamResultOfEventStore,\n  type EventStore,\n  type EventStoreSession,\n  type ExpectedStreamVersion,\n  type StreamPositionTypeOfEventStore,\n} from '../eventStore';\nimport type { Event } from '../typing';\nimport { asyncRetry, NoRetries, type AsyncRetryOptions } from '../utils';\n\nexport const CommandHandlerStreamVersionConflictRetryOptions: AsyncRetryOptions =\n  {\n    retries: 3,\n    minTimeout: 100,\n    factor: 1.5,\n    shouldRetryError: isExpectedVersionConflictError,\n  };\n\nexport type CommandHandlerRetryOptions =\n  | AsyncRetryOptions\n  | { onVersionConflict: true | number | AsyncRetryOptions };\n\nconst fromCommandHandlerRetryOptions = (\n  retryOptions: CommandHandlerRetryOptions | undefined,\n): AsyncRetryOptions => {\n  if (retryOptions === undefined) return NoRetries;\n\n  if ('onVersionConflict' in retryOptions) {\n    if (typeof retryOptions.onVersionConflict === 'boolean')\n      return CommandHandlerStreamVersionConflictRetryOptions;\n    else if (typeof retryOptions.onVersionConflict === 'number')\n      return {\n        ...CommandHandlerStreamVersionConflictRetryOptions,\n        retries: retryOptions.onVersionConflict,\n      };\n    else return retryOptions.onVersionConflict;\n  }\n\n  return retryOptions;\n};\n\n// #region command-handler\nexport type CommandHandlerResult<\n  State,\n  StreamEvent extends Event,\n  Store extends EventStore,\n> = AppendStreamResultOfEventStore<Store> & {\n  newState: State;\n  newEvents: StreamEvent[];\n};\n\nexport type CommandHandlerOptions<State, StreamEvent extends Event> = {\n  evolve: (state: State, event: StreamEvent) => State;\n  initialState: () => State;\n  mapToStreamId?: (id: string) => string;\n  retry?: CommandHandlerRetryOptions;\n};\n\nexport type HandleOptions<Store extends EventStore> = Parameters<\n  Store['appendToStream']\n>[2] &\n  (\n    | {\n        expectedStreamVersion?: ExpectedStreamVersion<\n          StreamPositionTypeOfEventStore<Store>\n        >;\n      }\n    | {\n        retry?: CommandHandlerRetryOptions;\n      }\n  );\n\ntype CommandHandlerFunction<State, StreamEvent extends Event> = (\n  state: State,\n) => StreamEvent | StreamEvent[] | Promise<StreamEvent | StreamEvent[]>;\n\nexport const CommandHandler =\n  <State, StreamEvent extends Event>(\n    options: CommandHandlerOptions<State, StreamEvent>,\n  ) =>\n  async <Store extends EventStore>(\n    store: Store,\n    id: string,\n    handle:\n      | CommandHandlerFunction<State, StreamEvent>\n      | CommandHandlerFunction<State, StreamEvent>[],\n    handleOptions?: HandleOptions<Store>,\n  ): Promise<CommandHandlerResult<State, StreamEvent, Store>> =>\n    asyncRetry(\n      async () => {\n        const result = await withSession<\n          Store,\n          CommandHandlerResult<\n            State,\n            StreamEvent,\n            StreamPositionTypeOfEventStore<Store>\n          >\n        >(store, async ({ eventStore }) => {\n          const { evolve, initialState } = options;\n          const mapToStreamId = options.mapToStreamId ?? ((id) => id);\n\n          const streamName = mapToStreamId(id);\n\n          // 1. Aggregate the stream\n          const aggregationResult = await eventStore.aggregateStream<\n            State,\n            StreamEvent\n          >(streamName, {\n            evolve,\n            initialState,\n            read: {\n              // expected stream version is passed to fail fast\n              // if stream is in the wrong state\n              expectedStreamVersion:\n                handleOptions?.expectedStreamVersion ?? NO_CONCURRENCY_CHECK,\n            },\n          });\n\n          // 2. Use the aggregate state\n\n          const {\n            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n            currentStreamVersion,\n            streamExists: _streamExists,\n            ...restOfAggregationResult\n          } = aggregationResult;\n\n          let state = aggregationResult.state;\n\n          const handlers = Array.isArray(handle) ? handle : [handle];\n          let eventsToAppend: StreamEvent[] = [];\n\n          // 3. Run business logic\n          for (const handler of handlers) {\n            const result = await handler(state);\n\n            const newEvents = Array.isArray(result) ? result : [result];\n\n            if (newEvents.length > 0) {\n              state = newEvents.reduce(evolve, state);\n            }\n\n            eventsToAppend = [...eventsToAppend, ...newEvents];\n          }\n\n          //const newEvents = Array.isArray(result) ? result : [result];\n\n          if (eventsToAppend.length === 0) {\n            return {\n              ...restOfAggregationResult,\n              newEvents: [],\n              newState: state,\n              // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n              nextExpectedStreamVersion: currentStreamVersion,\n              createdNewStream: false,\n            } as unknown as CommandHandlerResult<State, StreamEvent, Store>;\n          }\n\n          // Either use:\n          // - provided expected stream version,\n          // - current stream version got from stream aggregation,\n          // - or expect stream not to exists otherwise.\n          // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n          const expectedStreamVersion: ExpectedStreamVersion<\n            StreamPositionTypeOfEventStore<Store>\n          > =\n            handleOptions?.expectedStreamVersion ??\n            (aggregationResult.streamExists\n              ? (currentStreamVersion as ExpectedStreamVersion<\n                  StreamPositionTypeOfEventStore<Store>\n                >)\n              : STREAM_DOES_NOT_EXIST);\n\n          // 4. Append result to the stream\n          const appendResult = await eventStore.appendToStream(\n            streamName,\n            eventsToAppend,\n            {\n              ...handleOptions,\n              expectedStreamVersion,\n            },\n          );\n\n          // 5. Return result with updated state\n          return {\n            ...appendResult,\n            newEvents: eventsToAppend,\n            newState: state,\n          } as unknown as CommandHandlerResult<State, StreamEvent, Store>;\n        });\n\n        return result;\n      },\n      fromCommandHandlerRetryOptions(\n        handleOptions && 'retry' in handleOptions\n          ? handleOptions.retry\n          : options.retry,\n      ),\n    );\n// #endregion command-handler\n\nconst withSession = <EventStoreType extends EventStore, T = unknown>(\n  eventStore: EventStoreType,\n  callback: (session: EventStoreSession<EventStoreType>) => Promise<T>,\n) => {\n  const sessionFactory = canCreateEventStoreSession<EventStoreType>(eventStore)\n    ? eventStore\n    : nulloSessionFactory<EventStoreType>(eventStore);\n\n  return sessionFactory.withSession(callback);\n};\n","import type { EventStore } from '../eventStore';\nimport { type Command, type Event } from '../typing';\nimport type { Decider } from '../typing/decider';\nimport {\n  CommandHandler,\n  type CommandHandlerOptions,\n  type HandleOptions,\n} from './handleCommand';\n\n// #region command-handler\n\nexport type DeciderCommandHandlerOptions<\n  State,\n  CommandType extends Command,\n  StreamEvent extends Event,\n> = CommandHandlerOptions<State, StreamEvent> &\n  Decider<State, CommandType, StreamEvent>;\n\nexport const DeciderCommandHandler =\n  <State, CommandType extends Command, StreamEvent extends Event>(\n    options: DeciderCommandHandlerOptions<State, CommandType, StreamEvent>,\n  ) =>\n  async <Store extends EventStore>(\n    eventStore: Store,\n    id: string,\n    commands: CommandType | CommandType[],\n    handleOptions?: HandleOptions<Store>,\n  ) => {\n    const { decide, ...rest } = options;\n\n    const deciders = (Array.isArray(commands) ? commands : [commands]).map(\n      (command) => (state: State) => decide(command, state),\n    );\n\n    return CommandHandler<State, StreamEvent>(rest)(\n      eventStore,\n      id,\n      deciders,\n      handleOptions,\n    );\n  };\n// #endregion command-handler\n","import { EmmettError } from '../errors';\nimport {\n  type AnyCommand,\n  type AnyMessage,\n  type Command,\n  type CommandTypeOf,\n  type Event,\n  type EventTypeOf,\n  type Message,\n  type SingleMessageHandler,\n  type SingleRawMessageHandlerWithoutContext,\n} from '../typing';\n\nexport interface CommandSender {\n  send<CommandType extends Command = Command>(\n    command: CommandType,\n  ): Promise<void>;\n}\n\nexport interface EventsPublisher {\n  publish<EventType extends Event = Event>(event: EventType): Promise<void>;\n}\n\nexport type ScheduleOptions = { afterInMs: number } | { at: Date };\n\nexport interface MessageScheduler<CommandOrEvent extends Command | Event> {\n  schedule<MessageType extends CommandOrEvent>(\n    message: MessageType,\n    when?: ScheduleOptions,\n  ): void;\n}\n\nexport interface CommandBus extends CommandSender, MessageScheduler<Command> {}\n\nexport interface EventBus extends EventsPublisher, MessageScheduler<Event> {}\n\nexport interface MessageBus extends CommandBus, EventBus {\n  schedule<MessageType extends Command | Event>(\n    message: MessageType,\n    when?: ScheduleOptions,\n  ): void;\n}\n\nexport interface CommandProcessor {\n  handle<CommandType extends Command>(\n    commandHandler: SingleMessageHandler<CommandType>,\n    ...commandTypes: CommandTypeOf<CommandType>[]\n  ): void;\n}\nexport interface EventSubscription {\n  subscribe<EventType extends Event>(\n    eventHandler: SingleMessageHandler<EventType>,\n    ...eventTypes: EventTypeOf<EventType>[]\n  ): void;\n}\n\nexport type ScheduledMessage = {\n  message: Message;\n  options?: ScheduleOptions;\n};\n\nexport interface ScheduledMessageProcessor {\n  dequeue(): ScheduledMessage[];\n}\n\nexport type MessageSubscription = EventSubscription | CommandProcessor;\n\nexport const getInMemoryMessageBus = (): MessageBus &\n  EventSubscription &\n  CommandProcessor &\n  ScheduledMessageProcessor => {\n  const allHandlers = new Map<\n    string,\n    SingleRawMessageHandlerWithoutContext<AnyMessage>[]\n  >();\n  let pendingMessages: ScheduledMessage[] = [];\n\n  return {\n    send: async <CommandType extends Command = AnyCommand>(\n      command: CommandType,\n    ): Promise<void> => {\n      const handlers = allHandlers.get(command.type);\n\n      if (handlers === undefined || handlers.length === 0)\n        throw new EmmettError(\n          `No handler registered for command ${command.type}!`,\n        );\n\n      const commandHandler = handlers[0]!;\n\n      await commandHandler(command);\n    },\n\n    publish: async <EventType extends Event = Event>(\n      event: EventType,\n    ): Promise<void> => {\n      const handlers = allHandlers.get(event.type) ?? [];\n\n      for (const handler of handlers) {\n        const eventHandler = handler;\n\n        await eventHandler(event);\n      }\n    },\n\n    schedule: <MessageType extends Message>(\n      message: MessageType,\n      when?: ScheduleOptions,\n    ): void => {\n      pendingMessages = [...pendingMessages, { message, options: when }];\n    },\n\n    handle: <CommandType extends Command>(\n      commandHandler: SingleMessageHandler<CommandType>,\n      ...commandTypes: CommandTypeOf<CommandType>[]\n    ): void => {\n      const alreadyRegistered = [...allHandlers.keys()].filter((registered) =>\n        commandTypes.includes(registered),\n      );\n\n      if (alreadyRegistered.length > 0)\n        throw new EmmettError(\n          `Cannot register handler for commands ${alreadyRegistered.join(', ')} as they're already registered!`,\n        );\n      for (const commandType of commandTypes) {\n        allHandlers.set(commandType, [\n          commandHandler as SingleRawMessageHandlerWithoutContext<AnyMessage>,\n        ]);\n      }\n    },\n\n    subscribe<EventType extends Event>(\n      eventHandler: SingleMessageHandler<EventType>,\n      ...eventTypes: EventTypeOf<EventType>[]\n    ): void {\n      for (const eventType of eventTypes) {\n        if (!allHandlers.has(eventType)) allHandlers.set(eventType, []);\n\n        allHandlers.set(eventType, [\n          ...(allHandlers.get(eventType) ?? []),\n          eventHandler as SingleRawMessageHandlerWithoutContext<AnyMessage>,\n        ]);\n      }\n    },\n\n    dequeue: (): ScheduledMessage[] => {\n      const pending = pendingMessages;\n      pendingMessages = [];\n      return pending;\n    },\n  };\n};\n","import type { EmmettError } from '../errors';\nimport type { ProjectionDefinition } from '../projections';\nimport {\n  type AnyEvent,\n  type AnyMessage,\n  type AnyReadEventMetadata,\n  type AnyRecordedMessageMetadata,\n  type BatchRecordedMessageHandlerWithContext,\n  type CanHandle,\n  type DefaultRecord,\n  type Event,\n  type GlobalPositionTypeOfRecordedMessageMetadata,\n  type Message,\n  type MessageHandlerResult,\n  type RecordedMessage,\n  type SingleMessageHandlerWithContext,\n  type SingleRecordedMessageHandlerWithContext,\n} from '../typing';\nimport { isBigint } from '../validation';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CurrentMessageProcessorPosition<CheckpointType = any> =\n  | { lastCheckpoint: CheckpointType }\n  | 'BEGINNING'\n  | 'END';\n\nexport type GetCheckpoint<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = (\n  message: RecordedMessage<MessageType, MessageMetadataType>,\n) => CheckpointType | null;\n\nexport const getCheckpoint = <\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n>(\n  message: RecordedMessage<MessageType, MessageMetadataType>,\n): CheckpointType | null => {\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n  return 'checkpoint' in message.metadata &&\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n    isBigint(message.metadata.checkpoint)\n    ? // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n      message.metadata.checkpoint\n    : 'globalPosition' in message.metadata &&\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n        isBigint(message.metadata.globalPosition)\n      ? // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n        message.metadata.globalPosition\n      : 'streamPosition' in message.metadata &&\n          // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n          isBigint(message.metadata.streamPosition)\n        ? // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n          message.metadata.streamPosition\n        : null;\n};\n\nexport const wasMessageHandled = <\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n>(\n  message: RecordedMessage<MessageType, MessageMetadataType>,\n  checkpoint: CheckpointType | null,\n): boolean => {\n  //TODO Make it smarter\n  const messageCheckpoint = getCheckpoint(message);\n  const checkpointBigint = checkpoint as bigint | null;\n\n  return (\n    messageCheckpoint !== null &&\n    messageCheckpoint !== undefined &&\n    checkpointBigint !== null &&\n    checkpointBigint !== undefined &&\n    messageCheckpoint <= checkpointBigint\n  );\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MessageProcessorStartFrom<CheckpointType = any> =\n  | CurrentMessageProcessorPosition<CheckpointType>\n  | 'CURRENT';\n\nexport type MessageProcessorType = 'projector' | 'reactor';\nexport const MessageProcessorType = {\n  PROJECTOR: 'projector' as MessageProcessorType,\n  REACTOR: 'reactor' as MessageProcessorType,\n};\n\nexport type MessageProcessor<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n  id: string;\n  type: string;\n  start: (\n    options: Partial<HandlerContext>,\n  ) => Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined>;\n  close: () => Promise<void>;\n  isActive: boolean;\n  handle: BatchRecordedMessageHandlerWithContext<\n    MessageType,\n    MessageMetadataType,\n    Partial<HandlerContext>\n  >;\n};\n\nexport const MessageProcessor = {\n  result: {\n    skip: (options?: { reason?: string }): MessageHandlerResult => ({\n      type: 'SKIP',\n      ...(options ?? {}),\n    }),\n    stop: (options?: {\n      reason?: string;\n      error?: EmmettError;\n    }): MessageHandlerResult => ({\n      type: 'STOP',\n      ...(options ?? {}),\n    }),\n  },\n};\n\nexport type MessageProcessingScope<\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> = <Result = MessageHandlerResult>(\n  handler: (context: HandlerContext) => Result | Promise<Result>,\n  partialContext: Partial<HandlerContext>,\n) => Result | Promise<Result>;\n\nexport type Checkpointer<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n  read: ReadProcessorCheckpoint<CheckpointType, HandlerContext>;\n  store: StoreProcessorCheckpoint<\n    MessageType,\n    MessageMetadataType,\n    CheckpointType,\n    HandlerContext\n  >;\n};\n\nexport type BaseMessageProcessorOptions<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n  type?: string;\n  processorId: string;\n  version?: number;\n  partition?: string;\n  startFrom?: MessageProcessorStartFrom<CheckpointType>;\n  stopAfter?: (\n    message: RecordedMessage<MessageType, MessageMetadataType>,\n  ) => boolean;\n  processingScope?: MessageProcessingScope<HandlerContext>;\n  checkpoints?: Checkpointer<\n    MessageType,\n    MessageMetadataType,\n    HandlerContext,\n    CheckpointType\n  >;\n  canHandle?: CanHandle<MessageType>;\n  hooks?: {\n    onStart?: OnReactorStartHook<HandlerContext>;\n    onClose?: OnReactorCloseHook;\n  };\n};\n\nexport type HandlerOptions<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n> =\n  | {\n      eachMessage: SingleRecordedMessageHandlerWithContext<\n        MessageType,\n        MessageMetadataType,\n        HandlerContext\n      >;\n      eachBatch?: never;\n    }\n  | {\n      eachMessage?: never;\n      eachBatch: BatchRecordedMessageHandlerWithContext<\n        MessageType,\n        MessageMetadataType,\n        HandlerContext\n      >;\n    };\n\nexport type OnReactorStartHook<\n  HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type OnReactorCloseHook = () => Promise<void>;\n\nexport type ReactorOptions<\n  MessageType extends AnyMessage = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = BaseMessageProcessorOptions<\n  MessageType,\n  MessageMetadataType,\n  HandlerContext,\n  CheckpointType\n> &\n  HandlerOptions<MessageType, MessageMetadataType, HandlerContext>;\n\nexport type ProjectorOptions<\n  EventType extends AnyEvent = AnyEvent,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = Omit<\n  BaseMessageProcessorOptions<\n    EventType,\n    MessageMetadataType,\n    HandlerContext,\n    CheckpointType\n  >,\n  'type' | 'processorId'\n> & { processorId?: string } & {\n  truncateOnStart?: boolean;\n  projection: ProjectionDefinition<\n    EventType,\n    MessageMetadataType,\n    HandlerContext\n  >;\n};\n\nexport const defaultProcessingMessageProcessingScope = <\n  HandlerContext = never,\n  Result = MessageHandlerResult,\n>(\n  handler: (context: HandlerContext) => Result | Promise<Result>,\n  partialContext: Partial<HandlerContext>,\n) => handler(partialContext as HandlerContext);\n\nexport type ReadProcessorCheckpointResult<CheckpointType = unknown> = {\n  lastCheckpoint: CheckpointType | null;\n};\n\nexport type ReadProcessorCheckpoint<\n  CheckpointType = unknown,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n> = (\n  options: { processorId: string; partition?: string },\n  context: HandlerContext,\n) => Promise<ReadProcessorCheckpointResult<CheckpointType>>;\n\nexport type StoreProcessorCheckpointResult<CheckpointType = unknown> =\n  | {\n      success: true;\n      newCheckpoint: CheckpointType;\n    }\n  | { success: false; reason: 'IGNORED' | 'MISMATCH' };\n\nexport type StoreProcessorCheckpoint<\n  MessageType extends Message = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  CheckpointType = unknown,\n  HandlerContext extends DefaultRecord | undefined = undefined,\n> =\n  | ((\n      options: {\n        message: RecordedMessage<MessageType, MessageMetadataType>;\n        processorId: string;\n        version: number | undefined;\n        lastCheckpoint: CheckpointType | null;\n        partition?: string;\n      },\n      context: HandlerContext,\n    ) => Promise<StoreProcessorCheckpointResult<CheckpointType | null>>)\n  | ((\n      options: {\n        message: RecordedMessage<MessageType, MessageMetadataType>;\n        processorId: string;\n        version: number | undefined;\n        lastCheckpoint: CheckpointType | null;\n        partition?: string;\n      },\n      context: HandlerContext,\n    ) => Promise<StoreProcessorCheckpointResult<CheckpointType>>);\n\nexport const reactor = <\n  MessageType extends Message = AnyMessage,\n  MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n>(\n  options: ReactorOptions<\n    MessageType,\n    MessageMetadataType,\n    HandlerContext,\n    CheckpointType\n  >,\n): MessageProcessor<\n  MessageType,\n  MessageMetadataType,\n  HandlerContext,\n  CheckpointType\n> => {\n  const eachMessage: SingleMessageHandlerWithContext<\n    MessageType,\n    MessageMetadataType,\n    HandlerContext\n  > =\n    'eachMessage' in options && options.eachMessage\n      ? options.eachMessage\n      : () => Promise.resolve();\n  let isActive = true;\n\n  const { checkpoints, processorId, partition } = options;\n\n  const processingScope =\n    options.processingScope ?? defaultProcessingMessageProcessingScope;\n\n  let lastCheckpoint: CheckpointType | null = null;\n\n  return {\n    id: options.processorId,\n    type: options.type ?? MessageProcessorType.REACTOR,\n    close: () =>\n      options.hooks?.onClose ? options.hooks?.onClose() : Promise.resolve(),\n    start: async (\n      startOptions: Partial<HandlerContext>,\n    ): Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined> => {\n      isActive = true;\n\n      if (lastCheckpoint !== null)\n        return {\n          lastCheckpoint,\n        };\n\n      return await processingScope(async (context) => {\n        if (options.hooks?.onStart) {\n          await options.hooks?.onStart(context);\n        }\n\n        if (options.startFrom !== 'CURRENT' && options.startFrom)\n          return options.startFrom;\n\n        if (checkpoints) {\n          const readResult = await checkpoints?.read(\n            {\n              processorId: processorId,\n              partition: partition,\n            },\n            { ...startOptions, ...context },\n          );\n          lastCheckpoint = readResult.lastCheckpoint;\n        }\n\n        if (lastCheckpoint === null) return 'BEGINNING';\n\n        return {\n          lastCheckpoint,\n        };\n      }, startOptions);\n    },\n    get isActive() {\n      return isActive;\n    },\n    handle: async (\n      messages: RecordedMessage<MessageType, MessageMetadataType>[],\n      partialContext: Partial<HandlerContext>,\n    ): Promise<MessageHandlerResult> => {\n      if (!isActive) return Promise.resolve();\n\n      return await processingScope(async (context) => {\n        let result: MessageHandlerResult = undefined;\n\n        for (const message of messages) {\n          if (wasMessageHandled(message, lastCheckpoint)) continue;\n\n          const messageProcessingResult = await eachMessage(message, context);\n\n          if (checkpoints) {\n            const storeCheckpointResult: StoreProcessorCheckpointResult<CheckpointType | null> =\n              await checkpoints.store(\n                {\n                  processorId: options.processorId,\n                  version: options.version,\n                  message,\n                  lastCheckpoint,\n                  partition: options.partition,\n                },\n                context,\n              );\n\n            if (storeCheckpointResult.success) {\n              // TODO: Add correct handling of the storing checkpoint\n              lastCheckpoint = storeCheckpointResult.newCheckpoint;\n            }\n          }\n\n          if (\n            messageProcessingResult &&\n            messageProcessingResult.type === 'STOP'\n          ) {\n            isActive = false;\n            result = messageProcessingResult;\n            break;\n          }\n\n          if (options.stopAfter && options.stopAfter(message)) {\n            isActive = false;\n            result = { type: 'STOP', reason: 'Stop condition reached' };\n            break;\n          }\n\n          if (\n            messageProcessingResult &&\n            messageProcessingResult.type === 'SKIP'\n          )\n            continue;\n        }\n\n        return result;\n      }, partialContext);\n    },\n  };\n};\n\nexport const projector = <\n  EventType extends Event = Event,\n  EventMetaDataType extends\n    AnyRecordedMessageMetadata = AnyRecordedMessageMetadata,\n  HandlerContext extends DefaultRecord = DefaultRecord,\n  CheckpointType = GlobalPositionTypeOfRecordedMessageMetadata<EventMetaDataType>,\n>(\n  options: ProjectorOptions<\n    EventType,\n    EventMetaDataType,\n    HandlerContext,\n    CheckpointType\n  >,\n): MessageProcessor<\n  EventType,\n  EventMetaDataType,\n  HandlerContext,\n  CheckpointType\n> => {\n  const { projection, ...rest } = options;\n\n  return reactor<EventType, EventMetaDataType, HandlerContext, CheckpointType>({\n    ...rest,\n    type: MessageProcessorType.PROJECTOR,\n    processorId: options.processorId ?? `projection:${projection.name}`,\n    hooks: {\n      onStart:\n        (options.truncateOnStart && options.projection.truncate) ||\n        options.hooks?.onStart\n          ? async (context: HandlerContext) => {\n              if (options.truncateOnStart && options.projection.truncate)\n                await options.projection.truncate(context);\n\n              if (options.hooks?.onStart) await options.hooks?.onStart(context);\n            }\n          : undefined,\n      onClose: options.hooks?.onClose,\n    },\n    eachMessage: async (\n      event: RecordedMessage<EventType, EventMetaDataType>,\n      context: HandlerContext,\n    ) => {\n      if (!projection.canHandle.includes(event.type)) return;\n\n      await projection.handle([event], context);\n    },\n  });\n};\n","import { getInMemoryDatabase, type InMemoryDatabase } from '../database';\nimport { EmmettError } from '../errors';\nimport {\n  type AnyEvent,\n  type AnyMessage,\n  type BatchRecordedMessageHandlerWithContext,\n  type MessageHandlerResult,\n  type ReadEventMetadataWithGlobalPosition,\n  type SingleRecordedMessageHandlerWithContext,\n} from '../typing';\nimport {\n  getCheckpoint,\n  MessageProcessor,\n  projector,\n  reactor,\n  type Checkpointer,\n  type MessageProcessingScope,\n  type ProjectorOptions,\n  type ReactorOptions,\n} from './processors';\n\nexport type InMemoryProcessorHandlerContext = {\n  database: InMemoryDatabase;\n};\n\nexport type InMemoryProcessor<MessageType extends AnyMessage = AnyMessage> =\n  MessageProcessor<\n    MessageType,\n    // TODO: generalize this to support other metadata types\n    ReadEventMetadataWithGlobalPosition,\n    InMemoryProcessorHandlerContext\n  > & { database: InMemoryDatabase };\n\nexport type InMemoryProcessorEachMessageHandler<\n  MessageType extends AnyMessage = AnyMessage,\n> = SingleRecordedMessageHandlerWithContext<\n  MessageType,\n  ReadEventMetadataWithGlobalPosition,\n  InMemoryProcessorHandlerContext\n>;\n\nexport type InMemoryProcessorEachBatchHandler<\n  MessageType extends AnyMessage = AnyMessage,\n> = BatchRecordedMessageHandlerWithContext<\n  MessageType,\n  ReadEventMetadataWithGlobalPosition,\n  InMemoryProcessorHandlerContext\n>;\n\nexport type InMemoryProcessorConnectionOptions = {\n  database?: InMemoryDatabase;\n};\n\ntype CheckpointDocument = {\n  _id: string;\n  lastCheckpoint: bigint | null;\n};\n\nexport type InMemoryCheckpointer<MessageType extends AnyMessage = AnyMessage> =\n  Checkpointer<\n    MessageType,\n    ReadEventMetadataWithGlobalPosition,\n    InMemoryProcessorHandlerContext\n  >;\n\nexport const inMemoryCheckpointer = <\n  MessageType extends AnyMessage = AnyMessage,\n>(): InMemoryCheckpointer<MessageType> => {\n  return {\n    read: async ({ processorId }, { database }) => {\n      const checkpoint = await database\n        .collection<CheckpointDocument>('emt_processor_checkpoints')\n        .findOne((d) => d._id === processorId);\n\n      return Promise.resolve({\n        lastCheckpoint: checkpoint?.lastCheckpoint ?? null,\n      });\n    },\n    store: async (context, { database }) => {\n      const { message, processorId, lastCheckpoint } = context;\n      const checkpoints = database.collection<CheckpointDocument>(\n        'emt_processor_checkpoints',\n      );\n\n      const checkpoint = await checkpoints.findOne(\n        (d) => d._id === processorId,\n      );\n\n      const currentPosition = checkpoint?.lastCheckpoint ?? null;\n\n      const newCheckpoint: bigint | null = getCheckpoint(message);\n\n      if (\n        currentPosition &&\n        (currentPosition === newCheckpoint ||\n          currentPosition !== lastCheckpoint)\n      ) {\n        return {\n          success: false,\n          reason: currentPosition === newCheckpoint ? 'IGNORED' : 'MISMATCH',\n        };\n      }\n\n      await checkpoints.handle(processorId, (existing) => ({\n        ...(existing ?? {}),\n        _id: processorId,\n        lastCheckpoint: newCheckpoint,\n      }));\n\n      return { success: true, newCheckpoint };\n    },\n  };\n};\n\ntype InMemoryConnectionOptions = {\n  connectionOptions?: InMemoryProcessorConnectionOptions;\n};\n\nexport type InMemoryReactorOptions<\n  MessageType extends AnyMessage = AnyMessage,\n> = ReactorOptions<\n  MessageType,\n  ReadEventMetadataWithGlobalPosition,\n  InMemoryProcessorHandlerContext\n> &\n  InMemoryConnectionOptions;\n\nexport type InMemoryProjectorOptions<EventType extends AnyEvent = AnyEvent> =\n  ProjectorOptions<\n    EventType,\n    ReadEventMetadataWithGlobalPosition,\n    InMemoryProcessorHandlerContext\n  > &\n    InMemoryConnectionOptions;\n\nexport type InMemoryProcessorOptions<\n  MessageType extends AnyMessage = AnyMessage,\n> =\n  | InMemoryReactorOptions<MessageType>\n  | InMemoryProjectorOptions<MessageType & AnyEvent>;\n\nconst inMemoryProcessingScope = (options: {\n  database: InMemoryDatabase | null;\n  processorId: string;\n}): MessageProcessingScope<InMemoryProcessorHandlerContext> => {\n  const processorDatabase = options.database;\n\n  const processingScope: MessageProcessingScope<\n    InMemoryProcessorHandlerContext\n  > = <Result = MessageHandlerResult>(\n    handler: (\n      context: InMemoryProcessorHandlerContext,\n    ) => Result | Promise<Result>,\n    partialContext: Partial<InMemoryProcessorHandlerContext>,\n  ) => {\n    const database = processorDatabase ?? partialContext?.database;\n\n    if (!database)\n      throw new EmmettError(\n        `InMemory processor '${options.processorId}' is missing database. Ensure that you passed it through options`,\n      );\n\n    return handler({ ...partialContext, database });\n  };\n\n  return processingScope;\n};\n\nexport const inMemoryProjector = <EventType extends AnyEvent = AnyEvent>(\n  options: InMemoryProjectorOptions<EventType>,\n): InMemoryProcessor<EventType> => {\n  const database = options.connectionOptions?.database ?? getInMemoryDatabase();\n\n  const hooks = {\n    onStart: options.hooks?.onStart,\n    onClose: options.hooks?.onClose\n      ? async () => {\n          if (options.hooks?.onClose) await options.hooks?.onClose();\n        }\n      : undefined,\n  };\n\n  return {\n    ...projector<\n      EventType,\n      ReadEventMetadataWithGlobalPosition,\n      InMemoryProcessorHandlerContext\n    >({\n      ...options,\n      hooks,\n      processingScope: inMemoryProcessingScope({\n        database,\n        processorId:\n          options.processorId ?? `projection:${options.projection.name}`,\n      }),\n      checkpoints: inMemoryCheckpointer<EventType>(),\n    }),\n    database,\n  };\n};\n\nexport const inMemoryReactor = <MessageType extends AnyMessage = AnyMessage>(\n  options: InMemoryReactorOptions<MessageType>,\n): InMemoryProcessor<MessageType> => {\n  const database = options.connectionOptions?.database ?? getInMemoryDatabase();\n\n  const hooks = {\n    onStart: options.hooks?.onStart,\n    onClose: options.hooks?.onClose\n      ? async () => {\n          if (options.hooks?.onClose) await options.hooks?.onClose();\n        }\n      : undefined,\n  };\n\n  return {\n    ...reactor({\n      ...options,\n      hooks,\n      processingScope: inMemoryProcessingScope({\n        database,\n        processorId: options.processorId,\n      }),\n      checkpoints: inMemoryCheckpointer<MessageType>(),\n    }),\n    database,\n  };\n};\n","import { EmmettError } from '../errors';\nimport { JSONParser } from '../serialization';\nimport type {\n  AnyEvent,\n  AnyReadEventMetadata,\n  BatchRecordedMessageHandlerWithContext,\n  CanHandle,\n  DefaultRecord,\n  Event,\n} from '../typing';\nimport { arrayUtils } from '../utils';\n\nexport type ProjectionHandlingType = 'inline' | 'async';\n\nexport type ProjectionHandler<\n  EventType extends Event = AnyEvent,\n  EventMetaDataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n> = BatchRecordedMessageHandlerWithContext<\n  EventType,\n  EventMetaDataType,\n  ProjectionHandlerContext\n>;\n\nexport type TruncateProjection<\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: ProjectionHandlerContext) => Promise<void>;\n\nexport interface ProjectionDefinition<\n  EventType extends Event = AnyEvent,\n  EventMetaDataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n> {\n  name?: string;\n  canHandle: CanHandle<EventType>;\n  handle: ProjectionHandler<\n    EventType,\n    EventMetaDataType,\n    ProjectionHandlerContext\n  >;\n  truncate?: TruncateProjection<ProjectionHandlerContext>;\n}\n\nexport type ProjectionRegistration<\n  HandlingType extends ProjectionHandlingType,\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n> = {\n  type: HandlingType;\n  projection: ProjectionDefinition<\n    AnyEvent,\n    ReadEventMetadataType,\n    ProjectionHandlerContext\n  >;\n};\n\nexport const filterProjections = <\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n>(\n  type: ProjectionHandlingType,\n  projections: ProjectionRegistration<\n    ProjectionHandlingType,\n    ReadEventMetadataType,\n    ProjectionHandlerContext\n  >[],\n) => {\n  const inlineProjections = projections\n    .filter((projection) => projection.type === type)\n    .map(({ projection }) => projection);\n\n  const duplicateRegistrations = arrayUtils.getDuplicates(\n    inlineProjections,\n    (proj) => proj.name,\n  );\n\n  if (duplicateRegistrations.length > 0) {\n    throw new EmmettError(`You cannot register multiple projections with the same name (or without the name).\n      Ensure that:\n      ${JSONParser.stringify(duplicateRegistrations)}\n      have different names`);\n  }\n\n  return inlineProjections;\n};\n\nexport const projection = <\n  EventType extends Event = Event,\n  EventMetaDataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n>(\n  definition: ProjectionDefinition<\n    EventType,\n    EventMetaDataType,\n    ProjectionHandlerContext\n  >,\n): ProjectionDefinition<\n  EventType,\n  EventMetaDataType,\n  ProjectionHandlerContext\n> => definition;\n\nexport const inlineProjections = <\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n>(\n  definitions: ProjectionDefinition<\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    any,\n    ReadEventMetadataType,\n    ProjectionHandlerContext\n  >[],\n): ProjectionRegistration<\n  'inline',\n  ReadEventMetadataType,\n  ProjectionHandlerContext\n>[] =>\n  definitions.map((definition) => ({\n    type: 'inline',\n    projection: definition,\n  }));\n\nexport const asyncProjections = <\n  ReadEventMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n  ProjectionHandlerContext extends DefaultRecord = DefaultRecord,\n>(\n  definitions: ProjectionDefinition<\n    AnyEvent,\n    ReadEventMetadataType,\n    ProjectionHandlerContext\n  >[],\n): ProjectionRegistration<\n  'inline',\n  ReadEventMetadataType,\n  ProjectionHandlerContext\n>[] =>\n  definitions.map((definition) => ({\n    type: 'inline',\n    projection: definition,\n  }));\n\nexport const projections = {\n  inline: inlineProjections,\n  async: asyncProjections,\n};\n","export const concatUint8Arrays = (chunks: Uint8Array[]): Uint8Array => {\n  const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n  const result = new Uint8Array(totalLength);\n  let offset = 0;\n  for (const chunk of chunks) {\n    result.set(chunk, offset);\n    offset += chunk.length;\n  }\n  return result;\n};\n","import type { ReadableStream } from 'web-streams-polyfill';\n\nexport const collect = async <T>(stream: ReadableStream<T>): Promise<T[]> => {\n  const results: T[] = [];\n\n  for await (const value of stream) {\n    results.push(value as T);\n  }\n\n  return results;\n};\n","import type { Decoder } from '.';\nimport { concatUint8Arrays } from '../binaryArrays';\n\nexport class BinaryJsonDecoder<Decoded>\n  implements Decoder<Uint8Array, Decoded>\n{\n  private buffer: Uint8Array[] = [];\n\n  addToBuffer(data: Uint8Array): void {\n    this.buffer.push(data);\n  }\n\n  clearBuffer(): void {\n    this.buffer = [];\n  }\n\n  hasCompleteMessage(): boolean {\n    const combined = concatUint8Arrays(this.buffer);\n    const text = new TextDecoder().decode(combined);\n    return text.includes('\\n');\n  }\n\n  decode(): Decoded | null {\n    if (!this.hasCompleteMessage()) {\n      return null;\n    }\n\n    const combined = concatUint8Arrays(this.buffer);\n    const text = new TextDecoder().decode(combined);\n    const delimiterIndex = text.indexOf('\\n');\n\n    if (delimiterIndex === -1) {\n      return null;\n    }\n\n    const jsonString = text.slice(0, delimiterIndex);\n    const remaining = new Uint8Array(combined.buffer, delimiterIndex + 1);\n    this.buffer = remaining.byteLength > 0 ? [remaining] : [];\n\n    return JSON.parse(jsonString) as Decoded;\n  }\n}\n","import type { Decoder } from '.';\n\nexport class StringDecoder<Decoded> implements Decoder<string, Decoded> {\n  protected buffer: string[] = [];\n\n  constructor(private transform: (input: string) => Decoded) {\n    this.transform = transform;\n  }\n\n  addToBuffer(data: string): void {\n    this.buffer.push(data);\n  }\n\n  clearBuffer(): void {\n    this.buffer = [];\n  }\n\n  hasCompleteMessage(): boolean {\n    return this.buffer.some((chunk) => chunk.includes('\\n'));\n  }\n\n  decode(): Decoded | null {\n    const completeString = this.buffer.join('');\n\n    if (!this.hasCompleteMessage()) {\n      if (completeString.trim().length > 0) {\n        throw new Error('Unterminated string in JSON at position');\n      }\n      return null;\n    }\n\n    const delimiterIndex = completeString.indexOf('\\n');\n    const message = completeString.slice(0, delimiterIndex).trim();\n    this.buffer = [completeString.slice(delimiterIndex + 1)];\n\n    return this.transform(message);\n  }\n}\n","import { StringDecoder } from './string';\n\nexport class JsonDecoder<Decoded> extends StringDecoder<Decoded> {\n  constructor() {\n    super((jsonString) => JSON.parse(jsonString) as Decoded);\n  }\n}\n","import type { Decoder } from '.';\n\nexport class ObjectDecoder<Decoded> implements Decoder<Decoded, Decoded> {\n  private buffer: Decoded | null = null;\n\n  addToBuffer(data: Decoded): void {\n    this.buffer = data;\n  }\n\n  clearBuffer(): void {\n    this.buffer = null;\n  }\n\n  hasCompleteMessage(): boolean {\n    return this.buffer !== null;\n  }\n\n  decode(): Decoded | null {\n    if (!this.hasCompleteMessage() || !this.buffer) {\n      return null;\n    }\n\n    const data = this.buffer;\n    this.clearBuffer();\n    return data as Decoded;\n  }\n}\n","import type { Decoder } from '.';\nimport { BinaryJsonDecoder } from './binary';\nimport { JsonDecoder } from './json';\nimport { ObjectDecoder } from './object';\n\nexport class CompositeDecoder<Decoded> implements Decoder<unknown, Decoded> {\n  constructor(\n    private decoders: [(data: unknown) => boolean, Decoder<unknown, Decoded>][],\n  ) {}\n\n  private decoderFor(data: unknown): Decoder<unknown, unknown> | null {\n    const decoder = this.decoders.find((d) => d[0](data));\n\n    if (!decoder) return null;\n\n    return decoder[1];\n  }\n\n  addToBuffer(data: unknown): void {\n    this.decoderFor(data)?.addToBuffer(data);\n  }\n\n  clearBuffer(): void {\n    for (const decoder of this.decoders.map((d) => d[1])) {\n      decoder.clearBuffer();\n    }\n  }\n\n  hasCompleteMessage(): boolean {\n    return this.decoders.some((d) => d[1].hasCompleteMessage());\n  }\n\n  decode(): Decoded | null {\n    const decoder = this.decoders\n      .map((d) => d[1])\n      .find((d) => d.hasCompleteMessage());\n\n    return decoder?.decode() ?? null;\n  }\n}\n\nexport class DefaultDecoder<Decoded> extends CompositeDecoder<Decoded> {\n  constructor() {\n    super([\n      [(data) => typeof data === 'string', new JsonDecoder<Decoded>()],\n      [(data) => data instanceof Uint8Array, new BinaryJsonDecoder<Decoded>()],\n      [(data) => typeof data === 'object', new ObjectDecoder<Decoded>()],\n    ]);\n  }\n}\n","import { ReadableStream } from 'web-streams-polyfill';\n\nexport const fromArray = <T>(chunks: T[]) =>\n  new ReadableStream<T>({\n    start(controller) {\n      for (const chunk of chunks) controller.enqueue(chunk);\n      controller.close();\n    },\n  });\n","import { fromArray } from './fromArray';\nexport const streamGenerators = { fromArray };\n","import {\n  type ReadableStream,\n  type ReadableStreamDefaultReadResult,\n  type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport type { AsyncRetryOptions } from '../utils';\nimport type { Decoder } from './decoders';\nimport { DefaultDecoder } from './decoders/composite';\nimport { streamTransformations } from './transformations';\n\nconst { retry } = streamTransformations;\n\nexport const restream = <\n  Source = unknown,\n  Transformed = Source,\n  StreamType = Source,\n>(\n  createSourceStream: () => ReadableStream<StreamType>,\n  transform: (input: Source) => Transformed = (source) =>\n    source as unknown as Transformed,\n  retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n  decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n): ReadableStream<Transformed> =>\n  retry(createSourceStream, handleChunk(transform, decoder), retryOptions)\n    .readable;\n\nconst handleChunk =\n  <Source = unknown, Transformed = Source, StreamType = Source>(\n    transform: (input: Source) => Transformed = (source) =>\n      source as unknown as Transformed,\n    decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n  ) =>\n  (\n    readResult: ReadableStreamDefaultReadResult<StreamType>,\n    controller: TransformStreamDefaultController<Transformed>,\n  ): void => {\n    const { done: isDone, value } = readResult;\n\n    if (value) decoder.addToBuffer(value);\n\n    if (!isDone && !decoder.hasCompleteMessage()) return;\n\n    decodeAndTransform(decoder, transform, controller);\n  };\n\nconst decodeAndTransform = <StreamType, Source, Transformed = Source>(\n  decoder: Decoder<StreamType, Source>,\n  transform: (input: Source) => Transformed,\n  controller: TransformStreamDefaultController<Transformed>,\n) => {\n  try {\n    const decoded = decoder.decode();\n    if (!decoded) return; // TODO: Add a proper handling of decode errors\n\n    const transformed = transform(decoded);\n    controller.enqueue(transformed);\n  } catch (error) {\n    controller.error(new Error(`Decoding error: ${error?.toString()}`));\n  }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const filter = <Item>(filter: (item: Item) => boolean) =>\n  new TransformStream<Item, Item>({\n    transform(chunk, controller) {\n      if (filter(chunk)) {\n        controller.enqueue(chunk);\n      }\n    },\n  });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const map = <From, To>(map: (item: From) => To) =>\n  new TransformStream<From, To>({\n    transform(chunk, controller) {\n      controller.enqueue(map(chunk));\n    },\n  });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const reduce = <I, O>(\n  reducer: (accumulator: O, chunk: I) => O,\n  initialValue: O,\n) => new ReduceTransformStream<I, O>(reducer, initialValue);\n\nexport class ReduceTransformStream<I, O> extends TransformStream<I, O> {\n  private accumulator: O;\n  private reducer: (accumulator: O, chunk: I) => O;\n\n  constructor(reducer: (accumulator: O, chunk: I) => O, initialValue: O) {\n    super({\n      transform: (chunk) => {\n        this.accumulator = this.reducer(this.accumulator, chunk);\n      },\n      flush: (controller) => {\n        controller.enqueue(this.accumulator);\n        controller.terminate();\n      },\n    });\n\n    this.accumulator = initialValue;\n    this.reducer = reducer;\n  }\n}\n","import {\n  type ReadableStream,\n  type ReadableStreamDefaultReadResult,\n  TransformStream,\n  type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport { type AsyncRetryOptions, asyncRetry } from '../../utils';\n\nexport const retryStream = <\n  Source = unknown,\n  Transformed = Source,\n  StreamType = Source,\n>(\n  createSourceStream: () => ReadableStream<StreamType>,\n  handleChunk: (\n    readResult: ReadableStreamDefaultReadResult<StreamType>,\n    controller: TransformStreamDefaultController<Transformed>,\n  ) => Promise<void> | void,\n  retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n): TransformStream<Source, Transformed> =>\n  new TransformStream<Source, Transformed>({\n    start(controller) {\n      asyncRetry(\n        () => onRestream(createSourceStream, handleChunk, controller),\n        retryOptions,\n      ).catch((error) => {\n        controller.error(error);\n      });\n    },\n  });\n\nconst onRestream = async <StreamType, Source, Transformed = Source>(\n  createSourceStream: () => ReadableStream<StreamType>,\n  handleChunk: (\n    readResult: ReadableStreamDefaultReadResult<StreamType>,\n    controller: TransformStreamDefaultController<Transformed>,\n  ) => Promise<void> | void,\n  controller: TransformStreamDefaultController<Transformed>,\n): Promise<void> => {\n  const sourceStream = createSourceStream();\n  const reader = sourceStream.getReader();\n\n  try {\n    let done: boolean;\n\n    do {\n      const result = await reader.read();\n      done = result.done;\n\n      await handleChunk(result, controller);\n\n      if (done) {\n        controller.terminate();\n      }\n    } while (!done);\n  } finally {\n    reader.releaseLock();\n  }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const skip = <T>(limit: number) => new SkipTransformStream<T>(limit);\n\nexport class SkipTransformStream<T> extends TransformStream<T, T> {\n  private count = 0;\n  private skip: number;\n\n  constructor(skip: number) {\n    super({\n      transform: (chunk, controller) => {\n        this.count++;\n        if (this.count > this.skip) {\n          controller.enqueue(chunk);\n        }\n      },\n    });\n\n    this.skip = skip;\n  }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopAfter = <Item>(stopCondition: (item: Item) => boolean) =>\n  new TransformStream<Item, Item>({\n    transform(chunk, controller) {\n      controller.enqueue(chunk);\n\n      if (stopCondition(chunk)) {\n        controller.terminate();\n      }\n    },\n  });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopOn = <Item>(stopCondition: (item: Item) => boolean) =>\n  new TransformStream<Item, Item>({\n    async transform(chunk, controller) {\n      if (!stopCondition(chunk)) {\n        controller.enqueue(chunk);\n        return;\n      }\n      await Promise.resolve();\n      controller.terminate();\n    },\n  });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const take = <T>(limit: number) => new TakeTransformStream<T>(limit);\n\nexport class TakeTransformStream<T> extends TransformStream<T, T> {\n  private count = 0;\n  private limit: number;\n\n  constructor(limit: number) {\n    super({\n      transform: (chunk, controller) => {\n        if (this.count < this.limit) {\n          this.count++;\n          controller.enqueue(chunk);\n        } else {\n          controller.terminate();\n        }\n      },\n    });\n\n    this.limit = limit;\n  }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const waitAtMost = <Item>(waitTimeInMs: number) =>\n  new TransformStream<Item, Item>({\n    start(controller) {\n      const timeoutId = setTimeout(() => {\n        controller.terminate();\n      }, waitTimeInMs);\n\n      const originalTerminate = controller.terminate.bind(controller);\n\n      // Clear the timeout if the stream is terminated early\n      controller.terminate = () => {\n        clearTimeout(timeoutId);\n        originalTerminate();\n      };\n    },\n    transform(chunk, controller) {\n      controller.enqueue(chunk);\n    },\n  });\n","import { filter } from './filter';\nimport { map } from './map';\nimport {\n  notifyAboutNoActiveReadersStream,\n  NotifyAboutNoActiveReadersStream,\n} from './notifyAboutNoActiveReaders';\nimport { reduce, ReduceTransformStream } from './reduce';\nimport { retryStream } from './retry';\nimport { skip, SkipTransformStream } from './skip';\nimport { stopAfter } from './stopAfter';\nimport { stopOn } from './stopOn';\nimport { take, TakeTransformStream } from './take';\nimport { waitAtMost } from './waitAtMost';\n\nexport const streamTransformations = {\n  filter,\n  take,\n  TakeTransformStream,\n  skip,\n  SkipTransformStream,\n  map,\n  notifyAboutNoActiveReadersStream,\n  NotifyAboutNoActiveReadersStream,\n  reduce,\n  ReduceTransformStream,\n  retry: retryStream,\n  stopAfter,\n  stopOn,\n  waitAtMost,\n};\n"]}