Skip to main content

Workflow

We have a graphql-codegen library for code generation for event handlers and event publisher.

Dependencies​

npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations

Installation​

npm i -D graphql-eventbus-codegen

Code generator needs a yaml config file. In the sample file below, we are generating code for event handlers (for consuming events) and event publisher. Note that we are generating code for publisher (./src/generated/codegen-event-publisher.ts) and consumers (./src/generated/codegen-event-consumer.ts) in separate files. For the publisher, the input is the schema of events it publishes (src/schema.event.graphql). We use the publisher: true flag for graphql-eventbus-codegen plugin. For event consumer, we specify the URI of schemas: here we are downloading the schemas from Github for instance. We also need to specify the graphQL documents which has all the events the service is consuming. Finally, we use the conumer config for graphql-eventbus-codegen plugin. We specify our custom context object for the event handlers. We also specify a path to print the composed event schema that we are consuming. This schema will be used as an input to the event bus.

schema: ""
generates:
./src/generated/codegen-event-publisher.ts:
plugins:
- typescript
- graphql-eventbus-codegen:
publisher: true
schema:
- "src/schema.event.graphql"
config:
skipTypename: true
enumsAsTypes: true
./src/generated/codegen-event-consumer.ts:
plugins:
- graphql-eventbus-codegen:
consumer:
eventSampler: true
contextType: "../types#MessageHandlerContext"
schemaPrintPath: "src/generated/event-publisher.graphql"
- typescript
- typescript-operations:
documents:
- "./src/event-handlers/event-consumer.graphql"
schema:
- ${SERVICEA_SCHEMA_URL}:
token: ${GITHUB_TOKEN}
headers: ${HEADERS}
- ${SERVICEB_SCHEMA_URL}:
token: ${GITHUB_TOKEN}
headers: ${HEADERS}
config:
skipTypename: true

The signature of a publish function is generated like so:

function publish(
data:
| { topic: "UserCreatedEvent"; payload: UserCreatedEvent }
| { topic: "UserDeletedEvent"; payload: UserDeletedEvent },
): Promise<void>;
function publish(): Promise<void> {
return Promise.resolve();
}

export type Publish = typeof publish;

The signature of the event handler functions is generated like so:

export interface EventHandlers {
UserCreatedEvent: (
msg: UserCreatedEventQuery["UserCreatedEvent"],
ctx: MessageHandlerContext,
) => Promise<any>;
}

Each event handler function is passed the data that they queried as the first argument, and a context object as the second argument.