A modern Todo API built with Effect-TS, Hono, and Drizzle ORM, demonstrating functional programming patterns and robust error handling.
- ✅ Effect-TS Integration - Functional programming with composable effects
- ✅ Type-Safe Database - Drizzle ORM with PostgreSQL
- ✅ Schema Validation - Runtime type checking with Effect Schema
- ✅ Structured Error Handling - Comprehensive error types and responses
- ✅ RESTful API - Complete CRUD operations for todos
- ✅ Health Monitoring - Built-in health check endpoint
- Runtime: Bun
- Web Framework: Hono
- Effect System: Effect-TS
- Database: PostgreSQL with Drizzle ORM
- Schema Validation: Effect Schema
- Language: TypeScript
- Bun (latest version)
- PostgreSQL database
git clone https://github.com/novaru/effectful-todo
cd effectful-todo
bun installCreate a .env file based on .env.example:
cp .env.example .envConfigure your database connection:
DB_HOST=localhost
DB_PORT=5432
DB_NAME=hono_todos
DB_USER=postgres
DB_PASSWORD=your_passwordGenerate and run migrations:
# Generate migration files
bun run db:generate
# Run migrations
bun run db:migrate
# Optional: Open Drizzle Studio
bun run db:studiobun run devThe API will be available at http://localhost:3000
GET /health- Server health status
GET /todos- Get all todosGET /todos/:id- Get a specific todoPOST /todos- Create a new todoPATCH /todos/:id- Mark todo as completePUT /todos/:id- Update todo (limited functionality)DELETE /todos/:id- Delete a todo
curl -X POST http://localhost:3000/todos \
-H "Content-Type: application/json" \
-d '{"text": "Buy groceries"}'curl http://localhost:3000/todoscurl -X PATCH http://localhost:3000/todos/{todo-id}All responses follow a consistent structure:
{
"success": true,
"data": {
// Response data
}
}{
"success": false,
"error": {
"type": "VALIDATION_ERROR",
"message": "Todo text cannot be empty",
"field": "text"
}
}src/
├── shared/
│ ├── errors.ts # Custom error classes
│ ├── validation.ts # Request schemas & parsing
│ ├── effect-handler.ts # Effect handling logic
│ └── response.ts # Response utilities
├── routes/
│ ├── health.ts # Health check endpoint
│ ├── todos.ts # Todo routes
│ └── index.ts # Route composition
├── todo/
│ ├── model.ts # Todo domain models
│ └── repository.ts # Todo repository layer
├── drizzle/
│ ├── database.ts # Database configuration
│ └── schema.ts # Database schema
└── index.ts # App composition
# Development
bun run dev # Start development server with hot reload
# Production
bun run build # Build optimized bundle using scripts/build.ts
bun run start # Start development server
bun run start:prod # Start production server using built bundle
# Database operations
bun run db:generate # Generate migrations
bun run db:migrate # Run migrations
bun run db:studio # Open Drizzle Studio
# Testing
bun run test # Run tests- Composable Effects: All operations are modeled as Effect computations
- Type-Safe Error Handling: Compile-time guarantees for error types
- Dependency Injection: Clean service layer architecture
- Resource Management: Automatic cleanup and resource handling
- Separation of Concerns: Clear boundaries between layers
- Testability: Each module can be tested independently
- Maintainability: Easy to locate and modify functionality
- Scalability: Simple to extend with new features
The API provides comprehensive error handling with specific error types:
VALIDATION_ERROR- Invalid input dataNOT_FOUND- Resource not foundREQUEST_BODY_ERROR- Malformed request bodyINTERNAL_ERROR- Server errors
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request