ts-class-to-openapi 1.0.4 → 1.0.6

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.
Files changed (38) hide show
  1. package/README.md +369 -875
  2. package/dist/__test__/entities/additional-test-classes.d.ts +12 -0
  3. package/dist/__test__/entities/decorated-classes.d.ts +54 -0
  4. package/dist/__test__/entities/nested-classes.d.ts +70 -0
  5. package/dist/__test__/entities/pure-classes.d.ts +37 -0
  6. package/dist/__test__/entities/schema-validation-classes.d.ts +35 -0
  7. package/dist/__test__/index.d.ts +3 -6
  8. package/dist/__test__/test.d.ts +4 -0
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.esm.js +476 -1075
  11. package/dist/index.js +476 -1075
  12. package/dist/run.d.ts +1 -1
  13. package/dist/run.js +1064 -1101
  14. package/dist/transformer.d.ts +1 -471
  15. package/dist/transformer.fixtures.d.ts +21 -0
  16. package/dist/types.d.ts +55 -6
  17. package/package.json +16 -15
  18. package/dist/__test__/entities/address.entity.d.ts +0 -5
  19. package/dist/__test__/entities/array.entity.d.ts +0 -7
  20. package/dist/__test__/entities/broken.entity.d.ts +0 -7
  21. package/dist/__test__/entities/complete.entity.d.ts +0 -16
  22. package/dist/__test__/entities/complex-generics.entity.d.ts +0 -33
  23. package/dist/__test__/entities/comprehensive-enum.entity.d.ts +0 -23
  24. package/dist/__test__/entities/enum.entity.d.ts +0 -29
  25. package/dist/__test__/entities/generic.entity.d.ts +0 -11
  26. package/dist/__test__/entities/optional-properties.entity.d.ts +0 -11
  27. package/dist/__test__/entities/plain.entity.d.ts +0 -19
  28. package/dist/__test__/entities/simple.entity.d.ts +0 -5
  29. package/dist/__test__/entities/upload.entity.d.ts +0 -8
  30. package/dist/__test__/entities/user-role-generic.entity.d.ts +0 -13
  31. package/dist/__test__/test-entities/duplicate-name.entity.d.ts +0 -5
  32. package/dist/__test__/test-entities/generic.entity.d.ts +0 -11
  33. /package/dist/__test__/{enum.test.d.ts → testCases/debug.test.d.ts} +0 -0
  34. /package/dist/__test__/{generic-types.test.d.ts → testCases/decorated-classes.test.d.ts} +0 -0
  35. /package/dist/__test__/{integration.test.d.ts → testCases/edge-cases.test.d.ts} +0 -0
  36. /package/dist/__test__/{main.test.d.ts → testCases/nested-classes.test.d.ts} +0 -0
  37. /package/dist/__test__/{optional-properties.test.d.ts → testCases/pure-classes.test.d.ts} +0 -0
  38. /package/dist/__test__/{plain.test.d.ts → testCases/schema-validation.test.d.ts} +0 -0
package/README.md CHANGED
@@ -1,51 +1,34 @@
1
1
  # 🔄 ts-class-to-openapi
2
2
 
3
- ✨ **Transform TypeScript classes into OpenAPI 3.1.0 schema objects**
3
+ ✨ **Transform TypeScript classes into OpenAPI 3.1.0 schemas**
4
4
 
5
- A powerful library that automatically converts your TypeScript classes into OpenAPI-compatible schemas. Works with **pure TypeScript classes** and **class-validator decorated classes**, with zero runtime dependencies.
5
+ A robust and efficient library that automatically transforms TypeScript classes into OpenAPI-compatible schemas. Compatible with **pure TypeScript classes** and **class-validator decorated classes**.
6
6
 
7
- > **🎯 Latest Features**:
8
- >
9
- > - **Pure TypeScript classes** without requiring any decorators or external dependencies!
10
- > - **Full enum support** with `@IsEnum` decorator for string, numeric, and object enums
11
- > - Perfect for transforming existing codebases instantly.
7
+ > **What is OpenAPI?** OpenAPI (formerly Swagger) is the industry standard for describing REST APIs. This library generates OpenAPI 3.1.0 compatible schemas that can be used for API documentation, client SDK generation, and validation.
12
8
 
13
9
  ## 🚀 Key Features
14
10
 
15
- - ✅ **Pure TypeScript Support** - Transform any TypeScript class without decorators
16
- - ✅ **class-validator Compatible** - Enhanced schemas with validation decorators
17
- - ✅ **Enum Support** - Full support for TypeScript enums and object enums with @IsEnum
18
- - ✅ **CommonJS & ESM Compatible** - Works in any Node.js project
19
- - ✅ **Zero Runtime Dependencies** - No `reflect-metadata` or `emitDecoratorMetadata` required
20
- - ✅ **OpenAPI 3.1.0** - Industry-standard schema generation
21
- - ✅ **TypeScript Native** - Full type support and safety
22
- - ✅ **High Performance** - Singleton pattern with built-in caching
23
- - ✅ **Nested Objects** - Handles complex relationships automatically
24
- - ✅ **Typed Arrays** - Full support for arrays with validation
25
- - ✅ **File Uploads** - Binary file upload support
11
+ - ✅ **Direct transformation** - Convert any TypeScript class without additional configuration
12
+ - ✅ **Zero runtime dependencies** - No `reflect-metadata` or complex configurations required
13
+ - ✅ **class-validator integration** - Enrich schemas using validation decorators
14
+ - ✅ **Automatic documentation generation** - Generate Swagger documentation from existing classes
15
+ - ✅ **Native TypeScript support** - Full compatibility with enums, arrays, and nested objects
26
16
 
27
- ## 🎯 Why Use This Library?
17
+ ## 🎯 Quick Example
28
18
 
29
- Perfect for projects where you need to:
30
-
31
- - 🌐 **REST APIs**: Generate Swagger documentation from your existing TypeScript classes
32
- - 📚 **Auto Documentation**: Maintain consistency between TypeScript types and API contracts
33
- - 🧪 **API Testing**: Create mock data structures for testing
34
- - 🔧 **Microservices**: Ensure schema consistency across services
35
- - ⚡ **Legacy Projects**: Works without enabling `emitDecoratorMetadata`
36
- - 🎯 **Pure TypeScript**: Transform classes without any decorators
37
- - 🔍 **Enhanced Validation**: Add class-validator decorators for richer schemas
38
-
39
- ### 📋 About OpenAPI
40
-
41
- **OpenAPI** (formerly Swagger) is the industry standard specification for describing REST APIs in a structured, machine-readable format. This library generates **OpenAPI 3.1.0** compatible schemas from your TypeScript classes.
19
+ ```typescript
20
+ import { transform } from 'ts-class-to-openapi'
42
21
 
43
- **Benefits:**
22
+ class User {
23
+ id: number
24
+ name: string
25
+ email: string
26
+ age?: number
27
+ }
44
28
 
45
- - Automatic documentation generation
46
- - Client SDK generation
47
- - API testing automation
48
- - Consistency across your API ecosystem
29
+ const schema = transform(User)
30
+ // Returns complete OpenAPI schema ready for Swagger/API documentation
31
+ ```
49
32
 
50
33
  ## 📦 Installation
51
34
 
@@ -60,67 +43,77 @@ yarn add ts-class-to-openapi
60
43
  pnpm add ts-class-to-openapi
61
44
  ```
62
45
 
63
- ### For class-validator Enhanced Features
46
+ ### Additional Dependencies for class-validator
64
47
 
65
- If you want to use class-validator decorators for enhanced validation schemas:
48
+ To use validation decorators and generate more detailed schemas:
66
49
 
67
50
  ```bash
68
- # Using npm
69
51
  npm install ts-class-to-openapi class-validator
70
-
71
- # Using yarn
72
- yarn add ts-class-to-openapi class-validator
73
-
74
- # Using pnpm
75
- pnpm add ts-class-to-openapi class-validator
76
52
  ```
77
53
 
78
- > **Note**: `class-validator` is only required if you want to use validation decorators. Pure TypeScript classes work without it.
54
+ > **Note**: The `class-validator` dependency is optional and only required when using validation decorators.
79
55
 
80
- ## 🔧 Module Compatibility
56
+ ## 🎨 Class Transformation Examples
81
57
 
82
- This library is **100% compatible with both CommonJS and ESM**, allowing you to use it in any modern Node.js project.
58
+ ### 1. Basic TypeScript Class
83
59
 
84
- ### ESM (ES Modules) - Recommended
60
+ Fundamental method: transform any TypeScript class without decorators:
85
61
 
86
62
  ```typescript
87
- // ESM import
88
63
  import { transform } from 'ts-class-to-openapi'
89
- import { IsString, IsEmail, IsNotEmpty, IsEnum } from 'class-validator'
90
-
91
- enum UserType {
92
- ADMIN = 'admin',
93
- USER = 'user',
94
- }
95
64
 
65
+ // Basic TypeScript class - no decorators required
96
66
  class User {
97
- @IsString()
98
- @IsNotEmpty()
67
+ id: number
99
68
  name: string
100
-
101
- @IsEmail()
102
69
  email: string
103
-
104
- @IsEnum(UserType)
105
- type: UserType
70
+ age: number
71
+ active: boolean
72
+ tags: string[]
73
+ createdAt: Date
106
74
  }
107
75
 
108
- const schema = transform(User)
109
- console.log(JSON.stringify(schema, null, 2))
76
+ // Transform class to OpenAPI schema
77
+ const result = transform(User)
78
+ console.log(JSON.stringify(result, null, 2))
79
+ ```
80
+
81
+ **Generated output:**
82
+
83
+ ```json
84
+ {
85
+ "name": "User",
86
+ "schema": {
87
+ "type": "object",
88
+ "properties": {
89
+ "id": { "type": "number" },
90
+ "name": { "type": "string" },
91
+ "email": { "type": "string" },
92
+ "age": { "type": "number" },
93
+ "active": { "type": "boolean" },
94
+ "tags": {
95
+ "type": "array",
96
+ "items": { "type": "string" }
97
+ },
98
+ "createdAt": {
99
+ "type": "string",
100
+ "format": "date-time"
101
+ }
102
+ },
103
+ "required": ["id", "name", "email", "age", "active", "tags", "createdAt"]
104
+ }
105
+ }
110
106
  ```
111
107
 
112
- ### TypeScript with CommonJS
108
+ ### 2. Class with Advanced Validations
109
+
110
+ For more detailed schemas, class-validator decorators can be incorporated:
113
111
 
114
112
  ```typescript
115
- // TypeScript with CommonJS configuration
116
113
  import { transform } from 'ts-class-to-openapi'
117
- import { IsString, IsEmail, IsNotEmpty, IsEnum } from 'class-validator'
118
-
119
- enum UserType {
120
- ADMIN = 'admin',
121
- USER = 'user',
122
- }
114
+ import { IsString, IsEmail, IsNotEmpty, IsInt, Min, Max } from 'class-validator'
123
115
 
