feat: add peerDependencies

This commit is contained in:
2025-07-07 13:11:16 +02:00
parent 2093dd7097
commit dd1570d52e
36 changed files with 481 additions and 274 deletions

View File

@@ -77,9 +77,9 @@ Once we have defined our configs and printed our events we create a new event st
for `sqlite`, `postgres`, and `valkyr/db` which all works the same way. So for this example we will use the `sqlite`
store.
- Browser _(TODO)_
- Mongo _(TODO)_
- [Postgres](./adapters/postgres)
- Browser _(TODO)_
- Mongo _(TODO)_
- [Postgres](./adapters/postgres)
### Reducers
@@ -92,26 +92,33 @@ import { makeReducer } from "@valkyr/event-store";
import type { EventRecord } from "./generated/events.ts";
const reducer = makeReducer<{
name: string;
email: string;
}, EventRecord>((state, event) => {
switch (event.type) {
case "user:created": {
state.name = `${event.data.name.given} ${event.data.name.family}`;
state.email = event.data.email;
break;
const reducer = makeReducer<
{
name: string;
email: string;
},
EventRecord
>(
(state, event) => {
switch (event.type) {
case "user:created": {
state.name = `${event.data.name.given} ${event.data.name.family}`;
state.email = event.data.email;
break;
}
case "user:email-set": {
state.email = event.data.email;
break;
}
}
case "user:email-set": {
state.email = event.data.email;
break;
}
}
return state;
}, "user", () => ({
name: "",
email: "",
}));
return state;
},
"user",
() => ({
name: "",
email: "",
}),
);
```
### Aggreates
@@ -172,7 +179,7 @@ export class User extends AggregateRoot<EventRecord> {
type Name = {
given: string;
family: string;
}
};
```
### Projectors
@@ -194,14 +201,13 @@ projector.on("user:created", async (record) => {
### Hydration in Event Processing
When handling events in a distributed system or during event replay operations, it is important to differentiate between **new events** and **rehydrated events**.
When handling events in a distributed system or during event replay operations, it is important to differentiate between **new events** and **rehydrated events**.
- **New Events (`hydrate: false`)**: These events are being processed for the first time. They will trigger all projection handlers, including `.once()`, `.on()`, and `.all()`.
- **Rehydrated Events (`hydrate: true`)**: These events are being replayed, either as part of a stream synchronization, system recovery, or reprocessing in a distributed environment. They **will not trigger** `.once()` handlers to avoid redundant side effects but will still be processed by `.on()` and `.all()` handlers where applicable.
- **New Events (`hydrate: false`)**: These events are being processed for the first time. They will trigger all projection handlers, including `.once()`, `.on()`, and `.all()`.
- **Rehydrated Events (`hydrate: true`)**: These events are being replayed, either as part of a stream synchronization, system recovery, or reprocessing in a distributed environment. They **will not trigger** `.once()` handlers to avoid redundant side effects but will still be processed by `.on()` and `.all()` handlers where applicable.
This mechanism ensures that critical one-time operations (such as sending emails or initiating external API calls) are **not repeated** unnecessarily while still allowing stateful projections to update their read models correctly.
#### `.once("user:created", (event) => Promise<void>)`
This handler tells the projection that an event is only ever processed when the event is originating directly from the