Ad-hoc sends
When you don’t need a reusable definition, fire one channel directly:
import { notify } from "@warlock.js/notifications";
await notify.mail(user, { subject: "Welcome", html: "<p>Hi!</p>" });await notify.database(user, { type: "welcome", title: "Welcome!" });notify.<channel> is a typed proxy — payload is checked against the channel’s registry entry, and it works for any registered channel including custom ones. For multi-channel sends, use defineNotification; there’s no inline multi-channel form on purpose.
Raw targets
Section titled “Raw targets”Pass a string instead of a model to address it directly — no recipient lookup:
await notify.mail("guest@example.com", { subject: "Receipt", html: "…" });Runtime-dynamic channel
Section titled “Runtime-dynamic channel”When the channel name isn’t a compile-time literal:
const channel = await pickChannel(user);await notify.channel(channel).send(user, payload);This is the only path with an unknown-typed payload — prefer the literal notify.<channel> when the name is known at compile time. Even here, user (the first argument) is what decides the recipient: for the database channel, a recipientId-shaped key on payload is stripped before the row is written, so a payload built from request JSON can’t redirect the notification to a different recipient. See the in-app store — write side.
Opting into gating
Section titled “Opting into gating”Preference/rate-limit gates need a notification type. Ad-hoc sends provide it explicitly, or it’s auto-detected from a database payload’s type:
await notify.mail(user, payload, { type: "marketing.weekly" }); // explicitawait notify.database(user, { type: "welcome", title: "Hi" }); // auto-detectedWithout a type, ad-hoc sends skip the preference gate (there’s nothing to gate on). force: true bypasses preferences; rate limits always apply when a type is known.
Errors
Section titled “Errors”A send to an unregistered channel rejects with ChannelNotFoundError immediately. A channel whose route() returns undefined for the recipient rejects with UnresolvableRouteError.
- Define a notification — the reusable, multi-channel path.
- Custom channels — make
notify.<yourChannel>exist.