A comprehensive sample Node-Boot application using native node:http
framework that demonstrates best practices for building scalable TypeScript applications with dependency injection, validation, persistence, and more.
- Node.js (LTS version recommended)
- pnpm (package manager)
- SQLite (for local development)
-
Clone and install dependencies:
git clone https://github.com/nodejs-boot/sample-native-http.git cd sample-native-http pnpm install
-
Start development server:
pnpm star #or with nodemon for hot reload pnpm dev
-
Access the application:
- API: http://localhost:3000/api
- Swagger UI: http://localhost:3000/docs
- Actuator Metrics/info: http://localhost:3000/actuator
- Health Check: http://localhost:3000/actuator/health
-
Actuator Endpoints:
/actuator/health
- Application health status/actuator/info
- Application info/actuator/git
- Git info/actuator/config
- Current configuration/actuator/metrics
- Application metrics/actuator/prometheus
- Prometheus metrics/actuator/controllers
- Registered controllers/actuator/interceptors
- Registered interceptors/actuator/middlewares
- Registered middlewares
Script | Description |
---|---|
pnpm start |
Build and start production server |
pnpm start:prod |
Build and start with NODE_ENV=production |
pnpm dev |
Start development server with hot reload |
pnpm build |
Compile TypeScript to JavaScript |
pnpm postbuild |
Run Node-Boot AOT (Ahead of Time) compilation |
pnpm clean:build |
Remove dist directory |
pnpm lint |
Run ESLint |
pnpm lint:fix |
Run ESLint with auto-fix |
pnpm format |
Check code formatting |
pnpm format:fix |
Format code with Prettier |
pnpm test |
Run tests with Jest |
pnpm typecheck |
Type check without compilation |
pnpm nodeboot:update |
Update Node-boot framework - Update all @nodeboot packages |
pnpm rebuild:sqlite |
Rebuild SQLite native bindings |
pnpm create:migration |
Create new TypeORM migration |
The application uses YAML-based configuration with environment overrides:
app-config.yaml
- Main application configurationapp-config.local.yaml
- Local development overridesapp-credentials.local.yaml
- Local credentials (git-ignored)
app:
name: "native-http-service"
platform: "node-boot"
environment: "development"
port: 3000
api:
routePrefix: "/api"
validations:
enableDebugMessages: true
stopAtFirstError: true
server:
cors:
origin: "*"
methods: ["GET", "POST"]
src/
βββ app.ts # Main application class with decorators
βββ server.ts # Application entry point
βββ auth/ # Authentication & authorization
βββ clients/ # HTTP clients for external services
βββ config/ # Configuration classes
βββ controllers/ # REST API controllers
βββ exceptions/ # Custom exception handlers
βββ interfaces/ # TypeScript interfaces
βββ middlewares/ # Custom middleware
βββ models/ # DTOs and data models
βββ persistence/ # Database layer
β βββ entities/ # TypeORM entities
β βββ repositories/ # Custom repositories
β βββ migrations/ # Database migrations
β βββ listeners/ # Entity event listeners
βββ services/ # Business logic services
Main application class with feature decorators:
@EnableDI() // Enable Dependency Injection
@EnableOpenApi() // Enable OpenAPI (Swagger) documentation
@EnableSwaggerUI() // Enable SwaggerUI
@EnableAuthorization() // Enable Authorization
@EnableActuator() // Enable Actuator (health, metrics)
@EnableRepositories() // Enable persistence with TypeORM, transactions, migrations, listeners
@EnableScheduling() // Enable scheduled tasks
@EnableHttpClients() // Enable declarative HTTP clients
@EnableValidations() // Enable request/response validations
@EnableComponentScan() // Enable component scanning with AOT support
export class SampleApp implements NodeBootApp {
start(): Promise<NodeBootAppView> {
return NodeBoot.run(HttpServer);
}
}
REST API endpoints using decorators for routing and validation:
@Controller("/users", "v1")
export class UsersController {
@Get("/")
async getUsers(): Promise<User[]> {
return this.userService.findAllUser();
}
}
Key Features:
- Automatic route registration
- Built-in validation
- Swagger documentation generation
- Exception handling
Business logic layer with dependency injection:
@Service()
export class UserService {
constructor(
private readonly userRepository: UserRepository,
private readonly logger: Logger
) {}
}
Key Features:
- Singleton instances
- Constructor injection
- Transaction support with
@Transactional
- Logging integration
TypeORM entities for database mapping:
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
email: string;
}
Node-Boot Data repositories extending TypeORM Repository:
@DataRepository(User)
export class UserRepository extends Repository<User> {
// Custom query methods
}
Key Features:
- Automatic transaction management
- Custom naming strategies
- Entity event listeners
- Migration support
Data Transfer Objects with validation and OpenAPI metadata:
@Model()
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
@MinLength(8)
password: string;
}
Custom middleware for cross-cutting concerns:
LoggingMiddleware
- Request/response loggingCustomErrorHandler
- Global error handling
Type-safe configuration with @ConfigurationProperties
:
@ConfigurationProperties("app")
export class AppConfigProperties {
name: string;
port: number;
environment: string;
}
The application demonstrates various Node-Boot starters and features:
Feature | Decorator | Description |
---|---|---|
Dependency Injection | @EnableDI |
TypeDI container integration |
OpenAPI | @EnableOpenApi |
Automatic API documentation |
Swagger UI | @EnableSwaggerUI |
Interactive API explorer |
Authorization | @EnableAuthorization |
Role-based access control |
Actuator | @EnableActuator |
Health checks and metrics |
Persistence | @EnableRepositories |
TypeORM integration + Transactions management |
Scheduling | @EnableScheduling |
Cron jobs and scheduled tasks |
HTTP Clients | @EnableHttpClients |
Declarative HTTP clients |
Validations | @EnableValidations |
Request/response validation |
Component Scan | @EnableComponentScan |
AOT compilation support |
Development server uses nodemon for automatic restarts:
// nodemon.json
{
"watch": ["src"],
"ext": "ts,json,yaml",
"exec": "ts-node src/server.ts"
}
- Development: SQLite database (
sample-database.db
) - Migrations: Use
pnpm create:migration
to create new migrations and then add the@Migration
decorator to the generated migration class. - Seeding: Initial users loaded via
users.init.ts
The sample uses SQLite by default for simplicity and portability. The database file (sample-database.db
) is created automatically in the project root.
The Node-Boot starter persistence package supports all TypeORM-compatible databases. You can easily switch by updating your configuration:
- SQL Databases: PostgreSQL, MySQL, MariaDB, SQLite, Microsoft SQL Server, Oracle, CockroachDB
- NoSQL Databases: MongoDB
-
Install the appropriate database driver:
# PostgreSQL pnpm add pg pnpm add -D @types/pg # MySQL/MariaDB pnpm add mysql2 # MongoDB pnpm add mongodb # SQL Server pnpm add mssql # Oracle pnpm add oracledb
-
Update your configuration file (
app-config.yaml
orapp-config.local.yaml
):SQLite Example (default):
persistence: type: "better-sqlite3" synchronize: false # False, meaning that the application rely on migrations cache: true migrationsRun: true better-sqlite3: database: "sample-database.db" transactions: # Controls how many hooks (`commit`, `rollback`, `complete`) can be used simultaneously. # If you exceed the number of hooks of same type, you get a warning. This is a useful to find possible memory leaks. # You can set this options to `0` or `Infinity` to indicate an unlimited number of listeners. maxHookHandlers: 10 # Controls storage driver used for providing persistency during the async request timespan. # You can force any of the available drivers with this option. # By default, the modern AsyncLocalStorage will be preferred, if it is supported by your runtime. storageDriver: "AUTO"
PostgreSQL Example:
persistence: type: "postgres" synchronize: false # False, meaning that the application rely on migrations cache: true migrationsRun: true postgres: host: "localhost" port: 5432 username: "your_username" password: "your_password" database: "your_database"
MySQL Example:
datasource: type: "mysql" synchronize: false # False, meaning that the application rely on migrations cache: true migrationsRun: true mysql: host: "localhost" port: 3306 username: "root" password: "password" database: "sample-database"
MongoDB Example:
persistence: type: "mongodb" cache: false mongodb: database: "facts" #url: mongodb://localhost:27017/?directConnection=true url: mongodb+srv://${DATABASE_CREDS}@db-name.mongodb.net/?retryWrites=true&w=majority&appName=sample-database
-
Environment-specific Configuration: Use
app-config.local.yaml
for local development orapp-credentials.local.yaml
for sensitive credentials:# app-credentials.local.yaml (git-ignored) postgres: username: "your_username" password: "your_password"
For production environments, use environment variables or secure configuration management:
mysql:
username: "${DB_USERNAME}"
password: "${DB_PASSWORD}"
host: "${DB_HOST:localhost}"
port: "${DB_PORT:5432}"
database: "${DB_NAME}"
The Node-Boot starter persistence package provides:
- Automatic Connection Management - Connections are managed automatically
- Transaction Support - Use
@Transactional
decorator for transaction management - Migration System - TypeORM migrations with Node-Boot decorators
- Entity Event Listeners - Lifecycle hooks for entities
- Repository Pattern - Custom repositories with
@DataRepository
- Connection Pooling - Built-in connection pool management
# Create new migration
pnpm create:migration
Note: After creating the migration class, add the
@Migration
decorator to the generated class to register it. Build and run the application to execute pending migrations at bootstrap.
import {MigrationInterface, QueryRunner} from "typeorm";
import {Migration} from "@nodeboot/starter-persistence";
@Migration()
export class Migration1701786331338 implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "nb-user" ADD COLUMN "name" varchar(255)`);
}
async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "nb-user" DROP COLUMN "name"`);
}
}
For detailed database configuration options, visit the Node-Boot Starter Persistence.
- Framework: Jest with SWC compiler
- Configuration:
jest.config.js
- Run tests:
pnpm test
- Linting: ESLint with TypeScript rules
- Formatting: Prettier with import organization
- Type Checking: Strict TypeScript configuration
app.ts
- Main application bootstrap with feature decoratorsserver.ts
- Application entry pointpackage.json
- Dependencies and scriptstsconfig.json
- TypeScript configurationapp-config.yaml
- Application configurationDockerfile
- Container configuration
-
Build the application:
pnpm build
-
Start production server:
pnpm start:prod
-
Docker deployment:
- Build docker image
docker build -f Dockerfile -t native-http-sample .
- Run docker image
docker run --rm -it -p 3000:3000 native-http-sample
- Check container filesystem
docker run -t -i native-http-sample /bin/sh
Access the interactive API documentation at: http://localhost:3000/docs