Skip to content

and2352000/elegant-api-framework-node-js

Repository files navigation

Elegant API Framework (Node.js)

A self-assembled, opinionated Node.js API framework combining Koa, dependency injection, Zod validation, and auto-generated OpenAPI documentation.


Tech Stack

Library Role
Koa v3 HTTP web framework
@koa/router Route registration
@koa/cors CORS middleware
koa-bodyparser Request body parsing
awilix IoC / Dependency injection container
zod Schema validation (request body, query, params, env config)
zod-openapi Auto-generate OpenAPI 3.1 spec from Zod schemas
TypeORM ORM for PostgreSQL
typeorm-naming-strategies Auto snake_case column naming
dotenv Environment variable loading
ramda Functional utilities
axios HTTP client
moment Date/time utilities
TypeScript Language
ts-node + nodemon Development hot-reload server
tsup Production bundler
jest + ts-jest Unit testing

Node.js version: v22 (see .nvmrc)


Project Structure

src/
├── index.ts                   # Entry point: bootstraps Koa app, registers middleware & routes
├── setupContainer.ts          # Root DI wiring: calls repo & service container setup
│
├── config/
│   └── index.ts               # Loads .env and validates required vars with Zod
│
├── router/                    # Route handlers (auto-scanned at startup)
│   ├── user.ts                # User CRUD routes + Zod schemas for OpenAPI
│   └── openapi.ts             # GET /openapi — serves the generated OpenAPI JSON
│
├── service/                   # Business logic layer
│   ├── setupContainer.ts      # Registers services into the DI container
│   └── user.ts                # UserService (calls repository)
│
├── repository/                # Data access layer
│   ├── setupContainer.ts      # Registers repositories into the DI container
│   └── user.ts                # UserRepo (DB queries / in-memory mock)
│
├── middleware/
│   └── validator.ts           # routerSchemaCheck — Zod middleware for body/query/params
│
├── api-response/              # Standardized HTTP response helpers
│   ├── base.ts                # BaseResponse (status + code)
│   ├── general.ts             # GeneralResponse<T> — 200 success wrapper
│   ├── error.ts               # ErrorResponse / BadRequestErrorResponse
│   └── utils.ts               # generalResponse() / createErrorResponse() for Koa ctx
│
├── lib/
│   ├── container.ts           # Creates the global awilix container instance
│   └── openapi.ts             # register() + createOpenApiDocument() — builds the OAS spec
│
├── type/
│   ├── api.ts                 # Shared types: SchemaCheck, Options
│   └── openapi.ts             # OpenApiSchema interface
│
└── typeorm/
    ├── datasource.ts          # PostgreSQL DataSource config (supports IP & Unix socket)
    ├── entity/                # TypeORM entity definitions
    ├── migration/             # Database migrations
    └── type/                  # Custom decorators & shared TypeORM types

How It Works

Dependency Injection (awilix)

All services and repositories are registered into a single awilix container at startup using CLASSIC injection mode (constructor parameter order).

setupContainer()
  ├── setupRepoContainer()     → registers UserRepo
  └── setupServiceContainer()  → registers UserService (receives UserRepo via DI)

To add a new service: create the class, register it in the relevant setupContainer.ts, then resolve it in the router via container.resolve<YourService>('yourService').

Route & OpenAPI Registration

Each router file exports a schemas array of OpenApiSchema objects alongside the route handlers. At startup, index.ts auto-scans the src/router/ directory, calls register(schemas) for each file, and builds the OpenAPI document on demand at GET /openapi.

Request Validation

Wrap any route with routerSchemaCheck(schema) to validate body, query, and params through Zod. On failure it returns a structured 400 error response automatically.


Environment Variables

Create a .env file in the project root:

PORT=6969
APP_NAME=elegant-api-framework
HOST=0.0.0.0

# Required only if using TypeORM / PostgreSQL
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=app_db
POSTGRES_USER=app_user
POSTGRES_PASSWORD=secret
DB_CONNECT_MODE=IP        # IP | UNIX_SOCKET

Startup

Development

nvm use          # use Node.js version from .nvmrc
npm install
npm run dev      # nodemon + ts-node, hot-reload on file changes

Production

npm run build    # tsc → dist/
npm run start    # node dist/src/index.js

Bundle (single file)

npm run bundle   # tsup → dist/index.js

Database Migrations (TypeORM)

# Generate a new migration from entity changes
npm run mg:gen -- src/typeorm/migration/MigrationName

# Run pending migrations
npm run mg:run

# Revert the last migration
npm run mg:revert

# Create an empty migration file
npm run mg:create -- src/typeorm/migration/MigrationName

Testing

npm test

API Quick Test

# Create a user
curl -X POST http://localhost:6969/user \
  -H "Content-Type: application/json" \
  -d '{"name": "Aaron H"}'

# Get all users
curl http://localhost:6969/user

# Get user by ID
curl http://localhost:6969/user/1

# Get OpenAPI spec (paste into https://editor.swagger.io/)
curl http://localhost:6969/openapi

About

Elegant api framework for Node JS

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors