ts-deco
v1.1.2
Published
TypeScript decorator utilities for Node.js with strict validation standards
Maintainers
Readme
ts-deco
검증과 Swagger 문서화를 하나의 데코레이터로 처리하는 TypeScript 라이브러리
DTO 필드에 @Property, 컨트롤러에 @Resource / @Endpoint만 붙이면class-validator 검증과 Swagger(OpenAPI) 스키마가 함께 생성됩니다.
- NestJS:
@nestjs/swagger/ HTTP 메서드 데코레이터와 자동 연동 - Express:
ts-deco/express의setupApp으로 라우트·Swagger UI 자동 등록 - Fastify 어댑터는 현재 미지원
왜 ts-deco인가
프레임워크마다 검증·문서·라우팅을 각각 붙이는 방식이 다릅니다. ts-deco는 그걸 한 데코레이터 세트로 맞춥니다.
NestJS — 검증과 Swagger를 따로 쌓는 패턴
// DTO: class-validator + @nestjs/swagger를 필드마다 중복 선언
@ApiProperty({ description: '이름' })
@IsString()
@IsNotEmpty()
name: string;
// Controller: HTTP 메서드 + ApiTags / ApiOperation / ApiBody를 또 따로
@ApiTags('Users')
@Controller('users')
export class UserController {
@Post()
@ApiOperation({ summary: '사용자 생성' })
@ApiBody({ type: CreateUserDto })
create() {}
}ts-deco에서는 @Property / @Resource / @Endpoint만 쓰면
Nest 패키지가 있을 때 @Is*, @ApiProperty, @Controller, @Get/@Post, ApiTags 등이 함께 적용됩니다.
Express — 라우트·검증·Swagger를 손으로 묶는 패턴
// 라우트 등록, validation middleware, swagger-jsdoc 스키마를 각각 작성
app.post('/api/users', validationMiddleware(CreateUserDto), handler);
/**
* @openapi
* /api/users:
* post:
* summary: 사용자 생성
* ...
*/ts-deco에서는 동일한 @Resource / @Endpoint 메타데이터로setupApp이 라우트 등록 + body/query validation + Swagger UI까지 한 번에 처리합니다.
공통 — DTO는 한 줄
@Property({ type: String, description: '이름', isNotEmpty: true })
name: string;선택 필드·배열·enum·중첩 DTO까지 Nest/Express 모두 같은 @Property 옵션으로 맞출 수 있습니다.
설치
npm install ts-deco class-validator class-transformer reflect-metadatatsconfig.json에 legacy decorator 설정이 필요합니다.
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}NestJS
npm install @nestjs/common @nestjs/swaggerimport { Property, Resource, Endpoint } from "ts-deco";Nest 패키지가 있으면 @Controller, @Get/@Post, ApiTags 등이 @Resource / @Endpoint에 함께 적용됩니다.
Express (setupApp 사용 시)
npm install express swagger-ui-express swagger-jsdocimport { setupApp, autoRegisterRoutes } from "ts-deco/express";
import { Property, Resource, Endpoint } from "ts-deco";Express 헬퍼는 optional peer이므로 메인 엔트리(
ts-deco)에는 포함되지 않습니다.
Nest만 쓰는 프로젝트는ts-deco만 import하면 됩니다.
자세한 peer 의존성은 설치 및 환경을 참고하세요.
빠른 시작
1. DTO — @Property
import { Property } from "ts-deco";
enum UserRole {
ADMIN = "admin",
USER = "user",
}
class AddressDto {
@Property({ type: String, description: "도시" })
city: string;
}
class CreateUserDto {
@Property({
type: String,
description: "사용자 이름",
example: "홍길동",
isNotEmpty: true,
})
name: string;
@Property({ type: Number, min: 0, max: 120 })
age: number;
@Property({ enum: UserRole })
role: UserRole;
// 선택 필드: 검증은 optional, Swagger 표기는 nullable
@Property({ type: String, optional: true, nullable: true })
email?: string;
// 중첩 DTO
@Property({ type: AddressDto })
address: AddressDto;
// 중첩 DTO 배열
@Property({ type: AddressDto, isArray: true, optional: true, nullable: true })
addresses?: AddressDto[];
}| 옵션 | 역할 |
|------|------|
| optional: true | IsOptional 검증 (값이 없어도 통과) |
| nullable: true | Swagger 스키마 nullable/선택 표기 (검증과 무관) |
| isArray: true | 배열 필드 (단일 값도 배열로 정규화) |
| type: SomeDto | 중첩 DTO (ValidateNested + Type) |
isOptional은 deprecated alias입니다. 신규 코드에서는optional을 사용하세요.
세분화된 제어가 필요하면 DtoString, DtoNumber, DtoDate, DtoBoolean, DtoEnum, DtoNested를 쓸 수 있습니다.
→ Property 문서 · 개별 데코레이터
2. Controller — @Resource / @Endpoint
import { Resource, Endpoint } from "ts-deco";
@Resource({ tag: "Users", path: "/api/users" })
export class UserController {
@Endpoint({
method: "POST",
endpoint: "",
summary: "사용자 생성",
tags: ["Users"],
body: { type: CreateUserDto, required: true },
responses: [
{ status: 201, description: "생성 성공" },
{ status: 400, description: "Validation 실패" },
],
})
create(/* ... */) {}
@Endpoint({
method: "GET",
endpoint: "/:id",
summary: "사용자 조회",
params: [{ name: "id", type: String, required: true }],
responses: [{ status: 200, description: "성공", type: CreateUserDto }],
})
findOne(/* ... */) {}
}
// prefix로 관리용 경로: /mgmt/users
@Resource({ tag: "Users", prefix: "mgmt" })
export class AdminUserController {}Express 자동 라우트 등록 시 @Endpoint의 method / endpoint가 우선 사용됩니다.
Query 검증·Swagger 문서화는 queryDto만 지정하면 됩니다. (DTO 프로퍼티에서 query 파라미터 자동 생성)
@Endpoint({
method: "GET",
endpoint: "",
summary: "목록",
queryDto: ListQueryDto, // 검증 + Swagger query 자동 생성
})
list() {}명시 queries가 있으면 같은 이름에 대해 queryDto 파생 값을 덮어씁니다.
3. Express — setupApp
import express from "express";
import { setupApp } from "ts-deco/express";
import * as controllers from "./routers";
const app = express();
app.use(express.json());
setupApp({
app,
controllers,
swagger: {
title: "My API",
version: "1.0.0",
description: "API Documentation",
},
swaggerPath: "/api-docs",
});
app.listen(3000);setupApp은 Swagger UI 설정과 @Resource / @Endpoint 기반 라우트·validation middleware 등록을 한 번에 처리합니다.
프로젝트 구조
ts-deco/
├── src/
│ ├── index.ts # 퍼블릭 API (validators + controllers)
│ ├── decorators/
│ │ ├── validators/ # Property, DtoString, DtoNested 등
│ │ └── controllers/ # Resource, Endpoint, Doc* 등
│ └── configs/ # Express: setupApp, 라우트, Swagger factory
│ └── → import from "ts-deco/express"
├── app/ # Express 데모 앱
├── docs/ # 상세 문서
└── tests/| import | 내용 |
|--------|------|
| ts-deco | DTO·Controller 데코레이터 |
| ts-deco/express | setupApp, autoRegisterRoutes, validationMiddleware, Swagger 유틸 |
주요 기능
- 함축적 API: 검증 + Swagger를
@Property/@Endpoint한 곳에서 정의 - 중첩 DTO:
type: ClassDto/isArray로 객체·배열 검증 - Nest 브릿지:
@nestjs/common·@nestjs/swagger가 있으면 네이티브 데코레이터 자동 적용 - Express 자동화: 메타데이터 기반 라우트 등록 + body/query validation
- 타입 안전: TypeScript +
strict환경에서 옵션을 좁혀 사용
문서
| 문서 | 내용 |
|------|------|
| Property 데코레이터 | 옵션 레퍼런스, optional/nullable, 중첩 DTO, 검증 우선순위 |
| 개별 데코레이터 | DtoString, DtoNumber, DtoDate, DtoBoolean, DtoEnum, DtoNested |
| Controller 데코레이터 | Resource, Endpoint (Property, Dto*) |
| 사용 예제 | NestJS / Express 전체 예제 |
| 설치 및 환경 | peer 의존성, tsconfig, 지원 환경 |
데모 앱 실행:
npm run dev
# Swagger UI: http://localhost:<PORT>/api-docs라이선스
ISC License