116
+ // Class with validation decorators
124
117
  class User {
125
118
  @IsString()
126
119
  @IsNotEmpty()
@@ -129,79 +122,125 @@ class User {
129
122
  @IsEmail()
130
123
  email: string
131
124
 
132
- @IsEnum(UserType)
133
- type: UserType
125
+ @IsInt()
126
+ @Min(18)
127
+ @Max(100)
128
+ age: number
134
129
  }
135
130
 
136
- const schema = transform(User)
137
- console.log(JSON.stringify(schema, null, 2))
131
+ const result = transform(User)
138
132
  ```
139
133
 
140
- ## ⚙️ Requirements
134
+ **Generated output:**
141
135
 
142
- - Node.js >= 14.0.0
143
- - TypeScript with minimal compiler options in `tsconfig.json`:
144
- ```json
145
- {
146
- "compilerOptions": {
147
- "experimentalDecorators": true
148
- }
136
+ ```json
137
+ {
138
+ "name": "User",
139
+ "schema": {
140
+ "type": "object",
141
+ "properties": {
142
+ "name": { "type": "string" },
143
+ "email": {
144
+ "type": "string",
145
+ "format": "email"
146
+ },
147
+ "age": {
148
+ "type": "integer",
149
+ "format": "int32",
150
+ "minimum": 18,
151
+ "maximum": 100
152
+ }
153
+ },
154
+ "required": ["name", "email", "age"]
149
155
  }
150
- ```
151
-
152
- > **Note**: The `experimentalDecorators` option is only required if you plan to use class-validator decorators. Pure TypeScript classes work without any special configuration.
153
-
154
- ## 🎨 Two Transformation Modes
156
+ }
157
+ ```
155
158
 
156
- ### 1. Pure TypeScript Classes
159
+ ### 3. Nested Objects and Arrays
157
160
 
158
- Transform any TypeScript class without requiring any decorators or external dependencies:
161
+ Automatic processing of complex relationships:
159
162
 
160
163
  ```typescript
161
164
  import { transform } from 'ts-class-to-openapi'
162
165
 
163
- // Pure TypeScript - no decorators needed
164
- class Product {
166
+ class Address {
167
+ street: string
168
+ city: string
169
+ zipCode: string
170
+ }
171
+
172
+ class Role {
165
173
  id: number
166
174
  name: string
167
- price: number
168
- inStock: boolean
169
- categories: string[]
170
- metadata: Record<string, any>
171
- createdAt: Date
175
+ permissions: string[]
176
+ }
177
+
178
+ class User {
179
+ id: number
180
+ name: string
181
+ email: string
182
+ address: Address // Nested object
183
+ roles: Role[] // Array of objects
184
+ phone?: string // Optional property
172
185
  }
173
186
 
174
- const schema = transform(Product)
187
+ const schema = transform(User)
175
188
  ```
176
189
 
177
- **Benefits:**
190
+ **Generated output:**
178
191
 
179
- - ✅ No external dependencies required
180
- - ✅ Works with existing TypeScript codebases
181
- - ✅ Zero configuration needed
182
- - ✅ Automatic type inference
183
- - ✅ Perfect for legacy projects
192
+ ```json
193
+ {
194
+ "name": "User",
195
+ "schema": {
196
+ "type": "object",
197
+ "properties": {
198
+ "id": { "type": "number" },
199
+ "name": { "type": "string" },
200
+ "email": { "type": "string" },
201
+ "address": {
202
+ "type": "object",
203
+ "properties": {
204
+ "street": { "type": "string" },
205
+ "city": { "type": "string" },
206
+ "zipCode": { "type": "string" }
207
+ },
208
+ "required": ["street", "city", "zipCode"]
209
+ },
210
+ "roles": {
211
+ "type": "array",
212
+ "items": {
213
+ "type": "object",
214
+ "properties": {
215
+ "id": { "type": "number" },
216
+ "name": { "type": "string" },
217
+ "permissions": {
218
+ "type": "array",
219
+ "items": { "type": "string" }
220
+ }
221
+ },
222
+ "required": ["id", "name", "permissions"]
223
+ }
224
+ },
225
+ "phone": { "type": "string" }
226
+ },
227
+ "required": ["id", "name", "email", "address", "roles"]
228
+ }
229
+ }
230
+ ```
184
231
 
185
- ### 2. Enhanced with class-validator
232
+ ### 4. Enumerations and Special Types
186
233
 
187
- Add validation decorators for richer, more detailed schemas:
234
+ Full compatibility with TypeScript enumerations:
188
235
 
189
236
  ```typescript
190
237
  import { transform } from 'ts-class-to-openapi'
191
- import {
192
- IsString,
193
- IsNumber,
194
- IsPositive,
195
- IsArray,
196
- IsNotEmpty,
197
- IsEnum,
198
- } from 'class-validator'
238
+ import { IsEnum } from 'class-validator'
199
239
 
200
- // Define enums for better API contracts
201
- enum ProductStatus {
202
- DRAFT = 'draft',
203
- PUBLISHED = 'published',
204
- ARCHIVED = 'archived',
240
+ enum UserType {
241
+ ADMIN = 'admin',
242
+ USER = 'user',
243
+ MODERATOR = 'moderator',
205
244
  }
206
245
 
207
246
  enum Priority {
@@ -210,164 +249,105 @@ enum Priority {
210
249
  HIGH = 3,
211
250
  }
212
251
 
213
- // Enhanced with validation decorators
214
- class Product {
215
- @IsNumber()
216
- @IsPositive()
217
- id: number
218
-
219
- @IsString()
220
- @IsNotEmpty()
221
- name: string
222
-
223
- @IsNumber()
224
- @IsPositive()
225
- price: number
226
-
227
- @IsEnum(ProductStatus)
228
- @IsNotEmpty()
229
- status: ProductStatus
252
+ class Task {
253
+ @IsEnum(UserType)
254
+ assignedTo: UserType
230
255
 
231
256
  @IsEnum(Priority)
232
257
  priority?: Priority
233
258
 
234
- @IsArray()
235
- categories: string[]
236
- }
237
-
238
- const schema = transform(Product)
239
- ```
240
-
241
- **Benefits:**
242
-
243
- - ✅ Rich validation constraints
244
- - ✅ Required field specification
245
- - ✅ Format validation (email, date, etc.)
246
- - ✅ String length constraints
247
- - ✅ Number range validation
248
- - ✅ Array size validation
249
- - ✅ Enum value constraints with automatic type detection
250
-
251
- ## 🚀 Quick Start
252
-
253
- ### Pure TypeScript Classes
254
-
255
- Transform any TypeScript class without requiring decorators:
256
-
257
- ```typescript
258
- import { transform } from 'ts-class-to-openapi'
259
-
260
- // Pure TypeScript class - no decorators needed!
261
- class User {
262
- id: number
263
- name: string
264
- email: string
265
- age: number
266
- isActive: boolean
267
- tags: string[]
268
- createdAt: Date
259
+ title: string
260
+ completed: boolean
261
+ dueDate: Date
269
262
  }
270
263
 
271
- // Transform the class to OpenAPI schema
272
- const result = transform(User)
273
- console.log(JSON.stringify(result, null, 2))
264
+ const schema = transform(Task)
274
265
  ```
275
266
 
276
- **Generated Output:**
267
+ **Generated output:**
277
268
 
278
269
  ```json
279
270
  {
280
- "name": "User",
271
+ "name": "Task",
281
272
  "schema": {
282
273
  "type": "object",
283
274
  "properties": {
284
- "id": {
285
- "type": "number"
286
- },
287
- "name": {
288
- "type": "string"
289
- },
290
- "email": {
291
- "type": "string"
292
- },
293
- "age": {
294
- "type": "number"
295
- },
296
- "isActive": {
297
- "type": "boolean"
275
+ "assignedTo": {
276
+ "type": "string",
277
+ "enum": ["admin", "user", "moderator"]
298
278
  },
299
- "tags": {
300
- "type": "array",
301
- "items": {
302
- "type": "string"
303
- }
279
+ "priority": {
280
+ "type": "number",
281
+ "enum": [1, 2, 3]
304
282
  },
305
- "createdAt": {
283
+ "title": { "type": "string" },
284
+ "completed": { "type": "boolean" },
285
+ "dueDate": {
306
286
  "type": "string",
307
287
  "format": "date-time"
308
288
  }
309
289
  },
310
- "required": ["id", "name", "email", "age", "isActive", "tags", "createdAt"]
290
+ "required": ["assignedTo", "title", "completed", "dueDate"]
311
291
  }
312
292
  }
313
293
  ```
314
294
 
315
- ### Enhanced with class-validator Decorators
295
+ ### 5. File Upload
316
296
 
317
- For more detailed validation schemas, add class-validator decorators:
297
+ Integrated support for binary file handling:
318
298
 
319
299
  ```typescript
320
300
  import { transform } from 'ts-class-to-openapi'
321
- import { IsString, IsEmail, IsNotEmpty, IsInt, Min, Max } from 'class-validator'
301
+ import { IsNotEmpty, IsOptional } from 'class-validator'
322
302
 
323
- // Define your class with validation decorators
324
- class User {
325
- @IsString()
303
+ // Custom file type definition
304
+ class UploadFile {}
305
+
306
+ class UserProfile {
326
307
  @IsNotEmpty()
327
- name: string
308
+ profilePicture: UploadFile
328
309
 
329
- @IsEmail()
330
- email: string
310
+ @IsOptional()
311
+ resume: UploadFile
331
312
 
332
- @IsInt()
333
- @Min(18)
334
- @Max(100)
335
- age: number
313
+ documents: UploadFile[] // Multiple files
336
314
  }
337
315
 
338
- // Transform the class to OpenAPI schema
339
- const result = transform(User)
340
- console.log(JSON.stringify(result, null, 2))
316
+ const schema = transform(UserProfile)
341
317
  ```
342
318
 
343
- **Generated Output:**
319
+ **Generated output:**
344
320
 
345
321
  ```json
346
322
  {
347
- "name": "User",
323
+ "name": "UserProfile",
348
324
  "schema": {
349
325
  "type": "object",
350
326
  "properties": {
351
- "name": {
352
- "type": "string"
327
+ "profilePicture": {
328
+ "type": "string",
329
+ "format": "binary"
353
330
  },
354
- "email": {
331
+ "resume": {
355
332
  "type": "string",
356
- "format": "email"
333
+ "format": "binary"
357
334
  },
358
- "age": {
359
- "type": "integer",
360
- "format": "int32",
361
- "minimum": 18,
362
- "maximum": 100
335
+ "documents": {
336
+ "type": "array",
337
+ "items": {
338
+ "type": "string",
339
+ "format": "binary"
340
+ }
363
341
  }
364
342
  },
365
- "required": ["name", "email", "age"]
343
+ "required": ["profilePicture", "documents"]
366
344
  }
367
345
  }
368
346
  ```
369
347
 
370
- ### Express.js + Swagger UI Example
348
+ ## 🌐 REST API Integration
349
+
350
+ ### Implementation with Express.js and Swagger UI
371
351
 
372
352
  ```typescript
373
353
  import express from 'express'
@@ -375,7 +355,7 @@ import swaggerUi from 'swagger-ui-express'
375
355
  import { transform } from 'ts-class-to-openapi'
376
356
  import { IsString, IsEmail, IsNotEmpty, IsInt, Min, Max } from 'class-validator'
377
357
 
378
- // Define your DTOs with validation decorators
358
+ // DTO definition with validation decorators
379
359
  class User {
380
360
  @IsString()
381
361
  @IsNotEmpty()
@@ -401,14 +381,14 @@ class CreateUserDto {
401
381
 
402
382
  const app = express()
403
383
 
404
- // Generate schemas from your classes
384
+ // Schema generation from classes
405
385
  const userSchema = transform(User)
406
386
  const createUserSchema = transform(CreateUserDto)
407
387
 
408
- // Create OpenAPI specification
409
- const swaggerSpec = {
388
+ // OpenAPI specification configuration
389
+ const swaggerSpecification = {
410
390
  openapi: '3.1.0',
411
- info: { title: 'My API', version: '1.0.0' },
391
+ info: { title: 'Management API', version: '1.0.0' },
412
392
  components: {
413
393
  schemas: {
414
394
  [userSchema.name]: userSchema.schema,
@@ -417,17 +397,15 @@ const swaggerSpec = {
417
397
  },
418
398
  }
419
399
 
420
- // Setup Swagger UI at /api-docs
421
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
400
+ // Swagger UI configuration
401
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecification))
422
402
 
423
403
  app.listen(3000, () => {
424
- console.log('API docs available at http://localhost:3000/api-docs')
404
+ console.log('API documentation available at http://localhost:3000/api-docs')
425
405
  })
426
406
  ```
427
407
 
428
- #### Complete POST API Example with Schema Validation
429
-
430
- Here's a complete example of a POST endpoint that uses the generated schemas for both request validation and response structure:
408
+ ### Complete POST endpoint implementation with schema validation
431
409
 
432
410
  ```typescript
433
411
  import express from 'express'
@@ -443,7 +421,7 @@ import {
443
421
  IsOptional,
444
422
  } from 'class-validator'
445
423
 
446
- // Define your entities
424
+ // Domain entity definition
447
425
  class User {
448
426
  @IsInt()
449
427
  @Min(1)
@@ -466,7 +444,7 @@ class User {
466
444
  phone?: string
467
445
  }
468
446
 
469
- // DTO for creating a user
447
+ // DTO for user creation
470
448
  class CreateUserDto {
471
449
  @IsString()
472
450
  @IsNotEmpty()
@@ -485,29 +463,22 @@ class CreateUserDto {
485
463
  phone?: string
486
464
  }
487
465
 
488
- // Response wrapper (not transformed, defined manually in OpenAPI spec)
489
- interface ApiResponse<T> {
490
- data: T
491
- success: boolean
492
- }
493
-
494
466
  const app = express()
495
467
  app.use(express.json())
496
468
 
497
- // Generate schemas only for your entities
469
+ // Schema generation from classes
498
470
  const userSchema = transform(User)
499
471
  const createUserSchema = transform(CreateUserDto)
500
472
 
501
- // Create OpenAPI specification with POST endpoint
502
- const swaggerSpec = {
473
+ // Complete OpenAPI specification with POST endpoint
474
+ const swaggerSpecification = {
503
475
  openapi: '3.1.0',
504
476
  info: { title: 'User Management API', version: '1.0.0' },
505
477
  components: {
506
478
  schemas: {
507
479
  [userSchema.name]: userSchema.schema,
508
480
  [createUserSchema.name]: createUserSchema.schema,
509
- // ApiResponse schema defined manually
510
- UserApiResponse: {
481
+ UserResponse: {
511
482
  type: 'object',
512
483
  properties: {
513
484
  data: { $ref: `#/components/schemas/${userSchema.name}` },
@@ -525,7 +496,9 @@ const swaggerSpec = {
525
496
  required: true,
526
497
  content: {
527
498
  'application/json': {
528
- schema: { $ref: `#/components/schemas/${createUserSchema.name}` },
499
+ schema: {
500
+ $ref: `#/components/schemas/${createUserSchema.name}`,
501
+ },
529
502
  },
530
503
  },
531
504
  },
@@ -534,7 +507,7 @@ const swaggerSpec = {
534
507
  description: 'User created successfully',
535
508
  content: {
536
509
  'application/json': {
537
- schema: { $ref: '#/components/schemas/UserApiResponse' },
510
+ schema: { $ref: '#/components/schemas/UserResponse' },
538
511
  },
539
512
  },
540
513
  },
@@ -547,21 +520,19 @@ const swaggerSpec = {
547
520
  },
548
521
  }
549
522
 
550
- // Implement the POST endpoint
523
+ // POST endpoint implementation
551
524
  app.post('/users', (req, res) => {
552
525
  try {
553
- // In a real application, you would validate the request body
554
- // and save to database
555
526
  const userData = req.body as CreateUserDto
556
527
 
557
- // Mock user creation (replace with actual database logic)
528
+ // User creation simulation (replace with database logic)
558
529
  const newUser: User = {
559
530
  id: Math.floor(Math.random() * 1000) + 1,
560
531
  ...userData,
561
532
  }
562
533
 
563
- // Return response matching the schema
564
- const response: ApiResponse<User> = {
534
+ // Response that complies with the defined schema
535
+ const response = {
565
536
  data: newUser,
566
537
  success: true,
567
538
  }
@@ -576,400 +547,107 @@ app.post('/users', (req, res) => {
576
547
  }
577
548
  })
578
549
 
579
- // Setup Swagger UI
580
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
550
+ // Swagger UI configuration
551
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecification))
581
552
 
582
553
  app.listen(3000, () => {
583
- console.log('API docs available at http://localhost:3000/api-docs')
554
+ console.log('API documentation available at http://localhost:3000/api-docs')
584
555
  })
585
556
  ```
586
557
 
587
- This example demonstrates:
558
+ ## 📖 API Reference
588
559
 
589
- - **Request Schema**: Uses `CreateUserDto` schema for POST body validation
590
- - **Response Schema**: Returns data in `{ data: User, success: boolean }` format
591
- - **OpenAPI Documentation**: Complete Swagger specification with request/response schemas
592
- - **Type Safety**: Full TypeScript support for request and response types
560
+ ### `transform(class: Function)`
593
561
 
594
- ### File Upload Example
562
+ Transforms a class constructor function into an OpenAPI schema object.
595
563
 
596
- ```typescript
597
- import { transform } from 'ts-class-to-openapi'
598
- import { IsNotEmpty, IsOptional } from 'class-validator'
564
+ **Parameters:**
599
565
 
600
- // Define custom file type
601
- class UploadFile {}
566
+ - `class: Function` - The class constructor function to transform
602
567
 
603
- // Create your upload DTO
604
- class ProfileUpload {
605
- @IsNotEmpty()
606
- profilePicture: UploadFile
568
+ **Returns:**
607
569
 
608
- @IsOptional()
609
- resume: UploadFile
570
+ ```typescript
571
+ {
572
+ name: string; // Class name
573
+ schema: {
574
+ type: "object";
575
+ properties: Record<string, any>;
576
+ required: string[];
577
+ }
610
578
  }
611
-
612
- // Generate schema
613
- const schema = transform(ProfileUpload)
614
- console.log(JSON.stringify(schema, null, 2))
615
579
  ```
616
580
 
617
- **Generated Output:**
618
-
619
- ```json
620
- {
621
- "name": "ProfileUpload",
622
- "schema": {
623
- "type": "object",
624
- "properties": {
625
- "profilePicture": {
626
- "type": "string",
627
- "format": "binary"
628
- },
629
- "resume": {
630
- "type": "string",
631
- "format": "binary"
632
- }
633
- },
634
- "required": ["profilePicture"]
635
- }
636
- }
637
- ```
638
-
639
- ### Advanced Example with Nested Objects and Arrays
640
-
641
- #### Pure TypeScript Classes
581
+ **Example:**
642
582
 
643
583
  ```typescript
644
584
  import { transform } from 'ts-class-to-openapi'
585
+ import { User } from './entities/user.js'
645
586
 
646
- class Role {
647
- id: number
648
- name: string
649
- permissions: string[]
650
- }
651
-
652
- class Address {
653
- street: string
654
- city: string
655
- country: string
656
- zipCode: string
657
- }
658
-
659
- class User {
660
- id: number
661
- name: string
662
- email: string
663
- age: number
664
- isActive: boolean
665
- tags: string[]
666
- createdAt: Date
667
- role: Role // Nested object
668
- addresses: Address[] // Array of objects
669
- files: Buffer[] // Binary files
670
- }
671
-
672
- const schema = transform(User)
673
- ```
674
-
675
- #### Enhanced with class-validator
676
-
677
- ```typescript
678
- import {
679
- IsString,
680
- IsInt,
681
- IsEmail,
682
- IsDate,
683
- IsArray,
684
- IsNotEmpty,
685
- MinLength,
686
- MaxLength,
687
- Min,
688
- Max,
689
- ArrayNotEmpty,
690
- } from 'class-validator'
691
-
692
- class Role {
693
- @IsInt()
694
- @IsNotEmpty()
695
- id: number
696
-
697
- @IsString()
698
- @MinLength(1)
699
- @MaxLength(50)
700
- name: string
701
- }
702
-
703
- class User {
704
- @IsInt()
705
- @IsNotEmpty()
706
- @Min(1)
707
- id: number
708
-
709
- @IsString()
710
- @MinLength(2)
711
- @MaxLength(100)
712
- name: string
713
-
714
- @IsEmail()
715
- email: string
716
-
717
- @IsArray()
718
- @ArrayNotEmpty()
719
- tags: string[]
720
-
721
- @IsDate()
722
- createdAt: Date
723
-
724
- @IsNotEmpty()
725
- role: Role // Nested object
726
-
727
- files: Buffer[] // Binary files
728
-
729
- @IsNotEmpty()
730
- avatar: UploadFile // Custom file upload type
731
- }
732
-
733
- const schema = transform(User)
734
- ```
735
-
736
- **Generated Output:**
737
-
738
- ```json
739
- {
740
- "name": "User",
741
- "schema": {
742
- "type": "object",
743
- "properties": {
744
- "id": {
745
- "type": "integer",
746
- "format": "int32",
747
- "minimum": 1
748
- },
749
- "name": {
750
- "type": "string",
751
- "minLength": 2,
752
- "maxLength": 100
753
- },
754
- "email": {
755
- "type": "string",
756
- "format": "email"
757
- },
758
- "tags": {
759
- "type": "array",
760
- "items": {
761
- "type": "string"
762
- },
763
- "minItems": 1
764
- },
765
- "createdAt": {
766
- "type": "string",
767
- "format": "date-time"
768
- },
769
- "role": {
770
- "type": "object",
771
- "properties": {
772
- "id": {
773
- "type": "integer",
774
- "format": "int32"
775
- },
776
- "name": {
777
- "type": "string",
778
- "minLength": 1,
779
- "maxLength": 50
780
- }
781
- },
782
- "required": ["id"]
783
- },
784
- "files": {
785
- "type": "array",
786
- "items": {
787
- "type": "string",
788
- "format": "binary"
789
- }
790
- },
791
- "avatar": {
792
- "type": "string",
793
- "format": "binary"
794
- }
795
- },
796
- "required": ["id", "name", "email", "tags", "createdAt", "role", "files", "avatar"]
797
- }
798
- }
587
+ const result = transform(User)
588
+ console.log(result.name) // "User"
589
+ console.log(result.schema) // OpenAPI schema object
799
590
  ```
800
591
 
801
- > **Note**: Unlike other solutions, this package does **NOT** require `emitDecoratorMetadata: true` or `reflect-metadata`.
802
-
803
- ## 📊 Pure TypeScript vs Enhanced Mode Comparison
804
-
805
- | Feature | Pure TypeScript | Enhanced (class-validator) |
806
- | ---------------------- | ------------------------------------- | ------------------------------------ |
807
- | **Dependencies** | Zero | Requires `class-validator` |
808
- | **Configuration** | None | `experimentalDecorators: true` |
809
- | **Type Detection** | Automatic | Automatic + Decorators |
810
- | **Validation Rules** | Basic types only | Rich validation constraints |
811
- | **Required Fields** | Based on TypeScript optional operator (`?`) | TypeScript optional operator + decorators |
812
- | **String Constraints** | None | Min/max length, patterns |
813
- | **Number Constraints** | None | Min/max values, positive |
814
- | **Array Constraints** | None | Min/max items, non-empty |
815
- | **Email Validation** | None | Email format validation |
816
- | **Date Handling** | `date-time` format | `date-time` format |
817
- | **Use Case** | Existing codebases, rapid prototyping | APIs with validation, robust schemas |
592
+ ## 🎯 Required Properties Rules
818
593
 
819
- ### Example Comparison
594
+ ### TypeScript Optional Operator (`?`)
820
595
 
821
- **Pure TypeScript Class:**
596
+ The presence or absence of the TypeScript optional operator (`?`) determines whether a property is required:
822
597
 
823
598
  ```typescript
824
599
  class User {
825
- name: string // Required (no ? operator)
826
- email: string // Required (no ? operator)
827
- age: number // Required (no ? operator)
600
+ name: string // REQUIRED (no ? operator)
601
+ email: string // REQUIRED (no ? operator)
602
+ age?: number // OPTIONAL (has ? operator)
603
+ bio?: string // ❌ OPTIONAL (has ? operator)
828
604
  }
829
- // Generates: All properties required (no ? operator), basic types
830
- ```
831
-
832
- **Enhanced Class:**
833
605
 
834
- ```typescript
835
- class User {
836
- @IsString()
837
- @IsNotEmpty()
838
- name: string
839
-
840
- @IsEmail()
841
- email: string
842
-
843
- @IsInt()
844
- @Min(18)
845
- age: number
846
- }
847
- // Generates: All properties required, email format validation, age minimum 18
606
+ // Generated schema:
607
+ // "required": ["name", "email"]
848
608
  ```
849
609
 
850
- ## 🎨 Supported Decorators Reference
851
-
852
- ### Type Validation Decorators
853
-
854
- | Decorator | Generated Schema Property | Description |
855
- | --------------------- | ----------------------------------------------- | --------------------------- |
856
- | `@IsString()` | `type: "string"` | String type validation |
857
- | `@IsInt()` | `type: "integer", format: "int32"` | Integer type validation |
858
- | `@IsNumber()` | `type: "number", format: "double"` | Number type validation |
859
- | `@IsBoolean()` | `type: "boolean"` | Boolean type validation |
860
- | `@IsEmail()` | `type: "string", format: "email"` | Email format validation |
861
- | `@IsDate()` | `type: "string", format: "date-time"` | Date-time format validation |
862
- | `@IsEnum(enumObject)` | `type: "string/number/boolean", enum: [values]` | Enum constraint validation |
863
-
864
- ### Enum Validation with @IsEnum
610
+ ### Override via class-validator Decorators
865
611
 
866
- The `@IsEnum()` decorator provides powerful enum validation with automatic type detection and value extraction:
612
+ class-validator decorators can override the default behavior of the TypeScript optional operator:
867
613
 
868
614
  ```typescript
869
- import { transform } from 'ts-class-to-openapi'
870
- import { IsEnum, IsNotEmpty, IsArray } from 'class-validator'
871
-
872
- // String enum
873
- enum UserRole {
874
- ADMIN = 'admin',
875
- USER = 'user',
876
- MODERATOR = 'moderator',
877
- }
878
-
879
- // Numeric enum
880
- enum Priority {
881
- LOW = 1,
882
- MEDIUM = 2,
883
- HIGH = 3,
884
- }
885
-
886
- // Auto-incremented enum
887
- enum Size {
888
- SMALL, // 0
889
- MEDIUM, // 1
890
- LARGE, // 2
891
- }
892
-
893
- // Object enum with 'as const'
894
- const Status = {
895
- ACTIVE: 'active',
896
- INACTIVE: 'inactive',
897
- PENDING: 'pending',
898
- } as const
615
+ import { IsNotEmpty, IsOptional } from 'class-validator'
899
616
 
900
- class TaskEntity {
901
- @IsEnum(UserRole)
617
+ class User {
902
618
  @IsNotEmpty()
903
- assignedRole: UserRole // Required enum
904
-
905
- @IsEnum(Priority)
906
- priority?: Priority // Optional enum
907
-
908
- @IsEnum(Size)
909
- size?: Size // Auto-incremented enum
619
+ requiredField?: string // REQUIRED (@IsNotEmpty overrides ?)
910
620
 
911
- @IsEnum(Status)
912
- status?: keyof typeof Status // Object enum
621
+ @IsOptional()
622
+ optionalField: string // OPTIONAL (@IsOptional overrides absence of ?)
913
623
 
914
- @IsEnum(UserRole)
915
- @IsArray()
916
- allowedRoles?: UserRole[] // Array of enums
624
+ normalField: string // ✅ REQUIRED (no ? operator)
625
+ normalOptional?: string // ❌ OPTIONAL (has ? operator)
917
626
  }
918
627
 
919
- const result = transform(TaskEntity)
628
+ // Generated schema:
629
+ // "required": ["requiredField", "normalField"]
920
630
  ```
921
631
 
922
- **Generated Output:**
632
+ ## 🎨 Supported Decorators
923
633
 
924
- ```json
925
- {
926
- "name": "TaskEntity",
927
- "schema": {
928
- "type": "object",
929
- "properties": {
930
- "assignedRole": {
931
- "type": "string",
932
- "enum": ["admin", "user", "moderator"]
933
- },
934
- "priority": {
935
- "type": "number",
936
- "enum": [1, 2, 3]
937
- },
938
- "size": {
939
- "type": "number",
940
- "enum": [0, 1, 2]
941
- },
942
- "status": {
943
- "type": "string",
944
- "enum": ["active", "inactive", "pending"]
945
- },
946
- "allowedRoles": {
947
- "type": "array",
948
- "items": {
949
- "type": "string",
950
- "enum": ["admin", "user", "moderator"]
951
- }
952
- }
953
- },
954
- "required": ["assignedRole"]
955
- }
956
- }
957
- ```
958
-
959
- **Supported Enum Types:**
634
+ ### Type Validation Decorators
960
635
 
961
- - **String enums**: `enum Color { RED = 'red' }`
962
- - **Numeric enums**: `enum Status { ACTIVE = 1 }`
963
- - **Auto-incremented enums**: `enum Size { SMALL, MEDIUM }`
964
- - **Object enums**: `const Colors = { RED: 'red' } as const`
965
- - **Mixed enums**: `enum Mixed { NUM = 1, STR = 'text' }`
966
- - **Array of enums**: `roles: UserRole[]`
636
+ | Decorator | Generated Schema Property | Description |
637
+ | --------------------- | ----------------------------------------------- | -------------------------- |
638
+ | `@IsString()` | `type: "string"` | String type validation |
639
+ | `@IsInt()` | `type: "integer", format: "int32"` | Integer type validation |
640
+ | `@IsNumber()` | `type: "number", format: "double"` | Number type validation |
641
+ | `@IsBoolean()` | `type: "boolean"` | Boolean type validation |
642
+ | `@IsEmail()` | `type: "string", format: "email"` | Email format validation |
643
+ | `@IsDate()` | `type: "string", format: "date-time"` | Date format validation |
644
+ | `@IsEnum(enumObject)` | `type: "string/number/boolean", enum: [values]` | Enum constraint validation |
967
645
 
968
646
  ### String Validation Decorators
969
647
 
970
648
  | Decorator | Generated Schema Property | Description |
971
649
  | ------------------- | -------------------------------- | --------------------- |
972
- | `@IsNotEmpty()` | Adds to `required` array | Field is required |
650
+ | `@IsNotEmpty()` | Added to `required` array | Field is required |
973
651
  | `@MinLength(n)` | `minLength: n` | Minimum string length |
974
652
  | `@MaxLength(n)` | `maxLength: n` | Maximum string length |
975
653
  | `@Length(min, max)` | `minLength: min, maxLength: max` | String length range |
@@ -991,259 +669,146 @@ const result = transform(TaskEntity)
991
669
  | `@ArrayMinSize(n)` | `minItems: n` | Minimum array size |
992
670
  | `@ArrayMaxSize(n)` | `maxItems: n` | Maximum array size |
993
671
 
994
- ### Special Type Mappings
995
-
996
- | TypeScript Type | Generated OpenAPI Schema | Description |
997
- | --------------- | ------------------------------------- | ------------------------------ |
998
- | `Date` | `type: "string", format: "date-time"` | ISO date-time string |
999
- | `Buffer` | `type: "string", format: "binary"` | Binary data |
1000
- | `Uint8Array` | `type: "string", format: "binary"` | Binary array |
1001
- | `UploadFile` | `type: "string", format: "binary"` | Custom file upload type |
1002
- | `CustomClass` | Nested object schema | Recursive class transformation |
1003
- | `Type[]` | Array with typed items | Array of specific type |
672
+ ## 📊 Comparison: Pure TypeScript vs Enhanced Mode
1004
673
 
1005
- ### Automatic TypeScript Type Detection
1006
-
1007
- The library automatically detects and converts TypeScript types:
1008
-
1009
- ```typescript
1010
- class AutoDetectionExample {
1011
- // Primitives
1012
- id: number // type: "number"
1013
- name: string // type: "string"
1014
- isActive: boolean // type: "boolean"
1015
-
1016
- // Special types
1017
- createdAt: Date // → type: "string", format: "date-time"
1018
- file: Buffer // → type: "string", format: "binary"
1019
-
1020
- // Arrays
1021
- tags: string[] // → type: "array", items: { type: "string" }
1022
- scores: number[] // → type: "array", items: { type: "number" }
1023
-
1024
- // Objects
1025
- metadata: object // → type: "object"
1026
- data: any // → No schema constraints
1027
-
1028
- // Nested classes (automatically transformed)
1029
- profile: UserProfile // → Nested object schema
1030
- }
1031
- ```
1032
-
1033
- ## 📁 File Upload Support
1034
-
1035
- The library provides built-in support for file uploads with automatic binary format mapping:
1036
-
1037
- ```typescript
1038
- import { transform } from 'ts-class-to-openapi'
1039
- import { IsNotEmpty, IsArray, IsOptional } from 'class-validator'
1040
-
1041
- // Define your custom file type
1042
- class UploadFile {}
1043
-
1044
- class DocumentUpload {
1045
- @IsNotEmpty()
1046
- document: UploadFile // Single file upload (required)
1047
-
1048
- @IsArray()
1049
- attachments: UploadFile[] // Multiple file uploads
1050
-
1051
- @IsOptional()
1052
- avatar: UploadFile // Optional file upload
1053
- }
674
+ | Feature | Pure TypeScript | Enhanced (class-validator) |
675
+ | ---------------------- | ------------------------------------- | ------------------------------------ |
676
+ | **Dependencies** | Zero | Requires `class-validator` |
677
+ | **Configuration** | None | `experimentalDecorators: true` |
678
+ | **Type Detection** | Automatic | Automatic + Decorators |
679
+ | **Validation Rules** | Basic types only | Rich validation constraints |
680
+ | **Required Fields** | Based on optional operator (`?`) | Optional operator + decorators |
681
+ | **String Constraints** | None | Min/max length, patterns |
682
+ | **Number Constraints** | None | Min/max values, positive |
683
+ | **Array Constraints** | None | Min/max items, non-empty |
684
+ | **Use Case** | Existing codebases, rapid prototyping | APIs with validation, robust schemas |
1054
685
 
1055
- // Transform to OpenAPI schema
1056
- const schema = transform(DocumentUpload)
1057
- console.log(JSON.stringify(schema, null, 2))
1058
- ```
686
+ ## ⚙️ Configuration
1059
687
 
1060
- **Generated Schema:**
688
+ ### Requirements
1061
689
 
1062
- ```json
1063
- {
1064
- "name": "DocumentUpload",
1065
- "schema": {
1066
- "type": "object",
1067
- "properties": {
1068
- "document": {
1069
- "type": "string",
1070
- "format": "binary"
1071
- },
1072
- "attachments": {
1073
- "type": "array",
1074
- "items": {
1075
- "type": "string",
1076
- "format": "binary"
1077
- }
1078
- },
1079
- "avatar": {
1080
- "type": "string",
1081
- "format": "binary"
1082
- }
1083
- },
1084
- "required": ["document", "attachments"]
690
+ - Node.js >= 14.0.0
691
+ - TypeScript with minimal compiler options in `tsconfig.json`:
692
+ ```json
693
+ {
694
+ "compilerOptions": {
695
+ "experimentalDecorators": true
696
+ }
1085
697
  }
1086
- }
1087
- ```
1088
-
1089
- ### Supported File Types
1090
-
1091
- The following types are automatically converted to binary format:
1092
-
1093
- - `Buffer` - Node.js Buffer objects
1094
- - `Uint8Array` - Typed arrays
1095
- - `UploadFile` - Custom file upload classes
1096
- - Any class ending with "File" suffix (e.g., `ImageFile`, `VideoFile`)
1097
-
1098
- ## 📖 API Reference
1099
-
1100
- ### `transform(cls: Function)`
698
+ ```
1101
699
 
1102
- Transforms a class constructor function into an OpenAPI schema object.
700
+ > **Note**: The `experimentalDecorators` option is only required if you plan to use class-validator decorators. Pure TypeScript classes work without special configuration.
1103
701
 
1104
- **Parameters:**
702
+ ### TypeScript Support
1105
703
 
1106
- - `cls: Function` - The class constructor function to transform
704
+ This library works with:
1107
705
 
1108
- **Returns:**
706
+ - ✅ Pure TypeScript classes (no decorators needed)
707
+ - ✅ class-validator decorated classes
708
+ - ✅ Mixed usage (some classes with decorators, some without)
709
+ - ✅ All TypeScript types: primitives, arrays, enums, nested objects
1109
710
 
1110
- ```typescript
1111
- {
1112
- name: string; // Class name
1113
- schema: {
1114
- type: "object";
1115
- properties: Record<string, any>;
1116
- required: string[];
1117
- }
1118
- }
1119
- ```
711
+ ### Module Compatibility
1120
712
 
1121
- **Example:**
713
+ This library is **fully compatible with CommonJS and ESM**:
1122
714
 
1123
715
  ```typescript
716
+ // ESM (recommended)
1124
717
  import { transform } from 'ts-class-to-openapi'
1125
- import { User } from './entities/user.js'
1126
718
 
1127
- const result = transform(User)
1128
- console.log(result.name) // "User"
1129
- console.log(result.schema) // OpenAPI schema object
719
+ // CommonJS
720
+ const { transform } = require('ts-class-to-openapi')
1130
721
  ```
1131
722
 
1132
- ## 🔍 Required Properties Rules
723
+ ## 🔧 Troubleshooting
1133
724
 
1134
- Understanding how properties are marked as required is crucial for generating accurate schemas:
725
+ ### Common Issues
1135
726
 
1136
- ### TypeScript Optional Operator (`?`)
727
+ **Error: "Cannot find module 'ts-class-to-openapi'"**
1137
728
 
1138
- The presence or absence of the TypeScript optional operator (`?`) determines if a property is required:
729
+ ```bash
730
+ npm install ts-class-to-openapi
731
+ ```
1139
732
 
1140
- ```typescript
1141
- class User {
1142
- name: string // ✅ REQUIRED (no ? operator)
1143
- email: string // ✅ REQUIRED (no ? operator)
1144
- age?: number // ❌ OPTIONAL (has ? operator)
1145
- bio?: string // ❌ OPTIONAL (has ? operator)
1146
- }
733
+ **Error: "Cannot find module 'class-validator'"**
1147
734
 
1148
- // Generated schema:
1149
- // "required": ["name", "email"]
735
+ This dependency is only necessary for using validation decorators:
736
+
737
+ ```bash
738
+ npm install class-validator
1150
739
  ```
1151
740
 
1152
- ### class-validator Decorators Override
741
+ **Error: "Experimental decorators warning"**
1153
742
 
1154
- When using class-validator decorators, they can override the TypeScript optional behavior:
743
+ Add the following configuration to the `tsconfig.json` file:
1155
744
 
1156
- ```typescript
1157
- import { IsNotEmpty, IsOptional } from 'class-validator'
1158
-
1159
- class User {
1160
- @IsNotEmpty()
1161
- requiredField?: string // ✅ REQUIRED (@IsNotEmpty overrides ?)
1162
-
1163
- @IsOptional()
1164
- optionalField: string // ❌ OPTIONAL (@IsOptional overrides no ?)
1165
-
1166
- normalField: string // ✅ REQUIRED (no ? operator)
1167
- normalOptional?: string // ❌ OPTIONAL (has ? operator)
745
+ ```json
746
+ {
747
+ "compilerOptions": {
748
+ "experimentalDecorators": true
749
+ }
1168
750
  }
1169
-
1170
- // Generated schema:
1171
- // "required": ["requiredField", "normalField"]
1172
751
  ```
1173
752
 
1174
- ### Array Properties
1175
-
1176
- Array properties follow the same rules, with additional decorators:
1177
-
1178
- ```typescript
1179
- import { ArrayNotEmpty } from 'class-validator'
753
+ **Empty schema generated**
1180
754
 
1181
- class User {
1182
- tags: string[] // REQUIRED (no ? operator)
1183
-
1184
- @ArrayNotEmpty()
1185
- categories?: string[] // ✅ REQUIRED (@ArrayNotEmpty overrides ?)
1186
-
1187
- optionalTags?: string[] // ❌ OPTIONAL (has ? operator)
1188
- }
755
+ - For pure TypeScript classes: Verify that the class contains properties with correctly defined types
756
+ - For classes with decorators: Confirm that the class includes class-validator decorators
757
+ - Verify that the class is correctly exported and imported
758
+ - Confirm that TypeScript compilation runs without errors
1189
759
 
1190
- // Generated schema:
1191
- // "required": ["tags", "categories"]
1192
- ```
760
+ **Works without decorators but wants validation?**
1193
761
 
1194
- ### Summary of Rules
762
+ Pure TypeScript classes work immediately, but if you want enhanced validation schemas:
1195
763
 
1196
- 1. **No `?` operator** Property is **REQUIRED**
1197
- 2. **Has `?` operator** Property is **OPTIONAL**
1198
- 3. **`@IsNotEmpty()` or `@ArrayNotEmpty()`** Forces **REQUIRED** (overrides `?`)
1199
- 4. **`@IsOptional()`** → Forces **OPTIONAL** (overrides no `?`)
764
+ 1. Install class-validator: `npm install class-validator`
765
+ 2. Add decorators to the corresponding properties
766
+ 3. Enable `experimentalDecorators: true` in the tsconfig.json file
1200
767
 
1201
768
  ## 🌟 Advanced Features
1202
769
 
1203
- - ✅ **Pure TypeScript Support** - Works with any TypeScript class, no decorators required
1204
- - ✅ **Zero Runtime Dependencies** - Uses TypeScript Compiler API instead of reflect-metadata
1205
- - ✅ **High Performance** - Singleton pattern with built-in caching for repeated transformations
1206
- - ✅ **Nested Object Support** - Automatically handles complex object relationships
1207
- - ✅ **Array Type Support** - Full support for typed arrays with validation constraints
1208
- - ✅ **Built-in Caching** - Avoids reprocessing the same classes multiple times
1209
- - ✅ **Type Safety** - Complete TypeScript support with proper type definitions
1210
- - ✅ **Framework Agnostic** - Works with any TypeScript project configuration
1211
- - ✅ **Comprehensive Coverage** - Supports all major class-validator decorators
1212
- - ✅ **Flexible Usage** - Use with or without validation decorators
770
+ - ✅ **Native pure TypeScript support** - Compatible with any TypeScript class without requiring decorators
771
+ - ✅ **Zero runtime dependencies** - Uses TypeScript Compiler API instead of reflect-metadata
772
+ - ✅ **Optimized performance** - Singleton pattern implementation with caching system for repeated transformations
773
+ - ✅ **Nested object processing** - Automatic handling of complex relationships between objects
774
+ - ✅ **Full typed array support** - Comprehensive compatibility with arrays and validation constraints
775
+ - ✅ **Integrated caching system** - Avoids reprocessing the same classes
776
+ - ✅ **Type safety** - Complete TypeScript support with precise type definitions
777
+ - ✅ **Framework agnostic** - Compatible with any TypeScript project configuration
1213
778
 
1214
779
  ## 🔄 Migration Guide
1215
780
 
1216
- ### From reflect-metadata Solutions
781
+ ### Migration from reflect-metadata Based Solutions
1217
782
 
1218
- If you're migrating from a solution that requires `reflect-metadata`:
783
+ For projects using solutions that require `reflect-metadata`:
1219
784
 
1220
- **Before (with reflect-metadata):**
785
+ **Previous implementation (with reflect-metadata):**
1221
786
 
1222
787
  ```typescript
1223
788
  import 'reflect-metadata'
1224
789
  import { getMetadataStorage } from 'class-validator'
1225
790
 
1226
- // Complex setup required
791
+ // Complex configuration required
1227
792
  const schema = transformClassToSchema(User)
1228
793
  ```
1229
794
 
1230
- **After (with ts-class-to-openapi):**
795
+ **New implementation (with ts-class-to-openapi):**
1231
796
 
1232
797
  ```typescript
1233
798
  import { transform } from 'ts-class-to-openapi'
1234
799
 
1235
- // Simple, clean API
800
+ // Simplified API
1236
801
  const schema = transform(User)
1237
802
  ```
1238
803
 
1239
- ### New: Pure TypeScript Support
804
+ ### New Functionality: Pure TypeScript Support
1240
805
 
1241
- The biggest advantage is that you can now transform **any TypeScript class** without requiring decorators:
806
+ The main advantage lies in the ability to transform **any TypeScript class** without requiring decorators:
1242
807
 
1243
- **Before (required decorators):**
808
+ **Previous limitation (mandatory decorators):**
1244
809
 
1245
810
  ```typescript
1246
- // This would NOT work with traditional solutions
811
+ // This approach would NOT work with traditional solutions
1247
812
  class LegacyUser {
1248
813
  id: number
1249
814
  name: string
@@ -1251,92 +816,21 @@ class LegacyUser {
1251
816
  }
1252
817
  ```
1253
818
 
1254
- **Now (works immediately):**
819
+ **Current implementation (immediate functionality):**
1255
820
 
1256
821
  ```typescript
1257
822
  import { transform } from 'ts-class-to-openapi'
1258
823
 
1259
- // This works out of the box!
824
+ // Ready-to-use functionality
1260
825
  class LegacyUser {
1261
826
  id: number
1262
827
  name: string
1263
828
  email: string
1264
829
  }
1265
830
 
1266
- const schema = transform(LegacyUser) // ✅ Works perfectly
831
+ const schema = transform(LegacyUser) // ✅ Successful operation
1267
832
  ```
1268
833
 
1269
- ### Migration Steps
1270
-
1271
- 1. **Remove reflect-metadata imports** from your entities
1272
- 2. **Remove `emitDecoratorMetadata: true`** from tsconfig.json (optional)
1273
- 3. **Update transformation code** to use the new API
1274
- 4. **Remove reflect-metadata dependency** from package.json
1275
- 5. **Optional**: Keep decorators for enhanced validation or remove them entirely
1276
-
1277
- ### TypeScript Configuration
1278
-
1279
- You only need minimal TypeScript configuration:
1280
-
1281
- ```json
1282
- {
1283
- "compilerOptions": {
1284
- "experimentalDecorators": true
1285
- // emitDecoratorMetadata: true ← NOT REQUIRED!
1286
- }
1287
- }
1288
- ```
1289
-
1290
- ## 🔧 Troubleshooting
1291
-
1292
- ### Common Issues
1293
-
1294
- **Error: "Cannot find module 'ts-class-to-openapi'"**
1295
-
1296
- ```bash
1297
- npm install ts-class-to-openapi
1298
- ```
1299
-
1300
- **Error: "Cannot find module 'class-validator'"**
1301
-
1302
- This is only needed if you want to use validation decorators:
1303
-
1304
- ```bash
1305
- npm install class-validator
1306
- ```
1307
-
1308
- **Error: "Experimental decorators warning"**
1309
- Add to your `tsconfig.json`:
1310
-
1311
- ```json
1312
- {
1313
- "compilerOptions": {
1314
- "experimentalDecorators": true
1315
- }
1316
- }
1317
- ```
1318
-
1319
- **Empty schema generated**
1320
-
1321
- - For pure TypeScript classes: Ensure your class has properly typed properties
1322
- - For class-validator enhanced: Ensure your class has class-validator decorators
1323
- - Check that the class is properly exported/imported
1324
- - Verify TypeScript compilation is working
1325
-
1326
- **Works without decorators but want validation?**
1327
-
1328
- Pure TypeScript classes work immediately, but if you want enhanced validation schemas:
1329
-
1330
- 1. Install class-validator: `npm install class-validator`
1331
- 2. Add decorators to your properties
1332
- 3. Enable `experimentalDecorators: true` in tsconfig.json
1333
-
1334
- **Nested objects not working**
1335
-
1336
- - Make sure nested classes are in the same project
1337
- - Ensure nested classes have their own decorators
1338
- - Check file paths and imports
1339
-
1340
834
  ## 📄 License
1341
835
 
1342
836
  MIT