@formepdf/resend 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,37 +11,29 @@ npm install @formepdf/resend resend @formepdf/react @formepdf/core
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
+ import { renderDocument } from '@formepdf/core';
14
15
  import { sendPdf } from '@formepdf/resend';
16
+ import { MyInvoice } from './templates/invoice';
15
17
 
18
+ // Render the PDF first — works in plain .ts files
19
+ const pdfBytes = await renderDocument(MyInvoice({ customer, items }));
20
+
21
+ // Then email it
16
22
  const { data, error } = await sendPdf({
17
23
  resendApiKey: process.env.RESEND_API_KEY,
18
24
  from: 'Acme Corp <billing@acme.com>',
19
- to: 'customer@email.com',
25
+ to: customer.email,
20
26
  subject: 'Invoice #001',
21
- template: 'invoice',
22
- data: {
23
- invoiceNumber: 'INV-001',
24
- date: 'February 25, 2026',
25
- dueDate: 'March 27, 2026',
26
- company: { name: 'Acme Corp', initials: 'AC', address: '123 Main St', cityStateZip: 'San Francisco, CA 94105', email: 'billing@acme.com' },
27
- billTo: { name: 'Jane Smith', company: 'Smith Co', address: '456 Oak Ave', cityStateZip: 'Portland, OR 97201', email: 'jane@smith.co' },
28
- shipTo: { name: 'Jane Smith', address: '456 Oak Ave', cityStateZip: 'Portland, OR 97201' },
29
- items: [
30
- { description: 'Consulting', quantity: 10, unitPrice: 150 },
31
- ],
32
- taxRate: 0.08,
33
- paymentTerms: 'Net 30',
34
- },
27
+ pdf: pdfBytes,
28
+ filename: 'invoice-001.pdf',
35
29
  });
36
-
37
- if (error) {
38
- console.error(error.message);
39
- }
40
30
  ```
41
31
 
42
- One call. PDF rendered, email sent, invoice attached. Returns Resend's `{ data, error }` shape.
32
+ Generate the PDF separately, email it with `sendPdf`. You control the rendering, and the same bytes can go to email + storage + whatever else. Returns Resend's `{ data, error }` directly.
33
+
34
+ ## Render Callback
43
35
 
44
- ## Custom Templates
36
+ For one-liners in `.tsx` files:
45
37
 
46
38
  ```typescript
47
39
  import { sendPdf } from '@formepdf/resend';
@@ -56,6 +48,35 @@ const { data, error } = await sendPdf({
56
48
  });
57
49
  ```
58
50
 
51
+ ## Built-in Templates
52
+
53
+ Skip the render step and use a built-in template:
54
+
55
+ ```typescript
56
+ import { sendPdf } from '@formepdf/resend';
57
+
58
+ const { data, error } = await sendPdf({
59
+ resendApiKey: process.env.RESEND_API_KEY,
60
+ from: 'Acme Corp <billing@acme.com>',
61
+ to: 'customer@email.com',
62
+ subject: 'Invoice #001',
63
+ template: 'invoice',
64
+ data: {
65
+ invoiceNumber: 'INV-001',
66
+ date: 'February 25, 2026',
67
+ dueDate: 'March 27, 2026',
68
+ company: { name: 'Acme Corp', initials: 'AC', address: '123 Main St', cityStateZip: 'San Francisco, CA 94105', email: 'billing@acme.com' },
69
+ billTo: { name: 'Jane Smith', company: 'Smith Co', address: '456 Oak Ave', cityStateZip: 'Portland, OR 97201', email: 'jane@smith.co' },
70
+ shipTo: { name: 'Jane Smith', address: '456 Oak Ave', cityStateZip: 'Portland, OR 97201' },
71
+ items: [
72
+ { description: 'Consulting', quantity: 10, unitPrice: 150 },
73
+ ],
74
+ taxRate: 0.08,
75
+ paymentTerms: 'Net 30',
76
+ },
77
+ });
78
+ ```
79
+
59
80
  ## Add PDF to an Existing Resend Call
60
81
 
61
82
  ```typescript
@@ -88,9 +109,10 @@ Render a PDF and email it. Returns Resend's `{ data, error }` shape directly.
88
109
  | `from` | `string` | Yes | Sender address |
89
110
  | `to` | `string \| string[]` | Yes | Recipient(s) |
90
111
  | `subject` | `string` | Yes | Email subject |
