Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/docs/1-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ After years of using it at [Theodo](https://dev.to/slsbytheodo), we have grown t

With Castore, you'll be able to:

- Define your [event stores](/docs/the-basics#eventstore)
- Fetch and push new [events](/docs/the-basics#events) seamlessly
- Implement and test your [commands](/docs/the-basics#command)
- Define your [event stores](./3-event-sourcing/3-event-stores.md)
- Fetch and push new [events](./3-event-sourcing/1-events.md) seamlessly
- Implement and test your [commands](./3-event-sourcing/5-pushing-events.md)
- ...and much more!

All that with first-class developer experience and minimal boilerplate ✨
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/3-event-sourcing/1-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const pokemonAppearedEventType = new EventType<

:::info

Note that we only provided TS types for `payload` and `metadata` properties. That is because, as stated in the [core design](/docs/introduction#-core-design), **Castore is meant to be as flexible as possible**, and that includes the validation library you want to use (if any): The `EventType` class can be used directly if no validation is required, or implemented by [other classes](../5-resources.md) which will add run-time validation methods to it πŸ‘
Note that we only provided TS types for `payload` and `metadata` properties. That is because, as stated in the [core design](../1-introduction.md#-core-design), **Castore is meant to be as flexible as possible**, and that includes the validation library you want to use (if any): The `EventType` class can be used directly if no validation is required, or implemented by [other classes](../5-packages.md#-event-types) which will add run-time validation methods to it πŸ‘

:::

Expand Down
20 changes: 10 additions & 10 deletions docs/docs/3-event-sourcing/3-event-stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_position: 3

# πŸ“™ Event Store

Once you've defined your [event types](#eventtype) and how to [aggregate](#reducer) them, you can bundle them together in an `EventStore` class. Each event store in your application represents a business entity.
Once you've defined your [event types](./1-events.md) and how to [aggregate](./2-aggregates-reducers.md) them, you can bundle them together in an `EventStore` class. Each event store in your application represents a business entity.

:::note

Expand All @@ -14,7 +14,7 @@ Think of event stores as _"what tables would be in CRUD"_, except that instead o

![Event Store](../../assets/docSchemas/eventStore.png)

In Castore, `EventStore` classes are NOT responsible for actually storing data (this will come with [event storage adapters](#eventstorageadapter)). But rather to provide a boilerplate-free and type-safe interface to perform many actions such as:
In Castore, `EventStore` classes are NOT responsible for actually storing data (this will come with [event storage adapters](./4-fetching-events.md)). But rather to provide a boilerplate-free and type-safe interface to perform many actions such as:

- Listing aggregate ids
- Accessing events of an aggregate
Expand All @@ -39,7 +39,7 @@ const pokemonsEventStore = new EventStore({

:::info

> ☝️ The `EventStore` class is the heart of Castore, it even gave it its name!
☝️ The `EventStore` class is the heart of Castore, it even gave it its name!

:::

Expand All @@ -51,9 +51,9 @@ const pokemonsEventStore = new EventStore({
>
> - <code>eventStoreId <i>(string)</i></code>: A string identifying the event store
> - <code>eventStoreEvents <i>(EventType[])</i></code>: The list of event types in the event store
> - <code>reduce <i>(EventType[])</i></code>: A <a href="#reducer">reducer function</a> that can be applied to the store event types
> - <code>reduce <i>(EventType[])</i></code>: A <a href="../aggregates-reducers">reducer function</a> that can be applied to the store event types
> - <code>onEventPushed <i>?(pushEventResponse: PushEventResponse => Promise(void))</i></code>: To run a callback after events are pushed (input is exactly the return value of the <code>pushEvent</code> method)
> - <code>storageAdapter <i>(?EventStorageAdapter)</i></code>: See <a href="#eventstorageadapter">EventStorageAdapter</a>
> - <code>storageAdapter <i>(?EventStorageAdapter)</i></code>: See <a href="../fetching-events">EventStorageAdapter</a>
>
> ☝️ The return type of the `reducer` is used to infer the `Aggregate` type of the `EventStore`, so it is important to type it explicitely.
>
Expand Down Expand Up @@ -87,7 +87,7 @@ const pokemonsEventStore = new EventStore({
> // => undefined (we did not provide one in this example)
> ```
>
> - <code>storageAdapter <i>?EventStorageAdapter</i></code>: See <a href="#eventstorageadapter">EventStorageAdapter</a>
> - <code>storageAdapter <i>?EventStorageAdapter</i></code>: See <a href="../fetching-events">EventStorageAdapter</a>
>
> ```ts
> const storageAdapter = pokemonsEventStore.storageAdapter;
Expand Down Expand Up @@ -115,11 +115,11 @@ const pokemonsEventStore = new EventStore({
> const myPikachuAggregate = pokemonsEventStore.buildAggregate(myPikachuEvents);
> ```
>
> - <code>groupEvent <i>((eventDetail: EventDetail, opt?: OptionsObj = {}) => GroupedEvent)</i></code>: See <a href="#event-groups">Event Groups</a>.
> - <code>groupEvent <i>((eventDetail: EventDetail, opt?: OptionsObj = {}) => GroupedEvent)</i></code>: See <a href="../joining-data">Event Groups</a>.
>
> **Async Methods:**
>
> The following methods interact with the data layer of your event store through its [`EventStorageAdapter`](#eventstorageadapter). They will throw an `UndefinedStorageAdapterError` if you did not provide one.
> The following methods interact with the data layer of your event store through its [`EventStorageAdapter`](./4-fetching-events.md). They will throw an `UndefinedStorageAdapterError` if you did not provide one.
>
> - <code>getEvents <i>((aggregateId: string, opt?: OptionsObj = {}) => Promise(ResponseObj))</i></code>: Retrieves the events of an aggregate, ordered by <code>version</code>. Returns an empty array if no event is found for this <code>aggregateId</code>.
>
Expand Down Expand Up @@ -208,13 +208,13 @@ const pokemonsEventStore = new EventStore({
>
> `OptionsObj` contains the following properties:
>
> - <code>prevAggregate <i>(?Aggregate)</i></code>: The aggregate at the current version, i.e. before having pushed the event. Can be useful in some cases like when using the <a href="/docs/advanced-usage#connectedeventstore">ConnectedEventStore class</a>
> - <code>prevAggregate <i>(?Aggregate)</i></code>: The aggregate at the current version, i.e. before having pushed the event. Can be useful in some cases like when using the <a href="../../reacting-to-events/connected-event-store">ConnectedEventStore class</a>
> - <code>force <i>(?boolean)</i></code>: To force push the event even if one already exists for the corresponding <code>aggregateId</code> and <code>version</code>. Any existing event will be overridden, so use with extra care, mainly in <a href="https://www.npmjs.com/package/@castore/dam">data migrations</a>.
>
> `ResponseObj` contains the following properties:
>
> - <code>event <i>(EventDetail)</i></code>: The complete event (includes the <code>timestamp</code>)
> - <code>nextAggregate <i>(?Aggregate)</i></code>: The aggregate at the new version, i.e. after having pushed the event. Returned only if the event is an initial event, if the <code>prevAggregate</code> option was provided, or when using a <a href="/docs/advanced-usage#connectedeventstore">ConnectedEventStore class</a> connected to a <a href="/docs/advanced-usage#event-driven-architecture">state-carrying message bus or queue</a>
> - <code>nextAggregate <i>(?Aggregate)</i></code>: The aggregate at the new version, i.e. after having pushed the event. Returned only if the event is an initial event, if the <code>prevAggregate</code> option was provided, or when using a <a href="../../reacting-to-events/connected-event-store">ConnectedEventStore class</a> connected to a <a href="../../reacting-to-events/messages">state-carrying message bus or queue</a>
>
> ```ts
> const { event: completeEvent, nextAggregate } =
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/3-event-sourcing/4-fetching-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ const pokemonsEventStore = new EventStore({
pokemonsEventStore.storageAdapter = mySuperStorageAdapter;

const { events } = await pokemonsEventStore.getEvents('pikachu1');
const { aggregate } = await pokemonsEventStore.getAggregate('pikachu1');
// πŸ™Œ Will work!
```

:::info

You can choose to build an event storage adapter that suits your usage. However, we highly recommend using an [off-the-shelf adapter](../5-resources.md) (if the storage solution that you use does not have an adapter yet, feel free to create/upvote an issue, or contribute πŸ€—).
You can choose to build an event storage adapter that suits your usage. However, we highly recommend using an [off-the-shelf adapter](../5-packages.md#-event-storage-adapters) (if the storage solution that you use does not have an adapter yet, feel free to create/upvote an issue, or contribute πŸ€—).

:::
4 changes: 2 additions & 2 deletions docs/docs/3-event-sourcing/5-pushing-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ const catchPokemonCommand = new Command({

:::info

Note that we only provided TS types for `Input` and `Output` properties. That is because, as stated in the [core design](/docs/introduction#-core-design), **Castore is meant to be as flexible as possible**, and that includes the validation library you want to use (if any): The `Command` class can be used directly if no validation is required, or implemented by [other classes](../5-resources.md) which will add run-time validation methods to it πŸ‘
Note that we only provided TS types for `Input` and `Output` properties. That is because, as stated in the [core design](../1-introduction.md#-core-design), **Castore is meant to be as flexible as possible**, and that includes the validation library you want to use (if any): The `Command` class can be used directly if no validation is required, or implemented by [other classes](../5-packages.md#-commands) which will add run-time validation methods to it πŸ‘

:::

`Commands` handlers should NOT use [read models](/docs/advanced-usage#read-models) when validating that a modification is acceptable. Read models are like cache: They are not the source of truth, and may not represent the freshest state.
`Commands` handlers should NOT use [read models](../4-reacting-to-events/6-read-models.md) when validating that a modification is acceptable. Read models are like cache: They are not the source of truth, and may not represent the freshest state.

Fetching and pushing events non-simultaneously exposes your application to [race conditions](https://en.wikipedia.org/wiki/Race_condition). To counter that, commands are designed to be retried when an `EventAlreadyExistsError` is triggered (which is part of the `EventStorageAdapter` interface).

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/4-reacting-to-events/1-messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@ type PokemonEventStateCarryingMessage = EventStoreStateCarryingMessage<
>;
```

All types of message can be published through message channels, i.e. [Message Queues](#messagequeue) or [Message Buses](#messagebus).
All types of message can be published through message channels, i.e. [Message Queues](./2-message-queues.md) or [Message Buses](./3-message-buses.md).
6 changes: 3 additions & 3 deletions docs/docs/4-reacting-to-events/2-message-queues.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ await messageQueue.publishMessage(...);

:::info

You can code your own `MessageQueueAdapter` (simply implement the `MessageChannelAdapter` interface), but we highly recommend using an [off-the-shelf adapter](../5-resources.md) (if the messaging solution that you use does not have an adapter yet, feel free to create/upvote an issue, or contribute πŸ€—).
You can code your own `MessageQueueAdapter` (simply implement the `MessageChannelAdapter` interface), but we highly recommend using an [off-the-shelf adapter](../5-packages.md#-message-queue-adapters) (if the messaging solution that you use does not have an adapter yet, feel free to create/upvote an issue, or contribute πŸ€—).

:::

Expand Down Expand Up @@ -82,7 +82,7 @@ const appMessagesWorker = async ({ Records }: SQSMessageQueueMessage) => {
>
> - <code>messageQueueId <i>(string)</i></code>: A string identifying the message queue
> - <code>sourceEventStores <i>(EventStore[])</i></code>: List of event stores that the message queue will broadcast events from
> - <code>messageQueueAdapter <i>(?MessageChannelAdapter)</i></code>: See section on <a href="#messagequeueadapter">MessageQueueAdapters</a>
> - <code>messageQueueAdapter <i>(?MessageChannelAdapter)</i></code>: Message queue adapter
>
> **Properties:**
>
Expand All @@ -100,7 +100,7 @@ const appMessagesWorker = async ({ Records }: SQSMessageQueueMessage) => {
> // => [pokemonsEventStore, trainersEventStore...]
> ```
>
> - <code>messageChannelAdapter <i>?MessageChannelAdapter</i></code>: See section on <a href="#messagequeueadapter">MessageQueueAdapters</a>
> - <code>messageChannelAdapter <i>?MessageChannelAdapter</i></code>: Returns the associated message queue adapter (potentially undefined)
>
> ```ts
> const appMessageQueueAdapter = appMessageQueue.messageChannelAdapter;
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/4-reacting-to-events/3-message-buses.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ await messageBus.publishMessage(...);

:::info

You can code your own `MessageBusAdapter` (simply implement the `MessageChannelAdapter` interface), but we highly recommend using an [off-the-shelf adapter](../5-resources.md) (if the messaging solution that you use is missing, feel free to create/upvote an issue, or contribute πŸ€—).
You can code your own `MessageBusAdapter` (simply implement the `MessageChannelAdapter` interface), but we highly recommend using an [off-the-shelf adapter](../5-packages.md#-message-buses-adapters) (if the messaging solution that you use is missing, feel free to create/upvote an issue, or contribute πŸ€—).

:::

Expand Down Expand Up @@ -82,7 +82,7 @@ const pokemonMessagesListener = async (
>
> - <code>messageBusId <i>(string)</i></code>: A string identifying the message bus
> - <code>sourceEventStores <i>(EventStore[])</i></code>: List of event stores that the message bus will broadcast events from
> - <code>messageBusAdapter <i>(?MessageChannelAdapter)</i></code>: See section on <a href="#messagebusadapter">MessageBusAdapters</a>
> - <code>messageBusAdapter <i>(?MessageChannelAdapter)</i></code>: Message bus adapter
>
> **Properties:**
>
Expand All @@ -100,7 +100,7 @@ const pokemonMessagesListener = async (
> // => [pokemonsEventStore, trainersEventStore...]
> ```
>
> - <code>messageChannelAdapter <i>?MessageChannelAdapter</i></code>: See section on <a href="#messagebusadapter">MessageBusAdapters</a>
> - <code>messageChannelAdapter <i>?MessageChannelAdapter</i></code>: Returns the associated message bus adapter (potentially undefined)
>
> ```ts
> const appMessageBusAdapter = appMessageBus.messageChannelAdapter;
Expand Down