Upgrade resend integration to use resend-node 2.0.0 (#724)
* Upgrade resend integration to use resend-node 2.0.0, fixes issue with Next.js 14 * Create mighty-dodos-study.md
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@trigger.dev/resend": patch
|
||||
---
|
||||
|
||||
Upgrade resend integration to use resend-node 2.0.0
|
||||
@@ -67,7 +67,7 @@ client.defineJob({
|
||||
resend,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.resend.sendEmail("send-email", {
|
||||
await io.resend.emails.send("send-email", {
|
||||
to: payload.to,
|
||||
subject: payload.subject,
|
||||
text: payload.text,
|
||||
@@ -79,6 +79,10 @@ client.defineJob({
|
||||
|
||||
## Tasks
|
||||
|
||||
| Function Name | Description |
|
||||
| ------------- | ------------- |
|
||||
| `sendEmail` | Send an email |
|
||||
| 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 |
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.2.4",
|
||||
"@trigger.dev/sdk": "workspace:^2.2.4",
|
||||
"resend": "^1.0.0"
|
||||
"resend": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { IntegrationTaskKey, retry } from "@trigger.dev/sdk";
|
||||
import { Resend } from "resend";
|
||||
import type { ResendRunTask } from "./index";
|
||||
import { handleResendError } from "./utils";
|
||||
|
||||
type SendEmailResult = NonNullable<Awaited<ReturnType<Resend["batch"]["send"]>>["data"]>;
|
||||
type CreateEmailResult = NonNullable<Awaited<ReturnType<Resend["batch"]["create"]>>["data"]>;
|
||||
|
||||
export class Batch {
|
||||
constructor(private runTask: ResendRunTask) {}
|
||||
|
||||
send(
|
||||
key: IntegrationTaskKey,
|
||||
payload: Parameters<Resend["batch"]["send"]>[0],
|
||||
options?: Parameters<Resend["batch"]["send"]>[1]
|
||||
): Promise<SendEmailResult> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client, task) => {
|
||||
const { error, data } = await client.batch.send(payload, options);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error("No data returned from Resend");
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
{
|
||||
name: "Send Batch Email",
|
||||
params: payload,
|
||||
properties: [
|
||||
{
|
||||
label: "Count",
|
||||
text: String(payload.length),
|
||||
},
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
handleResendError
|
||||
);
|
||||
}
|
||||
|
||||
create(
|
||||
key: IntegrationTaskKey,
|
||||
payload: Parameters<Resend["batch"]["create"]>[0],
|
||||
options?: Parameters<Resend["batch"]["create"]>[1]
|
||||
): Promise<CreateEmailResult> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client, task) => {
|
||||
const { error, data } = await client.batch.create(payload, options);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error("No data returned from Resend");
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
{
|
||||
name: "Create Batch Email",
|
||||
params: payload,
|
||||
properties: [
|
||||
{
|
||||
label: "Count",
|
||||
text: String(payload.length),
|
||||
},
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
handleResendError
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import { IntegrationTaskKey, Prettify, retry } from "@trigger.dev/sdk";
|
||||
import type { ResendRunTask } from "./index";
|
||||
import { Resend } from "resend";
|
||||
import { handleResendError } from "./utils";
|
||||
|
||||
type SendEmailResult = NonNullable<Awaited<ReturnType<Resend["emails"]["send"]>>["data"]>;
|
||||
type CreateEmailResult = NonNullable<Awaited<ReturnType<Resend["emails"]["create"]>>["data"]>;
|
||||
type GetEmailResult = NonNullable<Awaited<ReturnType<Resend["emails"]["get"]>>["data"]>;
|
||||
|
||||
export class Emails {
|
||||
constructor(private runTask: ResendRunTask) {}
|
||||
|
||||
send(
|
||||
key: IntegrationTaskKey,
|
||||
payload: Parameters<Resend["emails"]["send"]>[0],
|
||||
options?: Parameters<Resend["emails"]["send"]>[1]
|
||||
): Promise<SendEmailResult> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client, task) => {
|
||||
const { error, data } = await client.emails.send(payload, options);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error("No data returned from Resend");
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
{
|
||||
name: "Send Email",
|
||||
params: payload,
|
||||
properties: [
|
||||
{
|
||||
label: "From",
|
||||
text: payload.from,
|
||||
},
|
||||
{
|
||||
label: "To",
|
||||
text: Array.isArray(payload.to) ? payload.to.join(", ") : payload.to,
|
||||
},
|
||||
...(payload.subject ? [{ label: "Subject", text: payload.subject }] : []),
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
handleResendError
|
||||
);
|
||||
}
|
||||
|
||||
create(
|
||||
key: IntegrationTaskKey,
|
||||
payload: Parameters<Resend["emails"]["create"]>[0],
|
||||
options?: Parameters<Resend["emails"]["create"]>[1]
|
||||
): Promise<CreateEmailResult> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client, task) => {
|
||||
const { error, data } = await client.emails.create(payload, options);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error("No data returned from Resend");
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
{
|
||||
name: "Create Email",
|
||||
params: payload,
|
||||
properties: [
|
||||
{
|
||||
label: "From",
|
||||
text: payload.from,
|
||||
},
|
||||
{
|
||||
label: "To",
|
||||
text: Array.isArray(payload.to) ? payload.to.join(", ") : payload.to,
|
||||
},
|
||||
...(payload.subject ? [{ label: "Subject", text: payload.subject }] : []),
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
handleResendError
|
||||
);
|
||||
}
|
||||
|
||||
get(key: IntegrationTaskKey, payload: string): Promise<GetEmailResult> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client, task) => {
|
||||
const { error, data } = await client.emails.get(payload);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error("No data returned from Resend");
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
{
|
||||
name: "Get Email",
|
||||
params: payload,
|
||||
properties: [
|
||||
{
|
||||
label: "ID",
|
||||
text: payload,
|
||||
},
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
handleResendError
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
retry,
|
||||
type ConnectionAuth,
|
||||
type IO,
|
||||
type IOTask,
|
||||
@@ -10,10 +9,8 @@ import {
|
||||
type TriggerIntegration,
|
||||
} from "@trigger.dev/sdk";
|
||||
import { Resend as ResendClient } from "resend";
|
||||
|
||||
type ResendType = InstanceType<typeof ResendClient>;
|
||||
type SendEmailData = Parameters<ResendType["sendEmail"]>[0];
|
||||
type SendEmailResponse = Awaited<ReturnType<ResendType["sendEmail"]>>;
|
||||
import { Emails } from "./emails";
|
||||
import { Batch } from "./batch";
|
||||
|
||||
type ErrorResponse = {
|
||||
statusCode: number;
|
||||
@@ -51,6 +48,8 @@ export type ResendIntegrationOptions = {
|
||||
apiKey?: string;
|
||||
};
|
||||
|
||||
export type ResendRunTask = InstanceType<typeof Resend>["runTask"];
|
||||
|
||||
export class Resend implements TriggerIntegration {
|
||||
/**
|
||||
* @internal
|
||||
@@ -120,33 +119,42 @@ export class Resend implements TriggerIntegration {
|
||||
);
|
||||
}
|
||||
|
||||
sendEmail(key: IntegrationTaskKey, params: SendEmailData): Promise<SendEmailResponse> {
|
||||
return this.runTask(
|
||||
key,
|
||||
async (client) => {
|
||||
const response = await client.sendEmail(params);
|
||||
if ("statusCode" in response) {
|
||||
throw response;
|
||||
}
|
||||
return response;
|
||||
},
|
||||
{
|
||||
name: "Send Email",
|
||||
params,
|
||||
properties: [
|
||||
{
|
||||
label: "From",
|
||||
text: params.from,
|
||||
},
|
||||
{
|
||||
label: "To",
|
||||
text: Array.isArray(params.to) ? params.to.join(", ") : params.to,
|
||||
},
|
||||
...(params.subject ? [{ label: "Subject", text: params.subject }] : []),
|
||||
],
|
||||
retry: retry.standardBackoff,
|
||||
},
|
||||
onError
|
||||
);
|
||||
/**
|
||||
* Access the Resend Emails API
|
||||
* @example
|
||||
* ```ts
|
||||
* const response = await io.resend.emails.send("📧", {
|
||||
* to: payload.to,
|
||||
* subject: payload.subject,
|
||||
* text: payload.text,
|
||||
* from: "hello@trigger.dev"
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
get emails() {
|
||||
return new Emails(this.runTask.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the Resend Batch Emails API
|
||||
* @example
|
||||
* ```ts
|
||||
* const response = await io.resend.batch.send("📧", [{
|
||||
* to: payload.to,
|
||||
* subject: payload.subject,
|
||||
* text: payload.text,
|
||||
* from: "hello@trigger.dev"
|
||||
* }]);
|
||||
* ```
|
||||
*/
|
||||
get batch() {
|
||||
return new Batch(this.runTask.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Please use resend.emails.send instead
|
||||
*/
|
||||
async sendEmail(...args: Parameters<typeof this.emails.send>) {
|
||||
return this.emails.send(...args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { ErrorResponse } from "resend";
|
||||
|
||||
interface ResendErrorResponse extends ErrorResponse {
|
||||
statusCode: number;
|
||||
}
|
||||
|
||||
function isRequestError(error: unknown): error is ResendErrorResponse {
|
||||
return (
|
||||
typeof error === "object" &&
|
||||
error !== null &&
|
||||
"message" in error &&
|
||||
"name" in error &&
|
||||
typeof error.name === "string" &&
|
||||
"statusCode" in error &&
|
||||
typeof error.statusCode === "number"
|
||||
);
|
||||
}
|
||||
|
||||
// See https://resend.com/docs/api-reference/errors
|
||||
const retriableErrorCode = ["rate_limit_exceeded", "application_error", "internal_server_error"];
|
||||
|
||||
export function handleResendError(error: unknown) {
|
||||
if (isRequestError(error)) {
|
||||
if (retriableErrorCode.includes(error.name)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return {
|
||||
skipRetrying: true,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (typeof error === "string") {
|
||||
return new Error(error);
|
||||
}
|
||||
|
||||
if (
|
||||
typeof error === "object" &&
|
||||
error !== null &&
|
||||
"message" in error &&
|
||||
typeof error.message === "string"
|
||||
) {
|
||||
return new Error(error.message);
|
||||
}
|
||||
|
||||
return new Error("Unknown error");
|
||||
}
|
||||
Generated
+61
-12
@@ -530,13 +530,13 @@ importers:
|
||||
'@trigger.dev/sdk': workspace:^2.2.4
|
||||
'@trigger.dev/tsconfig': workspace:*
|
||||
'@types/node': '18'
|
||||
resend: ^1.0.0
|
||||
resend: ^2.0.0
|
||||
rimraf: ^3.0.2
|
||||
tsup: ^6.5.0
|
||||
dependencies:
|
||||
'@trigger.dev/integration-kit': link:../../packages/integration-kit
|
||||
'@trigger.dev/sdk': link:../../packages/trigger-sdk
|
||||
resend: 1.0.0
|
||||
resend: 2.0.0
|
||||
devDependencies:
|
||||
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
|
||||
'@types/node': 18.15.13
|
||||
@@ -10601,6 +10601,16 @@ packages:
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-email/render/0.0.9:
|
||||
resolution: {integrity: sha512-nrim7wiACnaXsGtL7GF6jp3Qmml8J6vAjAH88jkC8lIbfNZaCyuPQHANjyYIXlvQeAbsWADQJFZgOHUqFqjh/A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
dependencies:
|
||||
html-to-text: 9.0.5
|
||||
pretty: 2.0.0
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-email/section/0.0.1:
|
||||
resolution: {integrity: sha512-Pb2HcGNhTOtFRJVB+Kq2vTUnd8M+LuZBuHfpUD16ua/m2/mbW5WeXAfSuJ2Tl6qspzvDKLHqVX+o6HBc1qgl2Q==}
|
||||
dependencies:
|
||||
@@ -11154,6 +11164,13 @@ packages:
|
||||
selderee: 0.10.0
|
||||
dev: false
|
||||
|
||||
/@selderee/plugin-htmlparser2/0.11.0:
|
||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
selderee: 0.11.0
|
||||
dev: false
|
||||
|
||||
/@sendgrid/client/7.7.0:
|
||||
resolution: {integrity: sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==}
|
||||
engines: {node: 6.* || 8.* || >=10.*}
|
||||
@@ -17627,7 +17644,6 @@ packages:
|
||||
/deepmerge/4.3.1:
|
||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/default-browser-id/3.0.0:
|
||||
resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==}
|
||||
@@ -20552,7 +20568,7 @@ packages:
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.5.3
|
||||
cosmiconfig: 7.1.0
|
||||
deepmerge: 4.2.2
|
||||
deepmerge: 4.3.1
|
||||
fs-extra: 10.1.0
|
||||
memfs: 3.5.3
|
||||
minimatch: 3.1.2
|
||||
@@ -21581,6 +21597,17 @@ packages:
|
||||
selderee: 0.10.0
|
||||
dev: false
|
||||
|
||||
/html-to-text/9.0.5:
|
||||
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
'@selderee/plugin-htmlparser2': 0.11.0
|
||||
deepmerge: 4.3.1
|
||||
dom-serializer: 2.0.0
|
||||
htmlparser2: 8.0.2
|
||||
selderee: 0.11.0
|
||||
dev: false
|
||||
|
||||
/html-void-elements/2.0.1:
|
||||
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
|
||||
|
||||
@@ -21616,6 +21643,15 @@ packages:
|
||||
entities: 4.4.0
|
||||
dev: false
|
||||
|
||||
/htmlparser2/8.0.2:
|
||||
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
domutils: 3.0.1
|
||||
entities: 4.4.0
|
||||
dev: false
|
||||
|
||||
/http-cache-semantics/4.1.1:
|
||||
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
|
||||
|
||||
@@ -26130,6 +26166,13 @@ packages:
|
||||
peberminta: 0.8.0
|
||||
dev: false
|
||||
|
||||
/parseley/0.12.1:
|
||||
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
|
||||
dependencies:
|
||||
leac: 0.6.0
|
||||
peberminta: 0.9.0
|
||||
dev: false
|
||||
|
||||
/parseurl/1.3.3:
|
||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -26222,6 +26265,10 @@ packages:
|
||||
resolution: {integrity: sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==}
|
||||
dev: false
|
||||
|
||||
/peberminta/0.9.0:
|
||||
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
|
||||
dev: false
|
||||
|
||||
/peek-stream/1.1.3:
|
||||
resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==}
|
||||
dependencies:
|
||||
@@ -28218,15 +28265,11 @@ packages:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/resend/1.0.0:
|
||||
resolution: {integrity: sha512-8LEE4gncmcm8bsvxvahZFpFk5hxUrKdagqWoX/MRXVU2YZ9coYxqZDeDYXG9pexz1A694bjE1hiQbBAA+bHAow==}
|
||||
engines: {node: '>=16'}
|
||||
/resend/2.0.0:
|
||||
resolution: {integrity: sha512-jAh0DN84ZjjmzGM2vMjJ1hphPBg1mG98dzopF7kJzmin62v8ESg4og2iCKWdkAboGOT2SeO5exbr/8Xh8gLddw==}
|
||||
engines: {node: '>=18'}
|
||||
dependencies:
|
||||
'@react-email/render': 0.0.7
|
||||
node-fetch: 2.6.12
|
||||
type-fest: 3.13.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
'@react-email/render': 0.0.9
|
||||
dev: false
|
||||
|
||||
/resize-observer-polyfill/1.5.1:
|
||||
@@ -28620,6 +28663,12 @@ packages:
|
||||
parseley: 0.11.0
|
||||
dev: false
|
||||
|
||||
/selderee/0.11.0:
|
||||
resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==}
|
||||
dependencies:
|
||||
parseley: 0.12.1
|
||||
dev: false
|
||||
|
||||
/sembear/0.5.2:
|
||||
resolution: {integrity: sha512-Ij1vCAdFgWABd7zTg50Xw1/p0JgESNxuLlneEAsmBrKishA06ulTTL/SHGmNy2Zud7+rKrHTKNI6moJsn1ppAQ==}
|
||||
dependencies:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createExpressServer } from "@trigger.dev/express";
|
||||
import { Resend } from "@trigger.dev/resend";
|
||||
import { TriggerClient, eventTrigger } from "@trigger.dev/sdk";
|
||||
import { TriggerClient, eventTrigger, invokeTrigger } from "@trigger.dev/sdk";
|
||||
import { z } from "zod";
|
||||
|
||||
export const client = new TriggerClient({
|
||||
@@ -20,12 +20,73 @@ client.defineJob({
|
||||
id: "send-resend-email",
|
||||
name: "Send Resend Email",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "send.email",
|
||||
trigger: invokeTrigger({
|
||||
schema: z.object({
|
||||
to: z.union([z.string(), z.array(z.string())]),
|
||||
subject: z.string(),
|
||||
text: z.string(),
|
||||
to: z.union([z.string(), z.array(z.string())]).default("eric@trigger.dev"),
|
||||
subject: z.string().default("This is a test email"),
|
||||
text: z.string().default("This is a test email"),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
resend,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
const response = await io.resend.emails.send("📧", {
|
||||
to: payload.to,
|
||||
subject: payload.subject,
|
||||
text: payload.text,
|
||||
from: "Trigger.dev <hello@email.trigger.dev>",
|
||||
});
|
||||
|
||||
await io.logger.info("Sent email", { response });
|
||||
|
||||
const emailDetails = await io.resend.emails.get("get-email", response.id);
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "batch-send-resend-email",
|
||||
name: "Batch Send Resend Email",
|
||||
version: "0.1.0",
|
||||
trigger: invokeTrigger({
|
||||
schema: z.object({
|
||||
to: z.union([z.string(), z.array(z.string())]).default("eric@trigger.dev"),
|
||||
subject: z.string().default("This is a test email"),
|
||||
text: z.string().default("This is a test email"),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
resend,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
const response = await io.resend.batch.send("📧", [
|
||||
{
|
||||
to: payload.to,
|
||||
subject: payload.subject,
|
||||
text: payload.text,
|
||||
from: "Trigger.dev <hello@email.trigger.dev>",
|
||||
},
|
||||
{
|
||||
to: payload.to,
|
||||
subject: payload.subject,
|
||||
text: payload.text,
|
||||
from: "Trigger.dev <hello@email.trigger.dev>",
|
||||
},
|
||||
]);
|
||||
|
||||
await io.logger.info("Sent batched email", { response });
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "send-resend-email-deprecated",
|
||||
name: "Send Resend Email Deprecated",
|
||||
version: "0.1.0",
|
||||
trigger: invokeTrigger({
|
||||
schema: z.object({
|
||||
to: z.union([z.string(), z.array(z.string())]).default("eric@trigger.dev"),
|
||||
subject: z.string().default("This is a test email"),
|
||||
text: z.string().default("This is a test email"),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
|
||||
Reference in New Issue
Block a user