Skip to content

Commit

Permalink
feat: Add support for the new Resend audience API endpoints (#850)
Browse files Browse the repository at this point in the history
* feat: Add support for the new Resend audience API endpoints

* update pnpm-lock.yaml

* update pnpm-lock.yaml

* Merge branch 'main' into feat/support-for-resend-audience-api

* latest pnpm-lock.yaml

* Create lovely-items-end.md

* Update pnpm-lock.yaml

---------

Co-authored-by: Matt Aitken <[email protected]>
  • Loading branch information
Kritik-J and matt-aitken authored Jan 17, 2024
1 parent adf66d2 commit 4dd6cf1
Show file tree
Hide file tree
Showing 8 changed files with 593 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-items-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/resend": patch
---

Add support for the new Resend audience API endpoints
23 changes: 16 additions & 7 deletions docs/integrations/apis/resend-tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,22 @@ Send an email to a recipient with a text payload. [Official Resend Docs](https:/

## Tasks

| Function Name | Description |
| --------------- | -------------------------------- |
| `emails.send` | Send an email |
| `emails.create` | Create an email |
| `emails.get` | Get an email |
| `batch.send` | Send a batch of emails at once |
| `batch.create` | Create a batch of emails at once |
| Function Name | Description |
| ------------------ | -------------------------------- |
| `emails.send` | Send an email |
| `emails.create` | Create an email |
| `emails.get` | Get an email |
| `batch.send` | Send a batch of emails at once |
| `batch.create` | Create a batch of emails at once |
| `audiences.create` | Create an audience |
| `audiences.get` | Get an audience |
| `audiences.remove` | Remove an audience |
| `audiences.list` | List audiences |
| `contacts.create` | Create a contact |
| `contacts.get` | Get a contact |
| `contacts.update` | Update a contact |
| `contacts.remove` | Remove a contact |
| `contacts.list` | List contacts |

## Example

Expand Down
2 changes: 1 addition & 1 deletion integrations/resend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"dependencies": {
"@trigger.dev/integration-kit": "workspace:^2.3.13",
"@trigger.dev/sdk": "workspace:^2.3.13",
"resend": "^2.0.0"
"resend": "^2.1.0"
},
"engines": {
"node": ">=18.0.0"
Expand Down
134 changes: 134 additions & 0 deletions integrations/resend/src/audiences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { IntegrationTaskKey, retry } from "@trigger.dev/sdk";
import type { ResendRunTask } from "./index";
import { Resend } from "resend";
import { handleResendError } from "./utils";

type CreateAudienceResult = NonNullable<Awaited<ReturnType<Resend["audiences"]["create"]>>["data"]>;
type GetAudienceResult = NonNullable<Awaited<ReturnType<Resend["audiences"]["get"]>>["data"]>;
type DeleteAudienceResult = NonNullable<Awaited<ReturnType<Resend["audiences"]["remove"]>>["data"]>;
type ListAudiencesResult = NonNullable<Awaited<ReturnType<Resend["audiences"]["list"]>>["data"]>;

export class Audiences {
constructor(private runTask: ResendRunTask) {}

create(
key: IntegrationTaskKey,
payload: Parameters<Resend["audiences"]["create"]>[0],
options?: Parameters<Resend["audiences"]["create"]>[1]
): Promise<CreateAudienceResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.audiences.create(payload, options);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Create Audience",
params: payload,
properties: [
{
label: "Name",
text: payload.name,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

get(key: IntegrationTaskKey, payload: string): Promise<GetAudienceResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.audiences.get(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Get Audience",
params: payload,
properties: [
{
label: "ID",
text: payload,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

remove(key: IntegrationTaskKey, payload: string): Promise<DeleteAudienceResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.audiences.remove(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Remove Audience",
params: payload,
properties: [
{
label: "ID",
text: payload,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

list(key: IntegrationTaskKey): Promise<ListAudiencesResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.audiences.list();

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "List Audiences",
retry: retry.standardBackoff,
},
handleResendError
);
}
}
188 changes: 188 additions & 0 deletions integrations/resend/src/contacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { IntegrationTaskKey, retry } from "@trigger.dev/sdk";
import type { ResendRunTask } from "./index";
import { Resend } from "resend";
import { handleResendError } from "./utils";

type CreateContactResult = NonNullable<Awaited<ReturnType<Resend["contacts"]["create"]>>["data"]>;
type GetContactResult = NonNullable<Awaited<ReturnType<Resend["contacts"]["get"]>>["data"]>;
type UpdateContactResult = NonNullable<Awaited<ReturnType<Resend["contacts"]["update"]>>["data"]>;
type DeleteContactResult = NonNullable<Awaited<ReturnType<Resend["contacts"]["remove"]>>["data"]>;
type ListContactsResult = NonNullable<Awaited<ReturnType<Resend["contacts"]["list"]>>["data"]>;

export class Contacts {
constructor(private runTask: ResendRunTask) {}

create(
key: IntegrationTaskKey,
payload: Parameters<Resend["contacts"]["create"]>[0],
options?: Parameters<Resend["contacts"]["create"]>[1]
): Promise<CreateContactResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.contacts.create(payload, options);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Create Contact",
params: payload,
properties: [
{
label: "Email",
text: payload.email,
},
...(payload.first_name && payload.last_name
? [{ label: "Name", text: payload.first_name + " " + payload.last_name }]
: []),
],
retry: retry.standardBackoff,
},
handleResendError
);
}

get(
key: IntegrationTaskKey,
payload: Parameters<Resend["contacts"]["get"]>[0]
): Promise<GetContactResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.contacts.get(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Get Contact",
params: payload,
properties: [
{
label: "Id",
text: payload.id,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

update(
key: IntegrationTaskKey,
payload: Parameters<Resend["contacts"]["update"]>[0]
): Promise<UpdateContactResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.contacts.update(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Update Contact",
params: payload,
properties: [
{
label: "Id",
text: payload.id,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

remove(
key: IntegrationTaskKey,
payload: Parameters<Resend["contacts"]["remove"]>[0]
): Promise<DeleteContactResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.contacts.remove(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "Remove Contact",
params: payload,
properties: [
{
label: "Id",
text: payload.id,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}

list(
key: IntegrationTaskKey,
payload: Parameters<Resend["contacts"]["list"]>[0]
): Promise<ListContactsResult> {
return this.runTask(
key,
async (client, task) => {
const { error, data } = await client.contacts.list(payload);

if (error) {
throw error;
}

if (!data) {
throw new Error("No data returned from Resend");
}

return data;
},
{
name: "List Contacts",
params: payload,
properties: [
{
label: "Audience Id",
text: payload.audience_id,
},
],
retry: retry.standardBackoff,
},
handleResendError
);
}
}
Loading

0 comments on commit 4dd6cf1

Please sign in to comment.