Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type-safe webhooks #1

Open
franky47 opened this issue Dec 23, 2021 · 2 comments
Open

Type-safe webhooks #1

franky47 opened this issue Dec 23, 2021 · 2 comments

Comments

@franky47
Copy link

franky47 commented Dec 23, 2021

I'm planning to use OhMySMTP in a Fastify app, for which I've made the fastify-ohmysmtp package, and next on my roadmap is to add a route and handlers for webhooks.

While I could list the event types and define the payload type within the plugin, I feel like those type definitions would be better located here in the Node.js API.

I've done a similar job for the Stripe webhooks here (though they had additional complexity that would be unneeded here if all webhooks have the same payload type), if that's something you're interested in, I can open a PR.

@franky47
Copy link
Author

Suggested API:

export const webhookEvents = [
  'email.queued',
  'email.delivered',
  'email.deferred',
  'email.bounced',
  'email.spam'
] as const

export type WebhookEvents = typeof webhookEvents[number]

export type ExtractStatusFromEvent<Event extends string> =
  Event extends `email.${infer T}` ? T : never

export interface WebhookPayload<Event extends WebhookEvents> {
  /**
   * Email status
   */
  status: ExtractStatusFromEvent<Event>

  /**
   * Reference ID of email
   */
  id: number

  /**
   * Reference ID of sending Domain
   */
  domain_id: number

  /**
   * Timestamp of when the email was first received by our API
   */
  created_at: Date

  /**
   * Timestamp of when the email was last updated, typically a status change
   */
  updated_at: Date

  /**
   * From email address
   */
  from: string

  /**
   * To email address, may be a comma separated list if multiple recipients provided
   */
  to: string | null

  /**
   * HTML body in email
   */
  htmlbody: string | null

  /**
   * Text body in email
   */
  textbody: string | null

  /**
   * Carbon Copy email address, may be a comma separated list if multiple recipients provided
   */
  cc: string | null

  /**
   * Blind Carbon Copy email address, may be a comma separated list if multiple recipients provided
   */
  bcc: string | null

  /**
   * Email subject
   */
  subject: string | null

  /**
   * Reply to address
   */
  replyto: string | null

  /**
   * Message ID set by OhMySMTP, in the format `<message-id>@<mailer.ohmysmtp.com>`
   */
  message_id: string

  /**
   * List-Unsubscribe header
   */
  list_unsubscribe: string | null
}

export type WebhookBody<Event extends WebhookEvents = WebhookEvents> = {
  event: Event
  payload: WebhookPayload<Event>
}

@franky47
Copy link
Author

Note: I've gone a different route when implementing webhook handlers in my plugin, to add a layer of input validation (because static types don't help much with runtime validation) with zod:
https://github.com/47ng/fastify-ohmysmtp/blob/main/src/webhooks.ts

Having the TypeScript definitions with JSDoc comments would be a nice DX though, to have documentation built-in in the editor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant