๐Ÿฆซ A simple way to implement event sourcing in TypeScript

Overview

โœจ Better DevX for Event Sourcing in TypeScript

Castore provides a unified interface for implementing Event Sourcing in TypeScript.

Define your events types:

import { EventTypesDetails } from 'castore';
import { JSONSchemaEventType } from 'castore/json-schema-event-type';

const counterCreatedEvent = new JSONSchemaEventType({
  type: 'COUNTER_CREATED',
  payloadSchema: {
    type: 'object',
    properties: {
      startCount: { type: 'integer' },
    },
  } as const,
});

const counterIncrementedEvent = new JSONSchemaEventType({
  type: 'COUNTER_INCREMENTED',
});

const counterRemovedEvent = new JSONSchemaEventType({
  type: 'COUNTER_REMOVED',
});

const eventTypes = [
  counterCreatedEvent,
  counterIncrementedEvent,
  counterRemovedEvent,
];

// Will infer correct union type ๐Ÿ™Œ
type CounterEventDetail = EventTypesDetails<typeof eventTypes>;

Define your aggregate type and reducer:

type CounterAggregate = {
  aggregateId: string;
  version: number;
  count: number;
  status: string;
};

const reducer = (
  aggregate: CounterAggregate,
  event: CounterEventDetail,
): CounterAggregate => {
  const { aggregateId, version } = event;

  switch (event.type) {
    case 'COUNTER_CREATED': {
      const { startCount = 0 } = event.payload;

      return {
        aggregateId,
        version,
        count: startCount,
        status: 'CREATED',
      };
    }
    case 'COUNTER_INCREMENTED':
      return {
        ...aggregate,
        version,
        count: aggregate.count + 1,
      };
    case 'COUNTER_REMOVED':
      return {
        ...aggregate,
        version,
        status: 'REMOVED',
      };
  }
};

Finally, initialize an EventStore class and start interacting with your event store:

const counterEventStore = new EventStore({
  eventStoreId: 'Counters',
  eventTypes,
  reducer,
  // ๐Ÿ‘‡ See storage adapters section
  storageAdapter,
});

const {
  events, // <= Typed events
  aggregate, // <= Reducer result
} = await counterEventStore.getAggregate(aggregateId);

// ๐Ÿ‘‡ Method input is correctly typed
await counterEventStore.pushEvent({
  aggregateId: '123',
  version: 1,
  type: 'COUNTER_CREATED',
  timestamp: new Date().toISOString(),
  payload: {
    startCount: 18,
  },
});

๐Ÿค” Why use Castore ?

  • ๐Ÿ’ฌ Verbosity: Castore classes are designed to increase dryness and provide the optimal developer experience. Event Sourcing is hard, don't make it harder!
  • ๐Ÿ“ Strong typings: We love type inference, we know you will to!
  • ๐Ÿ„โ€โ™‚๏ธ Interfaces before implementations: Castore provides a standard interface to modelize common event sourcing patterns in TypeScript. But it DOES NOT enforce any particular implementation (storage service, messaging system etc...). You can use Castore in React apps, containers or lambdas, it's up to you! Some common implementations are provided, but you are free to use any implementation you want via custom classes, as long as they follow the required interfaces.
  • ๐Ÿ‘ Enforces best practices: Gained from years of usage like using int versions instead of timestamps, transactions for multi-store events and state-carrying transfer events for projections.
  • ๐Ÿ›  Rich suite of helpers: Like mock events builder to help you write tests.

Table of content

Event

TODO

Event Store

TODO

Storage Adapter

TODO

Mock Events Builder

TODO

You might also like...

In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. All the elements of the user interface are fully functional.

In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. All the elements of the user interface are fully functional.

To Do list: add & remove In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. All the elements of th

Jan 3, 2023

A TypeScript friendly event emitter with easy re-emitting events

remitter A TypeScript friendly event emitter with easy re-emitting events. Install npm add remitter Usage import { Remitter } from "remitter"; interf

Dec 28, 2022

Catalogist is the easy way to catalog and make your software and (micro)services visible to your organization in a lightweight and developer-friendly way.

Catalogist is the easy way to catalog and make your software and (micro)services visible to your organization in a lightweight and developer-friendly way.

catalogist ๐Ÿ“š ๐Ÿ““ ๐Ÿ“’ ๐Ÿ“– ๐Ÿ”– The easy way to catalog and make your software and (micro)services visible to your organization through an API You were a pe

Dec 13, 2022

Nest.js project used it implement login page functionality.

Basic Login Backend (API) Description This project is the backend (API) portion of a basic login application. It calls a local frontend project basic-

Mar 21, 2022

An Electron app using NAPI-RS and a native Rust module to implement a Svelte store.

Svelte Store Written in Rust This repo shows a demo of an Electron app running a Svelte UI that reads and writes a Svelte store, but with a twist: the

Sep 20, 2022

How to implement Step-up Authentication using Amazon Cognito

How to implement Step-up Authentication using Amazon Cognito

