ts-class-to-openapi 1.0.0

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 ADDED
@@ -0,0 +1,959 @@
1
+ # ๐Ÿ”„ ts-class-to-openapi
2
+
3
+ โœจ **Transform TypeScript classes into OpenAPI 3.1.0 schema objects**
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.
6
+
7
+ > **๐ŸŽฏ New Feature**: Now supports **pure TypeScript classes** without requiring any decorators or external dependencies! Perfect for transforming existing codebases instantly.
8
+
9
+ ## ๐Ÿš€ Key Features
10
+
11
+ - โœ… **Pure TypeScript Support** - Transform any TypeScript class without decorators
12
+ - โœ… **class-validator Compatible** - Enhanced schemas with validation decorators
13
+ - โœ… **CommonJS & ESM Compatible** - Works in any Node.js project
14
+ - โœ… **Zero Runtime Dependencies** - No `reflect-metadata` or `emitDecoratorMetadata` required
15
+ - โœ… **OpenAPI 3.1.0** - Industry-standard schema generation
16
+ - โœ… **TypeScript Native** - Full type support and safety
17
+ - โœ… **High Performance** - Singleton pattern with built-in caching
18
+ - โœ… **Nested Objects** - Handles complex relationships automatically
19
+ - โœ… **Typed Arrays** - Full support for arrays with validation
20
+ - โœ… **File Uploads** - Binary file upload support
21
+
22
+ ## ๐ŸŽฏ Why Use This Library?
23
+
24
+ Perfect for projects where you need to:
25
+
26
+ - ๐ŸŒ **REST APIs**: Generate Swagger documentation from your existing TypeScript classes
27
+ - ๐Ÿ“š **Auto Documentation**: Maintain consistency between TypeScript types and API contracts
28
+ - ๐Ÿงช **API Testing**: Create mock data structures for testing
29
+ - ๐Ÿ”ง **Microservices**: Ensure schema consistency across services
30
+ - โšก **Legacy Projects**: Works without enabling `emitDecoratorMetadata`
31
+ - ๐ŸŽฏ **Pure TypeScript**: Transform classes without any decorators
32
+ - ๐Ÿ” **Enhanced Validation**: Add class-validator decorators for richer schemas
33
+
34
+ ### ๐Ÿ“‹ About OpenAPI
35
+
36
+ **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.
37
+
38
+ **Benefits:**
39
+
40
+ - Automatic documentation generation
41
+ - Client SDK generation
42
+ - API testing automation
43
+ - Consistency across your API ecosystem
44
+
45
+ ## ๐Ÿ“ฆ Installation
46
+
47
+ ```bash
48
+ # Using npm
49
+ npm install ts-class-to-openapi
50
+
51
+ # Using yarn
52
+ yarn add ts-class-to-openapi
53
+
54
+ # Using pnpm
55
+ pnpm add ts-class-to-openapi
56
+ ```
57
+
58
+ ### For class-validator Enhanced Features
59
+
60
+ If you want to use class-validator decorators for enhanced validation schemas:
61
+
62
+ ```bash
63
+ # Using npm
64
+ npm install ts-class-to-openapi class-validator
65
+
66
+ # Using yarn
67
+ yarn add ts-class-to-openapi class-validator
68
+
69
+ # Using pnpm
70
+ pnpm add ts-class-to-openapi class-validator
71
+ ```
72
+
73
+ > **Note**: `class-validator` is only required if you want to use validation decorators. Pure TypeScript classes work without it.
74
+
75
+ ## ๐Ÿ”ง Module Compatibility
76
+
77
+ This library is **100% compatible with both CommonJS and ESM**, allowing you to use it in any modern Node.js project.
78
+
79
+ ### ESM (ES Modules) - Recommended
80
+
81
+ ```typescript
82
+ // ESM import
83
+ import { transform } from 'ts-class-to-openapi'
84
+ import { IsString, IsEmail, IsNotEmpty } from 'class-validator'
85
+
86
+ class User {
87
+ @IsString()
88
+ @IsNotEmpty()
89
+ name: string
90
+
91
+ @IsEmail()
92
+ email: string
93
+ }
94
+
95
+ const schema = transform(User)
96
+ console.log(JSON.stringify(schema, null, 2))
97
+ ```
98
+
99
+ ### TypeScript with CommonJS
100
+
101
+ ```typescript
102
+ // TypeScript with CommonJS configuration
103
+ import { transform } from 'ts-class-to-openapi'
104
+ import { IsString, IsEmail, IsNotEmpty } from 'class-validator'
105
+
106
+ class User {
107
+ @IsString()
108
+ @IsNotEmpty()
109
+ name: string
110
+
111
+ @IsEmail()
112
+ email: string
113
+ }
114
+
115
+ const schema = transform(User)
116
+ console.log(JSON.stringify(schema, null, 2))
117
+ ```
118
+
119
+ ## โš™๏ธ Requirements
120
+
121
+ - Node.js >= 14.0.0
122
+ - TypeScript with minimal compiler options in `tsconfig.json`:
123
+ ```json
124
+ {
125
+ "compilerOptions": {
126
+ "experimentalDecorators": true
127
+ }
128
+ }
129
+ ```
130
+
131
+ > **Note**: The `experimentalDecorators` option is only required if you plan to use class-validator decorators. Pure TypeScript classes work without any special configuration.
132
+
133
+ ## ๐ŸŽจ Two Transformation Modes
134
+
135
+ ### 1. Pure TypeScript Classes
136
+
137
+ Transform any TypeScript class without requiring any decorators or external dependencies:
138
+
139
+ ```typescript
140
+ import { transform } from 'ts-class-to-openapi'
141
+
142
+ // Pure TypeScript - no decorators needed
143
+ class Product {
144
+ id: number
145
+ name: string
146
+ price: number
147
+ inStock: boolean
148
+ categories: string[]
149
+ metadata: Record<string, any>
150
+ createdAt: Date
151
+ }
152
+
153
+ const schema = transform(Product)
154
+ ```
155
+
156
+ **Benefits:**
157
+
158
+ - โœ… No external dependencies required
159
+ - โœ… Works with existing TypeScript codebases
160
+ - โœ… Zero configuration needed
161
+ - โœ… Automatic type inference
162
+ - โœ… Perfect for legacy projects
163
+
164
+ ### 2. Enhanced with class-validator
165
+
166
+ Add validation decorators for richer, more detailed schemas:
167
+
168
+ ```typescript
169
+ import { transform } from 'ts-class-to-openapi'
170
+ import {
171
+ IsString,
172
+ IsNumber,
173
+ IsPositive,
174
+ IsArray,
175
+ IsNotEmpty,
176
+ } from 'class-validator'
177
+
178
+ // Enhanced with validation decorators
179
+ class Product {
180
+ @IsNumber()
181
+ @IsPositive()
182
+ id: number
183
+
184
+ @IsString()
185
+ @IsNotEmpty()
186
+ name: string
187
+
188
+ @IsNumber()
189
+ @IsPositive()
190
+ price: number
191
+
192
+ @IsArray()
193
+ categories: string[]
194
+ }
195
+
196
+ const schema = transform(Product)
197
+ ```
198
+
199
+ **Benefits:**
200
+
201
+ - โœ… Rich validation constraints
202
+ - โœ… Required field specification
203
+ - โœ… Format validation (email, date, etc.)
204
+ - โœ… String length constraints
205
+ - โœ… Number range validation
206
+ - โœ… Array size validation
207
+
208
+ ## ๐Ÿš€ Quick Start
209
+
210
+ ### Pure TypeScript Classes
211
+
212
+ Transform any TypeScript class without requiring decorators:
213
+
214
+ ```typescript
215
+ import { transform } from 'ts-class-to-openapi'
216
+
217
+ // Pure TypeScript class - no decorators needed!
218
+ class User {
219
+ id: number
220
+ name: string
221
+ email: string
222
+ age: number
223
+ isActive: boolean
224
+ tags: string[]
225
+ createdAt: Date
226
+ }
227
+
228
+ // Transform the class to OpenAPI schema
229
+ const result = transform(User)
230
+ console.log(JSON.stringify(result, null, 2))
231
+ ```
232
+
233
+ **Generated Output:**
234
+
235
+ ```json
236
+ {
237
+ "name": "User",
238
+ "schema": {
239
+ "type": "object",
240
+ "properties": {
241
+ "id": {
242
+ "type": "number"
243
+ },
244
+ "name": {
245
+ "type": "string"
246
+ },
247
+ "email": {
248
+ "type": "string"
249
+ },
250
+ "age": {
251
+ "type": "number"
252
+ },
253
+ "isActive": {
254
+ "type": "boolean"
255
+ },
256
+ "tags": {
257
+ "type": "array",
258
+ "items": {
259
+ "type": "string"
260
+ }
261
+ },
262
+ "createdAt": {
263
+ "type": "string",
264
+ "format": "date-time"
265
+ }
266
+ },
267
+ "required": []
268
+ }
269
+ }
270
+ ```
271
+
272
+ ### Enhanced with class-validator Decorators
273
+
274
+ For more detailed validation schemas, add class-validator decorators:
275
+
276
+ ```typescript
277
+ import { transform } from 'ts-class-to-openapi'
278
+ import { IsString, IsEmail, IsNotEmpty, IsInt, Min, Max } from 'class-validator'
279
+
280
+ // Define your class with validation decorators
281
+ class User {
282
+ @IsString()
283
+ @IsNotEmpty()
284
+ name: string
285
+
286
+ @IsEmail()
287
+ email: string
288
+
289
+ @IsInt()
290
+ @Min(18)
291
+ @Max(100)
292
+ age: number
293
+ }
294
+
295
+ // Transform the class to OpenAPI schema
296
+ const result = transform(User)
297
+ console.log(JSON.stringify(result, null, 2))
298
+ ```
299
+
300
+ **Generated Output:**
301
+
302
+ ```json
303
+ {
304
+ "name": "User",
305
+ "schema": {
306
+ "type": "object",
307
+ "properties": {
308
+ "name": {
309
+ "type": "string"
310
+ },
311
+ "email": {
312
+ "type": "string",
313
+ "format": "email"
314
+ },
315
+ "age": {
316
+ "type": "integer",
317
+ "format": "int32",
318
+ "minimum": 18,
319
+ "maximum": 100
320
+ }
321
+ },
322
+ "required": ["name"]
323
+ }
324
+ }
325
+ ```
326
+
327
+ ### Express.js + Swagger UI Example
328
+
329
+ ```typescript
330
+ import express from 'express'
331
+ import swaggerUi from 'swagger-ui-express'
332
+ import { transform } from 'ts-class-to-openapi'
333
+ import { IsString, IsEmail, IsNotEmpty, IsInt, Min, Max } from 'class-validator'
334
+
335
+ // Define your DTOs with validation decorators
336
+ class User {
337
+ @IsString()
338
+ @IsNotEmpty()
339
+ name: string
340
+
341
+ @IsEmail()
342
+ email: string
343
+
344
+ @IsInt()
345
+ @Min(18)
346
+ @Max(100)
347
+ age: number
348
+ }
349
+
350
+ class CreateUserDto {
351
+ @IsString()
352
+ @IsNotEmpty()
353
+ name: string
354
+
355
+ @IsEmail()
356
+ email: string
357
+ }
358
+
359
+ const app = express()
360
+
361
+ // Generate schemas from your classes
362
+ const userSchema = transform(User)
363
+ const createUserSchema = transform(CreateUserDto)
364
+
365
+ // Create OpenAPI specification
366
+ const swaggerSpec = {
367
+ openapi: '3.1.0',
368
+ info: { title: 'My API', version: '1.0.0' },
369
+ components: {
370
+ schemas: {
371
+ [userSchema.name]: userSchema.schema,
372
+ [createUserSchema.name]: createUserSchema.schema,
373
+ },
374
+ },
375
+ }
376
+
377
+ // Setup Swagger UI at /api-docs
378
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
379
+
380
+ app.listen(3000, () => {
381
+ console.log('API docs available at http://localhost:3000/api-docs')
382
+ })
383
+ ```
384
+
385
+ ### File Upload Example
386
+
387
+ ```typescript
388
+ import { transform } from 'ts-class-to-openapi'
389
+ import { IsNotEmpty, IsOptional } from 'class-validator'
390
+
391
+ // Define custom file type
392
+ class UploadFile {}
393
+
394
+ // Create your upload DTO
395
+ class ProfileUpload {
396
+ @IsNotEmpty()
397
+ profilePicture: UploadFile
398
+
399
+ @IsOptional()
400
+ resume: UploadFile
401
+ }
402
+
403
+ // Generate schema
404
+ const schema = transform(ProfileUpload)
405
+ console.log(JSON.stringify(schema, null, 2))
406
+ ```
407
+
408
+ **Generated Output:**
409
+
410
+ ```json
411
+ {
412
+ "name": "ProfileUpload",
413
+ "schema": {
414
+ "type": "object",
415
+ "properties": {
416
+ "profilePicture": {
417
+ "type": "string",
418
+ "format": "binary"
419
+ },
420
+ "resume": {
421
+ "type": "string",
422
+ "format": "binary"
423
+ }
424
+ },
425
+ "required": ["profilePicture"]
426
+ }
427
+ }
428
+ ```
429
+
430
+ ### Advanced Example with Nested Objects and Arrays
431
+
432
+ #### Pure TypeScript Classes
433
+
434
+ ```typescript
435
+ import { transform } from 'ts-class-to-openapi'
436
+
437
+ class Role {
438
+ id: number
439
+ name: string
440
+ permissions: string[]
441
+ }
442
+
443
+ class Address {
444
+ street: string
445
+ city: string
446
+ country: string
447
+ zipCode: string
448
+ }
449
+
450
+ class User {
451
+ id: number
452
+ name: string
453
+ email: string
454
+ age: number
455
+ isActive: boolean
456
+ tags: string[]
457
+ createdAt: Date
458
+ role: Role // Nested object
459
+ addresses: Address[] // Array of objects
460
+ files: Buffer[] // Binary files
461
+ }
462
+
463
+ const schema = transform(User)
464
+ ```
465
+
466
+ #### Enhanced with class-validator
467
+
468
+ ```typescript
469
+ import {
470
+ IsString,
471
+ IsInt,
472
+ IsEmail,
473
+ IsDate,
474
+ IsArray,
475
+ IsNotEmpty,
476
+ MinLength,
477
+ MaxLength,
478
+ Min,
479
+ Max,
480
+ ArrayNotEmpty,
481
+ } from 'class-validator'
482
+
483
+ class Role {
484
+ @IsInt()
485
+ @IsNotEmpty()
486
+ id: number
487
+
488
+ @IsString()
489
+ @MinLength(1)
490
+ @MaxLength(50)
491
+ name: string
492
+ }
493
+
494
+ class User {
495
+ @IsInt()
496
+ @IsNotEmpty()
497
+ @Min(1)
498
+ id: number
499
+
500
+ @IsString()
501
+ @MinLength(2)
502
+ @MaxLength(100)
503
+ name: string
504
+
505
+ @IsEmail()
506
+ email: string
507
+
508
+ @IsArray()
509
+ @ArrayNotEmpty()
510
+ tags: string[]
511
+
512
+ @IsDate()
513
+ createdAt: Date
514
+
515
+ @IsNotEmpty()
516
+ role: Role // Nested object
517
+
518
+ files: Buffer[] // Binary files
519
+
520
+ @IsNotEmpty()
521
+ avatar: UploadFile // Custom file upload type
522
+ }
523
+
524
+ const schema = transform(User)
525
+ ```
526
+
527
+ **Generated Output:**
528
+
529
+ ```json
530
+ {
531
+ "name": "User",
532
+ "schema": {
533
+ "type": "object",
534
+ "properties": {
535
+ "id": {
536
+ "type": "integer",
537
+ "format": "int32",
538
+ "minimum": 1
539
+ },
540
+ "name": {
541
+ "type": "string",
542
+ "minLength": 2,
543
+ "maxLength": 100
544
+ },
545
+ "email": {
546
+ "type": "string",
547
+ "format": "email"
548
+ },
549
+ "tags": {
550
+ "type": "array",
551
+ "items": {
552
+ "type": "string"
553
+ },
554
+ "minItems": 1
555
+ },
556
+ "createdAt": {
557
+ "type": "string",
558
+ "format": "date-time"
559
+ },
560
+ "role": {
561
+ "type": "object",
562
+ "properties": {
563
+ "id": {
564
+ "type": "integer",
565
+ "format": "int32"
566
+ },
567
+ "name": {
568
+ "type": "string",
569
+ "minLength": 1,
570
+ "maxLength": 50
571
+ }
572
+ },
573
+ "required": ["id"]
574
+ },
575
+ "files": {
576
+ "type": "array",
577
+ "items": {
578
+ "type": "string",
579
+ "format": "binary"
580
+ }
581
+ },
582
+ "avatar": {
583
+ "type": "string",
584
+ "format": "binary"
585
+ }
586
+ },
587
+ "required": ["id", "tags", "role", "avatar"]
588
+ }
589
+ }
590
+ ```
591
+
592
+ > **Note**: Unlike other solutions, this package does **NOT** require `emitDecoratorMetadata: true` or `reflect-metadata`.
593
+
594
+ ## ๐Ÿ“Š Pure TypeScript vs Enhanced Mode Comparison
595
+
596
+ | Feature | Pure TypeScript | Enhanced (class-validator) |
597
+ | ---------------------- | ------------------------------------- | ------------------------------------ |
598
+ | **Dependencies** | Zero | Requires `class-validator` |
599
+ | **Configuration** | None | `experimentalDecorators: true` |
600
+ | **Type Detection** | Automatic | Automatic + Decorators |
601
+ | **Validation Rules** | Basic types only | Rich validation constraints |
602
+ | **Required Fields** | None (all optional) | Specified by decorators |
603
+ | **String Constraints** | None | Min/max length, patterns |
604
+ | **Number Constraints** | None | Min/max values, positive |
605
+ | **Array Constraints** | None | Min/max items, non-empty |
606
+ | **Email Validation** | None | Email format validation |
607
+ | **Date Handling** | `date-time` format | `date-time` format |
608
+ | **Use Case** | Existing codebases, rapid prototyping | APIs with validation, robust schemas |
609
+
610
+ ### Example Comparison
611
+
612
+ **Pure TypeScript Class:**
613
+
614
+ ```typescript
615
+ class User {
616
+ name: string
617
+ email: string
618
+ age: number
619
+ }
620
+ // Generates: All properties optional, basic types
621
+ ```
622
+
623
+ **Enhanced Class:**
624
+
625
+ ```typescript
626
+ class User {
627
+ @IsString()
628
+ @IsNotEmpty()
629
+ name: string
630
+
631
+ @IsEmail()
632
+ email: string
633
+
634
+ @IsInt()
635
+ @Min(18)
636
+ age: number
637
+ }
638
+ // Generates: name required, email format validation, age minimum 18
639
+ ```
640
+
641
+ ## ๐ŸŽจ Supported Decorators Reference
642
+
643
+ ### Type Validation Decorators
644
+
645
+ | Decorator | Generated Schema Property | Description |
646
+ | -------------- | ------------------------------------- | --------------------------- |
647
+ | `@IsString()` | `type: "string"` | String type validation |
648
+ | `@IsInt()` | `type: "integer", format: "int32"` | Integer type validation |
649
+ | `@IsNumber()` | `type: "number", format: "double"` | Number type validation |
650
+ | `@IsBoolean()` | `type: "boolean"` | Boolean type validation |
651
+ | `@IsEmail()` | `type: "string", format: "email"` | Email format validation |
652
+ | `@IsDate()` | `type: "string", format: "date-time"` | Date-time format validation |
653
+
654
+ ### String Validation Decorators
655
+
656
+ | Decorator | Generated Schema Property | Description |
657
+ | ------------------- | -------------------------------- | --------------------- |
658
+ | `@IsNotEmpty()` | Adds to `required` array | Field is required |
659
+ | `@MinLength(n)` | `minLength: n` | Minimum string length |
660
+ | `@MaxLength(n)` | `maxLength: n` | Maximum string length |
661
+ | `@Length(min, max)` | `minLength: min, maxLength: max` | String length range |
662
+
663
+ ### Number Validation Decorators
664
+
665
+ | Decorator | Generated Schema Property | Description |
666
+ | --------------- | ------------------------- | --------------------- |
667
+ | `@Min(n)` | `minimum: n` | Minimum numeric value |
668
+ | `@Max(n)` | `maximum: n` | Maximum numeric value |
669
+ | `@IsPositive()` | `minimum: 0` | Positive number (โ‰ฅ 0) |
670
+
671
+ ### Array Validation Decorators
672
+
673
+ | Decorator | Generated Schema Property | Description |
674
+ | ------------------ | ------------------------- | --------------------------- |
675
+ | `@IsArray()` | `type: "array"` | Array type validation |
676
+ | `@ArrayNotEmpty()` | `minItems: 1` + required | Non-empty array requirement |
677
+ | `@ArrayMinSize(n)` | `minItems: n` | Minimum array size |
678
+ | `@ArrayMaxSize(n)` | `maxItems: n` | Maximum array size |
679
+
680
+ ### Special Type Mappings
681
+
682
+ | TypeScript Type | Generated OpenAPI Schema | Description |
683
+ | --------------- | ------------------------------------- | ------------------------------ |
684
+ | `Date` | `type: "string", format: "date-time"` | ISO date-time string |
685
+ | `Buffer` | `type: "string", format: "binary"` | Binary data |
686
+ | `Uint8Array` | `type: "string", format: "binary"` | Binary array |
687
+ | `UploadFile` | `type: "string", format: "binary"` | Custom file upload type |
688
+ | `CustomClass` | Nested object schema | Recursive class transformation |
689
+ | `Type[]` | Array with typed items | Array of specific type |
690
+
691
+ ### Automatic TypeScript Type Detection
692
+
693
+ The library automatically detects and converts TypeScript types:
694
+
695
+ ```typescript
696
+ class AutoDetectionExample {
697
+ // Primitives
698
+ id: number // โ†’ type: "number"
699
+ name: string // โ†’ type: "string"
700
+ isActive: boolean // โ†’ type: "boolean"
701
+
702
+ // Special types
703
+ createdAt: Date // โ†’ type: "string", format: "date-time"
704
+ file: Buffer // โ†’ type: "string", format: "binary"
705
+
706
+ // Arrays
707
+ tags: string[] // โ†’ type: "array", items: { type: "string" }
708
+ scores: number[] // โ†’ type: "array", items: { type: "number" }
709
+
710
+ // Objects
711
+ metadata: object // โ†’ type: "object"
712
+ data: any // โ†’ No schema constraints
713
+
714
+ // Nested classes (automatically transformed)
715
+ profile: UserProfile // โ†’ Nested object schema
716
+ }
717
+ ```
718
+
719
+ ## ๐Ÿ“ File Upload Support
720
+
721
+ The library provides built-in support for file uploads with automatic binary format mapping:
722
+
723
+ ```typescript
724
+ import { transform } from 'ts-class-to-openapi'
725
+ import { IsNotEmpty, IsArray, IsOptional } from 'class-validator'
726
+
727
+ // Define your custom file type
728
+ class UploadFile {}
729
+
730
+ class DocumentUpload {
731
+ @IsNotEmpty()
732
+ document: UploadFile // Single file upload (required)
733
+
734
+ @IsArray()
735
+ attachments: UploadFile[] // Multiple file uploads
736
+
737
+ @IsOptional()
738
+ avatar: UploadFile // Optional file upload
739
+ }
740
+
741
+ // Transform to OpenAPI schema
742
+ const schema = transform(DocumentUpload)
743
+ console.log(JSON.stringify(schema, null, 2))
744
+ ```
745
+
746
+ **Generated Schema:**
747
+
748
+ ```json
749
+ {
750
+ "name": "DocumentUpload",
751
+ "schema": {
752
+ "type": "object",
753
+ "properties": {
754
+ "document": {
755
+ "type": "string",
756
+ "format": "binary"
757
+ },
758
+ "attachments": {
759
+ "type": "array",
760
+ "items": {
761
+ "type": "string",
762
+ "format": "binary"
763
+ }
764
+ },
765
+ "avatar": {
766
+ "type": "string",
767
+ "format": "binary"
768
+ }
769
+ },
770
+ "required": ["document"]
771
+ }
772
+ }
773
+ ```
774
+
775
+ ### Supported File Types
776
+
777
+ The following types are automatically converted to binary format:
778
+
779
+ - `Buffer` - Node.js Buffer objects
780
+ - `Uint8Array` - Typed arrays
781
+ - `UploadFile` - Custom file upload classes
782
+ - Any class ending with "File" suffix (e.g., `ImageFile`, `VideoFile`)
783
+
784
+ ## ๐Ÿ“– API Reference
785
+
786
+ ### `transform(cls: Function)`
787
+
788
+ Transforms a class constructor function into an OpenAPI schema object.
789
+
790
+ **Parameters:**
791
+
792
+ - `cls: Function` - The class constructor function to transform
793
+
794
+ **Returns:**
795
+
796
+ ```typescript
797
+ {
798
+ name: string; // Class name
799
+ schema: {
800
+ type: "object";
801
+ properties: Record<string, any>;
802
+ required: string[];
803
+ }
804
+ }
805
+ ```
806
+
807
+ **Example:**
808
+
809
+ ```typescript
810
+ import { transform } from 'ts-class-to-openapi'
811
+ import { User } from './entities/user.js'
812
+
813
+ const result = transform(User)
814
+ console.log(result.name) // "User"
815
+ console.log(result.schema) // OpenAPI schema object
816
+ ```
817
+
818
+ ## ๐ŸŒŸ Advanced Features
819
+
820
+ - โœ… **Pure TypeScript Support** - Works with any TypeScript class, no decorators required
821
+ - โœ… **Zero Runtime Dependencies** - Uses TypeScript Compiler API instead of reflect-metadata
822
+ - โœ… **High Performance** - Singleton pattern with built-in caching for repeated transformations
823
+ - โœ… **Nested Object Support** - Automatically handles complex object relationships
824
+ - โœ… **Array Type Support** - Full support for typed arrays with validation constraints
825
+ - โœ… **Built-in Caching** - Avoids reprocessing the same classes multiple times
826
+ - โœ… **Type Safety** - Complete TypeScript support with proper type definitions
827
+ - โœ… **Framework Agnostic** - Works with any TypeScript project configuration
828
+ - โœ… **Comprehensive Coverage** - Supports all major class-validator decorators
829
+ - โœ… **Flexible Usage** - Use with or without validation decorators
830
+
831
+ ## ๐Ÿ”„ Migration Guide
832
+
833
+ ### From reflect-metadata Solutions
834
+
835
+ If you're migrating from a solution that requires `reflect-metadata`:
836
+
837
+ **Before (with reflect-metadata):**
838
+
839
+ ```typescript
840
+ import 'reflect-metadata'
841
+ import { getMetadataStorage } from 'class-validator'
842
+
843
+ // Complex setup required
844
+ const schema = transformClassToSchema(User)
845
+ ```
846
+
847
+ **After (with ts-class-to-openapi):**
848
+
849
+ ```typescript
850
+ import { transform } from 'ts-class-to-openapi'
851
+
852
+ // Simple, clean API
853
+ const schema = transform(User)
854
+ ```
855
+
856
+ ### New: Pure TypeScript Support
857
+
858
+ The biggest advantage is that you can now transform **any TypeScript class** without requiring decorators:
859
+
860
+ **Before (required decorators):**
861
+
862
+ ```typescript
863
+ // This would NOT work with traditional solutions
864
+ class LegacyUser {
865
+ id: number
866
+ name: string
867
+ email: string
868
+ }
869
+ ```
870
+
871
+ **Now (works immediately):**
872
+
873
+ ```typescript
874
+ import { transform } from 'ts-class-to-openapi'
875
+
876
+ // This works out of the box!
877
+ class LegacyUser {
878
+ id: number
879
+ name: string
880
+ email: string
881
+ }
882
+
883
+ const schema = transform(LegacyUser) // โœ… Works perfectly
884
+ ```
885
+
886
+ ### Migration Steps
887
+
888
+ 1. **Remove reflect-metadata imports** from your entities
889
+ 2. **Remove `emitDecoratorMetadata: true`** from tsconfig.json (optional)
890
+ 3. **Update transformation code** to use the new API
891
+ 4. **Remove reflect-metadata dependency** from package.json
892
+ 5. **Optional**: Keep decorators for enhanced validation or remove them entirely
893
+
894
+ ### TypeScript Configuration
895
+
896
+ You only need minimal TypeScript configuration:
897
+
898
+ ```json
899
+ {
900
+ "compilerOptions": {
901
+ "experimentalDecorators": true
902
+ // emitDecoratorMetadata: true โ† NOT REQUIRED!
903
+ }
904
+ }
905
+ ```
906
+
907
+ ## ๐Ÿ”ง Troubleshooting
908
+
909
+ ### Common Issues
910
+
911
+ **Error: "Cannot find module 'ts-class-to-openapi'"**
912
+
913
+ ```bash
914
+ npm install ts-class-to-openapi
915
+ ```
916
+
917
+ **Error: "Cannot find module 'class-validator'"**
918
+
919
+ This is only needed if you want to use validation decorators:
920
+
921
+ ```bash
922
+ npm install class-validator
923
+ ```
924
+
925
+ **Error: "Experimental decorators warning"**
926
+ Add to your `tsconfig.json`:
927
+
928
+ ```json
929
+ {
930
+ "compilerOptions": {
931
+ "experimentalDecorators": true
932
+ }
933
+ }
934
+ ```
935
+
936
+ **Empty schema generated**
937
+
938
+ - For pure TypeScript classes: Ensure your class has properly typed properties
939
+ - For class-validator enhanced: Ensure your class has class-validator decorators
940
+ - Check that the class is properly exported/imported
941
+ - Verify TypeScript compilation is working
942
+
943
+ **Works without decorators but want validation?**
944
+
945
+ Pure TypeScript classes work immediately, but if you want enhanced validation schemas:
946
+
947
+ 1. Install class-validator: `npm install class-validator`
948
+ 2. Add decorators to your properties
949
+ 3. Enable `experimentalDecorators: true` in tsconfig.json
950
+
951
+ **Nested objects not working**
952
+
953
+ - Make sure nested classes are in the same project
954
+ - Ensure nested classes have their own decorators
955
+ - Check file paths and imports
956
+
957
+ ## ๐Ÿ“„ License
958
+
959
+ MIT