Skip to main content

Event

An Event is a named schema for a message that can be emitted to a Service's Bus and then routed to a Service's Subscriptions or to other Services.

Create an Event

You can create an event by importing the event function from @eventual/core and passing it a name for the event:

import { event } from "@eventual/core";

export const myEvent = event("MyEvent");

This registers an event with the name "MyEvent" on the Event Bus.

Emit an Event

You can then emit data to this event by calling the emit function on the event object and passing it the data you want to send:

await myEvent.emit({ message: "hello world" });

The function accepts multiple arguments for batch sending events.

await myEvent.emit(
{
prop: "value 1",
},
{
prop: "value 2",
}
);

Subscribe to an Event

See the Subscription page.

Defining the type of an Event

By default, an event's type is any. This is easy and flexible, but also unsafe. To associate a type with an event, you can use the <Type> syntax when creating the event. For example:

export interface MyEvent {
prop: string;
}

export const myEvent = event<MyEvent>("MyEvent");

This creates an event called "MyEvent" with a type of MyEvent. This ensures that when the event is emitted or subscribed to, the data adheres to the MyEvent interface.

await myEvent.emit({
prop: "my value", // okay
});

await myEvent.emit({
prop: 123, // error, prop must be a string
});

export const onMyEvent = subscription(
"onMyEvent",
{
events: [myEvent],
},
async (event) => {
event.key; // error, 'key' property does not exist
}
);

By defining the type of an event, you can improve the safety and reliability of your application by catching errors at compile time rather than runtime, as well as self-documenting your code by clearly outlining the shape of the data that the event is expected to contain.

Emit an Event from outside Eventual

To emit an event to a Service's Event Bus from outside Eventual, you will need to obtain the Event Bus's ARN. You can do this by accessing the events.bus property of the Service Construct, which is the Event Bus for the Service. For example, if you have a Service named myService:

const myService = new Service(..);

myService.events.bus; // <-- the Event Bus that belongs to "myService"

You can then provide this ARN to your external service, such as a Lambda Function, by adding it to the environment variables of the function. For example:

myFunction.addEnvironment(
"MY_SERVICE_BUS_ARN",
myService.events.bus.eventBusArn
);

Next, you will need to grant the external service permissions to emit events to the Event Bus. This can be done using the grantEmit method:

myService.events.grantEmit(myFunction);

With the necessary permissions and ARN in place, you can now use the PutEvents API, provided by the AWS SDK v3 for JavaScript EventBridge Client), to emit events to the Event Bus. For example:

import {
EventBridgeClient,
PutEventsCommand,
} from "@aws-sdk/client-eventbridge";

const client = new EventBridgeClient({});

export async function handler() {
await client.send(
new PutEventsCommand({
Entries: [
{
DetailType: "MyEvents",
Detail: `{ "prop": "value" }`,
// the ARN of the Event Bus that belongs to `myService`
EventBusName: process.env.MY_SERVICE_BUS_ARN,
},
],
})
);
}

The DetailType property must be the name of the event, e.g. MyEvents:

const myEvent = event("MyEvent"); // <-- this is the DetailType

The Detail property must be a stringified JSON payload of the event's data that matches the type. For example:

interface MyEvent {
prop: string;
}

const myEvent = event<MyEvent>("MyEvent");

The value of Detail must be a stringified JSON object with a single prop property with a value of type string. For example:

{
"prop": "value"
}