Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

EventCatalog - Typesafe events across sending and triggers #535

ericallam started this conversation in Ideas
Discussion options

Currently, you can only define an event schema when using an eventTrigger on a job:

client.defineJob({
 id: "example",
 name: "Example",
 version: "1.0.0",
 trigger: eventTrigger({
 name: "user.created",
 schema: z.object({
 userId: z.string(),
 isAdmin: z.boolean(),
 }),
 }),
 run: async (payload, io, ctx) => {
 },
});

And then when sending an event, that type/schema information is lost and the payload can very easily be wrongly typed:

// This currently works
await client.sendEvent({
 name: "user.created",
 payload: { foo: "bar" }
})

We should introduce a new concept called an "EventCatalog" that centralizes event schema definitions, and makes both eventTrigger and sendEvent typesafe.

Defining an Event Catalog

// userEventCatalog.ts
import { EventCatalog } from "@trigger.dev/sdk";
import { client } from "@/trigger";
export const userEventCatalog = client.defineEventCatalog({
 id: "user-catalog",
 description: "A collection of events related to Users",
 events: {
 "user.created": z.object({
 schema: {
 id: z.string(),
 isAdmin: z.boolean(),
 },
 }),
 "user.deleted": {
 schema: z.object({
 old_record: z.object({
 id: z.string(),
 }),
 deletedAt: z.coerce.date(),
 },
 }),
 },
});

The above defines two events, each with a payload schema type using Zod.

Sending events

import { userEventCatalog } from "./userEventCatalog";
// outside of a run
await userEventCatalog.sendEvent({
 id: "user_1234.created",
 name: "user.created",
 payload: {
 id: "user_1234",
 isAdmin: false,
 },
});
// inside of a run requires a key as the first param
await userEventCatalog.sendEvent("send-event", {
 id: "user_1234.created",
 name: "user.created",
 payload: {
 id: "user_1234",
 isAdmin: false,
 },
});

Now events are send through the event catalog, and the type of the payload field is automatically inferred from the event name. Now, both the event name and the payload will produce type errors if they don't exist in the catalog.

Event triggers will work in a similar way, and will go through the event catalog as well:

import { userEventCatalog } from "./userEventCatalog";
client.defineJob({
 id: "example",
 name: "Example",
 version: "1.0.0",
 trigger: userEventCatalog.on("user.created", {
 filter: { isAdmin: [true] } // EventFilter will also be typesafe
 }),
 run: async (payload, io, ctx) => {
 // payload is typed as { id: string; isAdmin: boolean }
 },
});
You must be logged in to vote

Replies: 3 comments

Comment options

EventFilter will also be typesafe

Love how you snuck this in there.

You must be logged in to vote
0 replies
Comment options

ericallam
Oct 5, 2023
Maintainer Author

You must be logged in to vote
0 replies
Comment options

ericallam
Oct 5, 2023
Maintainer Author

We should add a color option to the catalog

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /