|
1 week ago | |
---|---|---|
src | 1 week ago | |
.eslintrc.json | 2 years ago | |
.gitignore | 2 years ago | |
Dockerfile | 2 years ago | |
LICENSE | 2 years ago | |
README.md | 1 week ago | |
jest.config.js | 2 years ago | |
package-lock.json | 2 years ago | |
package.json | 2 years ago | |
push_server | 2 years ago | |
tsconfig.json | 2 years ago | |
tsconfig.release.json | 2 years ago |
README.md
Time Safari Push Notification Middleware Server
A custom-built push notification middleware service designed specifically for the Time Safari application. This server acts as an intermediary layer between the Time Safari client applications and various push notification providers, providing a unified interface for managing push subscriptions and delivering notifications.
Project Intent
The primary goal of this project was to build our own middleware service for push notifications rather than relying on third-party services. This approach provides several benefits:
- Complete Control: Full ownership over the notification delivery pipeline
- Customization: Ability to implement Time Safari-specific notification logic
- Privacy: No dependency on external services that might collect user data
- Cost Efficiency: Eliminates per-notification costs from third-party providers
- Reliability: Direct control over uptime and performance
Architecture Overview
The server is built using Node.js with TypeScript and follows a modular architecture:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Client Apps │───▶│ Push Server │───▶│ Push Providers │
│ (Time Safari) │ │ (Middleware) │ │ (FCM, etc.) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌──────────────────┐
│ SQLite DB │
│ (Subscriptions) │
└──────────────────┘
Core Components
- Subscription Management: Handles client subscription registration and storage
- VAPID Key Management: Generates and manages VAPID keys for secure push delivery
- Notification Service: Encrypts and delivers push notifications to subscribed clients
- Worker Thread: Handles periodic tasks (currently sends daily notifications)
- Database Layer: SQLite-based storage for subscriptions and VAPID keys
Features
🔐 Secure Push Delivery
- VAPID (Voluntary Application Server Identification) key generation and management
- End-to-end encryption using AES-128-GCM
- JWT-based authentication headers
📱 Subscription Management
- Client subscription registration via
/subscribe
endpoint - Subscription storage in SQLite database
- Support for subscription muting (planned)
- Subscription removal (planned)
⚡ Real-time Notifications
- Broadcast notifications to all subscribed clients
- Individual client notification delivery
- Automatic daily notification scheduling via worker thread
🛠️ Developer-Friendly
- TypeScript for type safety
- Comprehensive logging
- Modular service architecture
- Docker support for containerization
Technology Stack
- Runtime: Node.js 18.12+
- Language: TypeScript
- Framework: Express.js
- Database: SQLite with TypeORM
- Encryption: http_ece, elliptic, crypto
- Authentication: JWT (JSON Web Tokens)
- Containerization: Docker
Setup and Installation
Prerequisites
- Node.js 18.12 or higher
- npm 8.0 or higher
Quick Start with Tea (Recommended)
# Install Tea package manager
sh <(curl tea.xyz) -E sh
# Install dependencies
npm install
# Build the project
npm run build
# Start the server
npm run start
Manual Setup
# Clone the repository
git clone <repository-url>
cd pwa-push-server
# Install dependencies
npm install
# Build TypeScript
npm run build
# Start the server
npm run start
The server will start on http://localhost:3000
Docker Setup
# Build the Docker image
docker build -t timesafari-push-server .
# Run the container
docker run -p 3000:3000 timesafari-push-server
API Endpoints
POST /subscribe
Register a new push subscription.
Request Body:
{
"endpoint": "https://fcm.googleapis.com/fcm/send/...",
"keys": {
"p256dh": "base64-encoded-public-key",
"auth": "base64-encoded-auth-secret"
}
}
Response: 201 Created
GET /vapid
Retrieve the public VAPID key for client-side subscription.
Response:
{
"vapidKey": "base64-encoded-public-vapid-key"
}
POST /unsubscribe
(Planned)
Remove a push subscription.
POST /mute
(Planned)
Toggle notification muting for a subscription.
Client Integration
1. Request VAPID Key
const response = await fetch('/vapid');
const { vapidKey } = await response.json();
2. Subscribe to Push Notifications
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidKey
});
await fetch('/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(subscription)
});
3. Handle Push Notifications
// In your service worker
self.addEventListener('push', (event) => {
const data = event.data.json();
const options = {
title: data.title,
body: data.body,
icon: '/icon.png',
badge: '/badge.png'
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
Development
Available Scripts
npm run build
- Build the TypeScript projectnpm run start
- Start the production servernpm run test
- Run tests with coveragenpm run lint
- Run ESLintnpm run prettier
- Format code with Prettier
Project Structure
src/
├── main.ts # Server entry point and Express setup
├── notificationService.ts # Push notification delivery logic
├── subscriptionService.ts # Subscription management
├── vapidService.ts # VAPID key generation and management
├── db.ts # Database service and TypeORM setup
├── worker.ts # Background worker for periodic tasks
├── Subscription.ts # Subscription entity model
└── VapidKeys.ts # VAPID keys entity model
Security Considerations
- VAPID Keys: Automatically generated and securely stored
- Encryption: All push payloads are encrypted using AES-128-GCM
- Authentication: JWT-based VAPID authentication headers
- Database: SQLite with proper entity validation
- Input Validation: TypeScript provides compile-time type safety
Monitoring and Logging
The server includes comprehensive logging for:
- Subscription events (add/remove)
- Notification delivery attempts
- VAPID key operations
- Database operations
- Worker thread activities
Future Enhancements
- Subscription muting functionality
- Subscription removal endpoint
- Notification templates
- Delivery analytics and metrics
- Rate limiting and throttling
- Multi-tenant support
- Webhook support for external integrations
Contributing
- Fork the repository
- Create a feature branch
- Make your changes following the coding standards
- Add tests for new functionality
- Submit a pull request
License
Apache-2.0 License - see LICENSE file for details.
Author
Matthew Raymer - Lead Developer
This middleware service was built specifically for Time Safari to provide reliable, secure, and cost-effective push notification delivery without dependency on third-party services.
Last Updated: 2025-07-23
Project Started: 2023-09-06