Enterprise Patterns. Startup Speed.
Stop Fighting Your Framework.
Enterprise Patterns. Startup Speed.
Stop Fighting Your Framework.
Register controllers directly — no providers arrays, no forRoot(), no import/export ceremonies. DI resolves dependencies globally.
Decorator-based resolvers inject params, headers, body — your handlers stay pure and testable. Swap real data for mocks with zero changes to business logic.
HTTP, WebSocket, CLI, Workflows — the same controllers, DI, interceptors, and pipes work everywhere. Write an auth guard once, apply it anywhere.
@Injectable() with constructor types. Singleton or per-event scope. @Provide() / @Inject() to swap implementations. No ceremony.
Type-safe validation from your TypeScript types — no class-validator, no duplicate schemas. One source of truth for types, docs, and runtime checks.
10% ahead of NestJS+Fastify on real-world benchmarks. Lazy cookie parsing, short-circuit auth failures, and half the DI overhead.
@Controller()
export class HealthController {
@Get('health')
health() { return 'ok' }
}@Module({ controllers: [HealthController] })
export class HealthModule {}@Controller()
export class AppController {
@Get('hello/:name')
hello(@Param('name') name: string) {
return `Hello, ${name}!`
}
}@Module({
imports: [HealthModule],
controllers: [AppController],
})
export class AppModule {}const app = await NestFactory.create(AppModule)
await app.listen(3000)@Controller()
export class HealthController {
@Get('health')
health() { return 'ok' }
}@ImportController(HealthController)
class App extends Moost {
@Get('hello/:name')
hello(@Param('name') name: string) {
return `Hello, ${name}!`
}
}
const app = new App()
app.adapter(new MoostHttp()).listen(3000)
app.init()export class CreateUserDto {
@ApiProperty({ description: 'Name', example: 'Alice', minLength: 2 })
@IsString()
@MinLength(2)
@MaxLength(100)
name: string
@ApiProperty({ description: 'Email', example: 'a@b.com' })
@IsEmail()
email: string
@ApiProperty({ description: 'Password', minLength: 8 })
@IsString()
@MinLength(8)
password: string
@ApiProperty({ description: 'Role', required: false, enum: UserRole })
@IsOptional()
@IsEnum(UserRole)
role?: UserRole
@ApiProperty({ description: 'Address', type: () => AddressDto })
@ValidateNested()
@Type(() => AddressDto)
address: AddressDto
}export class AddressDto {
@ApiProperty({ example: '123 Main St' })
@IsString()
street: string
@ApiProperty({ example: 'Springfield' })
@IsString()
city: string
@ApiProperty({ example: '62704' })
@IsString()
@Matches(/^\d{5}$/)
zip: string
}export interface CreateUserDto {
@meta.example "Alice"
@expect.minLength 2
@expect.maxLength 100
name: string
@meta.example "a@b.com"
email: string.email
@meta.sensitive
@expect.minLength 8
password: string
role?: UserRole
address: {
@meta.example "123 Main St"
street: string
@meta.example "Springfield"
city: string
@meta.example "62704"
@expect.pattern /^\d{5}$/
zip: string
}
}HTTP, WebSocket, CLI, Workflows — the same controllers, DI, and decorators everywhere.
@Controller('users')
export class UsersController {
@Get(':id')
find(@Param('id') id: string) {
return this.db.findUser(id)
}
@Post()
create(@Body() dto: CreateUserDto) {
return this.db.createUser(dto)
}
}