@everystack/notifications
v0.2.1
Published
Notification delivery for Expo apps — pluggable providers, hooks pipeline, EventBridge Scheduler
Readme
@everystack/notifications
Notification delivery with pluggable providers and hooks pipeline. Notifications are jobs — they publish to SQS via @everystack/jobs and use EventBridge Scheduler for cancel/reschedule.
Install
pnpm add @everystack/notifications @everystack/jobsFor SES email delivery:
pnpm add @aws-sdk/client-sesEntry Points
| Import | Description |
|--------|-------------|
| @everystack/notifications | Service, handler, console provider, types |
| @everystack/notifications/plugin | Server plugin |
| @everystack/notifications/ses | AWS SES email provider |
Quick Start
import { createNotificationService, createConsoleProvider } from '@everystack/notifications';
// 1. Create service (wraps publishJob from your job adapter)
const notifications = createNotificationService({
publishJob: jobClient.publish.bind(jobClient),
cancelJob: jobClient.cancel.bind(jobClient),
rescheduleJob: jobClient.reschedule.bind(jobClient),
});
// 2. Send immediately
const id = await notifications.send({
channel: 'email',
to: '[email protected]',
subject: 'Welcome',
body: 'Hello!',
html: '<h1>Hello!</h1>',
});
// 3. Schedule for later (uses EventBridge Scheduler)
const id = await notifications.schedule(
{ channel: 'email', to: '[email protected]', subject: 'Reminder', body: 'Hey!' },
new Date('2026-07-01T09:00:00Z'),
);
// 4. Cancel or reschedule
await notifications.cancel(id);
await notifications.reschedule(id, new Date('2026-08-01T09:00:00Z'));Worker Handler
Register notification:send in your SQS job handler:
import { createNotificationHandler } from '@everystack/notifications';
import { createSesProvider } from '@everystack/notifications/ses';
const notificationHandler = createNotificationHandler({
providers: [
createSesProvider({ from: '[email protected]', region: 'us-east-1' }),
],
hooks: {
beforeSend: async (payload) => {
// Transform, filter, or cancel (return null to skip)
return payload;
},
afterSend: async (payload, result) => {
// Log, record metrics, trigger follow-ups
},
},
});
// Register in your SQS handler
const sqsHandler = createSqsJobHandler({
handlers: {
'notification:send': notificationHandler,
// ...other job handlers
},
adapter: jobAdapter,
});Providers
Console (dev/test)
Logs notifications to console. Always succeeds.
import { createConsoleProvider } from '@everystack/notifications';
const provider = createConsoleProvider(); // defaults to 'email' channel
const smsProvider = createConsoleProvider('sms');SES (email)
AWS SES email delivery. Lazy-loads @aws-sdk/client-ses.
import { createSesProvider } from '@everystack/notifications/ses';
const provider = createSesProvider({
from: '[email protected]',
region: 'us-east-1', // optional, defaults to AWS_REGION
});Maps payload.to, payload.subject, payload.body, and payload.html to SendEmailCommand.
Custom Providers
Implement NotificationProvider:
import type { NotificationProvider } from '@everystack/notifications';
const sendgridProvider: NotificationProvider = {
channel: 'email',
async send(payload) {
const res = await fetch('https://api.sendgrid.com/v3/mail/send', { ... });
return res.ok
? { success: true, messageId: res.headers.get('x-message-id') ?? undefined }
: { success: false, error: await res.text() };
},
};Plugin
For apps using the everystack plugin system:
import { notificationsPlugin } from '@everystack/notifications/plugin';
import { createSesProvider } from '@everystack/notifications/ses';
// In your plugin list
const plugins = [
notificationsPlugin({
providers: [createSesProvider({ from: '[email protected]' })],
hooks: { ... },
}),
];
// Exposes ctx.notifications in plugin context
// Contributes 'notification:send' named handlerHooks Pipeline
beforeSend(payload) → provider.send(resolved) → afterSend(resolved, result)
↓ null = cancel ↓ failure = throw → SQS retry- beforeSend — transform the payload or return
nullto cancel (job completes without sending) - afterSend — runs after provider send, receives the result. Called even on failure.
Peer Dependencies
| Package | Version | Required |
|---------|---------|----------|
| @everystack/jobs | >=0.2.0 | Always |
| @aws-sdk/client-ses | >=3.0.0 | For SES provider |
| @everystack/server | >=0.1.0 | For plugin |
Part of everystack — a self-hosted application stack for Expo apps on AWS.
License
AGPL-3.0-only
