Node.js SDK
The norq npm package provides a TypeScript SDK for sending and linting notification templates from Node.js applications.
Install
npm install @suprsend/norqThe package includes the norq binary for your platform (via optional dependencies for each OS/architecture).
Quick start
import { Norq } from "@suprsend/norq";
const notif = new Norq();
// Send a notification
const result = await notif.send("transactional/order-shipped", {
to: { email: "gaurav@example.com", phone: "+1234567890" },
data: { user: { first_name: "Gaurav" }, order: { id: "ORD-123" } },
});Constructor options
const notif = new Norq({
config: "./path/to/norq.config.yaml", // config file path
binaryPath: "/usr/local/bin/norq", // explicit binary path
cwd: "/path/to/project", // working directory
logger: myLogger, // structured logger
recipientResolver: myResolver, // user ID -> Recipient
});| Option | Type | Description |
|---|---|---|
config |
string |
Path to norq.config.yaml |
binaryPath |
string |
Explicit path to the norq binary |
cwd |
string |
Working directory (defaults to process.cwd()) |
logger |
Logger |
Structured logger for send/compile events |
recipientResolver |
RecipientResolver |
Resolves user ID strings to Recipient objects |
API
send(id, opts)
Compile and deliver a notification.
const result = await notif.send("transactional/welcome", {
to: { email: "user@example.com" }, // Recipient object
// or: to: "user-123", // user ID (requires recipientResolver)
data: { user: { first_name: "Gaurav" } },
channels: ["email"], // optional: send only these channels
dryRun: false, // optional: compile without sending
});
// result.results -> SendResult[] (one per channel)
// result.skipped -> SkippedChannel[] (channels that were skipped and why)lint(id?)
Lint notification templates.
const results = await notif.lint(); // all notifications
const results = await notif.lint("transactional/welcome"); // one notification
for (const result of results) {
for (const diag of result.diagnostics) {
console.log(`${diag.severity}: ${diag.message} [${diag.rule}]`);
}
}Recipient
const recipient: Recipient = {
email: "user@example.com",
phone: "+1234567890",
slack: { channel_id: "C01234567" },
push: {
tokens: [
{ token: "fcm-token-here", platform: "android" },
{ token: "apns-token-here", platform: "ios" },
],
},
whatsapp: { phone: "+1234567890" },
msteams: { webhook_url: "https://..." },
};The SDK intersects available channels (notification templates vs. recipient contact info) and silently skips unreachable channels, reporting skip reasons in result.skipped.
RecipientResolver
To send by user ID, implement a RecipientResolver:
const notif = new Norq({
recipientResolver: {
async resolve(userId: string): Promise<Recipient> {
const user = await db.users.findById(userId);
return {
email: user.email,
phone: user.phone,
};
},
},
});
await notif.send("transactional/welcome", { to: "user-123", data: { ... } });Logger
const notif = new Norq({
logger: {
info(msg, meta) { console.log(msg, meta); },
warn(msg, meta) { console.warn(msg, meta); },
error(msg, meta) { console.error(msg, meta); },
},
});The SDK logs compile and send events with timing, channel, and provider metadata.
Payload types
interface EmailPayload {
subject: string;
html: string;
text: string;
}
interface SmsPayload {
body: string;
segments: number;
encoding: string; // "gsm7" or "ucs2"
}
interface SlackPayload {
blocks: unknown[];
text: string;
}
interface PushPayload {
title: string;
body: string;
image: string | null;
action_url: string | null;
platforms: string[];
}
interface WhatsAppPayload {
type: string;
payload: unknown;
}
interface TeamsPayload {
card: unknown;
}Error handling
import { NorqError } from "@suprsend/norq";
try {
await notif.send("transactional/welcome", { to: "user-123", data: { ... } });
} catch (err) {
if (err instanceof NorqError) {
console.error("Norq error:", err.message);
}
}Codegen
Generate typed bindings for compile-time type safety:
norq codegen --lang typescript --out src/generated/norq.tsThis generates typed interfaces for each notification's data shape and channel availability.