express-hale
Version:
š Interactive Express.js scaffold CLI with comprehensive error handling, TypeScript/JavaScript, database integrations, Git Flow, and development tools
159 lines ⢠6.52 kB
JavaScript
;
/**
* Express Hale - Error Handling Demo
*
* This file demonstrates the comprehensive error handling system
* with HTTP status codes, middleware, and fallback mechanisms.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const error_handler_1 = require("./error-handler");
const app = (0, express_1.default)();
const errorHandler = error_handler_1.ErrorHandler.getInstance();
// Middleware setup
app.use(express_1.default.json());
app.use(errorHandler.createRequestIdMiddleware());
// Demo routes to showcase different error types
app.get('/api/health', (req, res) => {
const response = error_handler_1.ResponseFormatter.success({
status: 'healthy',
timestamp: new Date().toISOString()
});
res.json(response);
});
// Validation Error Demo
app.post('/api/users', errorHandler.asyncHandler(async (req, res) => {
const { email, name } = req.body;
if (!email || !name) {
throw new error_handler_1.ValidationError('Email and name are required', {
missing: !email ? ['email'] : [],
invalid: !name ? ['name'] : []
});
}
const response = error_handler_1.ResponseFormatter.success({
id: 1,
email,
name,
createdAt: new Date().toISOString()
});
res.status(201).json(response);
}));
// Authentication Error Demo
app.get('/api/protected', errorHandler.asyncHandler(async (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
throw new error_handler_1.AuthenticationError('Valid Bearer token required');
}
const response = error_handler_1.ResponseFormatter.success({
message: 'Access granted to protected resource',
user: { id: 1, role: 'user' }
});
res.json(response);
}));
// Database Error Demo with Retry
app.get('/api/data', errorHandler.asyncHandler(async (req, res) => {
// Simulate database operation that might fail
const fetchData = async () => {
const shouldFail = Math.random() > 0.7; // 30% success rate
if (shouldFail) {
throw new error_handler_1.DatabaseError('Connection timeout', 'SELECT users');
}
return { users: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }] };
};
try {
const data = await errorHandler.retry(fetchData, 'DATABASE_ERROR', {
endpoint: '/api/data',
method: 'GET'
});
const response = error_handler_1.ResponseFormatter.success(data);
res.json(response);
}
catch (error) {
throw new error_handler_1.DatabaseError('Failed to fetch data after retries');
}
}));
// External Service Error Demo with Circuit Breaker
app.get('/api/external', errorHandler.asyncHandler(async (req, res) => {
const externalServiceCall = async () => {
const shouldFail = Math.random() > 0.8; // 20% success rate
if (shouldFail) {
throw new error_handler_1.ExternalServiceError('Payment Gateway', 'Service temporarily unavailable');
}
return { status: 'success', transactionId: 'TXN' + Date.now() };
};
// Create circuit breaker for this service
const circuitBreaker = errorHandler.createCircuitBreaker(externalServiceCall, {
failureThreshold: 3,
resetTimeout: 60000, // 1 minute
monitoringPeriod: 30000 // 30 seconds
});
try {
const result = await circuitBreaker();
const response = error_handler_1.ResponseFormatter.success(result);
res.json(response);
}
catch (error) {
throw error; // Let the error middleware handle it
}
}));
// Custom HTTP Error Demo
app.get('/api/business-logic', errorHandler.asyncHandler(async (req, res) => {
const accountBalance = 100;
const requestedAmount = parseInt(req.query.amount) || 0;
if (requestedAmount > accountBalance) {
throw new error_handler_1.HttpError('Insufficient funds for transaction', error_handler_1.HttpStatusCode.UNPROCESSABLE_ENTITY, 'INSUFFICIENT_FUNDS', 'BUSINESS_LOGIC', true, {
accountBalance,
requestedAmount,
shortfall: requestedAmount - accountBalance
});
}
const response = error_handler_1.ResponseFormatter.success({
transactionId: 'TXN' + Date.now(),
amount: requestedAmount,
remainingBalance: accountBalance - requestedAmount
});
res.json(response);
}));
// Generic Error Demo
app.get('/api/error', (req, res, next) => {
// Simulate an unexpected error
const error = new Error('Something went terribly wrong!');
next(error);
});
// 404 Handler
app.use(errorHandler.createNotFoundMiddleware());
// Global Error Handler
app.use(errorHandler.createErrorMiddleware());
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`š Error Handling Demo Server running on port ${PORT}`);
console.log('\nš Available endpoints:');
console.log(' GET /api/health - Health check');
console.log(' POST /api/users - Create user (validation demo)');
console.log(' GET /api/protected - Protected route (auth demo)');
console.log(' GET /api/data - Database with retry demo');
console.log(' GET /api/external - External service with circuit breaker');
console.log(' GET /api/business-logic - Custom business logic error');
console.log(' GET /api/error - Generic error demo');
console.log('\nš” Test with curl or Postman:');
console.log(` curl http://localhost:${PORT}/api/health`);
console.log(` curl -X POST http://localhost:${PORT}/api/users -H "Content-Type: application/json" -d '{"name":"John"}'`);
console.log(` curl http://localhost:${PORT}/api/protected`);
console.log(` curl http://localhost:${PORT}/api/data`);
console.log(` curl http://localhost:${PORT}/api/business-logic?amount=200`);
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('\nš SIGTERM received, shutting down gracefully...');
process.exit(0);
});
process.on('SIGINT', () => {
console.log('\nš SIGINT received, shutting down gracefully...');
process.exit(0);
});
//# sourceMappingURL=demo-error-handling.js.map