How to implement Step-up Authentication using Amazon Cognito This repository contains accompanying source code for the AWS Blog post, How to implement

Dec 15, 2022

Based on Google Chrome recorder, implement UI interface capture and notify the result to the target mailbox

Based on Google Chrome recorder, implement UI interface capture and notify the result to the target mailbox

chrome-recoder-crawler README-CN Modify the .js file exported by Google Chrome recorder. By default, the innerText property of the node operated in th

Oct 18, 2022

this is a single-page web application. we built a book website where the user can add , remove and display books. we used modules to implement these functionalities. also, we used the Date class to display the date and time.

Awsome Books In this Project, we have built A Books websites. Built With ๐Ÿ”จ HTML CSS javascript Git & Github Live Demo Here you can find the live Demo

Aug 3, 2022

Implement MTCNN with Tensorflow.js. A face detection framework with MTCNN and Tensorflow.js

Implement MTCNN with Tensorflow.js. A face detection framework with MTCNN and Tensorflow.js

mtcnn-tfjs Implement mtcnn with Tensorflow.js What is this? A face detection framework with MTCNN and Tensorflow.js Give me a โญ๏ธ , if you like it โค๏ธ (

Nov 23, 2022
Releases(v1.1.0)
  • v1.1.0(Jul 29, 2022)

  • v1.0.7(Jul 29, 2022)

  • v1.0.6(Jul 29, 2022)

  • v1.0.5(Jul 29, 2022)

    Changes

    • fix: fix release script 3 @ThomasAribart (#81)
    • fix: fix release script (2) @ThomasAribart (#79)
    • fix: fix release script 1 @ThomasAribart (#78)
    • feature: create get existing aggregate method in event store @ThomasAribart (#74)
    • chore: use prettier for import order @ThomasAribart (#73)
    • chore: import logo assets @ThomasAribart (#72)
    • fix: release inmemory storage adapter to npm @ThomasAribart (#71)
    • feature: list aggregate ids pagination @charlesgery (#64)
    • feature: small improve of abstract event store definitions type @ThomasAribart (#67)
    • :wrench: skip release drafter on new release @valentinbeggi (#69)
    • feature: ๐Ÿคก Mock event store @julietteff (#66)
    • feature: hardly type event store ids @ThomasAribart (#65)
    Source code(tar.gz)
    Source code(zip)
  • v0.7.2(Jul 11, 2022)

    Changes

    • :package: add missing package step in release npm action @valentinbeggi (#63)
    • chore: remove unused helper @ThomasAribart (#62)
    • feature: rename event-store as core @ThomasAribart (#61)
    • feature: create inmemory storage adapter package @charlesgery (#56)
    • :construction_worker: release all castore packages @valentinbeggi (#60)
    • feature: remove dynamodb toolbox from dynamodb event storage adapter @ThomasAribart (#52)
    • feature: small refacto in inMemory adapter @ThomasAribart (#57)
    • feature: create events library @charlesgery (#43)
    • Test release 9 @valentinbeggi (#59)
    • :memo: update doc @valentinbeggi (#58)
    • :wrench: fix npm release @valentinbeggi (#54)
    Source code(tar.gz)
    Source code(zip)
  • v0.6.1(Jul 8, 2022)

  • v0.6.0(Jun 27, 2022)

  • v0.5.7(Jun 17, 2022)

  • v0.5.6(Jun 17, 2022)

  • v0.5.5(Jun 17, 2022)

  • v0.5.4(Jun 17, 2022)

  • v0.5.3(Jun 17, 2022)

  • v0.5.2(Jun 17, 2022)

  • v0.5.1(Jun 17, 2022)

  • v0.5.0(Jun 17, 2022)

  • v0.4.0(Jun 17, 2022)

    Changes

    • Change publish action ref @valentinbeggi (#37)
    • feature: implement automatic retry in commands in case of EventAlreadyExists errors @ThomasAribart (#27)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.6(Jun 10, 2022)

  • v0.3.5(Jun 10, 2022)

  • v0.3.4(Jun 10, 2022)

  • v0.3.3(Jun 10, 2022)

  • v0.3.2(Jun 10, 2022)

  • v0.3.1(Jun 10, 2022)

  • v0.3.0(Jun 10, 2022)

    Changes

    • :rocket: create release to npm action @valentinbeggi (#28)
    • feature: create command class @ThomasAribart (#26)
    • chore: label pr with semantic versioning increase @ThomasAribart (#25)
    • โœจ change getEvents output interface for more flexibility @ThomasAribart (#24)
    • docs: update readme 2 @ThomasAribart (#23)
    • feat: export EventTypesDetails utility type @ThomasAribart (#22)
    • docs: init README @ThomasAribart (#21)
    • chore: add event store unit tests @charlesgery (#20)
    • Fix/improve event implementations definitions @ThomasAribart (#18)
    • Storage adapter @ThomasAribart (#15)
    • chore: add zodEventType unit tests @charlesgery (#16)
    • ๐ŸŽฏ Implement first test for jsonSchemaEventType @ThomasAribart (#14)
    • โœจ Enable setting event type metadata @charlesgery (#13)
    • rename EventStoreEvent class to EventType @ThomasAribart (#12)
    • Improve event store and event store events definitions @ThomasAribart (#11)
    • feat: setup github actions @charlesgery (#3)
    • :wrench: update description @valentinbeggi (#10)
    • :wrench: change publish config @valentinbeggi (#9)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jun 3, 2022)

    Changes

    • chore: label pr with semantic versioning increase @ThomasAribart (#25)
    • โœจ change getEvents output interface for more flexibility @ThomasAribart (#24)
    • docs: update readme 2 @ThomasAribart (#23)
    • feat: export EventTypesDetails utility type @ThomasAribart (#22)
    • docs: init README @ThomasAribart (#21)
    • chore: add event store unit tests @charlesgery (#20)
    • Fix/improve event implementations definitions @ThomasAribart (#18)
    • Storage adapter @ThomasAribart (#15)
    • chore: add zodEventType unit tests @charlesgery (#16)
    • ๐ŸŽฏ Implement first test for jsonSchemaEventType @ThomasAribart (#14)
    • โœจ Enable setting event type metadata @charlesgery (#13)
    • rename EventStoreEvent class to EventType @ThomasAribart (#12)
    • Improve event store and event store events definitions @ThomasAribart (#11)
    • feat: setup github actions @charlesgery (#3)
    • :wrench: update description @valentinbeggi (#10)
    • :wrench: change publish config @valentinbeggi (#9)
    • ๐Ÿงน run prettier clean @valentinbeggi (#8)
    • :wrench: change lerna release base version @valentinbeggi (#7)
    • Improve event store and event store events definitions @ThomasAribart (#5)
    • ๐Ÿ™‚ add emoji in workspace names @valentinbeggi (#6)
    • ๐Ÿ™ˆ remove swarmion wording @valentinbeggi (#4)
    • :tada: move to monorepo architecture @valentinbeggi (#2)
    • ๐Ÿšš Import code from Kooalys event-store library @ThomasAribart (#1)
    Source code(tar.gz)
    Source code(zip)
Owner
Theodo.FR
Theodo.FR
Tax-finder - A web application sourcing and sharing tax data on Fortune 500 corporations.

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Bennett Huffman 1 Jan 1, 2022
Quickly create an interactive HTML mock-up by auto sourcing lorem ipsum/images generators, with minimal html markup, and no server side code

RoughDraft.js v0.1.5 Quickly mockup / prototype HTML pages with auto-generated content, without additional JavaScript or server side code. <section>

Nick Dreckshage 464 Dec 21, 2022
io-ts Typed Event Bus for the runtime of your Node.js application. A core for any event-driven architecture based app.

Typed Event Bus Based on io-ts types, this bus provides a handy interface to publish and consume events in the current runtime of the Node.js process.

Konstantin Knyazev 3 May 23, 2022
'event-driven' library aims to simplify building backends in an event driven style

'event-driven' library aims to simplify building backends in an event driven style(event driven architecture). For message broker, light weight Redis Stream is used and for event store, the well known NoSQL database, MongoDB, is used.

Sihoon Kim 11 Jan 4, 2023
The invoker based on event model provides an elegant way to call your methods in another container via promisify functions

The invoker based on event model provides an elegant way to call your methods in another container via promisify functions. (like child-processes, iframe, web worker etc).

ๅฐนๆŒš 7 Dec 29, 2022
Custom navigations for Solid written in Typescript. Implement custom page transition logic and โœจ animations โœจ

solid-custom-navigation Get, Set, Go! Custom navigations for Solid, written in Typescript. Implement custom page transition logic and โœจ animations โœจ .

Dirag Biswas 8 Nov 27, 2022
๐ŸŽจ Beautify your github profile with this amazing tool, creating the readme your way in a simple and fast way ๐Ÿš€ The best profile readme generator you will find โšก

Demo Profile Readme Generator The best profile readme generator you will find! About | Technologies | Requirements | Starting | Contributing ?? About

Mauro de Souza 476 Jan 1, 2023
A simple api to get data of microverse's staff members, made for microverse students so they cann implement them in their projects

Microverse Staff Api Api for some microverse staff members Built With Express NodeJs MongoDB (Mongoose) JavaScript Base URL https://microverse-staff.h

Ali Jendoubi 7 Sep 29, 2022
In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. I followed the JavaScript, CSS, HTML, DRY, KISS and YAGNI Best practices.

To Do list: add & remove In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. All the elements of th

Olivier 6 Nov 20, 2022
Leader Board is a simple project based on JavaScript programing language. The purpose of this project is to work with APIs and ASYNC & AWAIT methods. I have used vanilla JavaScript with web pack to implement this project

Leader Board - JavaScript Project Table of contents Overview The challenge Screenshot Links Project Setup commands My process Built with What I learne

Mahdi Rezaei 7 Oct 21, 2022