A batteries-included Express.js framework with automatic OpenAPI documentation generation, request/response validation, API versioning, and response serialization.
- π Express.js based REST API framework
- π Automatic OpenAPI/Swagger documentation generation
- β Request/Response validation using Zod
- π Auto-loading of route modules
- π‘οΈ Built-in security with Helmet
- π CORS support
- π― TypeScript support
- π’ Built-in API versioning (v1)
- π Multiple API documentation UIs (Swagger, ReDoc, Scalar)
- π₯ Hot-reload in development
- π Production-ready build setup
- π Response serialization and transformation
- βοΈ Automatic environment configuration
Terry includes automatic response serialization and transformation. Each response schema acts as a transformer:
// schema.ts
import { z } from 'zod';
export const HealthCheckResponse = z.object({
status: z.enum(['ok', 'error']),
uptime: z.number(),
memory: z.object({
used: z.number(),
total: z.number(),
}),
}).openapi('HealthCheckResponse');
// routes.ts
{
method: 'get',
path: '/',
schema: {
response: HealthCheckResponse,
},
handler: async (req, res) => {
// This will be validated against HealthCheckResponse schema
return {
status: 'ok', // Must be 'ok' or 'error'
uptime: process.uptime(),
memory: {
used: 100,
total: 1000,
}
};
}
}
// Invalid responses will throw 422 Unprocessable Entity
return {
status: 'unknown', // Error: Invalid enum value
uptime: 'invalid' // Error: Expected number, received string
};Terry automatically loads environment variables from .env file and validates them using Zod:
// config/env.ts
import { z } from 'zod';
const envSchema = z.object({
PORT: z.string().transform(Number).default('3456'),
NODE_ENV: z.enum(['development', 'production', 'test']),
API_PREFIX: z.string().default('/api'),
// ... other validations
});
// Usage in your code
import env from '../config/env';
app.listen(env.PORT);Create a .env file based on .env.example:
# Server
PORT=3456
NODE_ENV=development
# API
API_PREFIX=/api
# Documentation
DOCS_ENABLED=true
# Security
CORS_ORIGIN=*
RATE_LIMIT_WINDOW=15
RATE_LIMIT_MAX=100
# Logging
LOG_LEVEL=debug
PRETTY_LOGGING=truesrc/
βββ app/ # Application modules
β βββ users/ # User module example
β β βββ users.routes.ts # Route definitions
β β βββ users.schema.ts # Zod schemas
β βββ todos/ # Todo module example
β β βββ todos.routes.ts
β β βββ todos.schema.ts
β βββ health/ # Health check module
β βββ health.routes.ts
β βββ health.schema.ts
βββ lib/ # Framework core
β βββ openapi.ts # OpenAPI configuration
β βββ router.ts # Route builder
βββ config/ # Configuration
β βββ env.ts # Environment variables
β βββ logger.ts # Logging configuration
βββ main.ts # Application entry point
Each module should follow this structure:
*.routes.ts- Route definitions with handlers
import { ModuleRoutes } from '../../lib/openapi';
import { MySchema } from './my.schema';
const routes: ModuleRoutes = [
{
method: 'get',
path: '/',
schema: {
response: MySchema,
},
handler: async (req, res) => {
// Your handler logic
return { data: 'example' };
},
summary: 'List items',
description: 'Get a list of items',
tags: ['MyModule']
}
];
module.exports = routes;
module.exports.default = routes;*.schema.ts- Zod schemas for validation
import { z } from 'zod';
export const MySchema = z.object({
id: z.string().uuid(),
name: z.string(),
}).openapi('MySchema');- Uses TypeScript files directly
- Hot-reload enabled
- Detailed error logging
- Pretty-printed logs
- Source maps enabled
npm run dev- Uses compiled JavaScript
- Optimized for performance
- Minimal error logging
- JSON formatted logs
- No source maps
npm run build
npm run start:prodThe framework automatically generates OpenAPI documentation from your route definitions and schemas. Access the documentation at:
- Swagger UI:
http://localhost:3456/api/docs/swagger - ReDoc:
http://localhost:3456/api/docs/redoc - Scalar:
http://localhost:3456/api/docs/scalar - OpenAPI JSON:
http://localhost:3456/api/docs/api.json
docker compose build api
docker compose up apidocker compose --profile dev up api-devCreate a .env file in the root directory:
# Server
PORT=3456
NODE_ENV=development
# API
API_PREFIX=/api
# Documentation
DOCS_ENABLED=true
# Security
CORS_ORIGIN=*
RATE_LIMIT_WINDOW=15
RATE_LIMIT_MAX=100
# Logging
LOG_LEVEL=debug
PRETTY_LOGGING=truenpm run dev: Start development server with hot-reloadnpm run build: Build for productionnpm run start:prod: Start production servernpm run lint: Run linternpm run format: Format codenpm run clean: Clean build directory
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a new Pull Request
Terry is open-source software licensed under the MIT license.
Copyright (c) 2024 Cursor Inc.