Damjan
04/08/2022, 2:03 PMSeth Geoghegan
04/08/2022, 2:05 PMthdxr
04/08/2022, 2:07 PMthdxr
04/08/2022, 2:08 PMthdxr
04/08/2022, 2:09 PMthdxr
04/08/2022, 2:09 PMdeclare module "@acme/core/bus" {
export interface Events {
"business.created": {
id: string
name: string
}
"business.deleted": {
id: string
}
}
}
thdxr
04/08/2022, 2:10 PMBus.publish("type", properties)
function that is entirely typesafethdxr
04/08/2022, 2:10 PMBus.createHandler
function to receive events in a typesafe wayDamjan
04/08/2022, 2:52 PMDamjan
04/08/2022, 2:53 PMthdxr
04/08/2022, 2:53 PMthdxr
04/08/2022, 2:54 PM@serverless-stack/node
packagethdxr
04/08/2022, 2:55 PMexport interface Event {
id: string
source: "acme"
type: string
properties: any
actor: Actor
}
export interface Events {}
export type EventTypes = keyof Events
export type FromType<T extends EventTypes> = payload<T, Events[T]>
export type AnyEvent = FromType<EventTypes>
export type payload<T extends string, P extends Record<string, any>> = {
id: string
source: "acme"
type: T
properties: P
actor: Actor
}
export async function publish<T extends EventTypes>(
type: T,
properties: Events[T],
actor?: Actor
) {
const ctx = context()
const payload: Event = {
id: ulid(),
source: "acme",
type,
properties,
actor: actor ? actor : ctx.actor,
}
// Send event
return payload
}
thdxr
04/08/2022, 2:55 PMcontext()
and actor
stuff that's a bit specificthdxr
04/08/2022, 2:58 PMthdxr
04/08/2022, 2:58 PMexport function createHandler<T extends EventTypes>(
cb: (event: FromType<T>, record: SQSRecord) => Promise<void>
) {
const result = async (event: SQSEvent) => {
const promises = []
for (const record of event.Records) {
const msg = JSON.parse(record.body)
async function run() {
try {
await cb(msg.detail as FromType<T>, record)
return { type: "success" }
} catch (e) {
console.error(e)
return { type: "error", messageId: record.messageId }
}
}
promises.push(run())
}
const results = await Promise.all(promises)
return {
batchItemFailures: results
.filter((i) => i.type === "error")
.map((i) => ({
itemIdentifier: i,
})),
}
}
return AWSLambda.wrapHandler(result) // Sentry
}
Richard Simpson
04/08/2022, 5:47 PMDamjan
04/12/2022, 12:17 PMthdxr
04/12/2022, 12:18 PMDamjan
04/12/2022, 12:42 PM