@zzazz/slack
v1.0.8
Published
Production-grade, framework-agnostic error alerting library for Slack with first-class NestJS and Express support
Downloads
709
Maintainers
Readme
@zzazz/slack
Production-grade, framework-agnostic error alerting library for Slack with first-class support for NestJS and Express applications.
🚀 Features
| Feature | Description |
| --------------------------- | ----------------------------------------------------------------- |
| ✅ Plug-and-play | Initialize once, capture errors automatically |
| ✅ Framework-agnostic | Works with any Node.js application |
| ✅ First-class integrations | NestJS module and Express middleware included |
| ✅ Non-blocking | Fire-and-forget async alerting with retry logic |
| ✅ Slack Block Kit | Beautiful, structured messages with severity indicators |
| ✅ Production-safe | Rate limiting, sanitization, and graceful error handling |
| ✅ Severity levels | info, warning, error, critical |
| ✅ Smart mentions | Conditional @user or @usergroup tagging |
| ✅ Auto-capture | Uncaught exceptions and unhandled promise rejections |
| ✅ Secure | Automatic masking of sensitive data (tokens, passwords, API keys) |
| ✅ TypeScript | Full type safety and IntelliSense support |
📦 Installation
npm install @zzazz/slackyarn add @zzazz/slackpnpm add @zzazz/slack🎯 Quick Start
Plain Node.js
import { SlackAlerts } from '@zzazz/slack';
// Initialize at app startup
SlackAlerts.init({
webhookUrl: process.env.SLACK_WEBHOOK_URL!,
defaultChannel: '#alerts',
appName: 'my-app',
environment: 'production',
enabled: true,
});
// Send alerts
await SlackAlerts.error(new Error('Something went wrong'));
await SlackAlerts.critical('Database connection lost');
await SlackAlerts.warning('High memory usage detected');
await SlackAlerts.info('Deployment completed');NestJS
// app.module.ts
import { Module } from '@nestjs/common';
import { SlackAlertsModule, SlackExceptionFilter } from '@zzazz/slack';
import { APP_FILTER } from '@nestjs/core';
@Module({
imports: [
SlackAlertsModule.forRoot({
webhookUrl: process.env.SLACK_WEBHOOK_URL!,
defaultChannel: '#backend-alerts',
appName: 'accounts-service',
environment: 'production',
channelMappings: {
'#backend-alerts': '@backend-team',
},
mentionOnSeverity: ['critical'],
}),
],
providers: [
{
provide: APP_FILTER,
useClass: SlackExceptionFilter,
},
],
})
export class AppModule {}Express
import express from 'express';
import { SlackAlerts, slackErrorMiddleware, asyncHandler } from '@zzazz/slack';
const app = express();
// Initialize
SlackAlerts.init({
webhookUrl: process.env.SLACK_WEBHOOK_URL!,
defaultChannel: '#alerts',
appName: 'api-gateway',
environment: 'production',
});
// Routes
app.get(
'/users/:id',
asyncHandler(async (req, res) => {
const user = await fetchUser(req.params.id);
res.json(user);
})
);
// Error middleware (must be after routes)
app.use(slackErrorMiddleware());
app.listen(3000);🔧 Configuration
SlackAlertsConfig
SlackAlerts.init({
// Required
webhookUrl: string; // Slack webhook URL
appName: string; // Your application name
environment: string; // e.g., 'production', 'staging'
// Optional
defaultChannel?: string; // Default: '#alerts'
enabled?: boolean; // Default: true
maxAlertsPerMinute?: number; // Default: 10 (rate limiting)
// Channel-to-team mappings for mentions
channelMappings?: {
'#backend-alerts': '@backend-team',
'#critical-alerts': '@oncall',
};
// Severities that trigger mentions
mentionOnSeverity?: Severity[]; // Default: ['critical']
// Custom sanitization function
sanitize?: (data: unknown) => unknown;
// Additional sensitive fields to mask
sensitiveFields?: string[]; // Default: ['password', 'token', 'authorization', ...]
});📊 Severity Levels
| Severity | Emoji | Use Case | Auto-mention |
| ---------- | ----- | ------------------------------------------- | ------------------- |
| info | ℹ️ | Informational messages, startup events | No |
| warning | ⚠️ | Non-critical issues, degraded performance | No |
| error | ❌ | Application errors, failed operations | No |
| critical | 🚨 | System failures, data loss, security issues | Yes (if configured) |
🎨 Usage Examples
Manual Error Reporting
try {
await processPayment(userId, amount);
} catch (error) {
await SlackAlerts.critical(error as Error, {
channel: '#payments-alerts',
metadata: {
userId,
amount,
timestamp: new Date().toISOString(),
},
tags: ['payment', 'critical'],
mention: '@payments-oncall',
});
throw error;
}Custom Severity
await SlackAlerts.alert('warning', 'API rate limit approaching', {
metadata: {
currentRate: 950,
limit: 1000,
},
tags: ['rate-limiting', 'api'],
});With Metadata
await SlackAlerts.error(error, {
severity: 'critical',
metadata: {
userId: '12345',
action: 'checkout',
cartValue: 599.99,
paymentMethod: 'credit_card',
},
tags: ['payment', 'checkout'],
});Auto-Capture Global Errors
The library automatically captures:
- Uncaught exceptions
- Unhandled promise rejections
// This will be automatically sent to Slack
throw new Error('Uncaught exception');
// This will also be automatically sent
Promise.reject(new Error('Unhandled rejection'));🔐 Security & Sanitization
Automatic Masking
The library automatically masks sensitive data:
const error = new Error('Failed: password=secret123 token=abc123');
await SlackAlerts.error(error);
// Sent to Slack: "Failed: password=***REDACTED*** token=***REDACTED***"Automatically masked patterns:
- Bearer tokens
- JWT tokens
- API keys (sk**, pk**)
- AWS keys (AKIA...)
- Password fields
- Authorization headers
Custom Sanitization
SlackAlerts.init({
webhookUrl: '...',
appName: 'my-app',
environment: 'production',
// Custom sanitizer
sanitize: data => {
// Your custom logic
return sanitizedData;
},
// Additional sensitive fields
sensitiveFields: ['ssn', 'creditCard', 'customSecret'],
});⚡ Performance & Reliability
Non-Blocking
All alerts are sent asynchronously and never block your application flow:
await SlackAlerts.error(error); // Returns immediately
// Your app continues without waiting for SlackRetry Logic
Failed alerts are automatically retried with exponential backoff:
- Max attempts: 3
- Initial delay: 1s
- Max delay: 5s
Rate Limiting
Prevents alert spam with configurable rate limits:
SlackAlerts.init({
maxAlertsPerMinute: 15, // Max 15 alerts per minute
// ...
});Alerts exceeding the limit are silently dropped.
Graceful Degradation
If Slack is unreachable:
- ✅ Your app continues running
- ✅ Errors are logged to console
- ✅ No exceptions are thrown
🧪 Testing
The library includes comprehensive unit tests:
npm testnpm run test:coverageCoverage targets: 90%+ (branches, functions, lines, statements)
Mock for Testing
// In your tests
import { SlackAlerts } from '@zzazz/slack';
beforeEach(() => {
SlackAlerts.init({
webhookUrl: 'https://hooks.slack.com/services/TEST',
appName: 'test-app',
environment: 'test',
enabled: false, // Disable in tests
});
});📚 API Reference
SlackAlerts
Methods
init(config: SlackAlertsConfig): void- Initialize the clientisInitialized(): boolean- Check initialization statuserror(error: Error | string, options?: AlertOptions): Promise<void>critical(error: Error | string, options?: AlertOptions): Promise<void>warning(message: string, options?: AlertOptions): Promise<void>info(message: string, options?: AlertOptions): Promise<void>alert(severity: Severity, error: Error | string, options?: AlertOptions): Promise<void>
AlertOptions
interface AlertOptions {
severity?: 'info' | 'warning' | 'error' | 'critical';
channel?: string; // Override default channel
metadata?: Record<string, unknown>; // Additional context
tags?: string[]; // Categorization tags
mention?: string; // @user or @usergroup to mention
}🏗️ Architecture
@zzazz/slack/
├── src/
│ ├── client.ts # Main SlackAlerts client
│ ├── types.ts # TypeScript definitions
│ ├── formatter.ts # Slack Block Kit formatter
│ ├── http-client.ts # HTTP client for Slack API
│ ├── security.ts # Sanitization utilities
│ ├── rate-limiter.ts # Rate limiting logic
│ ├── retry.ts # Retry with backoff
│ ├── integrations/
│ │ ├── nestjs/ # NestJS module & filter
│ │ └── express/ # Express middleware
│ └── __tests__/ # Unit tests
├── examples/ # Usage examples
└── dist/ # Compiled output🤝 Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
🔗 Links
💡 Tips
Getting a Slack Webhook URL
- Go to https://api.slack.com/apps
- Create a new app or select an existing one
- Enable "Incoming Webhooks"
- Click "Add New Webhook to Workspace"
- Select a channel and authorize
- Copy the webhook URL
Environment Variables
# .env
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
NODE_ENV=productionBest Practices
✅ DO:
- Initialize once at app startup
- Use appropriate severity levels
- Include relevant metadata
- Test with
enabled: falsein development - Use channel mappings for team-specific alerts
❌ DON'T:
- Call
init()multiple times unnecessarily - Send info/warning alerts for every request (too noisy)
- Include sensitive data in metadata
- Rely on alerts for critical application logic
👋 Support
For any doubts, please reach out to Vinit Shahdeo.
📊 Roadmap
- [ ] Email fallback when Slack is down
- [ ] Alert aggregation (group similar alerts)
- [ ] Custom Slack Block Kit templates
- [ ] Webhook signature verification
- [ ] Alert dashboard and analytics
Built with ❤️ for production systems at ZZAZZ
