📅 Events
Event Sourcing is all about saving changes in your application state. Such changes are represented by events, and needless to say, they are quite important 🙃
Events that concern the same entity (like a Pokemon
) are aggregated through a common id called aggregateId
(and vice versa, events that have the same aggregateId
represent changes of the same entity). The index of an event in such a serie of events is called its version
.
In Castore, stored events (also called event details) always have exactly the following properties:
aggregateId (string)
version (integer ≥ 1)
timestamp (string)
: A date in ISO 8601 formattype (string)
: A string identifying the business meaning of the eventpayload (?any = never)
: A payload of any typemetadata (?any = never)
: Some metadata of any type
import type { EventDetail } from '@castore/core';
type PokemonAppearedEventDetail = EventDetail<
'POKEMON_APPEARED',
{ name: string; level: number },
{ trigger?: 'random' | 'scripted' }
>;
// 👇 Equivalent to:
type PokemonAppearedEventDetail = {
aggregateId: string;
version: number;
timestamp: string;
type: 'POKEMON_APPEARED';
payload: { name: string; level: number };
metadata: { trigger?: 'random' | 'scripted' };
};
Events are generally classified in events types (not to confuse with TS types). Castore lets you declare them via the EventType
class:
import { EventType } from '@castore/core';
const pokemonAppearedEventType = new EventType<
'POKEMON_APPEARED',
{ name: string; level: number },
{ trigger?: 'random' | 'scripted' }
>({ type: 'POKEMON_APPEARED' });
Note that we only provided TS types for payload
and metadata
properties. That is because, as stated in the 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 which will add run-time validation methods to it 👍
🔧 Reference
Constructor:
type (string)
: The event type
import { EventType } from '@castore/core';
const pokemonAppearedEventType = new EventType({
type: 'POKEMON_APPEARED',
});
Properties:
type (string)
: The event type
const eventType = pokemonAppearedEventType.type;
// => 'POKEMON_APPEARED'
Type Helpers:
EventTypeDetail
: Returns the event detail TS type of anEventType
import type { EventTypeDetail } from '@castore/core';
type PokemonAppearedEventTypeDetail = EventTypeDetail<
typeof pokemonAppearedEventType
>;
// 👇 Equivalent to:
type PokemonCaughtEventTypeDetail = {
aggregateId: string;
version: number;
timestamp: string;
type: 'POKEMON_APPEARED';
payload: { name: string; level: number };
metadata: { trigger?: 'random' | 'scripted' };
};
EventTypeDetails
: Returns the events details of a list ofEventType
import type { EventTypeDetails } from '@castore/core';
type PokemonEventTypeDetails = EventTypeDetails<
[typeof pokemonAppearedEventType, typeof pokemonCaughtEventType]
>;
// => EventTypeDetail<typeof pokemonAppearedEventType>
// | EventTypeDetail<typeof pokemonCaughtEventType>