UNPKG

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
#!/usr/bin/env node "use strict"; /** * 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