Quick Start

The following provides a quick introduction on how to get started with @valkyr/event-store.

Setup

This project is published at The JavaScript Registry providing support for deno, bun, and node.js

$ deno add @valkyr/event-store

Events

Our solution currently created to serve multiple platforms. As such we needed a way to easily take a central source of truth and generate platform specific outputs. For this we introduce a configuration approach using JSON files, and event generators.

First define one or more event folders which will house your applications events. In this example we simply create an events folder.

$ mkdir events

Now that we have our events folder we move into it and create our first event.

$ touch user-created.json

We now open the JSON file and add our event configuration.

{
  "event": {
    "type": "user:created",
    "data": {
      "name": {
        "type": "object",
        "properties": {
          "given": {
            "type": "string"
          },
          "family": {
            "type": "string"
          }
        }
      },
      "email": {
        "type": "string"
      }
    },
    "meta": {
      "auditor": {
        "type": "string"
      }
    }
  }
}

With this we should now have a folder events with a user-create.json configuration file. With this in place we can now create an event printer.

Printer

To convert our JSON configurations into event store consumable code, we need to create a new file which prints our configuration to code.

In our example we will start by creating a new generate file.

$ touch generate.ts

Then we add in the code to print our events.

import { printEvents } from "@valkyr/event-store";

await printEvents({
  paths: ["./events"],
  output: "./events.ts",
});

Executing this file will now consume the events folder and create a events.ts file which represents all the events for our application.

The output should look something like the following:

/* eslint-disable @typescript-eslint/no-unused-vars */
// deno-fmt-ignore-file
// This is an auto generated file. Do not modify this file!

import { type AnyZodObject, type Empty, type Event, type EventToRecord, z } from "@valkyr/event-store";

export const events = new Set(["user:created"] as const);

export const validators = new Map<SystemEvent["type"], AnyZodObject>([
  [
    "user:created",
    z.object({ 
      name: z.object({ 
        given: z.string(), 
        family: z.string(),
      }).strict(), 
      email: z.string(),
    }).strict(),
  ],
]);

export type SystemEventRecord = EventToRecord<SystemEvent>;

export type SystemEvent = UserCreated;

export type UserCreated = Event<"user:created", { 
  name: { 
    given: string; 
    family: string 
  }; 
  email: string 
}, { 
  auditor: string 
}>;

Event Store

Our current output target is only TypeScript with support for postgres, sqlite, and browsers.

Now that we have our events.ts file, we can instantiate a new event store and apply our events. First start by creating a new event-store.ts file.

$ touch event-store.ts

We open the new file and create our event store instance, in this example we will be using the sqlite driver.

import { Database } from "sqlite";

import { SQLiteEventStore } from "@valkyr/event-store/sqlite";

import { type Events, events, validators } from "./events.ts";

const eventStore = new SQLiteEventStore<Events>({
  database: new Database(":memory:"),
  events,
  validators,
});

And with this, we have create our initial event store instance for use in our application.

Before we can use the event store instance we need to migrate the event store tables onto our application databases. See the migrate section for more information.

Last updated