@arki/event-sourcing 0.1.0 → 0.1.2
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.
- package/dist/dot.d.ts +14 -8
- package/dist/dot.d.ts.map +1 -1
- package/dist/dot.js +29 -7
- package/dist/dot.js.map +1 -1
- package/package.json +10 -4
- package/src/builders/command-handler.ts +77 -0
- package/src/builders/command.ts +72 -0
- package/src/builders/decider.ts +288 -0
- package/src/builders/event.ts +68 -0
- package/src/builders/index.ts +40 -0
- package/src/builders/process-manager.ts +153 -0
- package/src/builders/projection.ts +151 -0
- package/src/builders/stateful-process-manager.ts +338 -0
- package/src/bus.ts +3 -0
- package/src/command-flow.ts +491 -0
- package/src/command.ts +52 -0
- package/src/debug.ts +36 -0
- package/src/decide.ts +10 -0
- package/src/dot.ts +161 -0
- package/src/error.ts +1 -0
- package/src/event-sourcing-features.ts +215 -0
- package/src/event.ts +46 -0
- package/src/index.ts +10 -0
- package/src/process-manager.ts +335 -0
- package/src/simple-process-manager.ts +70 -0
- package/src/store.ts +367 -0
- package/src/types.ts +9 -0
- package/dist/package.json +0 -5
package/src/dot.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOT adapter for `@arki/event-sourcing`.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `eventSourcingFeatures.initEventSourcing` + `initMessageBus` as a
|
|
5
|
+
* single `DotPip`. The pip opens the PostgreSQL event store in
|
|
6
|
+
* `boot`, attaches command handlers to an in-memory message bus, publishes
|
|
7
|
+
* both as `services.eventStore` and `services.messageBus`, and closes the
|
|
8
|
+
* event store pool in `dispose` (reverse-topological order).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { defineApp } from '@arki/dot';
|
|
13
|
+
* import { eventSourcing } from '@arki/event-sourcing/dot';
|
|
14
|
+
*
|
|
15
|
+
* const app = await defineApp('my-app')
|
|
16
|
+
* .use(eventSourcing({
|
|
17
|
+
* projections: [orderProjection, invoiceProjection],
|
|
18
|
+
* commandHandlers: [placeOrderHandler, cancelOrderHandler],
|
|
19
|
+
* }))
|
|
20
|
+
* .boot();
|
|
21
|
+
*
|
|
22
|
+
* await app.services.messageBus.send({ type: 'PlaceOrder', payload: { ... } });
|
|
23
|
+
* await app.dispose();
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* The connection URL is resolved in this order:
|
|
27
|
+
* 1. `options.dbUrl` if provided
|
|
28
|
+
* 2. `process.env.EVENT_STORE_URL`
|
|
29
|
+
* 3. `process.env.EVENTSTORE_URL`
|
|
30
|
+
* 4. `process.env.EVENT_DB_URL`
|
|
31
|
+
*
|
|
32
|
+
* If none are set, `boot` throws with a message naming every accepted env
|
|
33
|
+
* var — same contract as `eventSourcingFeatures.initEventSourcing`.
|
|
34
|
+
*
|
|
35
|
+
* The `@arki/dot` package is an OPTIONAL peer of `@arki/event-sourcing`.
|
|
36
|
+
* Importing this adapter without `@arki/dot` installed will fail at module
|
|
37
|
+
* load — that is intentional: the adapter only makes sense in a DOT app.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import type { EventStore, MessageBus } from '@event-driven-io/emmett';
|
|
41
|
+
|
|
42
|
+
import type { EmptyShape, Pip } from '@arki/dot/pip';
|
|
43
|
+
import { pip, DotPipError } from '@arki/dot/pip';
|
|
44
|
+
|
|
45
|
+
import type { CommandHandlerRegistration } from './command.js';
|
|
46
|
+
import type { PostgreSQLProjectionInput } from './event-sourcing-features.js';
|
|
47
|
+
import { EVENT_STORE_URL_VARIANTS, eventSourcingFeatures } from './event-sourcing-features.js';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Stable error codes thrown by the event-sourcing pip. Exported so consumers
|
|
51
|
+
* and coding agents can match against them — never parse the message.
|
|
52
|
+
*
|
|
53
|
+
* @see packages/dot/docs/principles.md — principle 1.3 ("errors are part
|
|
54
|
+
* of the API") and principle 4 ("agent-discoverable everywhere").
|
|
55
|
+
*/
|
|
56
|
+
export const EVENT_SOURCING_PIP_ERROR_CODES = {
|
|
57
|
+
/** boot was called without a configured event-store URL. */
|
|
58
|
+
dbUrlNotConfigured: 'EVENT_SOURCING_PIP_E001',
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Options for the event-sourcing DOT adapter.
|
|
63
|
+
*/
|
|
64
|
+
export type EventSourcingDotOptions = {
|
|
65
|
+
/**
|
|
66
|
+
* PostgreSQL projection definitions registered inline on the event store.
|
|
67
|
+
* Accepts the three projection builder patterns documented on
|
|
68
|
+
* {@link PostgreSQLProjectionInput}.
|
|
69
|
+
*/
|
|
70
|
+
readonly projections: readonly PostgreSQLProjectionInput[];
|
|
71
|
+
/**
|
|
72
|
+
* Command handlers wired into the in-memory message bus. Each handler's
|
|
73
|
+
* `getStreamName` callback maps an incoming command to its target stream.
|
|
74
|
+
*
|
|
75
|
+
* Defaults to `[]` — useful when an app only does projections / event
|
|
76
|
+
* appends without command-side dispatch.
|
|
77
|
+
*/
|
|
78
|
+
readonly commandHandlers?: readonly CommandHandlerRegistration[];
|
|
79
|
+
/**
|
|
80
|
+
* Connection URL for the event store. When omitted, the pip reads
|
|
81
|
+
* `EVENT_STORE_URL`, `EVENTSTORE_URL`, or `EVENT_DB_URL` from
|
|
82
|
+
* `process.env`. If none are set, `boot` throws.
|
|
83
|
+
*/
|
|
84
|
+
readonly dbUrl?: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** Services published by the event-sourcing adapter. */
|
|
88
|
+
export type EventSourcingServices = {
|
|
89
|
+
/** The Emmett event store handle, ready to load/append streams. */
|
|
90
|
+
readonly eventStore: EventStore;
|
|
91
|
+
/**
|
|
92
|
+
* The in-memory message bus. Already has the configured command handlers
|
|
93
|
+
* attached — call `messageBus.send(command)` to dispatch.
|
|
94
|
+
*/
|
|
95
|
+
readonly messageBus: MessageBus;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Resolve the event-store connection URL from explicit options first, then
|
|
100
|
+
* from the recognised env vars in priority order. Returns `undefined` when
|
|
101
|
+
* none are set so the underlying factory can throw the canonical error.
|
|
102
|
+
*/
|
|
103
|
+
function resolveDbUrl(explicit: string | undefined): string | undefined {
|
|
104
|
+
if (explicit !== undefined && explicit !== '') return explicit;
|
|
105
|
+
for (const name of EVENT_STORE_URL_VARIANTS) {
|
|
106
|
+
const value = process.env[name];
|
|
107
|
+
if (value !== undefined && value !== '') return value;
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Build a DOT pip that opens the event store, wires command handlers
|
|
114
|
+
* into an in-memory message bus, and publishes both as services. The
|
|
115
|
+
* kernel calls `dispose` in reverse declaration order to release the
|
|
116
|
+
* underlying PG pool.
|
|
117
|
+
*/
|
|
118
|
+
export function eventSourcing(options: EventSourcingDotOptions): Pip<EmptyShape, EventSourcingServices> {
|
|
119
|
+
const commandHandlers = options.commandHandlers ?? [];
|
|
120
|
+
|
|
121
|
+
// Captured at boot so dispose can call it without re-reading services
|
|
122
|
+
// (dispose is allowed to run even when services failed to publish).
|
|
123
|
+
let closeStore: (() => Promise<void>) | undefined;
|
|
124
|
+
|
|
125
|
+
return pip({
|
|
126
|
+
name: 'event-sourcing',
|
|
127
|
+
version: '0.1.0',
|
|
128
|
+
configure(ctx) {
|
|
129
|
+
ctx.registerService('eventStore', 'event-store');
|
|
130
|
+
ctx.registerService('messageBus', 'message-bus');
|
|
131
|
+
ctx.declareProvides('event-store', 'message-bus');
|
|
132
|
+
},
|
|
133
|
+
boot(): EventSourcingServices {
|
|
134
|
+
// Validate at the pip boundary so the DOT lifecycle gets a coded
|
|
135
|
+
// error. `eventSourcingFeatures.initEventSourcing` still throws raw
|
|
136
|
+
// `Error` for non-DOT consumers (its public contract is unchanged);
|
|
137
|
+
// the check here makes sure we never reach it without a URL.
|
|
138
|
+
const dbUrl = resolveDbUrl(options.dbUrl);
|
|
139
|
+
if (dbUrl === undefined) {
|
|
140
|
+
throw new DotPipError({
|
|
141
|
+
code: EVENT_SOURCING_PIP_ERROR_CODES.dbUrlNotConfigured,
|
|
142
|
+
message: '[event-sourcing] Event Store database URL is not configured.',
|
|
143
|
+
remediation: `Pass options.dbUrl to eventSourcing(...) or set one of ${EVENT_STORE_URL_VARIANTS.join(
|
|
144
|
+
', ',
|
|
145
|
+
)} in the environment before booting the app.`,
|
|
146
|
+
docsUrl: 'https://arki.dev/dot/errors/event-sourcing-pip-e001',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const { eventStore, close } = eventSourcingFeatures.initEventSourcing(options.projections, dbUrl);
|
|
150
|
+
closeStore = close;
|
|
151
|
+
const messageBus = eventSourcingFeatures.initMessageBus(eventStore, [...commandHandlers]);
|
|
152
|
+
return { eventStore, messageBus };
|
|
153
|
+
},
|
|
154
|
+
async dispose() {
|
|
155
|
+
if (closeStore !== undefined) {
|
|
156
|
+
await closeStore();
|
|
157
|
+
closeStore = undefined;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
package/src/error.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EmmettError, IllegalStateError } from '@event-driven-io/emmett';
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Event,
|
|
3
|
+
EventStore,
|
|
4
|
+
MessageBus,
|
|
5
|
+
MessageProcessor,
|
|
6
|
+
ProjectionDefinition,
|
|
7
|
+
} from '@event-driven-io/emmett';
|
|
8
|
+
import { getInMemoryMessageBus } from '@event-driven-io/emmett';
|
|
9
|
+
|
|
10
|
+
import type { CommandHandler } from './builders/command-handler.js';
|
|
11
|
+
import type { CommandHandlerRegistration } from './command.js';
|
|
12
|
+
import { debugCommand, debugStore } from './debug.js';
|
|
13
|
+
import type {
|
|
14
|
+
PostgresEventStore,
|
|
15
|
+
PostgreSQLProjectionHandlerContext,
|
|
16
|
+
PostgresReadEventMetadata,
|
|
17
|
+
} from './store.js';
|
|
18
|
+
import { getEventStore, projections } from './store.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Structural interface for projection definitions accepted by
|
|
22
|
+
* {@link initEventSourcing}.
|
|
23
|
+
*
|
|
24
|
+
* Uses method syntax for `handle` to enable TypeScript's bivariant parameter
|
|
25
|
+
* checking, which allows heterogeneous projection arrays where each projection
|
|
26
|
+
* is parametrised on a different event type.
|
|
27
|
+
*
|
|
28
|
+
* Accepts projections produced by three different builder patterns:
|
|
29
|
+
* 1. Emmett's `postgreSQLProjection` / `PostgreSQLProjectionDefinition<E>`.
|
|
30
|
+
* 2. The `defineProjection` builder from this package.
|
|
31
|
+
* 3. The `@arki/db` builder `projection.named().on().handle()`.
|
|
32
|
+
*/
|
|
33
|
+
export type PostgreSQLProjectionInput = {
|
|
34
|
+
name?: string;
|
|
35
|
+
canHandle: string[];
|
|
36
|
+
handle(events: Event[], context: object): void;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** Alternative names for the Event Store connection URL environment variable. */
|
|
40
|
+
export const EVENT_STORE_URL_VARIANTS = ['EVENT_STORE_URL', 'EVENTSTORE_URL', 'EVENT_DB_URL'];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Event sourcing wiring helpers.
|
|
44
|
+
*
|
|
45
|
+
* Bundles the three most common bootstrap operations into a single namespace:
|
|
46
|
+
*
|
|
47
|
+
* - {@link eventSourcingFeatures.initEventSourcing} — open the PostgreSQL
|
|
48
|
+
* event store with a set of inline projections, returning a `close()`
|
|
49
|
+
* function for graceful shutdown.
|
|
50
|
+
* - {@link eventSourcingFeatures.initMessageBus} — create an in-memory
|
|
51
|
+
* message bus and register a list of command handler descriptors against it.
|
|
52
|
+
* - {@link eventSourcingFeatures.setupProcessManagers} — attach process
|
|
53
|
+
* manager consumers to the event store, start them, and wire SIGTERM-driven
|
|
54
|
+
* graceful shutdown.
|
|
55
|
+
*
|
|
56
|
+
* The helpers are intentionally framework-agnostic: any composition root
|
|
57
|
+
* (DI container, plugin, plain `bus.ts` factory function) can call them.
|
|
58
|
+
*/
|
|
59
|
+
export const eventSourcingFeatures = {
|
|
60
|
+
/**
|
|
61
|
+
* Initialises the PostgreSQL event store with the given inline projections.
|
|
62
|
+
*
|
|
63
|
+
* @param p Projections to register inline on the event store.
|
|
64
|
+
* @param dbUrl Connection string for the event store. When omitted, an
|
|
65
|
+
* error is thrown that names the recognised environment variables.
|
|
66
|
+
* @returns The event store handle plus a `close()` function that releases
|
|
67
|
+
* the underlying connection pool.
|
|
68
|
+
*/
|
|
69
|
+
initEventSourcing(p: readonly PostgreSQLProjectionInput[], dbUrl?: string) {
|
|
70
|
+
if (!dbUrl) {
|
|
71
|
+
debugStore(
|
|
72
|
+
'[eventSourcingFeatures] Event Store URL not found. Required environment variables: %s',
|
|
73
|
+
EVENT_STORE_URL_VARIANTS.join(', '),
|
|
74
|
+
);
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Event Store database URL is not defined. Please set one of the following environment variables: ${EVENT_STORE_URL_VARIANTS.join(
|
|
77
|
+
', ',
|
|
78
|
+
)}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
debugStore('[eventSourcingFeatures] Initializing Event Store with %d projection(s)', p.length);
|
|
82
|
+
const { eventStore, close } = getEventStore(dbUrl, {
|
|
83
|
+
projections: projections.inline(
|
|
84
|
+
p as ProjectionDefinition<Event, PostgresReadEventMetadata, PostgreSQLProjectionHandlerContext>[],
|
|
85
|
+
),
|
|
86
|
+
});
|
|
87
|
+
debugStore('[eventSourcingFeatures] Event Store initialized successfully');
|
|
88
|
+
return { eventStore, close };
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Creates an in-memory message bus and registers a list of command handlers.
|
|
93
|
+
*
|
|
94
|
+
* Each registration is bound to the event store so command handlers can
|
|
95
|
+
* load and append to streams. If the event store is missing, a warning is
|
|
96
|
+
* logged and an empty bus is returned.
|
|
97
|
+
*
|
|
98
|
+
* @param eventStore Event store used to load and append streams.
|
|
99
|
+
* @param commandHandlers Command handler descriptors to register.
|
|
100
|
+
* @returns A message bus with handlers attached.
|
|
101
|
+
*/
|
|
102
|
+
initMessageBus(eventStore: EventStore | undefined, commandHandlers: CommandHandlerRegistration[]): MessageBus {
|
|
103
|
+
debugCommand(
|
|
104
|
+
'[eventSourcingFeatures] Initializing Message Bus with %d command handler(s)',
|
|
105
|
+
commandHandlers.length,
|
|
106
|
+
);
|
|
107
|
+
const messageBus = getInMemoryMessageBus();
|
|
108
|
+
|
|
109
|
+
if (!eventStore) {
|
|
110
|
+
if (commandHandlers.length > 0) {
|
|
111
|
+
debugCommand(
|
|
112
|
+
'[eventSourcingFeatures] Warning: %d command handler(s) configured but Event Store not initialized',
|
|
113
|
+
commandHandlers.length,
|
|
114
|
+
);
|
|
115
|
+
console.warn('Command handlers were configured, but the Event Store is not initialized. Commands may fail.');
|
|
116
|
+
} else {
|
|
117
|
+
debugCommand(
|
|
118
|
+
'[eventSourcingFeatures] No Event Store and no command handlers - returning empty Message Bus',
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return messageBus;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (commandHandlers.length > 0) {
|
|
125
|
+
const createCommandHandlerWrapper = <C extends { type: string }, State, StreamEvent extends Event>(
|
|
126
|
+
handler: CommandHandler<State, C, StreamEvent>,
|
|
127
|
+
getStreamNameFn: (cmd: C) => string,
|
|
128
|
+
) => {
|
|
129
|
+
return async (command: C) => {
|
|
130
|
+
const streamName = getStreamNameFn(command);
|
|
131
|
+
debugCommand('[MessageBus] Executing command handler for %s on stream: %s', command.type, streamName);
|
|
132
|
+
try {
|
|
133
|
+
if (typeof handler === 'function') {
|
|
134
|
+
await handler(eventStore, streamName, command);
|
|
135
|
+
debugCommand('[MessageBus] Command handler for %s completed successfully', command.type);
|
|
136
|
+
} else {
|
|
137
|
+
debugCommand('[MessageBus] Invalid handler type for command: %s', command.type);
|
|
138
|
+
console.error(`Invalid handler type encountered for command: ${command.type}`);
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
debugCommand(
|
|
142
|
+
'[MessageBus] Error executing command handler for %s on stream %s: %s',
|
|
143
|
+
command.type,
|
|
144
|
+
streamName,
|
|
145
|
+
error instanceof Error ? error.message : String(error),
|
|
146
|
+
);
|
|
147
|
+
console.error(`Error executing command handler for ${command.type} on stream ${streamName}:`, error);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
for (const config of commandHandlers) {
|
|
154
|
+
debugCommand('[eventSourcingFeatures] Registering command handler for type: %s', config.commandType);
|
|
155
|
+
// Type erasure boundary: registrations are stored with C=never so
|
|
156
|
+
// arrays of differently-typed handlers compose. We cast back to
|
|
157
|
+
// callable types for the runtime dispatch wrapper.
|
|
158
|
+
type Cmd = { type: string };
|
|
159
|
+
const handler = config.handler as CommandHandler<unknown, Cmd, Event>;
|
|
160
|
+
const getStreamName = config.getStreamName as (cmd: Cmd) => string;
|
|
161
|
+
messageBus.handle(createCommandHandlerWrapper(handler, getStreamName), config.commandType);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
debugCommand(
|
|
165
|
+
'[eventSourcingFeatures] Message Bus initialized with %d command handler(s)',
|
|
166
|
+
commandHandlers.length,
|
|
167
|
+
);
|
|
168
|
+
} else {
|
|
169
|
+
debugCommand('[eventSourcingFeatures] No command handlers to register');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return messageBus;
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Attaches process managers as event store consumers, starts them, and
|
|
177
|
+
* wires SIGTERM-driven shutdown of the resulting consumers.
|
|
178
|
+
*
|
|
179
|
+
* @param eventStore Event store the process managers consume from.
|
|
180
|
+
* @param processManagers Process manager `MessageProcessor` instances to
|
|
181
|
+
* register, typically produced by {@link createProcessManager},
|
|
182
|
+
* {@link createStatefulProcessManager}, or
|
|
183
|
+
* `createSimpleProcessManager`.
|
|
184
|
+
* @returns The started consumer handles. Useful for tests that need to
|
|
185
|
+
* stop them explicitly.
|
|
186
|
+
*/
|
|
187
|
+
async setupProcessManagers(eventStore: PostgresEventStore, processManagers: MessageProcessor[]) {
|
|
188
|
+
debugStore('[eventSourcingFeatures] Setting up %d process manager(s)', processManagers.length);
|
|
189
|
+
const processManagerConsumers = processManagers.map(pm => {
|
|
190
|
+
debugStore('[eventSourcingFeatures] Creating consumer for process manager: %s', pm.id);
|
|
191
|
+
return eventStore.consumer({
|
|
192
|
+
consumerId: pm.id,
|
|
193
|
+
processors: [pm],
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
debugStore(
|
|
198
|
+
'[eventSourcingFeatures] Starting %d process manager consumer(s)',
|
|
199
|
+
processManagerConsumers.length,
|
|
200
|
+
);
|
|
201
|
+
await Promise.all(processManagerConsumers.map(consumer => consumer.start()));
|
|
202
|
+
debugStore('[eventSourcingFeatures] All process manager consumers started successfully');
|
|
203
|
+
|
|
204
|
+
process.on('SIGTERM', async () => {
|
|
205
|
+
debugStore('[eventSourcingFeatures] SIGTERM received, stopping process managers');
|
|
206
|
+
await Promise.all(processManagerConsumers.map(consumer => consumer.stop()));
|
|
207
|
+
debugStore('[eventSourcingFeatures] All process managers stopped, closing consumers');
|
|
208
|
+
await Promise.all(processManagerConsumers.map(consumer => consumer.close()));
|
|
209
|
+
debugStore('[eventSourcingFeatures] All consumers closed, exiting');
|
|
210
|
+
process.exit(0);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return processManagerConsumers;
|
|
214
|
+
},
|
|
215
|
+
};
|
package/src/event.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DefaultRecord } from './types.js';
|
|
2
|
+
|
|
3
|
+
export type {
|
|
4
|
+
EventsPublisher,
|
|
5
|
+
EventStore,
|
|
6
|
+
ReadEvent,
|
|
7
|
+
ReadEventMetadataWithGlobalPosition,
|
|
8
|
+
} from '@event-driven-io/emmett';
|
|
9
|
+
|
|
10
|
+
export type Event<
|
|
11
|
+
EventType extends string = string,
|
|
12
|
+
EventData extends DefaultRecord = DefaultRecord,
|
|
13
|
+
EventMetaData extends DefaultRecord | undefined = undefined,
|
|
14
|
+
> = Readonly<{
|
|
15
|
+
type: EventType;
|
|
16
|
+
data: EventData;
|
|
17
|
+
metadata?: EventMetaData;
|
|
18
|
+
kind?: 'Event';
|
|
19
|
+
}>;
|
|
20
|
+
|
|
21
|
+
export type AnyEvent = Event<any, any, any>;
|
|
22
|
+
export type EventTypeOf<T extends Event> = T['type'];
|
|
23
|
+
export type EventDataOf<T extends Event> = T['data'];
|
|
24
|
+
export type EventMetaDataOf<T extends Event> = T extends {
|
|
25
|
+
metadata: infer M;
|
|
26
|
+
}
|
|
27
|
+
? M
|
|
28
|
+
: undefined;
|
|
29
|
+
export type CreateEventType<
|
|
30
|
+
EventType extends string,
|
|
31
|
+
EventData extends DefaultRecord,
|
|
32
|
+
EventMetaData extends DefaultRecord | undefined = undefined,
|
|
33
|
+
> = Readonly<
|
|
34
|
+
EventMetaData extends undefined
|
|
35
|
+
? {
|
|
36
|
+
type: EventType;
|
|
37
|
+
data: EventData;
|
|
38
|
+
}
|
|
39
|
+
: {
|
|
40
|
+
type: EventType;
|
|
41
|
+
data: EventData;
|
|
42
|
+
metadata: EventMetaData;
|
|
43
|
+
}
|
|
44
|
+
> & {
|
|
45
|
+
readonly kind?: 'Event';
|
|
46
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './command.js';
|
|
2
|
+
export * from './decide.js';
|
|
3
|
+
export * from './event.js';
|
|
4
|
+
export { createSimpleProcessManager } from './simple-process-manager.js';
|
|
5
|
+
export {
|
|
6
|
+
EVENT_STORE_URL_VARIANTS,
|
|
7
|
+
eventSourcingFeatures,
|
|
8
|
+
type PostgreSQLProjectionInput,
|
|
9
|
+
} from './event-sourcing-features.js';
|
|
10
|
+
export type { DefaultRecord } from './types.js';
|