diff --git a/package-lock.json b/package-lock.json index b36ae31a..7d2c4307 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@base44/sdk", - "version": "0.8.44", + "version": "0.8.45", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@base44/sdk", - "version": "0.8.44", + "version": "0.8.45", "license": "MIT", "dependencies": { "axios": "^1.18.1", diff --git a/package.json b/package.json index e4afe3fb..5d1b43a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@base44/sdk", - "version": "0.8.44", + "version": "0.8.45", "description": "JavaScript SDK for Base44 API", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/index.ts b/src/index.ts index 6886671b..16273cfd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -70,6 +70,7 @@ export type { GenerateImageResult, UploadFileParams, UploadFileResult, + EmailAttachment, SendEmailParams, SendEmailResult, ExtractDataFromUploadedFileParams, diff --git a/src/modules/integrations.types.ts b/src/modules/integrations.types.ts index 89369e7e..6f013bd2 100644 --- a/src/modules/integrations.types.ts +++ b/src/modules/integrations.types.ts @@ -87,20 +87,67 @@ export interface UploadFileResult { file_url: string; } +/** Requires at least one key from Keys to be present. */ +type RequireAtLeastOne = + Pick> & + { [K in Keys]-?: Required> & Partial>> }[Keys]; + /** - * Parameters for the SendEmail function. + * A file to attach to a `SendEmail` call. + * + * Provide exactly one content source per attachment: + * - `content` — base64-encoded bytes generated at runtime (e.g. a PDF built in the function). + * - `file_url` — a URL returned by `UploadFile` or `UploadPrivateFile` for a file already in storage. + * + * Allowed extensions: `pdf`, `png`, `jpg`/`jpeg`, `gif`, `webp`, `csv`, `txt`, `md`, `ics`, `xlsx`, `docx`. + * Limits: up to **5 attachments**, **5 MB each**, **10 MB total**. */ -export interface SendEmailParams { +export type EmailAttachment = + | { /** Attachment filename, including extension. */ filename: string; /** Base64-encoded file content. */ content: string; file_url?: never } + | { /** Attachment filename, including extension. */ filename: string; /** URL from `UploadFile` or `UploadPrivateFile`. */ file_url: string; content?: never }; + +interface SendEmailParamsBase { /** Recipient email address. */ to: string; /** Email subject line. */ subject: string; - /** Plain text email body content. */ - body: string; + /** HTML email body content. Alias of `html` — set one or the other, never both. */ + body?: string; + /** HTML email body content. The same thing as `body` under an explicit name. */ + html?: string; + /** + * Plain-text email body content. + * + * On its own, sends a plain-text (`text/plain`) email. Alongside `body`/`html`, + * both parts go out as a single `multipart/alternative` email and the recipient's + * mail client renders whichever it prefers — so the two must say the same thing. + */ + text?: string; /** The name of the sender. If omitted, the app's name will be used. */ from_name?: string; + /** + * Files to attach to the email. Up to 5 attachments, 5 MB each, 10 MB total. + * + * Each item must have a `filename` and exactly one content source: + * `content` (inline base64) or `file_url` (storage reference). + */ + attachments?: EmailAttachment[]; } +/** + * Parameters for the SendEmail function. + * + * At least one of `body`, `html`, or `text` is required; the backend returns 422 otherwise. + * + * | Fields set | Result | + * |---|---| + * | `body` or `html` alone | `text/html` email | + * | `text` alone | `text/plain` email | + * | `body`/`html` + `text` | `multipart/alternative` — one email, two representations; recipient sees whichever their client prefers — both parts must say the same thing | + * | `body` + `html` | **422** — same slot, set one not both | + */ +export type SendEmailParams = RequireAtLeastOne; + export type SendEmailResult = any; /** diff --git a/tests/types/integrations.types.ts b/tests/types/integrations.types.ts new file mode 100644 index 00000000..b74dabb5 --- /dev/null +++ b/tests/types/integrations.types.ts @@ -0,0 +1,81 @@ +import type { SendEmailParams, EmailAttachment } from "../../src/index.js"; + +// body-only (existing callers must still compile — backward compat) +const bodyOnly = { + to: "user@example.com", + subject: "Hello", + body: "

Hello

", +} satisfies SendEmailParams; + +// html-only +const htmlOnly = { + to: "user@example.com", + subject: "Hello", + html: "

Hello

", +} satisfies SendEmailParams; + +// text-only +const textOnly = { + to: "user@example.com", + subject: "Hello", + text: "Hello", +} satisfies SendEmailParams; + +// html + text → multipart/alternative +const htmlAndText = { + to: "user@example.com", + subject: "Hello", + html: "

Hello

", + text: "Hello", +} satisfies SendEmailParams; + +// body + text → multipart/alternative +const bodyAndText = { + to: "user@example.com", + subject: "Hello", + body: "

Hello

", + text: "Hello", +} satisfies SendEmailParams; + +// optional from_name +const withFromName = { + to: "user@example.com", + subject: "Hello", + body: "

Hello

", + from_name: "My App", +} satisfies SendEmailParams; + +// attachments: inline base64 +const inlineAttachment = { + filename: "receipt.pdf", + content: "JVBERi0x", +} satisfies EmailAttachment; + +// attachments: storage reference +const storedAttachment = { + filename: "logo.png", + file_url: "https://storage.example.com/logo.png", +} satisfies EmailAttachment; + +// with attachments on a full params object +const withAttachments = { + to: "user@example.com", + subject: "Invoice", + body: "

See attached.

", + attachments: [inlineAttachment, storedAttachment], +} satisfies SendEmailParams; + +// omitting all three content fields must be a compile error +// @ts-expect-error At least one of body/html/text is required. +const missingContent: SendEmailParams = { to: "user@example.com", subject: "Hello" }; + +void bodyOnly; +void htmlOnly; +void textOnly; +void htmlAndText; +void bodyAndText; +void withFromName; +void inlineAttachment; +void storedAttachment; +void withAttachments; +void missingContent;