91
- | `template` | `string` | One of template/render | Built-in template name |
112
+ | `pdf` | `Uint8Array` | One of pdf/render/template | Pre-rendered PDF bytes |
113
+ | `render` | `() => ReactElement` | One of pdf/render/template | Render callback |
114
+ | `template` | `string` | One of pdf/render/template | Built-in template name |
92
115
  | `data` | `object` | With template | Data for the template |
93
- | `render` | `() => ReactElement` | One of template/render | Custom render function |
94
116
  | `filename` | `string` | No | PDF filename (default: `{template}.pdf`) |
95
117
  | `html` | `string` | No | Email body HTML |
96
118
  | `text` | `string` | No | Email body plain text |
package/dist/send-pdf.js CHANGED
@@ -3,22 +3,25 @@ import { renderDocument } from '@formepdf/core';
3
3
  import { getTemplate } from './templates/index.js';
4
4
  import { buildDefaultEmail } from './default-email.js';
5
5
  export async function sendPdf(options) {
6
- const { resendApiKey, from, to, subject, template, data, render, filename, html, text, react, cc, bcc, replyTo, tags, headers, } = options;
7
- let element;
8
- if (render) {
9
- element = render();
6
+ const { resendApiKey, from, to, subject, filename, html, text, react, cc, bcc, replyTo, tags, headers, } = options;
7
+ let pdfBytes;
8
+ if ('pdf' in options && options.pdf) {
9
+ pdfBytes = options.pdf;
10
10
  }
11
- else if (template) {
12
- const templateFn = getTemplate(template);
11
+ else if ('render' in options && options.render) {
12
+ pdfBytes = await renderDocument(options.render());
13
+ }
14
+ else if ('template' in options && options.template) {
15
+ const templateFn = getTemplate(options.template);
13
16
  if (!templateFn) {
14
- throw new Error(`Unknown template: "${template}". Use listTemplates() to see available templates.`);
17
+ throw new Error(`Unknown template: "${options.template}". Use listTemplates() to see available templates.`);
15
18
  }
16
- element = templateFn(data || {});
19
+ pdfBytes = await renderDocument(templateFn(options.data || {}));
17
20
  }
18
21
  else {
19
- throw new Error('Either "template" or "render" must be provided.');
22
+ throw new Error('One of "pdf", "render", or "template" must be provided.');
20
23
  }
21
- const pdfBytes = await renderDocument(element);
24
+ const template = 'template' in options ? options.template : undefined;
22
25
  const pdfFilename = filename || `${template || 'document'}.pdf`;
23
26
  const attachment = {
24
27
  filename: pdfFilename,
@@ -27,6 +30,7 @@ export async function sendPdf(options) {
27
30
  let emailHtml = html;
28
31
  let emailText = text;
29
32
  if (!html && !text && !react) {
33
+ const data = 'data' in options ? options.data : undefined;
30
34
  const defaultEmail = buildDefaultEmail(template, data);
31
35
  emailHtml = defaultEmail.html;
32
36
  emailText = defaultEmail.text;
package/dist/types.d.ts CHANGED
@@ -17,17 +17,25 @@ interface BaseOptions {
17
17
  }[];
18
18
  headers?: Record<string, string>;
19
19
  }
20
+ interface PdfBytesOptions extends BaseOptions {
21
+ pdf: Uint8Array;
22
+ template?: never;
23
+ data?: never;
24
+ render?: never;
25
+ }
20
26
  interface TemplateOptions extends BaseOptions {
27
+ pdf?: never;
21
28
  template: string;
22
29
  data?: Record<string, any>;
23
30
  render?: never;
24
31
  }
25
32
  interface RenderOptions extends BaseOptions {
33
+ pdf?: never;
26
34
  template?: never;
27
35
  data?: never;
28
36
  render: () => ReactElement;
29
37
  }
30
- export type SendPdfOptions = TemplateOptions | RenderOptions;
38
+ export type SendPdfOptions = PdfBytesOptions | TemplateOptions | RenderOptions;
31
39
  export interface RenderAttachOptions {
32
40
  template?: string;
33
41
  data?: Record<string, any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formepdf/resend",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Render a PDF and email it in one call — Forme + Resend",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,8 +12,8 @@
12
12
  "dist"
13
13
  ],
14
14
  "dependencies": {
15
- "@formepdf/react": "0.6.0",
16
- "@formepdf/core": "0.6.0"
15
+ "@formepdf/react": "0.6.1",
16
+ "@formepdf/core": "0.6.1"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "resend": ">=3.0.0"