mirror of
https://github.com/devkitshq/notifkit.git
synced 2026-10-19 18:24:52 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Example project demonstrating how to use Notifkit via its HTTP API — no SDK,
|
||||
* just fetch. Any language that can POST JSON works the same way.
|
||||
*
|
||||
* Before running this, start a Notifkit server. The custom-server example is
|
||||
* one:
|
||||
* $ cd ../custom-server && node index.js
|
||||
*
|
||||
* To run this example:
|
||||
* $ ADMIN_API_KEY=my_super_secret_admin_key npm start
|
||||
*/
|
||||
|
||||
const API_BASE = process.env.NOTIFKIT_API_URL || 'http://localhost:3000/v1';
|
||||
const API_KEY = process.env.ADMIN_API_KEY || 'my_super_secret_admin_key';
|
||||
|
||||
// Every /v1 route is authenticated. Only /health, /live, /ready and /metrics are not.
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${API_KEY}`,
|
||||
};
|
||||
|
||||
async function main() {
|
||||
console.log('🚀 Starting Notifkit example...\n');
|
||||
|
||||
try {
|
||||
// 1. Sync Templates (Configure how notifications should look)
|
||||
console.log('1️⃣ Syncing email template...');
|
||||
const templateRes = await fetch(`${API_BASE}/templates`, {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
templates: [{
|
||||
id: 'welcome_email',
|
||||
channel: 'email',
|
||||
// The per-channel fields live under `content`.
|
||||
content: {
|
||||
subject: 'Welcome to Notifkit, {{name}}!',
|
||||
html: '<h1>Hello {{name}}</h1><p>Thanks for signing up!</p>',
|
||||
text: 'Hello {{name}}! Thanks for signing up!'
|
||||
}
|
||||
}]
|
||||
})
|
||||
});
|
||||
console.log('Template Response:', await templateRes.json());
|
||||
console.log();
|
||||
|
||||
// 2. Create a User (Register a recipient)
|
||||
console.log('2️⃣ Registering a user...');
|
||||
const userRes = await fetch(`${API_BASE}/users`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
id: 'user_123',
|
||||
email: 'test@example.com',
|
||||
preferences: {
|
||||
channels: { email: true }
|
||||
}
|
||||
})
|
||||
});
|
||||
console.log('User Response:', await userRes.json());
|
||||
console.log();
|
||||
|
||||
// 3. Send a Notification
|
||||
console.log('3️⃣ Sending notification...');
|
||||
const notifyRes = await fetch(`${API_BASE}/notify`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
user: 'user_123',
|
||||
template: 'welcome_email',
|
||||
channels: ['email'],
|
||||
data: {
|
||||
name: 'Alice'
|
||||
}
|
||||
})
|
||||
});
|
||||
// 202 Accepted — queued, not delivered. Track it with
|
||||
// GET /v1/notifications/{taskId}.
|
||||
console.log('Notify Response:', await notifyRes.json());
|
||||
console.log('\n✅ Example completed successfully!');
|
||||
|
||||
} catch (err) {
|
||||
console.error('❌ Error executing example:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "notifkit-example",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"description": "Example Node.js project demonstrating Notifkit API usage",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Custom Server Example
|
||||
|
||||
This example demonstrates how to bootstrap the `NotifkitServer` orchestrator with custom notification provider transports, custom concurrency options, and graceful process shutdown handlers.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js >= 22
|
||||
- Running PostgreSQL and Redis instances (or environment variables `DATABASE_URL` and `REDIS_URL`)
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
# Set environment variables (optional if running locally with defaults)
|
||||
export DATABASE_URL="postgresql://platform:platform@localhost:5432/notifkit"
|
||||
export REDIS_URL="redis://localhost:6379"
|
||||
|
||||
# Run the server example
|
||||
node index.js
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
import { NotifkitServer } from 'notifkit';
|
||||
|
||||
/**
|
||||
* Example Custom Email Transport Provider
|
||||
*/
|
||||
class CustomEmailTransport {
|
||||
constructor() {
|
||||
this.channel = 'email';
|
||||
}
|
||||
|
||||
async send(task) {
|
||||
console.log(`[CustomEmailTransport] Sending notification to ${task.recipient.email}...`);
|
||||
|
||||
// Simulate async network request to email gateway
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
return {
|
||||
success: true,
|
||||
providerMessageId: `custom-msg-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🚀 Starting custom Notifkit Server example...');
|
||||
|
||||
const server = new NotifkitServer({
|
||||
services: ['all'],
|
||||
port: Number(process.env.PORT || 4000),
|
||||
logLevel: process.env.LOG_LEVEL || 'info',
|
||||
redisUrl: process.env.REDIS_URL,
|
||||
databaseUrl: process.env.DATABASE_URL,
|
||||
workerConcurrency: 50,
|
||||
providers: [
|
||||
new CustomEmailTransport(),
|
||||
],
|
||||
});
|
||||
|
||||
try {
|
||||
await server.start();
|
||||
console.log('✅ Notifkit Server started successfully on port 4000.');
|
||||
|
||||
// Graceful shutdown handling
|
||||
const shutdown = async (signal) => {
|
||||
console.log(`\n🛑 Received ${signal}, stopping Notifkit Server...`);
|
||||
await server.stop();
|
||||
console.log('👋 Server stopped cleanly.');
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.once('SIGINT', () => shutdown('SIGINT'));
|
||||
process.once('SIGTERM', () => shutdown('SIGTERM'));
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to start Notifkit Server:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,14 @@
|
||||
# High-Throughput Load Test Example
|
||||
|
||||
This example measures request throughput and latency for the Notifkit REST API ingestion pipeline.
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
export NOTIFKIT_API_URL="http://localhost:4000"
|
||||
export ADMIN_API_KEY="your_admin_api_key"
|
||||
export COUNT=1000
|
||||
export CONCURRENCY=100
|
||||
|
||||
node index.js
|
||||
```
|
||||
@@ -0,0 +1,61 @@
|
||||
import { NotifkitClient } from 'notifkit';
|
||||
|
||||
/**
|
||||
* Load testing example for measuring Notifkit pipeline throughput.
|
||||
*/
|
||||
async function runLoadTest() {
|
||||
const baseUrl = process.env.NOTIFKIT_API_URL || 'http://localhost:4000';
|
||||
const apiKey = process.env.ADMIN_API_KEY || 'your_admin_api_key';
|
||||
const totalNotifications = Number(process.env.COUNT || 500);
|
||||
const concurrency = Number(process.env.CONCURRENCY || 50);
|
||||
|
||||
const client = new NotifkitClient({ baseUrl, apiKey });
|
||||
|
||||
console.log(`⚡ Starting load test: ${totalNotifications} notifications (Concurrency: ${concurrency})...`);
|
||||
const startTime = Date.now();
|
||||
|
||||
let completed = 0;
|
||||
let failed = 0;
|
||||
|
||||
const queue = Array.from({ length: totalNotifications }, (_, i) => ({
|
||||
template: 'benchmark-template',
|
||||
channels: ['email'],
|
||||
user: {
|
||||
id: `bench-user-${i % 100}`,
|
||||
email: `bench-user-${i % 100}@example.com`,
|
||||
},
|
||||
data: { index: i },
|
||||
}));
|
||||
|
||||
async function worker() {
|
||||
while (queue.length > 0) {
|
||||
const item = queue.pop();
|
||||
if (!item) break;
|
||||
|
||||
try {
|
||||
await client.notify(item);
|
||||
completed++;
|
||||
} catch (err) {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workers = Array.from({ length: concurrency }, () => worker());
|
||||
await Promise.all(workers);
|
||||
|
||||
const elapsedMs = Date.now() - startTime;
|
||||
const throughputSec = (completed / (elapsedMs / 1000)).toFixed(2);
|
||||
|
||||
console.log(`\n📊 Load Test Results:`);
|
||||
console.log(` - Total Processed: ${completed + failed}`);
|
||||
console.log(` - Successful: ${completed}`);
|
||||
console.log(` - Failed: ${failed}`);
|
||||
console.log(` - Elapsed Time: ${elapsedMs} ms`);
|
||||
console.log(` - Throughput: ${throughputSec} req/sec`);
|
||||
}
|
||||
|
||||
runLoadTest().catch((err) => {
|
||||
console.error('❌ Error executing load test:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
# Scheduled Notifications & Quiet Hours Example
|
||||
|
||||
This example demonstrates how to schedule future notification delivery (`sendAt`) and enforce recipient timezone-aware quiet hours deferrals.
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
export NOTIFKIT_API_URL="http://localhost:4000"
|
||||
export ADMIN_API_KEY="your_admin_api_key"
|
||||
|
||||
node index.js
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
import { NotifkitClient } from 'notifkit';
|
||||
|
||||
/**
|
||||
* Example demonstrating scheduled and quiet-hours aware notification delivery.
|
||||
*/
|
||||
async function runScheduledNotificationsExample() {
|
||||
const client = new NotifkitClient({
|
||||
baseUrl: process.env.NOTIFKIT_API_URL || 'http://localhost:4000',
|
||||
apiKey: process.env.ADMIN_API_KEY || 'your_admin_api_key',
|
||||
});
|
||||
|
||||
console.log('🔄 Syncing template...');
|
||||
await client.syncTemplates({
|
||||
templates: [
|
||||
{
|
||||
id: 'scheduled-reminder',
|
||||
channel: 'email',
|
||||
content: {
|
||||
subject: 'Scheduled Meeting Reminder',
|
||||
html: '<h3>Meeting Reminder</h3><p>Hi {{name}}, your meeting starts in 15 minutes.</p>',
|
||||
text: 'Hi {{name}}, your meeting starts in 15 minutes.',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Schedule notification for 10 minutes in the future
|
||||
const sendAt = new Date(Date.now() + 10 * 60 * 1000).toISOString();
|
||||
|
||||
console.log(`⏰ Dispatching scheduled notification for ${sendAt}...`);
|
||||
const response = await client.notify({
|
||||
template: 'scheduled-reminder',
|
||||
channels: ['email'],
|
||||
user: {
|
||||
id: 'user-2002',
|
||||
email: 'alex@example.com',
|
||||
timezone: 'America/New_York',
|
||||
// Quiet hours live under `preferences`, and are a list of UTC windows.
|
||||
preferences: {
|
||||
quietHours: [{ start: '22:00', end: '08:00' }],
|
||||
},
|
||||
},
|
||||
data: { name: 'Alex' },
|
||||
sendAt,
|
||||
});
|
||||
|
||||
console.log('✅ Scheduled notification response:', response);
|
||||
}
|
||||
|
||||
runScheduledNotificationsExample().catch((err) => {
|
||||
console.error('❌ Error executing scheduled notification example:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
# Multi-step Workflows Example
|
||||
|
||||
This example demonstrates how to define, sync, and trigger multi-step drip notification workflows using the `NotifkitClient` SDK.
|
||||
|
||||
## Workflow Structure
|
||||
|
||||
1. **Step 1**: Dispatches immediate welcome email (`onboarding-welcome`).
|
||||
2. **Step 2**: Pauses execution using `wait` (`1h`).
|
||||
3. **Step 3**: Dispatches follow-up email (`onboarding-followup`).
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
export NOTIFKIT_API_URL="http://localhost:4000"
|
||||
export ADMIN_API_KEY="your_admin_api_key"
|
||||
|
||||
node index.js
|
||||
```
|
||||
@@ -0,0 +1,84 @@
|
||||
import { NotifkitClient } from 'notifkit';
|
||||
|
||||
/**
|
||||
* Example demonstrating multi-step notification workflows (Notify -> Wait -> Notify)
|
||||
*/
|
||||
async function runWorkflowExample() {
|
||||
const client = new NotifkitClient({
|
||||
baseUrl: process.env.NOTIFKIT_API_URL || 'http://localhost:4000',
|
||||
apiKey: process.env.ADMIN_API_KEY || 'your_admin_api_key',
|
||||
});
|
||||
|
||||
console.log('🔄 Syncing onboarding template...');
|
||||
await client.syncTemplates({
|
||||
templates: [
|
||||
{
|
||||
id: 'onboarding-welcome',
|
||||
channel: 'email',
|
||||
content: {
|
||||
subject: 'Welcome to our Platform!',
|
||||
html: '<h3>Hello {{name}}!</h3><p>Thank you for signing up.</p>',
|
||||
text: 'Hello {{name}}! Thank you for signing up.',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'onboarding-followup',
|
||||
channel: 'email',
|
||||
content: {
|
||||
subject: 'Getting Started Tips',
|
||||
html: '<h3>Tips for {{name}}</h3><p>Check out our documentation to get started.</p>',
|
||||
text: 'Tips for {{name}}. Check out our documentation to get started.',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log('✅ Templates synced successfully.');
|
||||
|
||||
console.log('🔄 Registering multi-step workflow definition...');
|
||||
// No step names a recipient: each one inherits the user the instance was
|
||||
// triggered with, so the same definition serves every subscriber.
|
||||
const workflow = await client.createWorkflow({
|
||||
name: 'user-onboarding-drip',
|
||||
steps: [
|
||||
{
|
||||
action: 'notify',
|
||||
payload: {
|
||||
template: 'onboarding-welcome',
|
||||
channels: ['email'],
|
||||
data: { name: 'Jane Doe' },
|
||||
},
|
||||
},
|
||||
{
|
||||
action: 'wait',
|
||||
duration: '1h', // Wait 1 hour before next step
|
||||
},
|
||||
{
|
||||
action: 'notify',
|
||||
payload: {
|
||||
template: 'onboarding-followup',
|
||||
channels: ['email'],
|
||||
data: { name: 'Jane Doe' },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
console.log(`✅ Workflow registered: ${workflow.name}`);
|
||||
|
||||
console.log('🔄 Registering the recipient...');
|
||||
await client.addUser({ id: 'user-1001', email: 'user@example.com' });
|
||||
|
||||
console.log('🚀 Triggering workflow execution for recipient...');
|
||||
// input.user.id is who every notify step in this instance sends to.
|
||||
const execution = await client.triggerWorkflow({
|
||||
name: 'user-onboarding-drip',
|
||||
input: { user: { id: 'user-1001' } },
|
||||
});
|
||||
|
||||
console.log('🎉 Workflow triggered. Instance ID:', execution.instanceId);
|
||||
}
|
||||
|
||||
runWorkflowExample().catch((err) => {
|
||||
console.error('❌ Error executing workflow example:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user