@eventualize/core 1.0.0

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.
@@ -0,0 +1,123 @@
1
+ import EvDbStream from './EvDbStream.js';
2
+ import IEvDbStorageSnapshotAdapter from '@eventualize/types/IEvDbStorageSnapshotAdapter';
3
+ import IEvDbStorageStreamAdapter from '@eventualize/types/IEvDbStorageStreamAdapter';
4
+ import IEvDbEventPayload from "@eventualize/types/IEvDbEventPayload";
5
+ import { EvDbStreamFactory } from './EvDbStreamFactory.js';
6
+ /**
7
+ * Combined storage adapter interface
8
+ */
9
+ export interface IEvDbStorageAdapter extends IEvDbStorageStreamAdapter, IEvDbStorageSnapshotAdapter {
10
+ }
11
+ /**
12
+ * Storage configuration - either separate adapters or combined
13
+ */
14
+ interface StorageConfig {
15
+ streamAdapter: IEvDbStorageStreamAdapter;
16
+ snapshotAdapter: IEvDbStorageSnapshotAdapter;
17
+ }
18
+ /**
19
+ * Registry of stream factories by stream type
20
+ */
21
+ interface StreamFactoryRegistry {
22
+ [streamType: string]: EvDbStreamFactory<any, any>;
23
+ }
24
+ /**
25
+ * Store class - manages stream creation with configured adapters and factories
26
+ */
27
+ declare class BaseStore {
28
+ private readonly storage;
29
+ private readonly streamFactories;
30
+ constructor(storage: StorageConfig, streamFactories: StreamFactoryRegistry);
31
+ /**
32
+ * Create a stream instance by stream type and ID
33
+ */
34
+ createStream(streamType: string, streamId: string): EvDbStream;
35
+ /**
36
+ * Get a stream instance from the event store by stream type and ID
37
+ */
38
+ getStream(streamType: string, streamId: string): Promise<EvDbStream>;
39
+ /**
40
+ * Check if a stream type is registered
41
+ */
42
+ hasStreamType(streamType: string): boolean;
43
+ /**
44
+ * Get all registered stream types
45
+ */
46
+ getStreamTypes(): string[];
47
+ /**
48
+ * Create a builder for configuring the store
49
+ */
50
+ static builder(): BaseStoreBuilder;
51
+ close(): Promise<void>;
52
+ }
53
+ /**
54
+ * Builder for creating Store instances
55
+ */
56
+ declare class BaseStoreBuilder {
57
+ private streamAdapter?;
58
+ private snapshotAdapter?;
59
+ private streamFactories;
60
+ /**
61
+ * Configure with separate stream and snapshot adapters
62
+ */
63
+ withAdapters(streamAdapter: IEvDbStorageStreamAdapter, snapshotAdapter: IEvDbStorageSnapshotAdapter): this;
64
+ /**
65
+ * Configure with a combined adapter that implements both interfaces
66
+ */
67
+ withAdapter(adapter: IEvDbStorageAdapter): this;
68
+ /**
69
+ * Register a stream factory
70
+ */
71
+ withStreamFactory<TEvents extends IEvDbEventPayload, TStreamType extends string>(factory: EvDbStreamFactory<TEvents, TStreamType>): this;
72
+ /**
73
+ * Register multiple stream factories at once
74
+ */
75
+ withStreamFactories(factories: ReadonlyArray<EvDbStreamFactory<any, string>>): this;
76
+ /**
77
+ * Build the store instance
78
+ */
79
+ build(): BaseStore;
80
+ }
81
+ /**
82
+ * Helper type to create method signatures for each stream factory
83
+ */
84
+ export type StreamCreatorMethods<TStreamTypes extends Record<string, EvDbStreamFactory<any, any>>> = {
85
+ [K in keyof TStreamTypes as `create${K & string}`]: (streamId: string) => EvDbStream;
86
+ };
87
+ export type StreamMap = Record<string, any>;
88
+ /**
89
+ * Type-safe store that knows about specific stream types
90
+ */
91
+ export declare class EvDbEventStore<TStreamTypes extends Record<string, EvDbStreamFactory<any, any>>> {
92
+ private readonly store;
93
+ constructor(store: BaseStore);
94
+ /**
95
+ * Create a stream with type-safe stream type parameter (fallback method)
96
+ */
97
+ createStream<K extends keyof TStreamTypes & string>(streamType: K, streamId: string): EvDbStream;
98
+ /**
99
+ * Fetch a stream from the event store with type-safe stream type parameter (fallback method)
100
+ */
101
+ getStream<K extends keyof TStreamTypes & string>(streamType: K, streamId: string): Promise<EvDbStream>;
102
+ /**
103
+ * Create dynamic methods for each registered stream factory
104
+ */
105
+ private createDynamicMethods;
106
+ /**
107
+ * Get the underlying store
108
+ */
109
+ getStore(): BaseStore;
110
+ }
111
+ export type TypedStoreType<TStreamTypes extends Record<string, EvDbStreamFactory<any, any>>> = StreamCreatorMethods<TStreamTypes>;
112
+ /**
113
+ * Type-safe store builder
114
+ */
115
+ export declare class EvDbEventStoreBuilder<TStreamTypes extends Record<string, EvDbStreamFactory<any, string>> = {}> {
116
+ private builder;
117
+ withAdapters(streamAdapter: IEvDbStorageStreamAdapter, snapshotAdapter: IEvDbStorageSnapshotAdapter): this;
118
+ withAdapter(adapter: IEvDbStorageAdapter): this;
119
+ withStreamFactory<F extends EvDbStreamFactory<any, string>, K extends F extends EvDbStreamFactory<any, infer ST> ? ST : never>(factory: F): EvDbEventStoreBuilder<TStreamTypes & Record<K, F>>;
120
+ build(): EvDbEventStore<TStreamTypes> & StreamCreatorMethods<TStreamTypes>;
121
+ }
122
+ export type EvDbEventStoreType<TStreams extends StreamMap = StreamMap> = EvDbEventStore<TStreams> & StreamCreatorMethods<TStreams>;
123
+ export {};
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Store class - manages stream creation with configured adapters and factories
3
+ */
4
+ class BaseStore {
5
+ constructor(storage, streamFactories) {
6
+ this.streamFactories = {};
7
+ this.storage = storage;
8
+ this.streamFactories = streamFactories;
9
+ }
10
+ /**
11
+ * Create a stream instance by stream type and ID
12
+ */
13
+ createStream(streamType, streamId) {
14
+ const factory = this.streamFactories[streamType];
15
+ if (!factory) {
16
+ throw new Error(`No stream factory registered for stream type: ${streamType}. ` +
17
+ `Available types: ${Object.keys(this.streamFactories).join(', ')}`);
18
+ }
19
+ const stream = factory.create(streamId, this.storage.streamAdapter, this.storage.snapshotAdapter);
20
+ return stream;
21
+ }
22
+ /**
23
+ * Get a stream instance from the event store by stream type and ID
24
+ */
25
+ async getStream(streamType, streamId) {
26
+ const factory = this.streamFactories[streamType];
27
+ if (!factory) {
28
+ throw new Error(`No stream factory registered for stream type: ${streamType}. ` +
29
+ `Available types: ${Object.keys(this.streamFactories).join(', ')}`);
30
+ }
31
+ return factory.get(streamId, this.storage.streamAdapter, this.storage.snapshotAdapter);
32
+ }
33
+ /**
34
+ * Check if a stream type is registered
35
+ */
36
+ hasStreamType(streamType) {
37
+ return streamType in this.streamFactories;
38
+ }
39
+ /**
40
+ * Get all registered stream types
41
+ */
42
+ getStreamTypes() {
43
+ return Object.keys(this.streamFactories);
44
+ }
45
+ /**
46
+ * Create a builder for configuring the store
47
+ */
48
+ static builder() {
49
+ return new BaseStoreBuilder();
50
+ }
51
+ async close() {
52
+ await Promise.all([this.storage.snapshotAdapter.close(), this.storage.streamAdapter.close()]);
53
+ return;
54
+ }
55
+ }
56
+ /**
57
+ * Builder for creating Store instances
58
+ */
59
+ class BaseStoreBuilder {
60
+ constructor() {
61
+ this.streamFactories = {};
62
+ }
63
+ /**
64
+ * Configure with separate stream and snapshot adapters
65
+ */
66
+ withAdapters(streamAdapter, snapshotAdapter) {
67
+ this.streamAdapter = streamAdapter;
68
+ this.snapshotAdapter = snapshotAdapter;
69
+ return this;
70
+ }
71
+ /**
72
+ * Configure with a combined adapter that implements both interfaces
73
+ */
74
+ withAdapter(adapter) {
75
+ this.streamAdapter = adapter;
76
+ this.snapshotAdapter = adapter;
77
+ return this;
78
+ }
79
+ /**
80
+ * Register a stream factory
81
+ */
82
+ withStreamFactory(factory) {
83
+ const streamType = factory.getStreamType();
84
+ if (this.streamFactories[streamType]) {
85
+ throw new Error(`Stream factory for type '${streamType}' is already registered`);
86
+ }
87
+ this.streamFactories[streamType] = factory;
88
+ return this;
89
+ }
90
+ /**
91
+ * Register multiple stream factories at once
92
+ */
93
+ withStreamFactories(factories) {
94
+ factories.forEach(factory => {
95
+ this.withStreamFactory(factory);
96
+ });
97
+ return this;
98
+ }
99
+ /**
100
+ * Build the store instance
101
+ */
102
+ build() {
103
+ if (!this.streamAdapter || !this.snapshotAdapter) {
104
+ throw new Error('Storage adapters must be configured. Use withAdapter() or withAdapters()');
105
+ }
106
+ if (Object.keys(this.streamFactories).length === 0) {
107
+ console.warn('Store created with no stream factories registered');
108
+ }
109
+ return new BaseStore({
110
+ streamAdapter: this.streamAdapter,
111
+ snapshotAdapter: this.snapshotAdapter
112
+ }, this.streamFactories);
113
+ }
114
+ }
115
+ /**
116
+ * Type-safe store that knows about specific stream types
117
+ */
118
+ export class EvDbEventStore {
119
+ constructor(store) {
120
+ this.store = store;
121
+ // Create dynamic methods for each stream type
122
+ this.createDynamicMethods();
123
+ }
124
+ /**
125
+ * Create a stream with type-safe stream type parameter (fallback method)
126
+ */
127
+ createStream(streamType, streamId) {
128
+ return this.store.createStream(streamType, streamId);
129
+ }
130
+ /**
131
+ * Fetch a stream from the event store with type-safe stream type parameter (fallback method)
132
+ */
133
+ getStream(streamType, streamId) {
134
+ return this.store.getStream(streamType, streamId);
135
+ }
136
+ /**
137
+ * Create dynamic methods for each registered stream factory
138
+ */
139
+ createDynamicMethods() {
140
+ const streamTypes = this.store.getStreamTypes();
141
+ for (const streamType of streamTypes) {
142
+ const methodName = `create${streamType}`;
143
+ // Create the dynamic method
144
+ this[methodName] = (streamId) => {
145
+ return this.store.createStream(streamType, streamId);
146
+ };
147
+ }
148
+ }
149
+ /**
150
+ * Get the underlying store
151
+ */
152
+ getStore() {
153
+ return this.store;
154
+ }
155
+ }
156
+ /**
157
+ * Type-safe store builder
158
+ */
159
+ export class EvDbEventStoreBuilder {
160
+ constructor() {
161
+ this.builder = BaseStore.builder();
162
+ }
163
+ withAdapters(streamAdapter, snapshotAdapter) {
164
+ this.builder.withAdapters(streamAdapter, snapshotAdapter);
165
+ return this;
166
+ }
167
+ withAdapter(adapter) {
168
+ this.builder.withAdapter(adapter);
169
+ return this;
170
+ }
171
+ // Track stream type in generics
172
+ withStreamFactory(factory) {
173
+ this.builder.withStreamFactory(factory);
174
+ // return as the new type that tracks K
175
+ return this;
176
+ }
177
+ build() {
178
+ const store = new EvDbEventStore(this.builder.build());
179
+ return store;
180
+ }
181
+ }
182
+ //# sourceMappingURL=EvDbEventStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvDbEventStore.js","sourceRoot":"","sources":["../src/EvDbEventStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import EvDbEvent from "@eventualize/types/EvDbEvent";
2
+ import EvDbMessage from "@eventualize/types/EvDbMessage";
3
+ import IEvDbStorageStreamAdapter from "@eventualize/types/IEvDbStorageStreamAdapter";
4
+ import IEvDbView from "@eventualize/types/IEvDbView";
5
+ import EvDbStreamAddress from "@eventualize/types/EvDbStreamAddress";
6
+ import IEvDbStreamStore from "@eventualize/types/IEvDbStreamStore";
7
+ import IEvDbStreamStoreData from "@eventualize/types/IEvDbStreamStoreData";
8
+ import IEvDbEventPayload from "@eventualize/types/IEvDbEventPayload";
9
+ import StreamStoreAffected from "@eventualize/types/StreamStoreAffected";
10
+ import IEvDbEventMetadata from "@eventualize/types/IEvDbEventMetadata";
11
+ import { EvDbStreamType } from "@eventualize/types/primitiveTypes";
12
+ import EVDbMessagesProducer from "@eventualize/types/EvDbMessagesProducer";
13
+ import { EvDbView } from "./EvDbView.js";
14
+ type ImmutableIEvDbView = Readonly<EvDbView<unknown>>;
15
+ export type ImmutableIEvDbViewMap = Readonly<Record<string, ImmutableIEvDbView>>;
16
+ export default class EvDbStream implements IEvDbStreamStore, IEvDbStreamStoreData {
17
+ protected messagesProducer: EVDbMessagesProducer;
18
+ protected _pendingEvents: ReadonlyArray<EvDbEvent>;
19
+ protected _pendingMessages: ReadonlyArray<EvDbMessage>;
20
+ private static readonly ASSEMBLY_NAME;
21
+ private static readonly DEFAULT_CAPTURE_BY;
22
+ private readonly _storageAdapter;
23
+ protected readonly _views: ImmutableIEvDbViewMap;
24
+ getViews(): ImmutableIEvDbViewMap;
25
+ getView(viewName: string): Readonly<IEvDbView> | undefined;
26
+ /**
27
+ * Unspecialized events
28
+ */
29
+ getEvents(): ReadonlyArray<EvDbEvent>;
30
+ streamAddress: EvDbStreamAddress;
31
+ storedOffset: number;
32
+ constructor(streamType: EvDbStreamType, views: ImmutableIEvDbView[], storageAdapter: IEvDbStorageStreamAdapter, streamId: string, lastStoredOffset: number, messagesProducer: EVDbMessagesProducer);
33
+ protected appendEvent(payload: IEvDbEventPayload, capturedBy?: string | null): IEvDbEventMetadata;
34
+ private getNextCursor;
35
+ /**
36
+ * Put a row into the publication (out-box pattern).
37
+ */
38
+ appendToOutbox(e: EvDbMessage): void;
39
+ store(): Promise<StreamStoreAffected>;
40
+ /**
41
+ * number of events that were not stored yet.
42
+ */
43
+ get countOfPendingEvents(): number;
44
+ /**
45
+ * Unspecialized messages
46
+ */
47
+ getMessages(): ReadonlyArray<EvDbMessage>;
48
+ }
49
+ export {};
@@ -0,0 +1,115 @@
1
+ import EvDbEvent from "@eventualize/types/EvDbEvent";
2
+ import EvDbStreamAddress from "@eventualize/types/EvDbStreamAddress";
3
+ import StreamStoreAffected from "@eventualize/types/StreamStoreAffected";
4
+ import EvDbStreamCursor from "@eventualize/types/EvDbStreamCursor";
5
+ import OCCException from "@eventualize/types/OCCException";
6
+ class EvDbStream {
7
+ getViews() {
8
+ return this._views;
9
+ }
10
+ getView(viewName) {
11
+ return this._views[viewName];
12
+ }
13
+ // Events
14
+ /**
15
+ * Unspecialized events
16
+ */
17
+ getEvents() {
18
+ return this._pendingEvents;
19
+ }
20
+ // Constructor
21
+ constructor(streamType, views, storageAdapter, streamId, lastStoredOffset, messagesProducer) {
22
+ this.messagesProducer = messagesProducer;
23
+ this._pendingEvents = [];
24
+ this._pendingMessages = [];
25
+ this._views = views.reduce((acc, view) => {
26
+ const viewName = view.address.viewName;
27
+ acc[viewName] = view;
28
+ return acc;
29
+ }, {});
30
+ this._storageAdapter = storageAdapter;
31
+ this.streamAddress = new EvDbStreamAddress(streamType, streamId);
32
+ this.storedOffset = lastStoredOffset;
33
+ }
34
+ appendEvent(payload, capturedBy) {
35
+ capturedBy = capturedBy ?? EvDbStream.DEFAULT_CAPTURE_BY;
36
+ // const json = JSON.stringify(payload); // Or use custom serializer
37
+ const cursor = this.getNextCursor(this._pendingEvents);
38
+ const e = new EvDbEvent(payload.payloadType, cursor, payload, new Date(), capturedBy);
39
+ this._pendingEvents = [...this._pendingEvents, e];
40
+ // Apply to views
41
+ for (const view of Object.values(this._views)) {
42
+ view.applyEvent(e);
43
+ }
44
+ // Outbox producer
45
+ const viewsStates = Object.fromEntries(Object.entries(this._views)
46
+ .map(([k, v]) => {
47
+ return [k, v.state];
48
+ }));
49
+ const producedMessages = this.messagesProducer(e, viewsStates);
50
+ this._pendingMessages = [...this._pendingMessages, ...producedMessages];
51
+ return e;
52
+ }
53
+ getNextCursor(events) {
54
+ if (events.length === 0) {
55
+ return new EvDbStreamCursor(this.streamAddress, this.storedOffset + 1);
56
+ }
57
+ const lastEvent = events[events.length - 1];
58
+ const offset = lastEvent.streamCursor.offset;
59
+ return new EvDbStreamCursor(this.streamAddress, offset + 1);
60
+ }
61
+ // AppendToOutbox
62
+ /**
63
+ * Put a row into the publication (out-box pattern).
64
+ */
65
+ appendToOutbox(e) {
66
+ this._pendingMessages = [...this._pendingMessages, e];
67
+ }
68
+ // StoreAsync
69
+ async store() {
70
+ // Telemetry
71
+ // const tags = this.streamAddress.toOtelTags();
72
+ // const duration = EvDbStream._sysMeters.measureStoreEventsDuration(tags);
73
+ // const activity = EvDbStream._trace.startActivity(tags, 'EvDb.Store');
74
+ try {
75
+ if (this._pendingEvents.length === 0) {
76
+ return StreamStoreAffected.Empty;
77
+ }
78
+ const affected = await this._storageAdapter.storeStreamAsync(this._pendingEvents, this._pendingMessages);
79
+ const lastEvent = this._pendingEvents[this._pendingEvents.length - 1];
80
+ this.storedOffset = lastEvent.streamCursor.offset;
81
+ this._pendingEvents = [];
82
+ this._pendingMessages = [];
83
+ const viewSaveTasks = Object.values(this._views).map(v => v.store());
84
+ await Promise.all(viewSaveTasks);
85
+ return affected;
86
+ }
87
+ catch (error) {
88
+ if (error instanceof OCCException) {
89
+ throw error;
90
+ }
91
+ throw error;
92
+ }
93
+ }
94
+ // CountOfPendingEvents
95
+ /**
96
+ * number of events that were not stored yet.
97
+ */
98
+ get countOfPendingEvents() {
99
+ return this._pendingEvents.length;
100
+ }
101
+ // Notifications
102
+ /**
103
+ * Unspecialized messages
104
+ */
105
+ getMessages() {
106
+ return this._pendingMessages;
107
+ }
108
+ }
109
+ EvDbStream.ASSEMBLY_NAME = {
110
+ name: 'evdb-core',
111
+ version: '1.0.0'
112
+ };
113
+ EvDbStream.DEFAULT_CAPTURE_BY = `${EvDbStream.ASSEMBLY_NAME.name}-${EvDbStream.ASSEMBLY_NAME.version}`;
114
+ export default EvDbStream;
115
+ //# sourceMappingURL=EvDbStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvDbStream.js","sourceRoot":"","sources":["../src/EvDbStream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ import IEvDbStorageSnapshotAdapter from '@eventualize/types/IEvDbStorageSnapshotAdapter';
2
+ import IEvDbStorageStreamAdapter from '@eventualize/types/IEvDbStorageStreamAdapter';
3
+ import IEvDbEventPayload from "@eventualize/types/IEvDbEventPayload";
4
+ import EVDbMessagesProducer from '@eventualize/types/EvDbMessagesProducer';
5
+ import EvDbStream from './EvDbStream.js';
6
+ import { EvDbView } from './EvDbView.js';
7
+ import { ViewFactory, EvDbStreamEventHandlersMap } from './EvDbViewFactory.js';
8
+ /**
9
+ * Configuration for creating a stream factory
10
+ */
11
+ export interface EvDbStreamFactoryConfig<TEvents extends IEvDbEventPayload, TStreamType extends string> {
12
+ streamType: TStreamType;
13
+ viewFactories: ViewFactory<any, TEvents>[];
14
+ eventTypes: EventTypeConfig<TEvents>[];
15
+ viewNames: string[];
16
+ }
17
+ /**
18
+ * Configuration for each event type
19
+ */
20
+ export interface EventTypeConfig<TEvent extends IEvDbEventPayload> {
21
+ eventClass: new (...args: any[]) => TEvent;
22
+ eventName: string;
23
+ eventMessagesProducer?: EVDbMessagesProducer;
24
+ }
25
+ /**
26
+ * Type helper to extract event methods
27
+ */
28
+ type EventMethods<TEvents extends IEvDbEventPayload> = {
29
+ [K in TEvents as `appendEvent${K['payloadType']}`]: (event: K) => Promise<void>;
30
+ };
31
+ /**
32
+ * Type helper to create view accessors map
33
+ */
34
+ type ViewAccessors<TViews extends Record<string, EvDbView<any>>> = {
35
+ readonly views: TViews;
36
+ };
37
+ /**
38
+ * Combined stream type with event methods and view accessors
39
+ */
40
+ export type StreamWithEventMethods<TEvents extends IEvDbEventPayload, TViews extends Record<string, EvDbView<any>> = {}> = EvDbStream & EventMethods<TEvents> & ViewAccessors<TViews>;
41
+ /**
42
+ * Stream Factory - creates stream instances with configured views and dynamic event methods
43
+ */
44
+ export declare class EvDbStreamFactory<TEvents extends IEvDbEventPayload, TStreamType extends string, TViews extends Record<string, EvDbView<any>> = {}> {
45
+ private readonly config;
46
+ private DynamicStreamClass;
47
+ constructor(config: EvDbStreamFactoryConfig<TEvents, TStreamType>);
48
+ /**
49
+ * Creates a dynamic stream class with event-specific methods and view accessors
50
+ */
51
+ private createDynamicStreamClass;
52
+ /**
53
+ * Creates a stream instance with all configured views and dynamic event methods
54
+ */
55
+ create(streamId: string, streamStorageAdapter: IEvDbStorageStreamAdapter, snapshotStorageAdapter: IEvDbStorageSnapshotAdapter, lastStreamOffset?: number): StreamWithEventMethods<TEvents, TViews>;
56
+ private createViews;
57
+ private getViews;
58
+ /**
59
+ * Fetches from storage a stream instance with all configured views and dynamic event methods
60
+ */
61
+ get(streamId: string, streamStorageAdapter: IEvDbStorageStreamAdapter, snapshotStorageAdapter: IEvDbStorageSnapshotAdapter): Promise<StreamWithEventMethods<TEvents, TViews>>;
62
+ getStreamType(): TStreamType;
63
+ }
64
+ /**
65
+ * Factory function to create a StreamFactory
66
+ */
67
+ export declare function createEvDbStreamFactory<TEvents extends IEvDbEventPayload, TStreamType extends string, TViews extends Record<string, EvDbView<any>> = {}>(config: EvDbStreamFactoryConfig<TEvents, TStreamType>): EvDbStreamFactory<TEvents, TStreamType, TViews>;
68
+ /**
69
+ * Fluent builder for creating stream factories with inferred event types
70
+ */
71
+ export declare class StreamFactoryBuilder<TStreamType extends string, TEvents extends IEvDbEventPayload = never, TViews extends Record<string, EvDbView<any>> = {}> {
72
+ private streamType;
73
+ private viewFactories;
74
+ private eventTypes;
75
+ private viewNames;
76
+ constructor(streamType: TStreamType);
77
+ /**
78
+ * Register event type for dynamic method generation - infers the event name from class name
79
+ */
80
+ withEventType<TEvent extends IEvDbEventPayload>(eventClass: new (...args: any[]) => TEvent, eventMessagesProducer?: EVDbMessagesProducer): StreamFactoryBuilder<TStreamType, TEvents | TEvent, TViews>;
81
+ /**
82
+ * Add a view with inline handler definition
83
+ * This can only be called AFTER withEventType calls to ensure type safety
84
+ */
85
+ withView<TViewName extends string, TState>(viewName: TViewName, stateClass: new (...args: any[]) => TState, handlers: EvDbStreamEventHandlersMap<TState, TEvents>): StreamFactoryBuilder<TStreamType, TEvents, TViews & Record<TViewName, EvDbView<TState>>>;
86
+ /**
87
+ * Add a pre-created view factory (legacy support)
88
+ */
89
+ withViewFactory<TViewName extends string, TState>(viewName: TViewName, viewFactory: ViewFactory<TState, TEvents>): StreamFactoryBuilder<TStreamType, TEvents, TViews & Record<TViewName, EvDbView<TState>>>;
90
+ /**
91
+ * Build the stream factory
92
+ */
93
+ build(): EvDbStreamFactory<TEvents, TStreamType, TViews> & {
94
+ StreamType: StreamWithEventMethods<TEvents, TViews>;
95
+ };
96
+ }
97
+ export {};