@event-driven-io/emmett-esdb 0.43.0-alpha.1 → 0.43.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","../../emmett/src/validation/index.ts","../../emmett/src/errors/index.ts","../../emmett/src/eventStore/inMemoryEventStore.ts","../../emmett/src/database/inMemoryDatabase.ts","../../emmett/src/utils/retry.ts","../../emmett/src/eventStore/projections/inMemory/inMemoryProjectionSpec.ts","../../emmett/src/processors/processors.ts","../../emmett/src/typing/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/utils/deepEquals.ts","../../emmett/src/serialization/json/JSONParser.ts","../../emmett/src/utils/shutdown/gracefulShutdown.ts","../../emmett/src/utils/strings/hashText.ts","../../emmett/src/database/utils.ts","../../emmett/src/eventStore/versioning/downcasting.ts","../../emmett/src/eventStore/versioning/upcasting.ts","../../emmett/src/processors/inMemoryProcessors.ts","../src/eventStore/consumers/eventStoreDBEventStoreConsumer.ts","../src/eventStore/consumers/subscriptions/index.ts","../src/eventStore/eventstoreDBEventStore.ts"],"names":["operationResult"],"mappings":"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","file":"/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","sourcesContent":[null,"import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const isBigint = (val: any): val is bigint =>\n typeof val === 'bigint' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n\nexport * from './dates';\n","import { isNumber, isString } from '../validation';\n\nexport type ErrorConstructor<ErrorType extends Error> = new (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...args: any[]\n) => ErrorType;\n\nexport const isErrorConstructor = <ErrorType extends Error>(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n expect: Function,\n): expect is ErrorConstructor<ErrorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (\n typeof expect === 'function' &&\n expect.prototype &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect.prototype.constructor === expect\n );\n};\n\nexport class EmmettError extends Error {\n public static readonly Codes = {\n ValidationError: 400,\n IllegalStateError: 403,\n NotFoundError: 404,\n ConcurrencyError: 412,\n InternalServerError: 500,\n };\n\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : EmmettError.Codes.InternalServerError;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n\n public static mapFrom(\n error: Error | { message?: string; errorCode?: number },\n ): EmmettError {\n if (EmmettError.isInstanceOf(error)) {\n return error;\n }\n\n return new EmmettError({\n errorCode:\n 'errorCode' in error &&\n error.errorCode !== undefined &&\n error.errorCode !== null\n ? error.errorCode\n : EmmettError.Codes.InternalServerError,\n message: error.message ?? 'An unknown error occurred',\n });\n }\n\n public static isInstanceOf<ErrorType extends EmmettError = EmmettError>(\n error: unknown,\n errorCode?: (typeof EmmettError.Codes)[keyof typeof EmmettError.Codes],\n ): error is ErrorType {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'errorCode' in error &&\n isNumber(error.errorCode) &&\n (errorCode === undefined || error.errorCode === errorCode)\n );\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: EmmettError.Codes.ConcurrencyError,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\n// TODO: Make it derive from ConcurrencyError to avoid code duplication\n// Or add additional type to distinguinsh both errors\nexport class ConcurrencyInMemoryDatabaseError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.ConcurrencyError,\n message: message ?? `Expected document state does not match current one!`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyInMemoryDatabaseError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.ValidationError,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.IllegalStateError,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: EmmettError.Codes.NotFoundError,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\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 type StreamExistsResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\nimport { handleInMemoryProjections } from './projections/inMemory';\nimport { downcastRecordedMessages, upcastRecordedMessages } from './versioning';\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\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<\n State,\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options: AggregateStreamOptions<\n State,\n EventType,\n ReadEventMetadataWithGlobalPosition,\n EventPayloadType\n >,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const result = await this.readStream<EventType, EventPayloadType>(\n streamName,\n read,\n );\n\n const events = result?.events ?? [];\n\n const state = events.reduce((s, e) => evolve(s, e), initialState());\n\n return {\n currentStreamVersion: BigInt(events.length),\n state,\n streamExists: result.streamExists,\n };\n },\n\n readStream: <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options?: ReadStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\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 ?? 0);\n const to = Number(\n options?.to ??\n (options?.maxCount\n ? (options.from ?? 0n) + options.maxCount\n : (events?.length ?? 1)),\n );\n\n const resultEvents =\n events !== undefined && events.length > 0\n ? upcastRecordedMessages<\n EventType,\n EventPayloadType,\n ReadEventMetadataWithGlobalPosition\n >(\n events.slice(from, to) as ReadEvent<\n EventPayloadType,\n ReadEventMetadataWithGlobalPosition\n >[],\n options?.schema?.versioning,\n )\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 <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\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, [\n ...currentEvents,\n ...downcastRecordedMessages(newEvents, options?.schema?.versioning),\n ]);\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 streamExists: (streamName): Promise<StreamExistsResult> => {\n const events = streams.get(streamName);\n\n return Promise.resolve(events !== undefined && events.length > 0);\n },\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","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","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 InMemoryReadEventMetadata =\n 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 streamExists: async () => {\n return Promise.resolve(false);\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 InMemoryReadEventMetadata =\n 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 InMemoryReadEventMetadata =\n 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 { v7 as uuid } from 'uuid';\nimport type { EmmettError } from '../errors';\nimport { upcastRecordedMessage } from '../eventStore';\nimport type { ProjectionDefinition } from '../projections';\nimport {\n defaultTag,\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 { onShutdown } from '../utils/shutdown';\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 =\n 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 =\n 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 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 =\n 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 =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n id: string;\n instanceId: string;\n type: string;\n init: (options: Partial<HandlerContext>) => Promise<void>;\n start: (\n options: Partial<HandlerContext>,\n ) => Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined>;\n close: (closeOptions: Partial<HandlerContext>) => 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 =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n read: ReadProcessorCheckpoint<CheckpointType, HandlerContext>;\n store: StoreProcessorCheckpoint<\n MessageType,\n MessageMetadataType,\n CheckpointType,\n HandlerContext\n >;\n};\n\nexport type ProcessorHooks<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = {\n onInit?: OnReactorInitHook<HandlerContext>;\n onStart?: OnReactorStartHook<HandlerContext>;\n onClose?: OnReactorCloseHook<HandlerContext>;\n};\n\nexport type BaseMessageProcessorOptions<\n MessageType extends AnyMessage = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n type?: string;\n processorId: string;\n processorInstanceId?: 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?: ProcessorHooks<HandlerContext>;\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 OnReactorInitHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type OnReactorStartHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type OnReactorCloseHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type ReactorOptions<\n MessageType extends AnyMessage = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n MessagePayloadType extends AnyMessage = MessageType,\n> = BaseMessageProcessorOptions<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType\n> &\n HandlerOptions<MessageType, MessageMetadataType, HandlerContext> & {\n messageOptions?: {\n schema?: {\n versioning?: { upcast?: (event: MessagePayloadType) => MessageType };\n };\n };\n };\n\nexport type ProjectorOptions<\n EventType extends AnyEvent = AnyEvent,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n EventPayloadType extends Event = EventType,\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 EventPayloadType\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' | 'CURRENT_AHEAD' };\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 defaultProcessorVersion = 1;\nexport const defaultProcessorPartition = defaultTag;\n\nexport const getProcessorInstanceId = (processorId: string): string =>\n `${processorId}:${uuid()}`;\n\nexport const getProjectorId = (options: { projectionName: string }): string =>\n `emt:processor:projector:${options.projectionName}`;\n\nexport const reactor = <\n MessageType extends Message = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n MessagePayloadType extends Message = MessageType,\n>(\n options: ReactorOptions<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType,\n MessagePayloadType\n >,\n): MessageProcessor<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType\n> => {\n const {\n checkpoints,\n processorId,\n processorInstanceId: instanceId = getProcessorInstanceId(processorId),\n type = MessageProcessorType.REACTOR,\n version = defaultProcessorVersion,\n partition = defaultProcessorPartition,\n hooks = {},\n processingScope = defaultProcessingMessageProcessingScope,\n startFrom,\n canHandle,\n stopAfter,\n } = options;\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\n let isInitiated = false;\n let isActive = false;\n\n let lastCheckpoint: CheckpointType | null = null;\n let closeSignal: (() => void) | null = null;\n\n const init = async (initOptions: Partial<HandlerContext>): Promise<void> => {\n if (isInitiated) return;\n\n if (hooks.onInit === undefined) {\n isInitiated = true;\n return;\n }\n\n return await processingScope(async (context) => {\n await hooks.onInit!(context);\n isInitiated = true;\n }, initOptions);\n };\n\n const close = async (\n closeOptions: Partial<HandlerContext>,\n ): Promise<void> => {\n // TODO: Align when active is set to false\n // if (!isActive) return;\n\n isActive = false;\n\n if (closeSignal) {\n closeSignal();\n closeSignal = null;\n }\n\n if (hooks.onClose) {\n await processingScope(hooks.onClose, closeOptions);\n }\n };\n\n return {\n // TODO: Consider whether not make it optional or add URN prefix\n id: processorId,\n instanceId,\n type,\n init,\n start: async (\n startOptions: Partial<HandlerContext>,\n ): Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined> => {\n if (isActive) return;\n\n await init(startOptions);\n\n isActive = true;\n\n closeSignal = onShutdown(() => close({}));\n\n if (lastCheckpoint !== null)\n return {\n lastCheckpoint,\n };\n\n return await processingScope(async (context) => {\n if (hooks.onStart) {\n await hooks.onStart(context);\n }\n\n if (startFrom && startFrom !== 'CURRENT') return startFrom;\n\n if (checkpoints) {\n const readResult = await checkpoints?.read(\n {\n processorId: processorId,\n 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 close,\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 upcasted = upcastRecordedMessage(\n // TODO: Make it smarter\n message as unknown as RecordedMessage<\n MessagePayloadType,\n MessageMetadataType\n >,\n options.messageOptions?.schema?.versioning,\n );\n\n if (canHandle !== undefined && !canHandle.includes(upcasted.type))\n continue;\n\n const messageProcessingResult = await eachMessage(upcasted, context);\n\n if (checkpoints) {\n const storeCheckpointResult: StoreProcessorCheckpointResult<CheckpointType | null> =\n await checkpoints.store(\n {\n processorId,\n version,\n message: upcasted,\n lastCheckpoint,\n 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 (stopAfter && stopAfter(upcasted)) {\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 AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<EventMetaDataType>,\n EventPayloadType extends Event = EventType,\n>(\n options: ProjectorOptions<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType,\n EventPayloadType\n >,\n): MessageProcessor<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType\n> => {\n const {\n projection,\n processorId = getProjectorId({\n projectionName: projection.name ?? 'unknown',\n }),\n ...rest\n } = options;\n\n return reactor<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType,\n EventPayloadType\n >({\n ...rest,\n type: MessageProcessorType.PROJECTOR,\n canHandle: projection.canHandle,\n processorId,\n messageOptions: options.projection.eventsOptions,\n hooks: {\n onInit: options.hooks?.onInit,\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 ) => projection.handle([event], context),\n });\n};\n","export * from './deepReadonly';\n\nexport * from './command';\nexport * from './event';\nexport * from './message';\nexport * from './messageHandling';\n\nexport * from './decider';\nexport * from './workflow';\n\nexport type Brand<K, T> = K & { readonly __brand: T };\nexport type Flavour<K, T> = K & { readonly __brand?: T };\n\nexport type DefaultRecord = Record<string, unknown>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyRecord = Record<string, any>;\n\nexport type NonNullable<T> = T extends null | undefined ? never : T;\n\nexport const emmettPrefix = 'emt';\n\nexport const globalTag = 'global';\nexport const defaultTag = `${emmettPrefix}:default`;\nexport const unknownTag = `${emmettPrefix}:unknown`;\n","import { ConcurrencyError, EmmettError } 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 EmmettError.isInstanceOf<ConcurrencyError>(\n error,\n ExpectedVersionConflictError.Codes.ConcurrencyError,\n );\n","const isPrimitive = (value: unknown): boolean => {\n const type = typeof value;\n return (\n value === null ||\n value === undefined ||\n type === 'boolean' ||\n type === 'number' ||\n type === 'string' ||\n type === 'symbol' ||\n type === 'bigint'\n );\n};\n\nconst compareArrays = <T>(left: T[], right: T[]): boolean => {\n if (left.length !== right.length) {\n return false;\n }\n for (let i = 0; i < left.length; i++) {\n const leftHas = i in left;\n const rightHas = i in right;\n if (leftHas !== rightHas) return false;\n if (leftHas && !deepEquals(left[i], right[i])) return false;\n }\n return true;\n};\n\nconst compareDates = (left: Date, right: Date): boolean => {\n return left.getTime() === right.getTime();\n};\n\nconst compareRegExps = (left: RegExp, right: RegExp): boolean => {\n return left.toString() === right.toString();\n};\n\nconst compareErrors = (left: Error, right: Error): boolean => {\n if (left.message !== right.message || left.name !== right.name) {\n return false;\n }\n const leftKeys = Object.keys(left);\n const rightKeys = Object.keys(right);\n if (leftKeys.length !== rightKeys.length) return false;\n const rightKeySet = new Set(rightKeys);\n for (const key of leftKeys) {\n if (!rightKeySet.has(key)) return false;\n // @ts-expect-error - accessing dynamic keys\n if (!deepEquals(left[key], right[key])) return false;\n }\n return true;\n};\n\nconst compareMaps = (\n left: Map<unknown, unknown>,\n right: Map<unknown, unknown>,\n): boolean => {\n if (left.size !== right.size) return false;\n\n for (const [key, value] of left) {\n if (isPrimitive(key)) {\n if (!right.has(key) || !deepEquals(value, right.get(key))) {\n return false;\n }\n } else {\n let found = false;\n for (const [rightKey, rightValue] of right) {\n if (deepEquals(key, rightKey) && deepEquals(value, rightValue)) {\n found = true;\n break;\n }\n }\n if (!found) return false;\n }\n }\n return true;\n};\n\nconst compareSets = (left: Set<unknown>, right: Set<unknown>): boolean => {\n if (left.size !== right.size) return false;\n\n for (const leftItem of left) {\n if (isPrimitive(leftItem)) {\n if (!right.has(leftItem)) return false;\n } else {\n let found = false;\n for (const rightItem of right) {\n if (deepEquals(leftItem, rightItem)) {\n found = true;\n break;\n }\n }\n if (!found) return false;\n }\n }\n return true;\n};\n\nconst compareArrayBuffers = (\n left: ArrayBuffer,\n right: ArrayBuffer,\n): boolean => {\n if (left.byteLength !== right.byteLength) return false;\n const leftView = new Uint8Array(left);\n const rightView = new Uint8Array(right);\n for (let i = 0; i < leftView.length; i++) {\n if (leftView[i] !== rightView[i]) return false;\n }\n return true;\n};\n\nconst compareTypedArrays = (\n left: ArrayBufferView,\n right: ArrayBufferView,\n): boolean => {\n if (left.constructor !== right.constructor) return false;\n if (left.byteLength !== right.byteLength) return false;\n\n const leftArray = new Uint8Array(\n left.buffer,\n left.byteOffset,\n left.byteLength,\n );\n const rightArray = new Uint8Array(\n right.buffer,\n right.byteOffset,\n right.byteLength,\n );\n\n for (let i = 0; i < leftArray.length; i++) {\n if (leftArray[i] !== rightArray[i]) return false;\n }\n return true;\n};\n\nconst compareObjects = (\n left: Record<string, unknown>,\n right: Record<string, unknown>,\n): boolean => {\n const keys1 = Object.keys(left);\n const keys2 = Object.keys(right);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (left[key] instanceof Function && right[key] instanceof Function) {\n continue;\n }\n\n const isEqual = deepEquals(left[key], right[key]);\n if (!isEqual) {\n return false;\n }\n }\n\n return true;\n};\n\nconst getType = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n\n const primitiveType = typeof value;\n if (primitiveType !== 'object') return primitiveType;\n\n if (Array.isArray(value)) return 'array';\n if (value instanceof Boolean) return 'boxed-boolean';\n if (value instanceof Number) return 'boxed-number';\n if (value instanceof String) return 'boxed-string';\n if (value instanceof Date) return 'date';\n if (value instanceof RegExp) return 'regexp';\n if (value instanceof Error) return 'error';\n if (value instanceof Map) return 'map';\n if (value instanceof Set) return 'set';\n if (value instanceof ArrayBuffer) return 'arraybuffer';\n if (value instanceof DataView) return 'dataview';\n if (value instanceof WeakMap) return 'weakmap';\n if (value instanceof WeakSet) return 'weakset';\n\n if (ArrayBuffer.isView(value)) return 'typedarray';\n\n return 'object';\n};\n\nexport const deepEquals = <T>(left: T, right: T): boolean => {\n if (left === right) return true;\n\n if (isEquatable(left)) {\n return left.equals(right);\n }\n\n const leftType = getType(left);\n const rightType = getType(right);\n\n if (leftType !== rightType) return false;\n\n switch (leftType) {\n case 'null':\n case 'undefined':\n case 'boolean':\n case 'number':\n case 'bigint':\n case 'string':\n case 'symbol':\n case 'function':\n return left === right;\n\n case 'array':\n return compareArrays(left as unknown[], right as unknown[]);\n\n case 'date':\n return compareDates(left as Date, right as Date);\n\n case 'regexp':\n return compareRegExps(left as RegExp, right as RegExp);\n\n case 'error':\n return compareErrors(left as Error, right as Error);\n\n case 'map':\n return compareMaps(\n left as Map<unknown, unknown>,\n right as Map<unknown, unknown>,\n );\n\n case 'set':\n return compareSets(left as Set<unknown>, right as Set<unknown>);\n\n case 'arraybuffer':\n return compareArrayBuffers(left as ArrayBuffer, right as ArrayBuffer);\n\n case 'dataview':\n case 'weakmap':\n case 'weakset':\n return false;\n\n case 'typedarray':\n return compareTypedArrays(\n left as ArrayBufferView,\n right as ArrayBufferView,\n );\n\n case 'boxed-boolean':\n return (left as boolean).valueOf() === (right as boolean).valueOf();\n\n case 'boxed-number':\n return (left as number).valueOf() === (right as number).valueOf();\n\n case 'boxed-string':\n return (left as string).valueOf() === (right as string).valueOf();\n\n case 'object':\n return compareObjects(\n left as Record<string, unknown>,\n right as Record<string, unknown>,\n );\n\n default:\n return false;\n }\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 !== null &&\n left !== undefined &&\n typeof left === 'object' &&\n 'equals' in left &&\n typeof left['equals'] === 'function'\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","export type ShutdownHandler = () => void | Promise<void>;\n\n/**\n * Registers handlers for OS signals to enable graceful shutdown.\n * Handles SIGTERM and SIGINT by default.\n * Works in Node.js, Bun, and Deno. Safely no-ops in Browser/Cloudflare Workers.\n *\n * @param handler - Function to call when shutdown signal is received\n * @returns Cleanup function to unregister the handlers\n */\nexport const onShutdown = (handler: ShutdownHandler): (() => void) => {\n const signals = ['SIGTERM', 'SIGINT'] as const;\n\n // Node.js/Bun\n if (typeof process !== 'undefined' && typeof process.on === 'function') {\n for (const signal of signals) {\n process.on(signal, handler);\n }\n return () => {\n for (const signal of signals) {\n process.off(signal, handler);\n }\n };\n }\n\n // Deno\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const deno = (globalThis as any).Deno;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (deno && typeof deno.addSignalListener === 'function') {\n for (const signal of signals) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n deno.addSignalListener(signal, handler);\n }\n return () => {\n for (const signal of signals) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n deno.removeSignalListener(signal, handler);\n }\n };\n }\n\n // Browser/Cloudflare Workers: no-op\n return () => {};\n};\n","const textEncoder = new TextEncoder();\n\nexport const hashText = async (text: string): Promise<bigint> => {\n const hashBuffer = await crypto.subtle.digest(\n 'SHA-256',\n textEncoder.encode(text),\n );\n // Create an array with a single element that is a 64-bit signed integer\n // We take the first 8 bytes (so 64 bits) of the SHA-256 hash\n const view = new BigInt64Array(hashBuffer, 0, 1);\n return view[0]!;\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 {\n AnyMessage,\n AnyRecordedMessageMetadata,\n RecordedMessage,\n} from '../../typing';\n\nexport type MessageDowncast<\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n> =\n | ((\n message: RecordedMessage<MessageType, RecordedMessageMetadataType>,\n ) => RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>)\n | ((message: MessageType) => MessagePayloadType);\n\nexport const downcastRecordedMessage = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessage:\n | RecordedMessage<MessageType, RecordedMessageMetadataType>\n | MessageType,\n options?: {\n downcast?: MessageDowncast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessagePayloadType, RecordedMessageMetadataType> => {\n if (!options?.downcast)\n return recordedMessage as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n\n const downcasted = options.downcast(\n recordedMessage as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >,\n );\n\n return {\n ...recordedMessage,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n data: downcasted.data,\n ...('metadata' in recordedMessage || 'metadata' in downcasted\n ? {\n metadata: {\n ...('metadata' in recordedMessage\n ? (recordedMessage.metadata as object)\n : {}),\n ...('metadata' in downcasted\n ? (downcasted.metadata as object)\n : {}),\n },\n }\n : {}),\n } as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n};\n\nexport const downcastRecordedMessages = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessages:\n | RecordedMessage<MessageType, RecordedMessageMetadataType>[]\n | MessageType[],\n options?: {\n downcast?: MessageDowncast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>[] => {\n if (!options?.downcast)\n return recordedMessages as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >[];\n\n return recordedMessages.map((recordedMessage) =>\n downcastRecordedMessage(recordedMessage, options),\n );\n};\n","import type {\n AnyMessage,\n AnyRecordedMessageMetadata,\n RecordedMessage,\n} from '../../typing';\n\nexport type MessageUpcast<\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n> =\n | ((message: MessagePayloadType) => MessageType)\n | ((\n message: RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>,\n ) => RecordedMessage<MessageType, RecordedMessageMetadataType>);\n\nexport const upcastRecordedMessage = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessage:\n | RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>\n | MessagePayloadType,\n options?: {\n upcast?: MessageUpcast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessageType, RecordedMessageMetadataType> => {\n if (!options?.upcast)\n return recordedMessage as unknown as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >;\n\n const upcasted = options.upcast(\n recordedMessage as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >,\n );\n\n return {\n ...recordedMessage,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n data: upcasted.data,\n ...('metadata' in recordedMessage || 'metadata' in upcasted\n ? {\n metadata: {\n ...('metadata' in recordedMessage\n ? (recordedMessage.metadata as object)\n : {}),\n ...('metadata' in upcasted ? (upcasted.metadata as object) : {}),\n },\n }\n : {}),\n } as unknown as RecordedMessage<MessageType, RecordedMessageMetadataType>;\n};\n\nexport const upcastRecordedMessages = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessages:\n | RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>[]\n | MessagePayloadType[],\n options?: {\n upcast?: MessageUpcast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessageType, RecordedMessageMetadataType>[] => {\n if (!options?.upcast)\n return recordedMessages as unknown as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >[];\n\n return recordedMessages.map((recordedMessage) =>\n upcastRecordedMessage(recordedMessage, options),\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:\n currentPosition === newCheckpoint\n ? 'IGNORED'\n : newCheckpoint !== null && currentPosition > newCheckpoint\n ? 'CURRENT_AHEAD'\n : '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 onInit: options.hooks?.onInit,\n onStart: options.hooks?.onStart,\n onClose: options.hooks?.onClose\n ? async (context: InMemoryProcessorHandlerContext) => {\n if (options.hooks?.onClose) await options.hooks?.onClose(context);\n }\n : undefined,\n };\n\n const processor = 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\n return Object.assign(processor, { database });\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 onInit: options.hooks?.onInit,\n onStart: options.hooks?.onStart,\n onClose: options.hooks?.onClose,\n };\n\n const processor = reactor({\n ...options,\n hooks,\n processingScope: inMemoryProcessingScope({\n database,\n processorId: options.processorId,\n }),\n checkpoints: inMemoryCheckpointer<MessageType>(),\n });\n\n return Object.assign(processor, { database });\n};\n","import {\n EmmettError,\n inMemoryProjector,\n inMemoryReactor,\n MessageProcessor,\n type AnyEvent,\n type AnyMessage,\n type AnyRecordedMessageMetadata,\n type AsyncRetryOptions,\n type BatchRecordedMessageHandlerWithoutContext,\n type DefaultRecord,\n type InMemoryProcessor,\n type InMemoryProjectorOptions,\n type InMemoryReactorOptions,\n type Message,\n type MessageConsumer,\n type MessageConsumerOptions,\n} from '@event-driven-io/emmett';\nimport {\n EventStoreDBClient,\n type SubscribeToAllOptions,\n type SubscribeToStreamOptions,\n} from '@eventstore/db-client';\nimport { v7 as uuid } from 'uuid';\nimport type { EventStoreDBReadEventMetadata } from '../eventstoreDBEventStore';\nimport {\n DefaultEventStoreDBEventStoreProcessorBatchSize,\n eventStoreDBSubscription,\n zipEventStoreDBEventStoreMessageBatchPullerStartFrom,\n type EventStoreDBSubscription,\n} from './subscriptions';\n\nexport type EventStoreDBEventStoreConsumerConfig<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ConsumerMessageType extends Message = any,\n> = MessageConsumerOptions<ConsumerMessageType> & {\n from?: EventStoreDBEventStoreConsumerType;\n pulling?: {\n batchSize?: number;\n };\n resilience?: {\n resubscribeOptions?: AsyncRetryOptions;\n };\n};\n\nexport type EventStoreDBEventStoreConsumerOptions<\n ConsumerEventType extends Message = Message,\n> = EventStoreDBEventStoreConsumerConfig<ConsumerEventType> &\n (\n | {\n connectionString: string;\n client?: never;\n }\n | { client: EventStoreDBClient; connectionString?: never }\n );\n\nexport type $all = '$all';\nexport const $all = '$all';\n\nexport type EventStoreDBEventStoreConsumerType =\n | {\n stream: $all;\n options?: Exclude<SubscribeToAllOptions, 'fromPosition'>;\n }\n | {\n stream: string;\n options?: Exclude<SubscribeToStreamOptions, 'fromRevision'>;\n };\n\nexport type EventStoreDBEventStoreConsumer<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ConsumerMessageType extends AnyMessage = any,\n> = MessageConsumer<ConsumerMessageType> &\n Readonly<{\n reactor: <MessageType extends AnyMessage = ConsumerMessageType>(\n options: InMemoryReactorOptions<MessageType>,\n ) => InMemoryProcessor<MessageType>;\n }> &\n (AnyEvent extends ConsumerMessageType\n ? Readonly<{\n projector: <\n EventType extends AnyEvent = ConsumerMessageType & AnyEvent,\n >(\n options: InMemoryProjectorOptions<EventType>,\n ) => InMemoryProcessor<EventType>;\n }>\n : object);\n\nexport const eventStoreDBEventStoreConsumer = <\n ConsumerMessageType extends Message = AnyMessage,\n>(\n options: EventStoreDBEventStoreConsumerOptions<ConsumerMessageType>,\n): EventStoreDBEventStoreConsumer<ConsumerMessageType> => {\n let isRunning = false;\n const { pulling } = options;\n const processors = options.processors ?? [];\n\n let start: Promise<void>;\n\n let currentSubscription: EventStoreDBSubscription | undefined;\n\n const client =\n 'client' in options && options.client\n ? options.client\n : EventStoreDBClient.connectionString(options.connectionString);\n\n const eachBatch: BatchRecordedMessageHandlerWithoutContext<\n ConsumerMessageType,\n EventStoreDBReadEventMetadata\n > = async (messagesBatch) => {\n const activeProcessors = processors.filter((s) => s.isActive);\n\n if (activeProcessors.length === 0)\n return {\n type: 'STOP',\n reason: 'No active processors',\n };\n\n const result = await Promise.allSettled(\n activeProcessors.map(async (s) => {\n // TODO: Add here filtering to only pass messages that can be handled by\n return await s.handle(messagesBatch, { client });\n }),\n );\n\n const error = result.find((r) => r.status === 'rejected')?.reason as\n | Error\n | undefined;\n\n return result.some(\n (r) => r.status === 'fulfilled' && r.value?.type !== 'STOP',\n )\n ? undefined\n : {\n type: 'STOP',\n error: error ? EmmettError.mapFrom(error) : undefined,\n };\n };\n\n const subscription = (currentSubscription = eventStoreDBSubscription({\n client,\n from: options.from,\n eachBatch,\n batchSize:\n pulling?.batchSize ?? DefaultEventStoreDBEventStoreProcessorBatchSize,\n resilience: options.resilience,\n }));\n\n const stop = async () => {\n if (!isRunning) return;\n isRunning = false;\n if (currentSubscription) {\n await currentSubscription.stop();\n currentSubscription = undefined;\n }\n await start;\n };\n\n return {\n consumerId: options.consumerId ?? uuid(),\n get isRunning() {\n return isRunning;\n },\n processors,\n reactor: <MessageType extends AnyMessage = ConsumerMessageType>(\n options: InMemoryReactorOptions<MessageType>,\n ): InMemoryProcessor<MessageType> => {\n const processor = inMemoryReactor(options);\n\n processors.push(\n // TODO: change that\n processor as unknown as MessageProcessor<\n ConsumerMessageType,\n AnyRecordedMessageMetadata,\n DefaultRecord\n >,\n );\n\n return processor;\n },\n projector: <EventType extends AnyEvent = ConsumerMessageType & AnyEvent>(\n options: InMemoryProjectorOptions<EventType>,\n ): InMemoryProcessor<EventType> => {\n const processor = inMemoryProjector(options);\n\n processors.push(\n // TODO: change that\n processor as unknown as MessageProcessor<\n ConsumerMessageType,\n AnyRecordedMessageMetadata,\n DefaultRecord\n >,\n );\n\n return processor;\n },\n start: () => {\n if (isRunning) return start;\n\n start = (async () => {\n if (processors.length === 0)\n return Promise.reject(\n new EmmettError(\n 'Cannot start consumer without at least a single processor',\n ),\n );\n\n isRunning = true;\n\n const startFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom(\n await Promise.all(processors.map((o) => o.start(client))),\n );\n\n return subscription.start({ startFrom });\n })();\n\n return start;\n },\n stop,\n close: stop,\n };\n};\n","import {\n asyncRetry,\n getCheckpoint,\n isBigint,\n JSONParser,\n type AnyMessage,\n type AsyncRetryOptions,\n type BatchRecordedMessageHandlerWithoutContext,\n type EmmettError,\n type Message,\n type MessageHandlerResult,\n} from '@event-driven-io/emmett';\nimport {\n END,\n EventStoreDBClient,\n excludeSystemEvents,\n START,\n type ResolvedEvent,\n type StreamSubscription,\n} from '@eventstore/db-client';\nimport { pipeline, Transform, Writable, type WritableOptions } from 'stream';\nimport {\n mapFromESDBEvent,\n type EventStoreDBReadEventMetadata,\n} from '../../eventstoreDBEventStore';\nimport {\n $all,\n type EventStoreDBEventStoreConsumerType,\n} from '../eventStoreDBEventStoreConsumer';\n\nexport const DefaultEventStoreDBEventStoreProcessorBatchSize = 100;\nexport const DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = 50;\n\nexport type EventStoreDBEventStoreMessagesBatchHandlerResult = void | {\n type: 'STOP';\n reason?: string;\n error?: EmmettError;\n};\n\nexport type EventStoreDBSubscriptionOptions<\n MessageType extends Message = Message,\n> = {\n from?: EventStoreDBEventStoreConsumerType;\n client: EventStoreDBClient;\n batchSize: number;\n eachBatch: BatchRecordedMessageHandlerWithoutContext<\n MessageType,\n EventStoreDBReadEventMetadata\n >;\n resilience?: {\n resubscribeOptions?: AsyncRetryOptions;\n };\n};\n\nexport type EventStoreDBSubscriptionStartFrom =\n | { lastCheckpoint: bigint }\n | 'BEGINNING'\n | 'END';\n\nexport type EventStoreDBSubscriptionStartOptions = {\n startFrom: EventStoreDBSubscriptionStartFrom;\n};\n\nexport type EventStoreDBSubscription = {\n isRunning: boolean;\n start(options: EventStoreDBSubscriptionStartOptions): Promise<void>;\n stop(): Promise<void>;\n};\n\nconst toGlobalPosition = (startFrom: EventStoreDBSubscriptionStartFrom) =>\n startFrom === 'BEGINNING'\n ? START\n : startFrom === 'END'\n ? END\n : {\n prepare: startFrom.lastCheckpoint,\n commit: startFrom.lastCheckpoint,\n };\n\nconst toStreamPosition = (startFrom: EventStoreDBSubscriptionStartFrom) =>\n startFrom === 'BEGINNING'\n ? START\n : startFrom === 'END'\n ? END\n : startFrom.lastCheckpoint;\n\nconst subscribe = (\n client: EventStoreDBClient,\n from: EventStoreDBEventStoreConsumerType | undefined,\n options: EventStoreDBSubscriptionStartOptions,\n) =>\n from == undefined || from.stream == $all\n ? client.subscribeToAll({\n ...(from?.options ?? {}),\n fromPosition: toGlobalPosition(options.startFrom),\n filter: excludeSystemEvents(),\n })\n : client.subscribeToStream(from.stream, {\n ...(from.options ?? {}),\n fromRevision: toStreamPosition(options.startFrom),\n });\n\nexport const isDatabaseUnavailableError = (error: unknown) =>\n error instanceof Error &&\n 'type' in error &&\n error.type === 'unavailable' &&\n 'code' in error &&\n error.code === 14;\n\nexport const EventStoreDBResubscribeDefaultOptions: AsyncRetryOptions = {\n forever: true,\n minTimeout: 100,\n factor: 1.5,\n shouldRetryError: (error) => !isDatabaseUnavailableError(error),\n};\n\ntype SubscriptionSequentialHandlerOptions<\n MessageType extends AnyMessage = AnyMessage,\n> = EventStoreDBSubscriptionOptions<MessageType> & WritableOptions;\n\nclass SubscriptionSequentialHandler<\n MessageType extends AnyMessage = AnyMessage,\n> extends Transform {\n private options: SubscriptionSequentialHandlerOptions<MessageType>;\n private from: EventStoreDBEventStoreConsumerType | undefined;\n public isRunning: boolean;\n\n constructor(options: SubscriptionSequentialHandlerOptions<MessageType>) {\n super({ objectMode: true, ...options });\n this.options = options;\n this.from = options.from;\n this.isRunning = true;\n }\n\n async _transform(\n resolvedEvent: ResolvedEvent<MessageType>,\n _encoding: BufferEncoding,\n callback: (error?: Error | null) => void,\n ): Promise<void> {\n try {\n if (!this.isRunning || !resolvedEvent.event) {\n callback();\n return;\n }\n\n const message = mapFromESDBEvent(resolvedEvent, this.from);\n const messageCheckpoint = getCheckpoint(message);\n\n const result = await this.options.eachBatch([message]);\n\n if (result && result.type === 'STOP') {\n this.isRunning = false;\n if (!result.error) this.push(messageCheckpoint);\n\n this.push(result);\n this.push(null);\n callback();\n return;\n }\n\n this.push(messageCheckpoint);\n callback();\n } catch (error) {\n callback(error as Error);\n }\n }\n}\n\nexport const eventStoreDBSubscription = <\n MessageType extends AnyMessage = AnyMessage,\n>({\n client,\n from,\n batchSize,\n eachBatch,\n resilience,\n}: EventStoreDBSubscriptionOptions<MessageType>): EventStoreDBSubscription => {\n let isRunning = false;\n\n let start: Promise<void>;\n let processor: SubscriptionSequentialHandler<MessageType>;\n\n let subscription: StreamSubscription<MessageType>;\n\n const resubscribeOptions: AsyncRetryOptions =\n resilience?.resubscribeOptions ?? {\n ...EventStoreDBResubscribeDefaultOptions,\n shouldRetryResult: () => isRunning,\n shouldRetryError: (error) =>\n isRunning &&\n EventStoreDBResubscribeDefaultOptions.shouldRetryError!(error),\n };\n\n const stopSubscription = (callback?: () => void): Promise<void> => {\n isRunning = false;\n if (processor) processor.isRunning = false;\n return subscription\n .unsubscribe()\n .then(() => {\n subscription.destroy();\n })\n .catch((err) => console.error('Error during unsubscribe.%s', err))\n .finally(callback ?? (() => {}));\n };\n\n const pipeMessages = (options: EventStoreDBSubscriptionStartOptions) => {\n let retry = 0;\n return asyncRetry(\n () =>\n new Promise<void>((resolve, reject) => {\n if (!isRunning) {\n resolve();\n return;\n }\n console.info(\n `Starting subscription. ${retry++} retries. From: ${JSONParser.stringify(from ?? '$all')}, Start from: ${JSONParser.stringify(\n options.startFrom,\n )}`,\n );\n subscription = subscribe(client, from, options);\n\n processor = new SubscriptionSequentialHandler({\n client,\n from,\n batchSize,\n eachBatch,\n resilience,\n });\n\n const handler = new (class extends Writable {\n async _write(\n result: bigint | MessageHandlerResult,\n _encoding: string,\n done: () => void,\n ) {\n if (!isRunning) return;\n\n if (isBigint(result)) {\n options.startFrom = {\n lastCheckpoint: result,\n };\n done();\n return;\n }\n\n if (result && result.type === 'STOP' && result.error) {\n console.error(\n `Subscription stopped with error code: ${result.error.errorCode}, message: ${\n result.error.message\n }.`,\n );\n }\n\n await stopSubscription();\n done();\n }\n })({ objectMode: true });\n\n pipeline(\n subscription,\n processor,\n handler,\n async (error: Error | null) => {\n console.info(`Stopping subscription.`);\n await stopSubscription(() => {\n if (!error) {\n console.info('Subscription ended successfully.');\n resolve();\n return;\n }\n console.error(\n `Received error: ${JSONParser.stringify(error)}.`,\n );\n reject(error);\n });\n },\n );\n }),\n resubscribeOptions,\n );\n };\n\n return {\n get isRunning() {\n return isRunning;\n },\n start: (options) => {\n if (isRunning) return start;\n\n start = (async () => {\n isRunning = true;\n\n return pipeMessages(options);\n })();\n\n return start;\n },\n stop: async () => {\n if (!isRunning) return start ? await start : Promise.resolve();\n await stopSubscription();\n await start;\n },\n };\n};\n\nexport const zipEventStoreDBEventStoreMessageBatchPullerStartFrom = (\n options: (EventStoreDBSubscriptionStartFrom | undefined)[],\n): EventStoreDBSubscriptionStartFrom => {\n if (\n options.length === 0 ||\n options.some((o) => o === undefined || o === 'BEGINNING')\n )\n return 'BEGINNING';\n\n if (options.every((o) => o === 'END')) return 'END';\n\n return options\n .filter((o) => o !== undefined && o !== 'BEGINNING' && o !== 'END')\n .sort((a, b) => (a > b ? 1 : -1))[0]!;\n};\n","import {\n ExpectedVersionConflictError,\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n STREAM_EXISTS,\n assertExpectedVersionMatchesCurrent,\n downcastRecordedMessages,\n upcastRecordedMessage,\n type AggregateStreamOptions,\n type AggregateStreamResultWithGlobalPosition,\n type AnyMessage,\n type AppendToStreamOptions,\n type AppendToStreamResultWithGlobalPosition,\n type BigIntStreamPosition,\n type Event,\n type EventStore,\n type ExpectedStreamVersion,\n type ReadEvent,\n type ReadEventMetadataWithGlobalPosition,\n type ReadStreamOptions,\n type ReadStreamResult,\n type RecordedMessage,\n type StreamExistsResult,\n} from '@event-driven-io/emmett';\nimport {\n ANY,\n STREAM_EXISTS as ESDB_STREAM_EXISTS,\n EventStoreDBClient,\n NO_STREAM,\n StreamNotFoundError,\n WrongExpectedVersionError,\n jsonEvent,\n type AppendExpectedRevision,\n type ReadStreamOptions as ESDBReadStreamOptions,\n type ResolvedEvent,\n} from '@eventstore/db-client';\nimport {\n $all,\n eventStoreDBEventStoreConsumer,\n type EventStoreDBEventStoreConsumer,\n type EventStoreDBEventStoreConsumerConfig,\n type EventStoreDBEventStoreConsumerType,\n} from './consumers';\n\nconst toEventStoreDBReadOptions = <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n>(\n options:\n | ReadStreamOptions<BigIntStreamPosition, EventType, EventPayloadType>\n | undefined,\n): ESDBReadStreamOptions | undefined => {\n return options\n ? {\n fromRevision: 'from' in options ? options.from : undefined,\n maxCount:\n 'maxCount' in options\n ? options.maxCount\n : 'to' in options\n ? options.to\n : undefined,\n }\n : undefined;\n};\n\nexport const EventStoreDBEventStoreDefaultStreamVersion = -1n;\n\nexport type EventStoreDBReadEventMetadata = ReadEventMetadataWithGlobalPosition;\n\nexport type EventStoreDBReadEvent<EventType extends Event = Event> = ReadEvent<\n EventType,\n EventStoreDBReadEventMetadata\n>;\n\nexport interface EventStoreDBEventStore extends EventStore<EventStoreDBReadEventMetadata> {\n appendToStream<\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<AppendToStreamResultWithGlobalPosition>;\n consumer<ConsumerEventType extends Event = Event>(\n options?: EventStoreDBEventStoreConsumerConfig<ConsumerEventType>,\n ): EventStoreDBEventStoreConsumer<ConsumerEventType>;\n}\n\nexport const getEventStoreDBEventStore = (\n eventStore: EventStoreDBClient,\n): EventStoreDBEventStore => {\n return {\n async aggregateStream<\n State,\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options: AggregateStreamOptions<\n State,\n EventType,\n EventStoreDBReadEventMetadata,\n EventPayloadType\n >,\n ): Promise<AggregateStreamResultWithGlobalPosition<State>> {\n const { evolve, initialState, read } = options;\n\n const expectedStreamVersion = read?.expectedStreamVersion;\n\n let state = initialState();\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n let lastEventGlobalPosition: bigint | undefined = undefined;\n\n try {\n for await (const resolvedEvent of eventStore.readStream<EventPayloadType>(\n streamName,\n toEventStoreDBReadOptions(options.read),\n )) {\n const { event } = resolvedEvent;\n if (!event) continue;\n\n state = evolve(\n state,\n upcastRecordedMessage(\n mapFromESDBEvent<EventPayloadType>(resolvedEvent),\n options?.read?.schema?.versioning,\n ),\n );\n currentStreamVersion = event.revision;\n lastEventGlobalPosition = event.position?.commit;\n }\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n expectedStreamVersion,\n EventStoreDBEventStoreDefaultStreamVersion,\n );\n\n return lastEventGlobalPosition\n ? {\n currentStreamVersion,\n lastEventGlobalPosition,\n state,\n streamExists: true,\n }\n : {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n readStream: async <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options?: ReadStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<ReadStreamResult<EventType, EventStoreDBReadEventMetadata>> => {\n const events: ReadEvent<EventType, EventStoreDBReadEventMetadata>[] = [];\n\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const resolvedEvent of eventStore.readStream<EventPayloadType>(\n streamName,\n toEventStoreDBReadOptions(options),\n )) {\n const { event } = resolvedEvent;\n if (!event) continue;\n events.push(\n upcastRecordedMessage(\n mapFromESDBEvent<EventPayloadType>(resolvedEvent),\n options?.schema?.versioning,\n ),\n );\n\n currentStreamVersion = event.revision;\n }\n return {\n currentStreamVersion,\n events,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n events: [],\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n appendToStream: async <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<AppendToStreamResultWithGlobalPosition> => {\n try {\n const eventsToStore = downcastRecordedMessages(\n events,\n options?.schema?.versioning,\n );\n const serializedEvents = eventsToStore.map(jsonEvent);\n\n const expectedRevision = toExpectedRevision(\n options?.expectedStreamVersion,\n );\n\n const appendResult = await eventStore.appendToStream(\n streamName,\n serializedEvents,\n {\n expectedRevision,\n },\n );\n\n return {\n nextExpectedStreamVersion: appendResult.nextExpectedRevision,\n lastEventGlobalPosition: appendResult.position!.commit,\n createdNewStream:\n appendResult.nextExpectedRevision >=\n BigInt(serializedEvents.length),\n };\n } catch (error) {\n if (error instanceof WrongExpectedVersionError) {\n throw new ExpectedVersionConflictError(\n error.actualVersion,\n toExpectedVersion(error.expectedVersion),\n );\n }\n\n throw error;\n }\n },\n\n consumer: <ConsumerEventType extends Event = Event>(\n options?: EventStoreDBEventStoreConsumerConfig<ConsumerEventType>,\n ): EventStoreDBEventStoreConsumer<ConsumerEventType> =>\n eventStoreDBEventStoreConsumer<ConsumerEventType>({\n ...(options ?? {}),\n client: eventStore,\n }),\n\n streamExists: async (streamName: string): Promise<StreamExistsResult> => {\n try {\n for await (const resolvedEvent of eventStore.readStream(streamName)) {\n const { event } = resolvedEvent;\n\n if (!event) continue;\n\n return true;\n }\n\n return false;\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return false;\n }\n\n throw error;\n }\n },\n\n //streamEvents: streamEvents(eventStore),\n };\n};\n\nconst getCheckpoint = <MessageType extends AnyMessage = AnyMessage>(\n resolvedEvent: ResolvedEvent<MessageType>,\n from?: EventStoreDBEventStoreConsumerType,\n): bigint => {\n return !from || from?.stream === $all\n ? (resolvedEvent.link?.position?.commit ??\n resolvedEvent.event?.position?.commit)!\n : (resolvedEvent.link?.revision ?? resolvedEvent.event!.revision);\n};\n\nexport const mapFromESDBEvent = <MessageType extends AnyMessage = AnyMessage>(\n resolvedEvent: ResolvedEvent<MessageType>,\n from?: EventStoreDBEventStoreConsumerType,\n): RecordedMessage<MessageType, EventStoreDBReadEventMetadata> => {\n const event = resolvedEvent.event!;\n return <RecordedMessage<MessageType, EventStoreDBReadEventMetadata>>{\n type: event.type,\n data: event.data,\n metadata: {\n ...((event.metadata as EventStoreDBReadEventMetadata) ??\n ({} as EventStoreDBReadEventMetadata)),\n eventId: event.id,\n streamName: event.streamId,\n streamPosition: event.revision,\n globalPosition: event.position!.commit,\n checkpoint: getCheckpoint(resolvedEvent, from),\n },\n };\n};\n\nconst toExpectedRevision = (\n expected: ExpectedStreamVersion | undefined,\n): AppendExpectedRevision => {\n if (expected === undefined) return ANY;\n\n if (expected === NO_CONCURRENCY_CHECK) return ANY;\n\n if (expected == STREAM_DOES_NOT_EXIST) return NO_STREAM;\n\n if (expected == STREAM_EXISTS) return ESDB_STREAM_EXISTS;\n\n return expected as bigint;\n};\n\nconst toExpectedVersion = (\n expected: AppendExpectedRevision | undefined,\n): ExpectedStreamVersion => {\n if (expected === undefined) return NO_CONCURRENCY_CHECK;\n\n if (expected === ANY) return NO_CONCURRENCY_CHECK;\n\n if (expected == NO_STREAM) return STREAM_DOES_NOT_EXIST;\n\n if (expected == ESDB_STREAM_EXISTS) return STREAM_EXISTS;\n\n return expected;\n};\n\n// const { map } = streamTransformations;\n//\n// // eslint-disable-next-line @typescript-eslint/no-unused-vars\n// const convertToWebReadableStream = (\n// allStreamSubscription: AllStreamSubscription,\n// ): ReadableStream<AllStreamResolvedEvent | GlobalStreamCaughtUp> => {\n// // Validate the input type\n// if (!(allStreamSubscription instanceof Readable)) {\n// throw new Error('Provided stream is not a Node.js Readable stream.');\n// }\n\n// let globalPosition = 0n;\n\n// const stream = Readable.toWeb(\n// allStreamSubscription,\n// ) as ReadableStream<AllStreamResolvedEvent>;\n\n// const writable = new WritableStream<\n// AllStreamResolvedEvent | GlobalStreamCaughtUp\n// >();\n\n// allStreamSubscription.on('caughtUp', async () => {\n// console.log(globalPosition);\n// await writable.getWriter().write(globalStreamCaughtUp({ globalPosition }));\n// });\n\n// const transform = map<\n// AllStreamResolvedEvent,\n// AllStreamResolvedEvent | GlobalStreamCaughtUp\n// >((event) => {\n// if (event?.event?.position.commit)\n// globalPosition = event.event?.position.commit;\n\n// return event;\n// });\n\n// return stream.pipeThrough<AllStreamResolvedEvent | GlobalStreamCaughtUp>(\n// transform,\n// );\n// };\n\n// const streamEvents = (eventStore: EventStoreDBClient) => () => {\n// return restream<\n// AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// | ReadEvent<Event, EventStoreDBReadEventMetadata>\n// | GlobalSubscriptionEvent\n// >(\n// (): ReadableStream<AllStreamResolvedEvent | GlobalSubscriptionEvent> =>\n// convertToWebReadableStream(\n// eventStore.subscribeToAll({\n// fromPosition: START,\n// filter: excludeSystemEvents(),\n// }),\n// ),\n// (\n// resolvedEvent: AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// ): ReadEvent<Event, EventStoreDBReadEventMetadata> =>\n// mapFromESDBEvent(resolvedEvent.event as JSONRecordedEvent<Event>),\n// );\n// };\n"]}
1
+ {"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","../../emmett/src/validation/index.ts","../../emmett/src/errors/index.ts","../../emmett/src/eventStore/inMemoryEventStore.ts","../../emmett/src/database/inMemoryDatabase.ts","../../emmett/src/utils/retry.ts","../../emmett/src/eventStore/projections/inMemory/inMemoryProjectionSpec.ts","../../emmett/src/processors/processors.ts","../../emmett/src/typing/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/utils/deepEquals.ts","../../emmett/src/serialization/json/JSONParser.ts","../../emmett/src/utils/shutdown/gracefulShutdown.ts","../../emmett/src/utils/strings/hashText.ts","../../emmett/src/database/utils.ts","../../emmett/src/eventStore/versioning/downcasting.ts","../../emmett/src/eventStore/versioning/upcasting.ts","../../emmett/src/processors/inMemoryProcessors.ts","../src/eventStore/consumers/eventStoreDBEventStoreConsumer.ts","../src/eventStore/consumers/subscriptions/index.ts","../src/eventStore/eventstoreDBEventStore.ts"],"names":["operationResult"],"mappings":"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","file":"/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","sourcesContent":[null,"import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const isBigint = (val: any): val is bigint =>\n typeof val === 'bigint' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n\nexport * from './dates';\n","import { isNumber, isString } from '../validation';\n\nexport type ErrorConstructor<ErrorType extends Error> = new (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...args: any[]\n) => ErrorType;\n\nexport const isErrorConstructor = <ErrorType extends Error>(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n expect: Function,\n): expect is ErrorConstructor<ErrorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (\n typeof expect === 'function' &&\n expect.prototype &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect.prototype.constructor === expect\n );\n};\n\nexport class EmmettError extends Error {\n public static readonly Codes = {\n ValidationError: 400,\n IllegalStateError: 403,\n NotFoundError: 404,\n ConcurrencyError: 412,\n InternalServerError: 500,\n };\n\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : EmmettError.Codes.InternalServerError;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n\n public static mapFrom(\n error: Error | { message?: string; errorCode?: number },\n ): EmmettError {\n if (EmmettError.isInstanceOf(error)) {\n return error;\n }\n\n return new EmmettError({\n errorCode:\n 'errorCode' in error &&\n error.errorCode !== undefined &&\n error.errorCode !== null\n ? error.errorCode\n : EmmettError.Codes.InternalServerError,\n message: error.message ?? 'An unknown error occurred',\n });\n }\n\n public static isInstanceOf<ErrorType extends EmmettError = EmmettError>(\n error: unknown,\n errorCode?: (typeof EmmettError.Codes)[keyof typeof EmmettError.Codes],\n ): error is ErrorType {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'errorCode' in error &&\n isNumber(error.errorCode) &&\n (errorCode === undefined || error.errorCode === errorCode)\n );\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: EmmettError.Codes.ConcurrencyError,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\n// TODO: Make it derive from ConcurrencyError to avoid code duplication\n// Or add additional type to distinguinsh both errors\nexport class ConcurrencyInMemoryDatabaseError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.ConcurrencyError,\n message: message ?? `Expected document state does not match current one!`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyInMemoryDatabaseError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.ValidationError,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: EmmettError.Codes.IllegalStateError,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: EmmettError.Codes.NotFoundError,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\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 type {\n AggregateStreamOptions,\n AggregateStreamResult,\n AppendToStreamOptions,\n AppendToStreamResult,\n DefaultEventStoreOptions,\n EventStore,\n ReadStreamOptions,\n ReadStreamResult,\n StreamExistsResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\nimport { handleInMemoryProjections } from './projections/inMemory';\nimport { downcastRecordedMessages, upcastRecordedMessages } from './versioning';\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\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<\n State,\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options: AggregateStreamOptions<\n State,\n EventType,\n ReadEventMetadataWithGlobalPosition,\n EventPayloadType\n >,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const result = await this.readStream<EventType, EventPayloadType>(\n streamName,\n read,\n );\n\n const events = result?.events ?? [];\n\n const state = events.reduce((s, e) => evolve(s, e), initialState());\n\n return {\n currentStreamVersion: BigInt(events.length),\n state,\n streamExists: result.streamExists,\n };\n },\n\n readStream: <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options?: ReadStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\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 ?? 0);\n const to = Number(\n options?.to ??\n (options?.maxCount\n ? (options.from ?? 0n) + options.maxCount\n : (events?.length ?? 1)),\n );\n\n const resultEvents =\n events !== undefined && events.length > 0\n ? upcastRecordedMessages<\n EventType,\n EventPayloadType,\n ReadEventMetadataWithGlobalPosition\n >(\n events.slice(from, to) as ReadEvent<\n EventPayloadType,\n ReadEventMetadataWithGlobalPosition\n >[],\n options?.schema?.versioning,\n )\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 <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\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, [\n ...currentEvents,\n ...downcastRecordedMessages(newEvents, options?.schema?.versioning),\n ]);\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 streamExists: (streamName): Promise<StreamExistsResult> => {\n const events = streams.get(streamName);\n\n return Promise.resolve(events !== undefined && events.length > 0);\n },\n };\n\n return eventStore;\n};\n","import { v7 as uuid } from 'uuid';\nimport { deepEquals } from '../utils';\nimport type {\n DatabaseHandleOptionErrors,\n DatabaseHandleOptions,\n DatabaseHandleResult,\n DeleteResult,\n Document,\n DocumentHandler,\n InsertOneResult,\n OptionalUnlessRequiredIdAndVersion,\n ReplaceOneOptions,\n UpdateResult,\n WithIdAndVersion,\n 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","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","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 InMemoryReadEventMetadata =\n 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 streamExists: async () => {\n return Promise.resolve(false);\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 InMemoryReadEventMetadata =\n 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 InMemoryReadEventMetadata =\n 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 { v7 as uuid } from 'uuid';\nimport type { EmmettError } from '../errors';\nimport { upcastRecordedMessage } from '../eventStore';\nimport type { ProjectionDefinition } from '../projections';\nimport {\n defaultTag,\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 { onShutdown } from '../utils/shutdown';\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 =\n 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 =\n 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 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 =\n 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 =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n id: string;\n instanceId: string;\n type: string;\n init: (options: Partial<HandlerContext>) => Promise<void>;\n start: (\n options: Partial<HandlerContext>,\n ) => Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined>;\n close: (closeOptions: Partial<HandlerContext>) => 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 =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n read: ReadProcessorCheckpoint<CheckpointType, HandlerContext>;\n store: StoreProcessorCheckpoint<\n MessageType,\n MessageMetadataType,\n CheckpointType,\n HandlerContext\n >;\n};\n\nexport type ProcessorHooks<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = {\n onInit?: OnReactorInitHook<HandlerContext>;\n onStart?: OnReactorStartHook<HandlerContext>;\n onClose?: OnReactorCloseHook<HandlerContext>;\n};\n\nexport type BaseMessageProcessorOptions<\n MessageType extends AnyMessage = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n> = {\n type?: string;\n processorId: string;\n processorInstanceId?: 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?: ProcessorHooks<HandlerContext>;\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 OnReactorInitHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type OnReactorStartHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type OnReactorCloseHook<\n HandlerContext extends DefaultRecord = DefaultRecord,\n> = (context: HandlerContext) => Promise<void>;\n\nexport type ReactorOptions<\n MessageType extends AnyMessage = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n MessagePayloadType extends AnyMessage = MessageType,\n> = BaseMessageProcessorOptions<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType\n> &\n HandlerOptions<MessageType, MessageMetadataType, HandlerContext> & {\n messageOptions?: {\n schema?: {\n versioning?: { upcast?: (event: MessagePayloadType) => MessageType };\n };\n };\n };\n\nexport type ProjectorOptions<\n EventType extends AnyEvent = AnyEvent,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n EventPayloadType extends Event = EventType,\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 EventPayloadType\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' | 'CURRENT_AHEAD' };\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 defaultProcessorVersion = 1;\nexport const defaultProcessorPartition = defaultTag;\n\nexport const getProcessorInstanceId = (processorId: string): string =>\n `${processorId}:${uuid()}`;\n\nexport const getProjectorId = (options: { projectionName: string }): string =>\n `emt:processor:projector:${options.projectionName}`;\n\nexport const reactor = <\n MessageType extends Message = AnyMessage,\n MessageMetadataType extends AnyReadEventMetadata = AnyReadEventMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<MessageMetadataType>,\n MessagePayloadType extends Message = MessageType,\n>(\n options: ReactorOptions<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType,\n MessagePayloadType\n >,\n): MessageProcessor<\n MessageType,\n MessageMetadataType,\n HandlerContext,\n CheckpointType\n> => {\n const {\n checkpoints,\n processorId,\n processorInstanceId: instanceId = getProcessorInstanceId(processorId),\n type = MessageProcessorType.REACTOR,\n version = defaultProcessorVersion,\n partition = defaultProcessorPartition,\n hooks = {},\n processingScope = defaultProcessingMessageProcessingScope,\n startFrom,\n canHandle,\n stopAfter,\n } = options;\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\n let isInitiated = false;\n let isActive = false;\n\n let lastCheckpoint: CheckpointType | null = null;\n let closeSignal: (() => void) | null = null;\n\n const init = async (initOptions: Partial<HandlerContext>): Promise<void> => {\n if (isInitiated) return;\n\n if (hooks.onInit === undefined) {\n isInitiated = true;\n return;\n }\n\n return await processingScope(async (context) => {\n await hooks.onInit!(context);\n isInitiated = true;\n }, initOptions);\n };\n\n const close = async (\n closeOptions: Partial<HandlerContext>,\n ): Promise<void> => {\n // TODO: Align when active is set to false\n // if (!isActive) return;\n\n isActive = false;\n\n if (closeSignal) {\n closeSignal();\n closeSignal = null;\n }\n\n if (hooks.onClose) {\n await processingScope(hooks.onClose, closeOptions);\n }\n };\n\n return {\n // TODO: Consider whether not make it optional or add URN prefix\n id: processorId,\n instanceId,\n type,\n init,\n start: async (\n startOptions: Partial<HandlerContext>,\n ): Promise<CurrentMessageProcessorPosition<CheckpointType> | undefined> => {\n if (isActive) return;\n\n await init(startOptions);\n\n isActive = true;\n\n closeSignal = onShutdown(() => close({}));\n\n if (lastCheckpoint !== null)\n return {\n lastCheckpoint,\n };\n\n return await processingScope(async (context) => {\n if (hooks.onStart) {\n await hooks.onStart(context);\n }\n\n if (startFrom && startFrom !== 'CURRENT') return startFrom;\n\n if (checkpoints) {\n const readResult = await checkpoints?.read(\n {\n processorId: processorId,\n 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 close,\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 upcasted = upcastRecordedMessage(\n // TODO: Make it smarter\n message as unknown as RecordedMessage<\n MessagePayloadType,\n MessageMetadataType\n >,\n options.messageOptions?.schema?.versioning,\n );\n\n if (canHandle !== undefined && !canHandle.includes(upcasted.type))\n continue;\n\n const messageProcessingResult = await eachMessage(upcasted, context);\n\n if (checkpoints) {\n const storeCheckpointResult: StoreProcessorCheckpointResult<CheckpointType | null> =\n await checkpoints.store(\n {\n processorId,\n version,\n message: upcasted,\n lastCheckpoint,\n 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 (stopAfter && stopAfter(upcasted)) {\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 AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n HandlerContext extends DefaultRecord = DefaultRecord,\n CheckpointType =\n GlobalPositionTypeOfRecordedMessageMetadata<EventMetaDataType>,\n EventPayloadType extends Event = EventType,\n>(\n options: ProjectorOptions<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType,\n EventPayloadType\n >,\n): MessageProcessor<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType\n> => {\n const {\n projection,\n processorId = getProjectorId({\n projectionName: projection.name ?? 'unknown',\n }),\n ...rest\n } = options;\n\n return reactor<\n EventType,\n EventMetaDataType,\n HandlerContext,\n CheckpointType,\n EventPayloadType\n >({\n ...rest,\n type: MessageProcessorType.PROJECTOR,\n canHandle: projection.canHandle,\n processorId,\n messageOptions: options.projection.eventsOptions,\n hooks: {\n onInit: options.hooks?.onInit,\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 ) => projection.handle([event], context),\n });\n};\n","export * from './deepReadonly';\n\nexport * from './command';\nexport * from './event';\nexport * from './message';\nexport * from './messageHandling';\n\nexport * from './decider';\nexport * from './workflow';\n\nexport type Brand<K, T> = K & { readonly __brand: T };\nexport type Flavour<K, T> = K & { readonly __brand?: T };\n\nexport type DefaultRecord = Record<string, unknown>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyRecord = Record<string, any>;\n\nexport type NonNullable<T> = T extends null | undefined ? never : T;\n\nexport const emmettPrefix = 'emt';\n\nexport const globalTag = 'global';\nexport const defaultTag = `${emmettPrefix}:default`;\nexport const unknownTag = `${emmettPrefix}:unknown`;\n","import { ConcurrencyError, EmmettError } 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 EmmettError.isInstanceOf<ConcurrencyError>(\n error,\n ExpectedVersionConflictError.Codes.ConcurrencyError,\n );\n","const isPrimitive = (value: unknown): boolean => {\n const type = typeof value;\n return (\n value === null ||\n value === undefined ||\n type === 'boolean' ||\n type === 'number' ||\n type === 'string' ||\n type === 'symbol' ||\n type === 'bigint'\n );\n};\n\nconst compareArrays = <T>(left: T[], right: T[]): boolean => {\n if (left.length !== right.length) {\n return false;\n }\n for (let i = 0; i < left.length; i++) {\n const leftHas = i in left;\n const rightHas = i in right;\n if (leftHas !== rightHas) return false;\n if (leftHas && !deepEquals(left[i], right[i])) return false;\n }\n return true;\n};\n\nconst compareDates = (left: Date, right: Date): boolean => {\n return left.getTime() === right.getTime();\n};\n\nconst compareRegExps = (left: RegExp, right: RegExp): boolean => {\n return left.toString() === right.toString();\n};\n\nconst compareErrors = (left: Error, right: Error): boolean => {\n if (left.message !== right.message || left.name !== right.name) {\n return false;\n }\n const leftKeys = Object.keys(left);\n const rightKeys = Object.keys(right);\n if (leftKeys.length !== rightKeys.length) return false;\n const rightKeySet = new Set(rightKeys);\n for (const key of leftKeys) {\n if (!rightKeySet.has(key)) return false;\n // @ts-expect-error - accessing dynamic keys\n if (!deepEquals(left[key], right[key])) return false;\n }\n return true;\n};\n\nconst compareMaps = (\n left: Map<unknown, unknown>,\n right: Map<unknown, unknown>,\n): boolean => {\n if (left.size !== right.size) return false;\n\n for (const [key, value] of left) {\n if (isPrimitive(key)) {\n if (!right.has(key) || !deepEquals(value, right.get(key))) {\n return false;\n }\n } else {\n let found = false;\n for (const [rightKey, rightValue] of right) {\n if (deepEquals(key, rightKey) && deepEquals(value, rightValue)) {\n found = true;\n break;\n }\n }\n if (!found) return false;\n }\n }\n return true;\n};\n\nconst compareSets = (left: Set<unknown>, right: Set<unknown>): boolean => {\n if (left.size !== right.size) return false;\n\n for (const leftItem of left) {\n if (isPrimitive(leftItem)) {\n if (!right.has(leftItem)) return false;\n } else {\n let found = false;\n for (const rightItem of right) {\n if (deepEquals(leftItem, rightItem)) {\n found = true;\n break;\n }\n }\n if (!found) return false;\n }\n }\n return true;\n};\n\nconst compareArrayBuffers = (\n left: ArrayBuffer,\n right: ArrayBuffer,\n): boolean => {\n if (left.byteLength !== right.byteLength) return false;\n const leftView = new Uint8Array(left);\n const rightView = new Uint8Array(right);\n for (let i = 0; i < leftView.length; i++) {\n if (leftView[i] !== rightView[i]) return false;\n }\n return true;\n};\n\nconst compareTypedArrays = (\n left: ArrayBufferView,\n right: ArrayBufferView,\n): boolean => {\n if (left.constructor !== right.constructor) return false;\n if (left.byteLength !== right.byteLength) return false;\n\n const leftArray = new Uint8Array(\n left.buffer,\n left.byteOffset,\n left.byteLength,\n );\n const rightArray = new Uint8Array(\n right.buffer,\n right.byteOffset,\n right.byteLength,\n );\n\n for (let i = 0; i < leftArray.length; i++) {\n if (leftArray[i] !== rightArray[i]) return false;\n }\n return true;\n};\n\nconst compareObjects = (\n left: Record<string, unknown>,\n right: Record<string, unknown>,\n): boolean => {\n const keys1 = Object.keys(left);\n const keys2 = Object.keys(right);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (const key of keys1) {\n if (left[key] instanceof Function && right[key] instanceof Function) {\n continue;\n }\n\n const isEqual = deepEquals(left[key], right[key]);\n if (!isEqual) {\n return false;\n }\n }\n\n return true;\n};\n\nconst getType = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n\n const primitiveType = typeof value;\n if (primitiveType !== 'object') return primitiveType;\n\n if (Array.isArray(value)) return 'array';\n if (value instanceof Boolean) return 'boxed-boolean';\n if (value instanceof Number) return 'boxed-number';\n if (value instanceof String) return 'boxed-string';\n if (value instanceof Date) return 'date';\n if (value instanceof RegExp) return 'regexp';\n if (value instanceof Error) return 'error';\n if (value instanceof Map) return 'map';\n if (value instanceof Set) return 'set';\n if (value instanceof ArrayBuffer) return 'arraybuffer';\n if (value instanceof DataView) return 'dataview';\n if (value instanceof WeakMap) return 'weakmap';\n if (value instanceof WeakSet) return 'weakset';\n\n if (ArrayBuffer.isView(value)) return 'typedarray';\n\n return 'object';\n};\n\nexport const deepEquals = <T>(left: T, right: T): boolean => {\n if (left === right) return true;\n\n if (isEquatable(left)) {\n return left.equals(right);\n }\n\n const leftType = getType(left);\n const rightType = getType(right);\n\n if (leftType !== rightType) return false;\n\n switch (leftType) {\n case 'null':\n case 'undefined':\n case 'boolean':\n case 'number':\n case 'bigint':\n case 'string':\n case 'symbol':\n case 'function':\n return left === right;\n\n case 'array':\n return compareArrays(left as unknown[], right as unknown[]);\n\n case 'date':\n return compareDates(left as Date, right as Date);\n\n case 'regexp':\n return compareRegExps(left as RegExp, right as RegExp);\n\n case 'error':\n return compareErrors(left as Error, right as Error);\n\n case 'map':\n return compareMaps(\n left as Map<unknown, unknown>,\n right as Map<unknown, unknown>,\n );\n\n case 'set':\n return compareSets(left as Set<unknown>, right as Set<unknown>);\n\n case 'arraybuffer':\n return compareArrayBuffers(left as ArrayBuffer, right as ArrayBuffer);\n\n case 'dataview':\n case 'weakmap':\n case 'weakset':\n return false;\n\n case 'typedarray':\n return compareTypedArrays(\n left as ArrayBufferView,\n right as ArrayBufferView,\n );\n\n case 'boxed-boolean':\n return (left as boolean).valueOf() === (right as boolean).valueOf();\n\n case 'boxed-number':\n return (left as number).valueOf() === (right as number).valueOf();\n\n case 'boxed-string':\n return (left as string).valueOf() === (right as string).valueOf();\n\n case 'object':\n return compareObjects(\n left as Record<string, unknown>,\n right as Record<string, unknown>,\n );\n\n default:\n return false;\n }\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 !== null &&\n left !== undefined &&\n typeof left === 'object' &&\n 'equals' in left &&\n typeof left['equals'] === 'function'\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","export type ShutdownHandler = () => void | Promise<void>;\n\n/**\n * Registers handlers for OS signals to enable graceful shutdown.\n * Handles SIGTERM and SIGINT by default.\n * Works in Node.js, Bun, and Deno. Safely no-ops in Browser/Cloudflare Workers.\n *\n * @param handler - Function to call when shutdown signal is received\n * @returns Cleanup function to unregister the handlers\n */\nexport const onShutdown = (handler: ShutdownHandler): (() => void) => {\n const signals = ['SIGTERM', 'SIGINT'] as const;\n\n // Node.js/Bun\n if (typeof process !== 'undefined' && typeof process.on === 'function') {\n for (const signal of signals) {\n process.on(signal, handler);\n }\n return () => {\n for (const signal of signals) {\n process.off(signal, handler);\n }\n };\n }\n\n // Deno\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const deno = (globalThis as any).Deno;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (deno && typeof deno.addSignalListener === 'function') {\n for (const signal of signals) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n deno.addSignalListener(signal, handler);\n }\n return () => {\n for (const signal of signals) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n deno.removeSignalListener(signal, handler);\n }\n };\n }\n\n // Browser/Cloudflare Workers: no-op\n return () => {};\n};\n","const textEncoder = new TextEncoder();\n\nexport const hashText = async (text: string): Promise<bigint> => {\n const hashBuffer = await crypto.subtle.digest(\n 'SHA-256',\n textEncoder.encode(text),\n );\n // Create an array with a single element that is a 64-bit signed integer\n // We take the first 8 bytes (so 64 bits) of the SHA-256 hash\n const view = new BigInt64Array(hashBuffer, 0, 1);\n return view[0]!;\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 {\n AnyMessage,\n AnyRecordedMessageMetadata,\n RecordedMessage,\n} from '../../typing';\n\nexport type MessageDowncast<\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n> =\n | ((\n message: RecordedMessage<MessageType, RecordedMessageMetadataType>,\n ) => RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>)\n | ((message: MessageType) => MessagePayloadType);\n\nexport const downcastRecordedMessage = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessage:\n | RecordedMessage<MessageType, RecordedMessageMetadataType>\n | MessageType,\n options?: {\n downcast?: MessageDowncast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessagePayloadType, RecordedMessageMetadataType> => {\n if (!options?.downcast)\n return recordedMessage as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n\n const downcasted = options.downcast(\n recordedMessage as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >,\n );\n\n return {\n ...recordedMessage,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n data: downcasted.data,\n ...('metadata' in recordedMessage || 'metadata' in downcasted\n ? {\n metadata: {\n ...('metadata' in recordedMessage\n ? (recordedMessage.metadata as object)\n : {}),\n ...('metadata' in downcasted\n ? (downcasted.metadata as object)\n : {}),\n },\n }\n : {}),\n } as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n};\n\nexport const downcastRecordedMessages = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessages:\n | RecordedMessage<MessageType, RecordedMessageMetadataType>[]\n | MessageType[],\n options?: {\n downcast?: MessageDowncast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>[] => {\n if (!options?.downcast)\n return recordedMessages as unknown as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >[];\n\n return recordedMessages.map((recordedMessage) =>\n downcastRecordedMessage(recordedMessage, options),\n );\n};\n","import type {\n AnyMessage,\n AnyRecordedMessageMetadata,\n RecordedMessage,\n} from '../../typing';\n\nexport type MessageUpcast<\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n> =\n | ((message: MessagePayloadType) => MessageType)\n | ((\n message: RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>,\n ) => RecordedMessage<MessageType, RecordedMessageMetadataType>);\n\nexport const upcastRecordedMessage = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessage:\n | RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>\n | MessagePayloadType,\n options?: {\n upcast?: MessageUpcast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessageType, RecordedMessageMetadataType> => {\n if (!options?.upcast)\n return recordedMessage as unknown as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >;\n\n const upcasted = options.upcast(\n recordedMessage as RecordedMessage<\n MessagePayloadType,\n RecordedMessageMetadataType\n >,\n );\n\n return {\n ...recordedMessage,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n data: upcasted.data,\n ...('metadata' in recordedMessage || 'metadata' in upcasted\n ? {\n metadata: {\n ...('metadata' in recordedMessage\n ? (recordedMessage.metadata as object)\n : {}),\n ...('metadata' in upcasted ? (upcasted.metadata as object) : {}),\n },\n }\n : {}),\n } as unknown as RecordedMessage<MessageType, RecordedMessageMetadataType>;\n};\n\nexport const upcastRecordedMessages = <\n MessageType extends AnyMessage,\n MessagePayloadType extends AnyMessage = MessageType,\n RecordedMessageMetadataType extends AnyRecordedMessageMetadata =\n AnyRecordedMessageMetadata,\n>(\n recordedMessages:\n | RecordedMessage<MessagePayloadType, RecordedMessageMetadataType>[]\n | MessagePayloadType[],\n options?: {\n upcast?: MessageUpcast<\n MessageType,\n MessagePayloadType,\n RecordedMessageMetadataType\n >;\n },\n): RecordedMessage<MessageType, RecordedMessageMetadataType>[] => {\n if (!options?.upcast)\n return recordedMessages as unknown as RecordedMessage<\n MessageType,\n RecordedMessageMetadataType\n >[];\n\n return recordedMessages.map((recordedMessage) =>\n upcastRecordedMessage(recordedMessage, options),\n );\n};\n","import { getInMemoryDatabase, type InMemoryDatabase } from '../database';\nimport { EmmettError } from '../errors';\nimport type {\n AnyEvent,\n AnyMessage,\n BatchRecordedMessageHandlerWithContext,\n MessageHandlerResult,\n ReadEventMetadataWithGlobalPosition,\n SingleRecordedMessageHandlerWithContext,\n} from '../typing';\nimport type { MessageProcessor } from './processors';\nimport {\n getCheckpoint,\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:\n currentPosition === newCheckpoint\n ? 'IGNORED'\n : newCheckpoint !== null && currentPosition > newCheckpoint\n ? 'CURRENT_AHEAD'\n : '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 onInit: options.hooks?.onInit,\n onStart: options.hooks?.onStart,\n onClose: options.hooks?.onClose\n ? async (context: InMemoryProcessorHandlerContext) => {\n if (options.hooks?.onClose) await options.hooks?.onClose(context);\n }\n : undefined,\n };\n\n const processor = 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\n return Object.assign(processor, { database });\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 onInit: options.hooks?.onInit,\n onStart: options.hooks?.onStart,\n onClose: options.hooks?.onClose,\n };\n\n const processor = reactor({\n ...options,\n hooks,\n processingScope: inMemoryProcessingScope({\n database,\n processorId: options.processorId,\n }),\n checkpoints: inMemoryCheckpointer<MessageType>(),\n });\n\n return Object.assign(processor, { database });\n};\n","import type { MessageProcessor } from '@event-driven-io/emmett';\nimport {\n EmmettError,\n inMemoryProjector,\n inMemoryReactor,\n type AnyEvent,\n type AnyMessage,\n type AnyRecordedMessageMetadata,\n type AsyncRetryOptions,\n type BatchRecordedMessageHandlerWithoutContext,\n type DefaultRecord,\n type InMemoryProcessor,\n type InMemoryProjectorOptions,\n type InMemoryReactorOptions,\n type Message,\n type MessageConsumer,\n type MessageConsumerOptions,\n} from '@event-driven-io/emmett';\nimport {\n EventStoreDBClient,\n type SubscribeToAllOptions,\n type SubscribeToStreamOptions,\n} from '@eventstore/db-client';\nimport { v7 as uuid } from 'uuid';\nimport type { EventStoreDBReadEventMetadata } from '../eventstoreDBEventStore';\nimport {\n DefaultEventStoreDBEventStoreProcessorBatchSize,\n eventStoreDBSubscription,\n zipEventStoreDBEventStoreMessageBatchPullerStartFrom,\n type EventStoreDBSubscription,\n} from './subscriptions';\n\nexport type EventStoreDBEventStoreConsumerConfig<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ConsumerMessageType extends Message = any,\n> = MessageConsumerOptions<ConsumerMessageType> & {\n from?: EventStoreDBEventStoreConsumerType;\n pulling?: {\n batchSize?: number;\n };\n resilience?: {\n resubscribeOptions?: AsyncRetryOptions;\n };\n};\n\nexport type EventStoreDBEventStoreConsumerOptions<\n ConsumerEventType extends Message = Message,\n> = EventStoreDBEventStoreConsumerConfig<ConsumerEventType> &\n (\n | {\n connectionString: string;\n client?: never;\n }\n | { client: EventStoreDBClient; connectionString?: never }\n );\n\nexport type $all = '$all';\nexport const $all = '$all';\n\nexport type EventStoreDBEventStoreConsumerType =\n | {\n stream: $all;\n options?: Exclude<SubscribeToAllOptions, 'fromPosition'>;\n }\n | {\n stream: string;\n options?: Exclude<SubscribeToStreamOptions, 'fromRevision'>;\n };\n\nexport type EventStoreDBEventStoreConsumer<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ConsumerMessageType extends AnyMessage = any,\n> = MessageConsumer<ConsumerMessageType> &\n Readonly<{\n reactor: <MessageType extends AnyMessage = ConsumerMessageType>(\n options: InMemoryReactorOptions<MessageType>,\n ) => InMemoryProcessor<MessageType>;\n }> &\n (AnyEvent extends ConsumerMessageType\n ? Readonly<{\n projector: <\n EventType extends AnyEvent = ConsumerMessageType & AnyEvent,\n >(\n options: InMemoryProjectorOptions<EventType>,\n ) => InMemoryProcessor<EventType>;\n }>\n : object);\n\nexport const eventStoreDBEventStoreConsumer = <\n ConsumerMessageType extends Message = AnyMessage,\n>(\n options: EventStoreDBEventStoreConsumerOptions<ConsumerMessageType>,\n): EventStoreDBEventStoreConsumer<ConsumerMessageType> => {\n let isRunning = false;\n const { pulling } = options;\n const processors = options.processors ?? [];\n\n let start: Promise<void>;\n\n let currentSubscription: EventStoreDBSubscription | undefined;\n\n const client =\n 'client' in options && options.client\n ? options.client\n : EventStoreDBClient.connectionString(options.connectionString);\n\n const eachBatch: BatchRecordedMessageHandlerWithoutContext<\n ConsumerMessageType,\n EventStoreDBReadEventMetadata\n > = async (messagesBatch) => {\n const activeProcessors = processors.filter((s) => s.isActive);\n\n if (activeProcessors.length === 0)\n return {\n type: 'STOP',\n reason: 'No active processors',\n };\n\n const result = await Promise.allSettled(\n activeProcessors.map(async (s) => {\n // TODO: Add here filtering to only pass messages that can be handled by\n return await s.handle(messagesBatch, { client });\n }),\n );\n\n const error = result.find((r) => r.status === 'rejected')?.reason as\n | Error\n | undefined;\n\n return result.some(\n (r) => r.status === 'fulfilled' && r.value?.type !== 'STOP',\n )\n ? undefined\n : {\n type: 'STOP',\n error: error ? EmmettError.mapFrom(error) : undefined,\n };\n };\n\n const subscription = (currentSubscription = eventStoreDBSubscription({\n client,\n from: options.from,\n eachBatch,\n batchSize:\n pulling?.batchSize ?? DefaultEventStoreDBEventStoreProcessorBatchSize,\n resilience: options.resilience,\n }));\n\n const stop = async () => {\n if (!isRunning) return;\n isRunning = false;\n if (currentSubscription) {\n await currentSubscription.stop();\n currentSubscription = undefined;\n }\n await start;\n };\n\n return {\n consumerId: options.consumerId ?? uuid(),\n get isRunning() {\n return isRunning;\n },\n processors,\n reactor: <MessageType extends AnyMessage = ConsumerMessageType>(\n options: InMemoryReactorOptions<MessageType>,\n ): InMemoryProcessor<MessageType> => {\n const processor = inMemoryReactor(options);\n\n processors.push(\n // TODO: change that\n processor as unknown as MessageProcessor<\n ConsumerMessageType,\n AnyRecordedMessageMetadata,\n DefaultRecord\n >,\n );\n\n return processor;\n },\n projector: <EventType extends AnyEvent = ConsumerMessageType & AnyEvent>(\n options: InMemoryProjectorOptions<EventType>,\n ): InMemoryProcessor<EventType> => {\n const processor = inMemoryProjector(options);\n\n processors.push(\n // TODO: change that\n processor as unknown as MessageProcessor<\n ConsumerMessageType,\n AnyRecordedMessageMetadata,\n DefaultRecord\n >,\n );\n\n return processor;\n },\n start: () => {\n if (isRunning) return start;\n\n start = (async () => {\n if (processors.length === 0)\n return Promise.reject(\n new EmmettError(\n 'Cannot start consumer without at least a single processor',\n ),\n );\n\n isRunning = true;\n\n const startFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom(\n await Promise.all(processors.map((o) => o.start(client))),\n );\n\n return subscription.start({ startFrom });\n })();\n\n return start;\n },\n stop,\n close: stop,\n };\n};\n","import {\n asyncRetry,\n getCheckpoint,\n isBigint,\n JSONParser,\n type AnyMessage,\n type AsyncRetryOptions,\n type BatchRecordedMessageHandlerWithoutContext,\n type EmmettError,\n type Message,\n type MessageHandlerResult,\n} from '@event-driven-io/emmett';\nimport type { EventStoreDBClient } from '@eventstore/db-client';\nimport {\n END,\n excludeSystemEvents,\n START,\n type ResolvedEvent,\n type StreamSubscription,\n} from '@eventstore/db-client';\nimport { pipeline, Transform, Writable, type WritableOptions } from 'stream';\nimport {\n mapFromESDBEvent,\n type EventStoreDBReadEventMetadata,\n} from '../../eventstoreDBEventStore';\nimport {\n $all,\n type EventStoreDBEventStoreConsumerType,\n} from '../eventStoreDBEventStoreConsumer';\n\nexport const DefaultEventStoreDBEventStoreProcessorBatchSize = 100;\nexport const DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = 50;\n\nexport type EventStoreDBEventStoreMessagesBatchHandlerResult = void | {\n type: 'STOP';\n reason?: string;\n error?: EmmettError;\n};\n\nexport type EventStoreDBSubscriptionOptions<\n MessageType extends Message = Message,\n> = {\n from?: EventStoreDBEventStoreConsumerType;\n client: EventStoreDBClient;\n batchSize: number;\n eachBatch: BatchRecordedMessageHandlerWithoutContext<\n MessageType,\n EventStoreDBReadEventMetadata\n >;\n resilience?: {\n resubscribeOptions?: AsyncRetryOptions;\n };\n};\n\nexport type EventStoreDBSubscriptionStartFrom =\n | { lastCheckpoint: bigint }\n | 'BEGINNING'\n | 'END';\n\nexport type EventStoreDBSubscriptionStartOptions = {\n startFrom: EventStoreDBSubscriptionStartFrom;\n};\n\nexport type EventStoreDBSubscription = {\n isRunning: boolean;\n start(options: EventStoreDBSubscriptionStartOptions): Promise<void>;\n stop(): Promise<void>;\n};\n\nconst toGlobalPosition = (startFrom: EventStoreDBSubscriptionStartFrom) =>\n startFrom === 'BEGINNING'\n ? START\n : startFrom === 'END'\n ? END\n : {\n prepare: startFrom.lastCheckpoint,\n commit: startFrom.lastCheckpoint,\n };\n\nconst toStreamPosition = (startFrom: EventStoreDBSubscriptionStartFrom) =>\n startFrom === 'BEGINNING'\n ? START\n : startFrom === 'END'\n ? END\n : startFrom.lastCheckpoint;\n\nconst subscribe = (\n client: EventStoreDBClient,\n from: EventStoreDBEventStoreConsumerType | undefined,\n options: EventStoreDBSubscriptionStartOptions,\n) =>\n from == undefined || from.stream == $all\n ? client.subscribeToAll({\n ...(from?.options ?? {}),\n fromPosition: toGlobalPosition(options.startFrom),\n filter: excludeSystemEvents(),\n })\n : client.subscribeToStream(from.stream, {\n ...(from.options ?? {}),\n fromRevision: toStreamPosition(options.startFrom),\n });\n\nexport const isDatabaseUnavailableError = (error: unknown) =>\n error instanceof Error &&\n 'type' in error &&\n error.type === 'unavailable' &&\n 'code' in error &&\n error.code === 14;\n\nexport const EventStoreDBResubscribeDefaultOptions: AsyncRetryOptions = {\n forever: true,\n minTimeout: 100,\n factor: 1.5,\n shouldRetryError: (error) => !isDatabaseUnavailableError(error),\n};\n\ntype SubscriptionSequentialHandlerOptions<\n MessageType extends AnyMessage = AnyMessage,\n> = EventStoreDBSubscriptionOptions<MessageType> & WritableOptions;\n\nclass SubscriptionSequentialHandler<\n MessageType extends AnyMessage = AnyMessage,\n> extends Transform {\n private options: SubscriptionSequentialHandlerOptions<MessageType>;\n private from: EventStoreDBEventStoreConsumerType | undefined;\n public isRunning: boolean;\n\n constructor(options: SubscriptionSequentialHandlerOptions<MessageType>) {\n super({ objectMode: true, ...options });\n this.options = options;\n this.from = options.from;\n this.isRunning = true;\n }\n\n async _transform(\n resolvedEvent: ResolvedEvent<MessageType>,\n _encoding: BufferEncoding,\n callback: (error?: Error | null) => void,\n ): Promise<void> {\n try {\n if (!this.isRunning || !resolvedEvent.event) {\n callback();\n return;\n }\n\n const message = mapFromESDBEvent(resolvedEvent, this.from);\n const messageCheckpoint = getCheckpoint(message);\n\n const result = await this.options.eachBatch([message]);\n\n if (result && result.type === 'STOP') {\n this.isRunning = false;\n if (!result.error) this.push(messageCheckpoint);\n\n this.push(result);\n this.push(null);\n callback();\n return;\n }\n\n this.push(messageCheckpoint);\n callback();\n } catch (error) {\n callback(error as Error);\n }\n }\n}\n\nexport const eventStoreDBSubscription = <\n MessageType extends AnyMessage = AnyMessage,\n>({\n client,\n from,\n batchSize,\n eachBatch,\n resilience,\n}: EventStoreDBSubscriptionOptions<MessageType>): EventStoreDBSubscription => {\n let isRunning = false;\n\n let start: Promise<void>;\n let processor: SubscriptionSequentialHandler<MessageType>;\n\n let subscription: StreamSubscription<MessageType>;\n\n const resubscribeOptions: AsyncRetryOptions =\n resilience?.resubscribeOptions ?? {\n ...EventStoreDBResubscribeDefaultOptions,\n shouldRetryResult: () => isRunning,\n shouldRetryError: (error) =>\n isRunning &&\n EventStoreDBResubscribeDefaultOptions.shouldRetryError!(error),\n };\n\n const stopSubscription = (callback?: () => void): Promise<void> => {\n isRunning = false;\n if (processor) processor.isRunning = false;\n return subscription\n .unsubscribe()\n .then(() => {\n subscription.destroy();\n })\n .catch((err) => console.error('Error during unsubscribe.%s', err))\n .finally(callback ?? (() => {}));\n };\n\n const pipeMessages = (options: EventStoreDBSubscriptionStartOptions) => {\n let retry = 0;\n return asyncRetry(\n () =>\n new Promise<void>((resolve, reject) => {\n if (!isRunning) {\n resolve();\n return;\n }\n console.info(\n `Starting subscription. ${retry++} retries. From: ${JSONParser.stringify(from ?? '$all')}, Start from: ${JSONParser.stringify(\n options.startFrom,\n )}`,\n );\n subscription = subscribe(client, from, options);\n\n processor = new SubscriptionSequentialHandler({\n client,\n from,\n batchSize,\n eachBatch,\n resilience,\n });\n\n const handler = new (class extends Writable {\n async _write(\n result: bigint | MessageHandlerResult,\n _encoding: string,\n done: () => void,\n ) {\n if (!isRunning) return;\n\n if (isBigint(result)) {\n options.startFrom = {\n lastCheckpoint: result,\n };\n done();\n return;\n }\n\n if (result && result.type === 'STOP' && result.error) {\n console.error(\n `Subscription stopped with error code: ${result.error.errorCode}, message: ${\n result.error.message\n }.`,\n );\n }\n\n await stopSubscription();\n done();\n }\n })({ objectMode: true });\n\n pipeline(\n subscription,\n processor,\n handler,\n async (error: Error | null) => {\n console.info(`Stopping subscription.`);\n await stopSubscription(() => {\n if (!error) {\n console.info('Subscription ended successfully.');\n resolve();\n return;\n }\n console.error(\n `Received error: ${JSONParser.stringify(error)}.`,\n );\n reject(error);\n });\n },\n );\n }),\n resubscribeOptions,\n );\n };\n\n return {\n get isRunning() {\n return isRunning;\n },\n start: (options) => {\n if (isRunning) return start;\n\n start = (async () => {\n isRunning = true;\n\n return pipeMessages(options);\n })();\n\n return start;\n },\n stop: async () => {\n if (!isRunning) return start ? await start : Promise.resolve();\n await stopSubscription();\n await start;\n },\n };\n};\n\nexport const zipEventStoreDBEventStoreMessageBatchPullerStartFrom = (\n options: (EventStoreDBSubscriptionStartFrom | undefined)[],\n): EventStoreDBSubscriptionStartFrom => {\n if (\n options.length === 0 ||\n options.some((o) => o === undefined || o === 'BEGINNING')\n )\n return 'BEGINNING';\n\n if (options.every((o) => o === 'END')) return 'END';\n\n return options\n .filter((o) => o !== undefined && o !== 'BEGINNING' && o !== 'END')\n .sort((a, b) => (a > b ? 1 : -1))[0]!;\n};\n","import {\n ExpectedVersionConflictError,\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n STREAM_EXISTS,\n assertExpectedVersionMatchesCurrent,\n downcastRecordedMessages,\n upcastRecordedMessage,\n type AggregateStreamOptions,\n type AggregateStreamResultWithGlobalPosition,\n type AnyMessage,\n type AppendToStreamOptions,\n type AppendToStreamResultWithGlobalPosition,\n type BigIntStreamPosition,\n type Event,\n type EventStore,\n type ExpectedStreamVersion,\n type ReadEvent,\n type ReadEventMetadataWithGlobalPosition,\n type ReadStreamOptions,\n type ReadStreamResult,\n type RecordedMessage,\n type StreamExistsResult,\n} from '@event-driven-io/emmett';\nimport type { EventStoreDBClient } from '@eventstore/db-client';\nimport {\n ANY,\n STREAM_EXISTS as ESDB_STREAM_EXISTS,\n NO_STREAM,\n StreamNotFoundError,\n WrongExpectedVersionError,\n jsonEvent,\n type AppendExpectedRevision,\n type ReadStreamOptions as ESDBReadStreamOptions,\n type ResolvedEvent,\n} from '@eventstore/db-client';\nimport {\n $all,\n eventStoreDBEventStoreConsumer,\n type EventStoreDBEventStoreConsumer,\n type EventStoreDBEventStoreConsumerConfig,\n type EventStoreDBEventStoreConsumerType,\n} from './consumers';\n\nconst toEventStoreDBReadOptions = <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n>(\n options:\n | ReadStreamOptions<BigIntStreamPosition, EventType, EventPayloadType>\n | undefined,\n): ESDBReadStreamOptions | undefined => {\n return options\n ? {\n fromRevision: 'from' in options ? options.from : undefined,\n maxCount:\n 'maxCount' in options\n ? options.maxCount\n : 'to' in options\n ? options.to\n : undefined,\n }\n : undefined;\n};\n\nexport const EventStoreDBEventStoreDefaultStreamVersion = -1n;\n\nexport type EventStoreDBReadEventMetadata = ReadEventMetadataWithGlobalPosition;\n\nexport type EventStoreDBReadEvent<EventType extends Event = Event> = ReadEvent<\n EventType,\n EventStoreDBReadEventMetadata\n>;\n\nexport interface EventStoreDBEventStore extends EventStore<EventStoreDBReadEventMetadata> {\n appendToStream<\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<AppendToStreamResultWithGlobalPosition>;\n consumer<ConsumerEventType extends Event = Event>(\n options?: EventStoreDBEventStoreConsumerConfig<ConsumerEventType>,\n ): EventStoreDBEventStoreConsumer<ConsumerEventType>;\n}\n\nexport const getEventStoreDBEventStore = (\n eventStore: EventStoreDBClient,\n): EventStoreDBEventStore => {\n return {\n async aggregateStream<\n State,\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options: AggregateStreamOptions<\n State,\n EventType,\n EventStoreDBReadEventMetadata,\n EventPayloadType\n >,\n ): Promise<AggregateStreamResultWithGlobalPosition<State>> {\n const { evolve, initialState, read } = options;\n\n const expectedStreamVersion = read?.expectedStreamVersion;\n\n let state = initialState();\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n let lastEventGlobalPosition: bigint | undefined = undefined;\n\n try {\n for await (const resolvedEvent of eventStore.readStream<EventPayloadType>(\n streamName,\n toEventStoreDBReadOptions(options.read),\n )) {\n const { event } = resolvedEvent;\n if (!event) continue;\n\n state = evolve(\n state,\n upcastRecordedMessage(\n mapFromESDBEvent<EventPayloadType>(resolvedEvent),\n options?.read?.schema?.versioning,\n ),\n );\n currentStreamVersion = event.revision;\n lastEventGlobalPosition = event.position?.commit;\n }\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n expectedStreamVersion,\n EventStoreDBEventStoreDefaultStreamVersion,\n );\n\n return lastEventGlobalPosition\n ? {\n currentStreamVersion,\n lastEventGlobalPosition,\n state,\n streamExists: true,\n }\n : {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n readStream: async <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n options?: ReadStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<ReadStreamResult<EventType, EventStoreDBReadEventMetadata>> => {\n const events: ReadEvent<EventType, EventStoreDBReadEventMetadata>[] = [];\n\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const resolvedEvent of eventStore.readStream<EventPayloadType>(\n streamName,\n toEventStoreDBReadOptions(options),\n )) {\n const { event } = resolvedEvent;\n if (!event) continue;\n events.push(\n upcastRecordedMessage(\n mapFromESDBEvent<EventPayloadType>(resolvedEvent),\n options?.schema?.versioning,\n ),\n );\n\n currentStreamVersion = event.revision;\n }\n return {\n currentStreamVersion,\n events,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n events: [],\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n appendToStream: async <\n EventType extends Event,\n EventPayloadType extends Event = EventType,\n >(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions<\n BigIntStreamPosition,\n EventType,\n EventPayloadType\n >,\n ): Promise<AppendToStreamResultWithGlobalPosition> => {\n try {\n const eventsToStore = downcastRecordedMessages(\n events,\n options?.schema?.versioning,\n );\n const serializedEvents = eventsToStore.map(jsonEvent);\n\n const expectedRevision = toExpectedRevision(\n options?.expectedStreamVersion,\n );\n\n const appendResult = await eventStore.appendToStream(\n streamName,\n serializedEvents,\n {\n expectedRevision,\n },\n );\n\n return {\n nextExpectedStreamVersion: appendResult.nextExpectedRevision,\n lastEventGlobalPosition: appendResult.position!.commit,\n createdNewStream:\n appendResult.nextExpectedRevision >=\n BigInt(serializedEvents.length),\n };\n } catch (error) {\n if (error instanceof WrongExpectedVersionError) {\n throw new ExpectedVersionConflictError(\n error.actualVersion,\n toExpectedVersion(error.expectedVersion),\n );\n }\n\n throw error;\n }\n },\n\n consumer: <ConsumerEventType extends Event = Event>(\n options?: EventStoreDBEventStoreConsumerConfig<ConsumerEventType>,\n ): EventStoreDBEventStoreConsumer<ConsumerEventType> =>\n eventStoreDBEventStoreConsumer<ConsumerEventType>({\n ...(options ?? {}),\n client: eventStore,\n }),\n\n streamExists: async (streamName: string): Promise<StreamExistsResult> => {\n try {\n for await (const resolvedEvent of eventStore.readStream(streamName)) {\n const { event } = resolvedEvent;\n\n if (!event) continue;\n\n return true;\n }\n\n return false;\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return false;\n }\n\n throw error;\n }\n },\n\n //streamEvents: streamEvents(eventStore),\n };\n};\n\nconst getCheckpoint = <MessageType extends AnyMessage = AnyMessage>(\n resolvedEvent: ResolvedEvent<MessageType>,\n from?: EventStoreDBEventStoreConsumerType,\n): bigint => {\n return !from || from?.stream === $all\n ? (resolvedEvent.link?.position?.commit ??\n resolvedEvent.event?.position?.commit)!\n : (resolvedEvent.link?.revision ?? resolvedEvent.event!.revision);\n};\n\nexport const mapFromESDBEvent = <MessageType extends AnyMessage = AnyMessage>(\n resolvedEvent: ResolvedEvent<MessageType>,\n from?: EventStoreDBEventStoreConsumerType,\n): RecordedMessage<MessageType, EventStoreDBReadEventMetadata> => {\n const event = resolvedEvent.event!;\n return <RecordedMessage<MessageType, EventStoreDBReadEventMetadata>>{\n type: event.type,\n data: event.data,\n metadata: {\n ...((event.metadata as EventStoreDBReadEventMetadata) ??\n ({} as EventStoreDBReadEventMetadata)),\n eventId: event.id,\n streamName: event.streamId,\n streamPosition: event.revision,\n globalPosition: event.position!.commit,\n checkpoint: getCheckpoint(resolvedEvent, from),\n },\n };\n};\n\nconst toExpectedRevision = (\n expected: ExpectedStreamVersion | undefined,\n): AppendExpectedRevision => {\n if (expected === undefined) return ANY;\n\n if (expected === NO_CONCURRENCY_CHECK) return ANY;\n\n if (expected == STREAM_DOES_NOT_EXIST) return NO_STREAM;\n\n if (expected == STREAM_EXISTS) return ESDB_STREAM_EXISTS;\n\n return expected as bigint;\n};\n\nconst toExpectedVersion = (\n expected: AppendExpectedRevision | undefined,\n): ExpectedStreamVersion => {\n if (expected === undefined) return NO_CONCURRENCY_CHECK;\n\n if (expected === ANY) return NO_CONCURRENCY_CHECK;\n\n if (expected == NO_STREAM) return STREAM_DOES_NOT_EXIST;\n\n if (expected == ESDB_STREAM_EXISTS) return STREAM_EXISTS;\n\n return expected;\n};\n\n// const { map } = streamTransformations;\n//\n// // eslint-disable-next-line @typescript-eslint/no-unused-vars\n// const convertToWebReadableStream = (\n// allStreamSubscription: AllStreamSubscription,\n// ): ReadableStream<AllStreamResolvedEvent | GlobalStreamCaughtUp> => {\n// // Validate the input type\n// if (!(allStreamSubscription instanceof Readable)) {\n// throw new Error('Provided stream is not a Node.js Readable stream.');\n// }\n\n// let globalPosition = 0n;\n\n// const stream = Readable.toWeb(\n// allStreamSubscription,\n// ) as ReadableStream<AllStreamResolvedEvent>;\n\n// const writable = new WritableStream<\n// AllStreamResolvedEvent | GlobalStreamCaughtUp\n// >();\n\n// allStreamSubscription.on('caughtUp', async () => {\n// console.log(globalPosition);\n// await writable.getWriter().write(globalStreamCaughtUp({ globalPosition }));\n// });\n\n// const transform = map<\n// AllStreamResolvedEvent,\n// AllStreamResolvedEvent | GlobalStreamCaughtUp\n// >((event) => {\n// if (event?.event?.position.commit)\n// globalPosition = event.event?.position.commit;\n\n// return event;\n// });\n\n// return stream.pipeThrough<AllStreamResolvedEvent | GlobalStreamCaughtUp>(\n// transform,\n// );\n// };\n\n// const streamEvents = (eventStore: EventStoreDBClient) => () => {\n// return restream<\n// AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// | ReadEvent<Event, EventStoreDBReadEventMetadata>\n// | GlobalSubscriptionEvent\n// >(\n// (): ReadableStream<AllStreamResolvedEvent | GlobalSubscriptionEvent> =>\n// convertToWebReadableStream(\n// eventStore.subscribeToAll({\n// fromPosition: START,\n// filter: excludeSystemEvents(),\n// }),\n// ),\n// (\n// resolvedEvent: AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// ): ReadEvent<Event, EventStoreDBReadEventMetadata> =>\n// mapFromESDBEvent(resolvedEvent.event as JSONRecordedEvent<Event>),\n// );\n// };\n"]}