ts-deco 1.0.25 → 1.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -583
- package/dist/src/decorators/controllers/controller.decorator.d.ts +3 -3
- package/dist/src/decorators/controllers/controller.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/controller.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-body.decorator.d.ts +2 -2
- package/dist/src/decorators/controllers/doc-body.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-body.decorator.js +1 -1
- package/dist/src/decorators/controllers/doc-body.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-operation.decorator.d.ts +2 -2
- package/dist/src/decorators/controllers/doc-operation.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-operation.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-param.decorator.d.ts +2 -2
- package/dist/src/decorators/controllers/doc-param.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-param.decorator.js +1 -1
- package/dist/src/decorators/controllers/doc-param.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-query.decorator.d.ts +2 -2
- package/dist/src/decorators/controllers/doc-query.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-query.decorator.js +1 -1
- package/dist/src/decorators/controllers/doc-query.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-response.decorator.d.ts +2 -2
- package/dist/src/decorators/controllers/doc-response.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-response.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/doc-tags.decorator.d.ts +1 -1
- package/dist/src/decorators/controllers/doc-tags.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/doc-tags.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/endpoint.decorator.d.ts +27 -0
- package/dist/src/decorators/controllers/endpoint.decorator.d.ts.map +1 -0
- package/dist/src/decorators/controllers/endpoint.decorator.js +95 -0
- package/dist/src/decorators/controllers/endpoint.decorator.js.map +1 -0
- package/dist/src/decorators/controllers/index.d.ts +3 -3
- package/dist/src/decorators/controllers/index.d.ts.map +1 -1
- package/dist/src/decorators/controllers/index.js +5 -5
- package/dist/src/decorators/controllers/index.js.map +1 -1
- package/dist/src/decorators/controllers/operation.decorator.d.ts +3 -3
- package/dist/src/decorators/controllers/operation.decorator.d.ts.map +1 -1
- package/dist/src/decorators/controllers/operation.decorator.js.map +1 -1
- package/dist/src/decorators/controllers/resource.decorator.d.ts +28 -0
- package/dist/src/decorators/controllers/resource.decorator.d.ts.map +1 -0
- package/dist/src/decorators/controllers/resource.decorator.js +53 -0
- package/dist/src/decorators/controllers/resource.decorator.js.map +1 -0
- package/dist/src/decorators/controllers/types/controller.types.d.ts +100 -0
- package/dist/src/decorators/controllers/types/controller.types.d.ts.map +1 -0
- package/dist/src/decorators/controllers/types/controller.types.js +6 -0
- package/dist/src/decorators/controllers/types/controller.types.js.map +1 -0
- package/dist/src/decorators/controllers/utils/index.d.ts +2 -2
- package/dist/src/decorators/controllers/utils/index.d.ts.map +1 -1
- package/dist/src/decorators/controllers/utils/index.js +3 -3
- package/dist/src/decorators/controllers/utils/index.js.map +1 -1
- package/dist/src/decorators/controllers/utils/parse-controller-args.d.ts +2 -2
- package/dist/src/decorators/controllers/utils/parse-controller-args.d.ts.map +1 -1
- package/dist/src/decorators/controllers/utils/parse-controller-args.js +1 -1
- package/dist/src/decorators/controllers/utils/parse-controller-args.js.map +1 -1
- package/dist/src/decorators/controllers/utils/parse-resource-args.d.ts +12 -0
- package/dist/src/decorators/controllers/utils/parse-resource-args.d.ts.map +1 -0
- package/dist/src/decorators/controllers/utils/parse-resource-args.js +18 -0
- package/dist/src/decorators/controllers/utils/parse-resource-args.js.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
TypeScript decorator utilities with **strict validation standards** and **automatic Swagger documentation**
|
|
6
6
|
|
|
7
|
-
하나의 데코레이터로 **타입 검증과 Swagger API 문서화를 동시에** 처리하는 Node.js/TypeScript용 DTO 데코레이터 라이브러리입니다.
|
|
7
|
+
하나의 데코레이터로 **타입 검증과 Swagger API 문서화를 동시에** 처리하는 Node.js/TypeScript용 DTO 데코레이터 라이브러리입니다.
|
|
8
|
+
**NestJS**와 **Node.js (Express, Fastify 등)** 모든 프로젝트에서 사용할 수 있습니다.
|
|
9
|
+
|
|
10
|
+
---
|
|
8
11
|
|
|
9
12
|
## 설치
|
|
10
13
|
|
|
@@ -12,568 +15,58 @@ TypeScript decorator utilities with **strict validation standards** and **automa
|
|
|
12
15
|
npm install ts-deco
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
**`Property` 데코레이터 하나로 검증과 Swagger 문서 작성을 동시에** 처리할 수 있습니다:
|
|
18
|
-
|
|
19
|
-
### NestJS에서 사용
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { Property } from 'ts-deco';
|
|
23
|
-
|
|
24
|
-
class CreateUserDto {
|
|
25
|
-
@Property({ type: String, optional: false })
|
|
26
|
-
name: string;
|
|
27
|
-
|
|
28
|
-
@Property({ type: Number, min: 0, max: 120, optional: false })
|
|
29
|
-
age: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// NestJS Controller에서 자동으로 Swagger 문서 생성 및 검증 수행
|
|
33
|
-
@Post()
|
|
34
|
-
create(@Body() dto: CreateUserDto) {
|
|
35
|
-
// 자동 검증 완료, Swagger 문서에 자동 반영
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Node.js/Express에서 사용
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { Property } from 'ts-deco';
|
|
43
|
-
|
|
44
|
-
class CreateUserDto {
|
|
45
|
-
@Property({ type: String, optional: false })
|
|
46
|
-
name: string;
|
|
47
|
-
|
|
48
|
-
@Property({ type: Number, min: 0, max: 120, optional: false })
|
|
49
|
-
age: number;
|
|
50
|
-
}
|
|
18
|
+
---
|
|
51
19
|
|
|
52
|
-
|
|
53
|
-
app.post('/users', validationMiddleware(CreateUserDto), (req, res) => {
|
|
54
|
-
// 자동 검증 완료, Swagger 문서에 자동 반영
|
|
55
|
-
});
|
|
56
|
-
```
|
|
20
|
+
## 빠른 시작
|
|
57
21
|
|
|
58
|
-
###
|
|
22
|
+
### DTO 검증 + Swagger 문서화
|
|
59
23
|
|
|
60
|
-
`Property` 데코레이터 하나로
|
|
24
|
+
`Property` 데코레이터 하나로 **타입 검증과 Swagger 문서 작성을 동시에** 처리할 수 있습니다:
|
|
61
25
|
|
|
62
26
|
```typescript
|
|
63
|
-
import { Property } from
|
|
27
|
+
import { Property } from "ts-deco";
|
|
64
28
|
|
|
65
29
|
class CreateUserDto {
|
|
66
|
-
@Property({
|
|
67
|
-
name: string;
|
|
68
|
-
|
|
69
|
-
@Property({ type: Number, min: 0, max: 120, optional: false })
|
|
70
|
-
age: number;
|
|
71
|
-
|
|
72
|
-
@Property({ type: String, optional: true })
|
|
73
|
-
email?: string;
|
|
74
|
-
|
|
75
|
-
@Property({ type: Boolean, optional: false })
|
|
76
|
-
isActive: boolean;
|
|
77
|
-
|
|
78
|
-
@Property({ type: Date, optional: true })
|
|
79
|
-
createdAt?: Date;
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## 주요 기능
|
|
84
|
-
|
|
85
|
-
### ⚡ 하나의 데코레이터로 검증 + Swagger 문서화
|
|
86
|
-
|
|
87
|
-
**`Property` 데코레이터는 타입에 따라 자동으로 적절한 검증을 적용하고, 동시에 Swagger API 문서를 자동 생성합니다.**
|
|
88
|
-
|
|
89
|
-
- ✅ **검증**: `class-validator`를 사용한 런타임 타입 검증
|
|
90
|
-
- ✅ **Swagger**: `@nestjs/swagger` 호환 메타데이터로 자동 API 문서 생성
|
|
91
|
-
- ✅ **함축적**: 하나의 데코레이터로 두 가지 작업을 동시에 처리
|
|
92
|
-
- ✅ **호환성**: NestJS와 Node.js (Express, Fastify 등) 모두 지원
|
|
93
|
-
|
|
94
|
-
### Property 데코레이터 (권장)
|
|
95
|
-
|
|
96
|
-
`Property` 데코레이터는 타입에 따라 자동으로 적절한 검증과 Swagger 스키마를 적용합니다.
|
|
97
|
-
|
|
98
|
-
#### 기본 타입
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { Property } from 'ts-deco';
|
|
102
|
-
|
|
103
|
-
class UserDto {
|
|
104
|
-
// 문자열
|
|
105
|
-
@Property({ type: String, optional: false })
|
|
106
|
-
name: string;
|
|
107
|
-
|
|
108
|
-
// 숫자 (범위 검증)
|
|
109
|
-
@Property({
|
|
110
|
-
type: Number,
|
|
111
|
-
min: 1,
|
|
112
|
-
max: 100,
|
|
113
|
-
optional: false
|
|
114
|
-
})
|
|
115
|
-
score: number;
|
|
116
|
-
|
|
117
|
-
// 날짜
|
|
118
|
-
@Property({ type: Date, optional: true })
|
|
119
|
-
birthDate?: Date;
|
|
120
|
-
|
|
121
|
-
// 불린
|
|
122
|
-
@Property({ type: Boolean, optional: false })
|
|
123
|
-
isActive: boolean;
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
#### 열거형 (Enum)
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { Property } from 'ts-deco';
|
|
131
|
-
|
|
132
|
-
enum UserRole {
|
|
133
|
-
ADMIN = 'admin',
|
|
134
|
-
USER = 'user',
|
|
135
|
-
GUEST = 'guest',
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
class UserDto {
|
|
139
|
-
@Property({
|
|
140
|
-
enum: UserRole,
|
|
141
|
-
optional: false
|
|
142
|
-
})
|
|
143
|
-
role: UserRole;
|
|
144
|
-
|
|
145
|
-
// 특정 값 제외
|
|
146
|
-
@Property({
|
|
147
|
-
enum: UserRole,
|
|
148
|
-
exclude: [UserRole.GUEST],
|
|
149
|
-
optional: false
|
|
150
|
-
})
|
|
151
|
-
allowedRole: UserRole;
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
#### 배열
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
import { Property } from 'ts-deco';
|
|
159
|
-
|
|
160
|
-
class UserDto {
|
|
161
|
-
@Property({
|
|
162
|
-
type: String,
|
|
163
|
-
isArray: true,
|
|
164
|
-
optional: false
|
|
165
|
-
})
|
|
166
|
-
tags: string[];
|
|
167
|
-
|
|
168
|
-
@Property({
|
|
169
|
-
type: Number,
|
|
170
|
-
isArray: true,
|
|
171
|
-
min: 1,
|
|
172
|
-
max: 10,
|
|
173
|
-
optional: false
|
|
174
|
-
})
|
|
175
|
-
scores: number[];
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
#### 빈 값 검증 (isNotEmpty)
|
|
180
|
-
|
|
181
|
-
문자열이나 배열이 비어있지 않은지 검증하려면 `isNotEmpty` 옵션을 사용합니다:
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
import { Property } from 'ts-deco';
|
|
185
|
-
|
|
186
|
-
class UserDto {
|
|
187
|
-
@Property({
|
|
30
|
+
@Property({
|
|
188
31
|
type: String,
|
|
189
32
|
optional: false,
|
|
190
|
-
|
|
191
|
-
|
|
33
|
+
description: "사용자 이름",
|
|
34
|
+
example: "홍길동",
|
|
192
35
|
})
|
|
193
36
|
name: string;
|
|
194
37
|
|
|
195
|
-
@Property({
|
|
196
|
-
type: String,
|
|
197
|
-
isArray: true,
|
|
198
|
-
optional: false,
|
|
199
|
-
isNotEmpty: true,
|
|
200
|
-
arrayMessage: '태그는 배열이어야 합니다',
|
|
201
|
-
notEmptyMessage: '태그는 최소 1개 이상 필요합니다'
|
|
202
|
-
})
|
|
203
|
-
tags: string[];
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
#### 커스텀 에러 메시지
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
import { Property } from 'ts-deco';
|
|
211
|
-
|
|
212
|
-
class UserDto {
|
|
213
|
-
@Property({
|
|
214
|
-
type: Number,
|
|
215
|
-
min: 1,
|
|
216
|
-
max: 100,
|
|
217
|
-
minMessage: '최소값은 1 이상이어야 합니다',
|
|
218
|
-
maxMessage: '최대값은 100 이하여야 합니다',
|
|
219
|
-
validatorMessage: '숫자 타입이어야 합니다',
|
|
220
|
-
optional: false
|
|
221
|
-
})
|
|
222
|
-
score: number;
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### 개별 데코레이터
|
|
227
|
-
|
|
228
|
-
더 세밀한 제어가 필요한 경우 개별 데코레이터를 사용할 수 있습니다:
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
import { DtoString, DtoNumber, DtoDate, DtoBoolean, DtoEnum } from 'ts-deco';
|
|
232
|
-
|
|
233
|
-
class UserDto {
|
|
234
|
-
@DtoString({ optional: false, isNotEmpty: true })
|
|
235
|
-
name: string;
|
|
236
|
-
|
|
237
|
-
@DtoNumber({ min: 0, max: 120, optional: false })
|
|
38
|
+
@Property({ type: Number, min: 0, max: 120, optional: false })
|
|
238
39
|
age: number;
|
|
239
|
-
|
|
240
|
-
@DtoDate({ optional: true })
|
|
241
|
-
birthDate?: Date;
|
|
242
|
-
|
|
243
|
-
@DtoBoolean({ optional: false })
|
|
244
|
-
isActive: boolean;
|
|
245
|
-
|
|
246
|
-
@DtoEnum(UserRole, { optional: false })
|
|
247
|
-
role: UserRole;
|
|
248
40
|
}
|
|
249
41
|
```
|
|
250
42
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
각 개별 데코레이터는 `Property` 데코레이터와 동일한 옵션을 지원합니다:
|
|
43
|
+
### Controller Swagger 문서화
|
|
254
44
|
|
|
255
|
-
|
|
256
|
-
- **DtoNumber**: `optional`, `isNotEmpty`, `isArray`, `isInt`, `min`, `max`, `minMessage`, `maxMessage`, `validatorMessage`, `notEmptyMessage`, `arrayMessage` 및 Swagger 옵션
|
|
257
|
-
- **DtoDate**: `optional`, `isNotEmpty`, `isArray`, `validatorMessage`, `notEmptyMessage`, `arrayMessage` 및 Swagger 옵션
|
|
258
|
-
- **DtoBoolean**: `optional`, `isNotEmpty`, `isArray`, `validatorMessage`, `notEmptyMessage`, `arrayMessage` 및 Swagger 옵션
|
|
259
|
-
- **DtoEnum**: `optional`, `isNotEmpty`, `isArray`, `exclude`, `validatorMessage`, `notEmptyMessage`, `arrayMessage` 및 Swagger 옵션
|
|
260
|
-
|
|
261
|
-
## Controller 데코레이터 (NestJS 스타일)
|
|
262
|
-
|
|
263
|
-
**검증과 Swagger 문서 작성을 동시에 처리하는 DTO 데코레이터** 외에도, **API 엔드포인트의 Swagger 문서를 자동 생성하는 Controller 데코레이터**를 제공합니다.
|
|
264
|
-
|
|
265
|
-
### 사용 예제
|
|
266
|
-
|
|
267
|
-
#### NestJS에서 사용
|
|
45
|
+
`Resource`와 `Endpoint`로 Controller 문서화를 한 번에 처리할 수 있습니다:
|
|
268
46
|
|
|
269
47
|
```typescript
|
|
270
|
-
import {
|
|
48
|
+
import { Resource, Endpoint } from "ts-deco";
|
|
271
49
|
|
|
272
|
-
@
|
|
273
|
-
@Controller('users')
|
|
50
|
+
@Resource("Users", "/api/users")
|
|
274
51
|
export class UserController {
|
|
275
|
-
@
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
@DocOperation({ summary: '사용자 업데이트' })
|
|
285
|
-
@DocResponse({ status: 200, description: '사용자 업데이트 성공' })
|
|
286
|
-
@DocParam({ name: 'id', type: String, required: true })
|
|
287
|
-
@DocBody({ type: UpdateUserDto, required: true })
|
|
288
|
-
@Patch(':id')
|
|
289
|
-
update(@Param('id') id: string, @Body() dto: UpdateUserDto) {
|
|
290
|
-
// ...
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
@DocOperation({ summary: '사용자 목록 조회' })
|
|
294
|
-
@DocQuery({ name: 'page', type: Number, required: false, minimum: 1 })
|
|
295
|
-
@DocQuery({ name: 'limit', type: Number, required: false, minimum: 1, maximum: 100 })
|
|
296
|
-
@Get()
|
|
297
|
-
findAll(@Query('page') page?: number, @Query('limit') limit?: number) {
|
|
298
|
-
// ...
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
#### Node.js/Express에서 사용
|
|
304
|
-
|
|
305
|
-
```typescript
|
|
306
|
-
import { DocTags, DocOperation, DocResponse, DocParam, DocBody, DocQuery } from 'ts-deco';
|
|
307
|
-
|
|
308
|
-
class UserRoutes {
|
|
309
|
-
@DocTags('Users')
|
|
310
|
-
@DocOperation({ summary: '사용자 생성' })
|
|
311
|
-
@DocResponse({ status: 200, description: '사용자 생성 성공' })
|
|
312
|
-
@DocResponse({ status: 400, description: 'Validation 실패' })
|
|
313
|
-
@DocBody({ type: CreateUserDto, required: true })
|
|
314
|
-
static createUser(req: Request, res: Response) {
|
|
315
|
-
// ...
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
@DocTags('Users')
|
|
319
|
-
@DocOperation({ summary: '사용자 업데이트' })
|
|
320
|
-
@DocResponse({ status: 200, description: '사용자 업데이트 성공' })
|
|
321
|
-
@DocParam({ name: 'id', type: String, required: true })
|
|
322
|
-
@DocBody({ type: UpdateUserDto, required: true })
|
|
323
|
-
static updateUser(req: Request, res: Response) {
|
|
324
|
-
// ...
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
app.post('/api/users', validationMiddleware(CreateUserDto), UserRoutes.createUser);
|
|
329
|
-
app.patch('/api/users/:id', validationMiddleware(UpdateUserDto), UserRoutes.updateUser);
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
### Controller 데코레이터 목록
|
|
333
|
-
|
|
334
|
-
#### DocTags
|
|
335
|
-
클래스 또는 메서드에 Swagger 태그를 설정합니다.
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
@DocTags('Users')
|
|
339
|
-
@DocTags('Admin', 'Users') // 여러 태그
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
#### DocOperation
|
|
343
|
-
메서드에 Swagger 작업(operation) 정보를 설정합니다.
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
@DocOperation({
|
|
347
|
-
summary: '사용자 생성',
|
|
348
|
-
description: '새로운 사용자를 생성합니다',
|
|
349
|
-
operationId: 'createUser',
|
|
350
|
-
deprecated: false,
|
|
351
|
-
tags: ['Users']
|
|
352
|
-
})
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
#### DocResponse
|
|
356
|
-
메서드에 Swagger 응답 정보를 설정합니다. 여러 번 사용 가능합니다.
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
@DocResponse({ status: 200, description: '성공' })
|
|
360
|
-
@DocResponse({ status: 400, description: 'Validation 실패' })
|
|
361
|
-
@DocResponse({ status: 404, description: '사용자를 찾을 수 없음' })
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
#### DocParam
|
|
365
|
-
경로 파라미터에 대한 Swagger 정보를 설정합니다.
|
|
366
|
-
|
|
367
|
-
```typescript
|
|
368
|
-
@DocParam({ name: 'id', type: String, required: true, description: '사용자 ID' })
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
#### DocQuery
|
|
372
|
-
쿼리 파라미터에 대한 Swagger 정보를 설정합니다.
|
|
373
|
-
|
|
374
|
-
```typescript
|
|
375
|
-
@DocQuery({ name: 'page', type: Number, required: false, minimum: 1 })
|
|
376
|
-
@DocQuery({ name: 'limit', type: Number, required: false, minimum: 1, maximum: 100 })
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
#### DocBody
|
|
380
|
-
요청 본문에 대한 Swagger 정보를 설정합니다.
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
@DocBody({ type: CreateUserDto, description: '사용자 생성 데이터' })
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
## Property 데코레이터 옵션
|
|
387
|
-
|
|
388
|
-
### 공통 옵션
|
|
389
|
-
|
|
390
|
-
| 옵션 | 타입 | 기본값 | 설명 |
|
|
391
|
-
|------|------|--------|------|
|
|
392
|
-
| `type` | `String \| Number \| Date \| Boolean` | 필수 | 필드 타입 |
|
|
393
|
-
| `enum` | `object` | - | 열거형 타입 (type 대신 사용) |
|
|
394
|
-
| `optional` | `boolean` | `false` | 선택적 필드 여부. `true`일 경우 `IsOptional` 검증 적용 |
|
|
395
|
-
| `isArray` | `boolean` | `false` | 배열 타입 여부 |
|
|
396
|
-
| `isNotEmpty` | `boolean` | `false` | 빈 값 검증 여부. `true`일 경우 `IsNotEmpty` 검증 적용 (optional이 false일 때만) |
|
|
397
|
-
| `validatorMessage` | `string` | - | 타입 검증 실패 메시지 |
|
|
398
|
-
| `arrayMessage` | `string` | - | 배열 검증 실패 메시지 |
|
|
399
|
-
| `notEmptyMessage` | `string` | - | 빈 값 검증 실패 메시지 (isNotEmpty가 true일 때 사용) |
|
|
400
|
-
|
|
401
|
-
### 숫자 타입 전용 옵션
|
|
402
|
-
|
|
403
|
-
| 옵션 | 타입 | 기본값 | 설명 |
|
|
404
|
-
|------|------|--------|------|
|
|
405
|
-
| `min` | `number` | - | 최소값 |
|
|
406
|
-
| `max` | `number` | - | 최대값 |
|
|
407
|
-
| `isInt` | `boolean` | `false` | 정수만 허용 |
|
|
408
|
-
| `minMessage` | `string` | - | 최소값 검증 실패 메시지 |
|
|
409
|
-
| `maxMessage` | `string` | - | 최대값 검증 실패 메시지 |
|
|
410
|
-
|
|
411
|
-
### 열거형 전용 옵션
|
|
412
|
-
|
|
413
|
-
| 옵션 | 타입 | 기본값 | 설명 |
|
|
414
|
-
|------|------|--------|------|
|
|
415
|
-
| `exclude` | `any[]` | `[]` | 제외할 enum 값들 |
|
|
416
|
-
|
|
417
|
-
### Swagger 옵션 (자동 생성)
|
|
418
|
-
|
|
419
|
-
**`Property` 데코레이터는 자동으로 Swagger API 문서를 생성합니다.** `@nestjs/swagger`의 `ApiPropertyOptions`를 모두 사용할 수 있어 NestJS와 완벽하게 호환됩니다:
|
|
420
|
-
|
|
421
|
-
#### 검증 + Swagger 자동 생성 예제
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
@Property({
|
|
425
|
-
type: String,
|
|
426
|
-
description: '사용자 이름', // Swagger 문서에 표시
|
|
427
|
-
example: '홍길동', // Swagger 문서에 표시
|
|
428
|
-
optional: false // 검증 규칙 + Swagger required
|
|
429
|
-
})
|
|
430
|
-
name: string;
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
이렇게 작성하면:
|
|
434
|
-
- ✅ **검증**: `name`이 필수이며 문자열이어야 함
|
|
435
|
-
- ✅ **Swagger**: API 문서에 `name` 필드가 필수 문자열로 자동 등록됨
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
@Property({
|
|
439
|
-
type: String,
|
|
440
|
-
description: '사용자 이름',
|
|
441
|
-
example: '홍길동',
|
|
442
|
-
optional: false
|
|
443
|
-
})
|
|
444
|
-
name: string;
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
## 사용 예제
|
|
448
|
-
|
|
449
|
-
### 기본 사용법
|
|
450
|
-
|
|
451
|
-
```typescript
|
|
452
|
-
import { Property } from 'ts-deco';
|
|
453
|
-
import { validate } from 'class-validator';
|
|
454
|
-
import { plainToInstance } from 'class-transformer';
|
|
455
|
-
|
|
456
|
-
class CreateUserDto {
|
|
457
|
-
// 필수 문자열 필드
|
|
458
|
-
@Property({ type: String, optional: false })
|
|
459
|
-
name: string;
|
|
460
|
-
|
|
461
|
-
// 선택적 이메일 필드
|
|
462
|
-
@Property({ type: String, optional: true })
|
|
463
|
-
email?: string;
|
|
464
|
-
|
|
465
|
-
// 필수 숫자 필드 (범위 제한)
|
|
466
|
-
@Property({ type: Number, min: 0, max: 120, optional: false })
|
|
467
|
-
age: number;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// 사용 예제
|
|
471
|
-
const userData = {
|
|
472
|
-
name: '홍길동',
|
|
473
|
-
age: 25
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
const dto = plainToInstance(CreateUserDto, userData);
|
|
477
|
-
const errors = await validate(dto);
|
|
478
|
-
|
|
479
|
-
if (errors.length > 0) {
|
|
480
|
-
console.log('검증 실패:', errors);
|
|
481
|
-
} else {
|
|
482
|
-
console.log('검증 성공:', dto);
|
|
483
|
-
}
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
### 빈 값 검증 예제
|
|
487
|
-
|
|
488
|
-
```typescript
|
|
489
|
-
import { Property } from 'ts-deco';
|
|
490
|
-
|
|
491
|
-
class PostDto {
|
|
492
|
-
// 빈 문자열 허용 안 함
|
|
493
|
-
@Property({
|
|
494
|
-
type: String,
|
|
495
|
-
optional: false,
|
|
496
|
-
isNotEmpty: true,
|
|
497
|
-
notEmptyMessage: '제목은 필수이며 비어있을 수 없습니다'
|
|
498
|
-
})
|
|
499
|
-
title: string;
|
|
500
|
-
|
|
501
|
-
// 빈 문자열 허용 (기본값)
|
|
502
|
-
@Property({
|
|
503
|
-
type: String,
|
|
504
|
-
optional: false,
|
|
505
|
-
isNotEmpty: false // 기본값
|
|
52
|
+
@Endpoint({
|
|
53
|
+
method: "POST",
|
|
54
|
+
summary: "사용자 생성",
|
|
55
|
+
tags: ["Users"],
|
|
56
|
+
body: { type: CreateUserDto, required: true },
|
|
57
|
+
responses: [
|
|
58
|
+
{ status: 201, description: "생성 성공" },
|
|
59
|
+
{ status: 400, description: "Validation 실패" },
|
|
60
|
+
],
|
|
506
61
|
})
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// 빈 배열 허용 안 함
|
|
510
|
-
@Property({
|
|
511
|
-
type: String,
|
|
512
|
-
isArray: true,
|
|
513
|
-
optional: false,
|
|
514
|
-
isNotEmpty: true,
|
|
515
|
-
notEmptyMessage: '태그는 최소 1개 이상 필요합니다'
|
|
516
|
-
})
|
|
517
|
-
tags: string[];
|
|
62
|
+
@Post()
|
|
63
|
+
create(@Body() dto: CreateUserDto) {}
|
|
518
64
|
}
|
|
519
65
|
```
|
|
520
66
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
### optional 옵션
|
|
67
|
+
---
|
|
524
68
|
|
|
525
|
-
|
|
526
|
-
- 값이 `undefined` 또는 `null`이면 `IsDefined` 검증 실패
|
|
527
|
-
- `isNotEmpty: true`인 경우 `IsNotEmpty` 검증 적용 (빈 문자열, 빈 배열 등도 검증)
|
|
528
|
-
- `optional: true`: 필드가 선택적입니다
|
|
529
|
-
- 값이 없어도 통과 (`IsOptional` 검증 적용)
|
|
530
|
-
- 값이 있으면 타입 검증 수행
|
|
531
|
-
|
|
532
|
-
### isNotEmpty 옵션
|
|
533
|
-
|
|
534
|
-
- `isNotEmpty: false` (기본값): 빈 값 검증 없음
|
|
535
|
-
- `optional: false`일 때 `IsDefined` 검증만 수행
|
|
536
|
-
- `isNotEmpty: true`: 빈 값 검증 수행
|
|
537
|
-
- `optional: false`일 때만 적용됨
|
|
538
|
-
- `IsNotEmpty` 검증 적용 (빈 문자열 `""`, 빈 배열 `[]` 등도 검증 실패)
|
|
539
|
-
|
|
540
|
-
### 검증 우선순위
|
|
541
|
-
|
|
542
|
-
1. `optional: true` → `IsOptional` 적용 (값이 없어도 통과)
|
|
543
|
-
2. `optional: false` + `isNotEmpty: true` → `IsNotEmpty` 적용 (빈 값 검증)
|
|
544
|
-
3. `optional: false` + `isNotEmpty: false` → `IsDefined` 적용 (값 존재 여부만 검증)
|
|
545
|
-
4. 타입 검증 (IsString, IsNumber, IsDate, IsBoolean, IsEnum 등)
|
|
546
|
-
5. 추가 검증 (min/max, exclude 등)
|
|
547
|
-
|
|
548
|
-
## 왜 ts-deco를 사용해야 할까요?
|
|
549
|
-
|
|
550
|
-
### 🎯 검증과 Swagger 작성을 한 번에
|
|
551
|
-
|
|
552
|
-
기존에는 검증 데코레이터와 Swagger 데코레이터를 따로 작성해야 했습니다:
|
|
553
|
-
|
|
554
|
-
```typescript
|
|
555
|
-
// 기존 방식 (번거로움)
|
|
556
|
-
@IsString()
|
|
557
|
-
@IsNotEmpty()
|
|
558
|
-
@ApiProperty({ type: String, description: '사용자 이름', example: '홍길동' })
|
|
559
|
-
name: string;
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
**ts-deco를 사용하면 하나의 데코레이터로 처리합니다:**
|
|
563
|
-
|
|
564
|
-
```typescript
|
|
565
|
-
// ts-deco 방식 (간결함)
|
|
566
|
-
@Property({
|
|
567
|
-
type: String,
|
|
568
|
-
optional: false,
|
|
569
|
-
isNotEmpty: true,
|
|
570
|
-
description: '사용자 이름',
|
|
571
|
-
example: '홍길동'
|
|
572
|
-
})
|
|
573
|
-
name: string;
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
### 🌟 주요 장점
|
|
69
|
+
## 주요 기능
|
|
577
70
|
|
|
578
71
|
- ✅ **함축적**: 하나의 데코레이터로 검증과 Swagger 문서화 동시 처리
|
|
579
72
|
- ✅ **간결함**: 코드 중복 제거, 가독성 향상
|
|
@@ -582,55 +75,19 @@ name: string;
|
|
|
582
75
|
- ✅ **호환성**: NestJS와 Node.js (Express, Fastify 등) 모두 지원
|
|
583
76
|
- ✅ **런타임 안정성**: 명확한 에러 메시지 제공
|
|
584
77
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
`ts-deco`는 다음과 같은 엄격한 검증 규칙을 적용합니다:
|
|
588
|
-
|
|
589
|
-
- ✅ **타입 안전성**: 모든 데코레이터는 엄격한 타입 체크를 거칩니다
|
|
590
|
-
- ✅ **명시적 검증**: 옵션과 검증 규칙이 명확하게 정의되어 있습니다
|
|
591
|
-
- ✅ **일관된 동작**: 모든 데코레이터가 동일한 기준으로 동작합니다
|
|
592
|
-
- ✅ **런타임 안정성**: 잘못된 타입이나 값에 대해 명확한 에러를 제공합니다
|
|
593
|
-
- ✅ **자동 문서화**: 검증 규칙이 Swagger 문서에 자동으로 반영됩니다
|
|
594
|
-
|
|
595
|
-
### 검증 규칙
|
|
596
|
-
|
|
597
|
-
- **타입 불일치 시 즉시 에러**: 잘못된 타입이 전달되면 명확한 에러 메시지 제공
|
|
598
|
-
- **범위 검증**: `min`/`max` 옵션이 제공되면 반드시 검증
|
|
599
|
-
- **필수 필드 검증**: `optional: false`인 경우 값이 없으면 에러
|
|
600
|
-
- **빈 값 검증**: `isNotEmpty: true`인 경우 빈 문자열, 빈 배열 등도 검증 실패
|
|
601
|
-
- **배열 검증**: `isArray: true`인 경우 배열 타입만 허용
|
|
602
|
-
- **열거형 검증**: `enum`이 제공되면 해당 값만 허용
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
⚠️ **주의**: 모든 데코레이터는 동일한 타입이어야 합니다.
|
|
606
|
-
|
|
607
|
-
## 데코레이터 지원
|
|
608
|
-
|
|
609
|
-
이 라이브러리는 **TypeScript legacy decorators**를 지원합니다. Stage 3 decorators는 아직 지원하지 않습니다.
|
|
610
|
-
|
|
611
|
-
## 의존성
|
|
612
|
-
|
|
613
|
-
이 라이브러리는 다음 패키지들을 **dependencies**로 포함하고 있어, `npm install ts-deco` 실행 시 자동으로 함께 설치됩니다:
|
|
614
|
-
|
|
615
|
-
| 패키지 | 버전 | 용도 |
|
|
616
|
-
|--------|------|------|
|
|
617
|
-
| `class-transformer` | ^0.5.0 | 타입 변환 데코레이터 |
|
|
618
|
-
| `class-validator` | ^0.14.0 | 검증 데코레이터 |
|
|
619
|
-
| `reflect-metadata` | ^0.1.13 | 메타데이터 리플렉션 (데코레이터 지원) |
|
|
620
|
-
| `@nestjs/swagger` | ^7.0.0 | Swagger API 문서화 데코레이터 (선택적) |
|
|
78
|
+
---
|
|
621
79
|
|
|
622
|
-
|
|
623
|
-
> - 별도로 설치할 필요 없이 `npm install ts-deco`만 실행하면 모든 의존성이 자동으로 설치됩니다.
|
|
624
|
-
> - **이 라이브러리는 NestJS에 종속되지 않습니다.** `class-validator`와 `class-transformer`는 독립적인 라이브러리이며, **NestJS와 Node.js (Express, Fastify 등) 모든 프로젝트에서 사용할 수 있습니다.**
|
|
625
|
-
> - `@nestjs/swagger`는 Swagger API 문서화 기능을 사용할 때만 필요합니다. 문서화 기능을 사용하지 않더라도 검증 기능은 정상적으로 동작합니다.
|
|
626
|
-
> - **하나의 데코레이터로 검증과 Swagger 문서 작성을 동시에 처리**하므로 코드 중복을 줄이고 유지보수를 쉽게 만듭니다.
|
|
80
|
+
## 문서
|
|
627
81
|
|
|
628
|
-
|
|
82
|
+
| 문서 | 내용 |
|
|
83
|
+
| --------------------------------------------- | ------------------------------------------------------------ |
|
|
84
|
+
| [Property 데코레이터](./docs/property.md) | `Property` 데코레이터 사용법, 옵션 레퍼런스, 검증 동작 방식 |
|
|
85
|
+
| [개별 데코레이터](./docs/validators.md) | `DtoString`, `DtoNumber`, `DtoDate`, `DtoBoolean`, `DtoEnum` |
|
|
86
|
+
| [Controller 데코레이터](./docs/controller.md) | `Resource`, `Endpoint`, `DocTags`, `DocOperation` 등 |
|
|
87
|
+
| [사용 예제](./docs/examples.md) | NestJS, Express 전체 예제 |
|
|
88
|
+
| [설치 및 환경](./docs/installation.md) | 의존성, 지원 환경, tsconfig 설정 |
|
|
629
89
|
|
|
630
|
-
|
|
631
|
-
- ✅ **Node.js**: Express, Fastify 등 모든 Node.js 프레임워크에서 사용 가능
|
|
632
|
-
- ✅ **TypeScript**: TypeScript 프로젝트 필수 (타입 안전성 보장)
|
|
633
|
-
- ✅ **Swagger**: 자동 API 문서 생성 지원
|
|
90
|
+
---
|
|
634
91
|
|
|
635
92
|
## 라이선스
|
|
636
93
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { ControllerOptions } from
|
|
3
|
-
export type { ControllerOptions } from
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import type { ControllerOptions } from "./types/controller.types";
|
|
3
|
+
export type { ControllerOptions } from "./types/controller.types";
|
|
4
4
|
/**
|
|
5
5
|
* Controller 데코레이터 - NestJS 스타일의 컨트롤러 데코레이터
|
|
6
6
|
* 클래스에 적용하여 모든 메서드에 자동으로 태그를 적용하고 경로를 설정
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.decorator.d.ts","sourceRoot":"","sources":["../../../../src/decorators/controllers/controller.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"controller.decorator.d.ts","sourceRoot":"","sources":["../../../../src/decorators/controllers/controller.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,GAAG,iBAAiB,EACxC,IAAI,CAAC,EAAE,MAAM,GACZ,cAAc,CA6BhB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.decorator.js","sourceRoot":"","sources":["../../../../src/decorators/controllers/controller.decorator.ts"],"names":[],"mappings":";;AA0BA,
|
|
1
|
+
{"version":3,"file":"controller.decorator.js","sourceRoot":"","sources":["../../../../src/decorators/controllers/controller.decorator.ts"],"names":[],"mappings":";;AA0BA,gCAgCC;AA1DD,4BAA0B;AAC1B,+DAA4D;AAE5D,yEAAoE;AAIpE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,UAAU,CACxB,YAAwC,EACxC,IAAa;IAEb,OAAO,UAAU,MAAW;QAC1B,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,IAAA,2CAAmB,EACvD,YAAY,EACZ,IAAI,CACL,CAAC;QAEF,QAAQ;QACR,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,YAAY,GAChB,OAAO,CAAC,WAAW,CAAC,yCAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAClE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,cAAc,CACpB,yCAAmB,CAAC,QAAQ,EAC5B,CAAC,GAAG,YAAY,EAAE,GAAG,CAAC,EACtB,MAAM,CACP,CAAC;YACJ,CAAC;QACH,CAAC;QAED,QAAQ;QACR,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,cAAc,CACpB,yCAAmB,CAAC,eAAe,EACnC,cAAc,EACd,MAAM,CACP,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|