Decorators

Decorators

Wrap any channel transport with retry, fallback, preview, or idempotency.

Decorators wrap another transport. The channel sender still calls send the same way — only the transport path changes. Retry, fallback, and weighted fallback work for email, SMS, WhatsApp, and push. Preview and idempotency remain email-oriented.

The one rule

Pass the outermost decorator to the matching channel sender (createMailer, createSmsSender, …).

Available decorators

DecoratorImportChannels
Previewsently/transports/previewEmail
Retrysently/transports/retryEmail, SMS, WhatsApp, Push
Fallbacksently/transports/fallbackEmail, SMS, WhatsApp, Push
Weighted fallbacksently/transports/weighted-fallbackEmail, SMS, WhatsApp, Push
Idempotencysently/idempotencyEmail

Typical stack (email)

import { createMailer } from "sently/mailer";
import { ResendTransport } from "sently/transports/resend";
import { RetryTransport } from "sently/transports/retry";
import { FallbackTransport } from "sently/transports/fallback";

const transport = new FallbackTransport([
  new RetryTransport(new ResendTransport({ apiKey: process.env.RESEND_API_KEY! })),
  new ResendTransport({ apiKey: process.env.RESEND_BACKUP_KEY! }),
]);

const mailer = await createMailer({ transport });

Typical stack (SMS)

import { createSmsSender } from "sently/sms";
import { FallbackTransport } from "sently/transports/fallback";
import { TaqnyatSmsTransport } from "sently/transports/taqnyat-sms";
import { UnifonicTransport } from "sently/transports/unifonic";

const sms = createSmsSender({
  transport: new FallbackTransport([
    new TaqnyatSmsTransport({ bearerToken: process.env.TAQNYAT_TOKEN!, sender: "MyBrand" }),
    new UnifonicTransport({ appSid: process.env.UNIFONIC_APPSID!, senderId: "MyBrand" }),
  ]),
});

Learn more

Next

On this page