@cerios/openapi-to-zod 0.5.3 → 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 CHANGED
@@ -6,7 +6,7 @@ Transform OpenAPI YAML specifications into Zod v4 compliant schemas with full Ty
6
6
 
7
7
  - ✅ **Zod v4 Compatible**: Uses latest Zod features, no deprecated methods
8
8
  - 📝 **TypeScript Types**: Automatically generates TypeScript types from schemas using `z.infer`
9
- - 🎯 **Enums**: Creates proper TypeScript enums with PascalCase properties
9
+ - 🎯 **Zod Enums**: Creates Zod enum schemas from OpenAPI enums
10
10
  - 🔧 **Flexible Modes**: Strict, normal, or loose validation
11
11
  - 📐 **Format Support**: Full support for string formats (uuid, email, url, date, etc.)
12
12
  - 🎨 **camelCase Schemas**: Schemas follow camelCase naming with Schema suffix
@@ -35,14 +35,12 @@ npm install @cerios/openapi-to-zod
35
35
 
36
36
  ## CLI Usage
37
37
 
38
- > **Breaking Change in v2.0:** All CLI options have been removed. Use configuration files instead.
39
-
40
38
  ### Quick Start
41
39
 
42
40
  #### 1. Initialize Configuration
43
41
 
44
42
  ```bash
45
- npx @cerios/openapi-to-zod --init
43
+ npx @cerios/openapi-to-zod init
46
44
  ```
47
45
 
48
46
  This interactive command will:
@@ -128,12 +126,6 @@ export default defineConfig({
128
126
 
129
127
  **openapi-to-zod.config.json:**
130
128
 
131
- ```json
132
- {
133
- "defaults": {
134
- "mode": "strict",
135
- "includeDescriptions": true,
136
- "enumType": "zod",
137
129
  ```json
138
130
  {
139
131
  "defaults": {
@@ -156,13 +148,15 @@ openapi-to-zod [options]
156
148
 
157
149
  Options:
158
150
  -c, --config <path> Path to config file (optional if using auto-discovery)
159
- --init Initialize a new config file
160
151
  -V, --version Output version number
161
152
  -h, --help Display help
162
153
 
154
+ Commands:
155
+ init Initialize a new config file
156
+
163
157
  Examples:
164
158
  # Create config
165
- $ openapi-to-zod --init
159
+ $ openapi-to-zod init
166
160
 
167
161
  # Generate (auto-discover config)
168
162
  $ openapi-to-zod
@@ -171,35 +165,6 @@ Examples:
171
165
  $ openapi-to-zod --config custom.config.ts
172
166
  ```
173
167
 
174
- ### Migration from v1.x
175
-
176
- **Before (v1.x):**
177
- ```bash
178
- openapi-to-zod -i openapi.yaml -o schemas.ts --mode strict --prefix Api
179
- ```
180
-
181
- **After (v2.0):**
182
- ```typescript
183
- // openapi-to-zod.config.ts
184
- import { defineConfig } from '@cerios/openapi-to-zod';
185
-
186
- export default defineConfig({
187
- specs: [
188
- {
189
- input: 'openapi.yaml',
190
- output: 'schemas.ts',
191
- mode: 'strict',
192
- prefix: 'Api',
193
- },
194
- ],
195
- });
196
- ```
197
-
198
- Then run:
199
- ```bash
200
- openapi-to-zod
201
- ```
202
-
203
168
  ### Configuration Options
204
169
 
205
170
 
@@ -218,15 +183,45 @@ openapi-to-zod
218
183
  | `output` | `string` | Output TypeScript file path (required) |
219
184
  | `mode` | `"strict"` \| `"normal"` \| `"loose"` | Validation mode |
220
185
  | `includeDescriptions` | `boolean` | Include JSDoc comments |
221
- | `enumType` | `"zod"` \| `"typescript"` | Enum generation type |
222
186
  | `useDescribe` | `boolean` | Add `.describe()` calls |
223
187
  | `schemaType` | `"all"` \| `"request"` \| `"response"` | Schema filtering |
224
188
  | `prefix` | `string` | Prefix for schema names |
225
189
  | `suffix` | `string` | Suffix for schema names |
226
190
  | `showStats` | `boolean` | Include generation statistics |
227
- | `nativeEnumType` | `"union"` \| `"enum"` | Native enum type when using TypeScript enums |
228
- | `request` | `object` | Request-specific options (mode, typeMode, enumType, etc.) |
229
- | `response` | `object` | Response-specific options (mode, enumType, etc.) |
191
+ | `request` | `object` | Request-specific options (mode, includeDescriptions, useDescribe) |
192
+ | `response` | `object` | Response-specific options (mode, includeDescriptions, useDescribe) |
193
+ | `operationFilters` | `object` | Filter operations by tags, paths, methods, etc. (see below) |
194
+
195
+ #### Operation Filters
196
+
197
+ Filter which operations to include/exclude during schema generation. Useful for generating separate schemas for different API subsets.
198
+
199
+ | Filter | Type | Description |
200
+ |--------|------|-------------|
201
+ | `includeTags` | `string[]` | Include only operations with these tags |
202
+ | `excludeTags` | `string[]` | Exclude operations with these tags |
203
+ | `includePaths` | `string[]` | Include only these paths (supports glob patterns like `/users/**`) |
204
+ | `excludePaths` | `string[]` | Exclude these paths (supports glob patterns) |
205
+ | `includeMethods` | `string[]` | Include only these HTTP methods (`get`, `post`, etc.) |
206
+ | `excludeMethods` | `string[]` | Exclude these HTTP methods |
207
+ | `includeOperationIds` | `string[]` | Include only these operationIds (supports glob patterns) |
208
+ | `excludeOperationIds` | `string[]` | Exclude these operationIds (supports glob patterns) |
209
+ | `excludeDeprecated` | `boolean` | Exclude deprecated operations |
210
+
211
+ **Example:**
212
+ ```typescript
213
+ export default defineConfig({
214
+ specs: [{
215
+ input: 'openapi.yaml',
216
+ output: 'schemas.ts',
217
+ operationFilters: {
218
+ includeTags: ['public'], // Only public endpoints
219
+ excludeDeprecated: true, // Skip deprecated operations
220
+ excludePaths: ['/internal/**'] // Exclude internal paths
221
+ }
222
+ }]
223
+ });
224
+ ```
230
225
 
231
226
  ### Batch Execution
232
227
 
@@ -416,6 +411,141 @@ The generator supports all OpenAPI string formats with Zod v4:
416
411
 
417
412
  ## Advanced Features
418
413
 
414
+ ### Operation Filtering
415
+
416
+ Filter which operations are included in schema generation. This is useful when you want to generate schemas for only a subset of your API.
417
+
418
+ **Example 1: Filter by tags**
419
+ ```typescript
420
+ export default defineConfig({
421
+ specs: [{
422
+ input: 'openapi.yaml',
423
+ output: 'public-schemas.ts',
424
+ operationFilters: {
425
+ includeTags: ['public', 'users'] // Only include operations tagged with 'public' or 'users'
426
+ }
427
+ }]
428
+ });
429
+ ```
430
+
431
+ **Example 2: Filter by paths**
432
+ ```typescript
433
+ export default defineConfig({
434
+ specs: [{
435
+ input: 'openapi.yaml',
436
+ output: 'v1-schemas.ts',
437
+ operationFilters: {
438
+ includePaths: ['/api/v1/**'], // Only v1 endpoints
439
+ excludePaths: ['/api/v1/admin/**'] // But exclude admin endpoints
440
+ }
441
+ }]
442
+ });
443
+ ```
444
+
445
+ **Example 3: Exclude deprecated operations**
446
+ ```typescript
447
+ export default defineConfig({
448
+ specs: [{
449
+ input: 'openapi.yaml',
450
+ output: 'current-schemas.ts',
451
+ operationFilters: {
452
+ excludeDeprecated: true // Skip all deprecated operations
453
+ }
454
+ }]
455
+ });
456
+ ```
457
+
458
+ **Filtering Logic:**
459
+ 1. If no filters specified, all operations are included
460
+ 2. Empty arrays are treated as "no constraint"
461
+ 3. Include filters are applied first (allowlist)
462
+ 4. Exclude filters are applied second (blocklist)
463
+ 5. Exclude rules always win over include rules
464
+
465
+ **Statistics:** When using operation filters, generation statistics will show how many operations were filtered out.
466
+
467
+ ### Request/Response Schema Separation
468
+
469
+ Generate separate schemas for requests and responses by filtering `readOnly` and `writeOnly` properties.
470
+
471
+ **Example: Request schemas (exclude readOnly)**
472
+ ```typescript
473
+ export default defineConfig({
474
+ specs: [{
475
+ input: 'openapi.yaml',
476
+ output: 'request-schemas.ts',
477
+ schemaType: 'request' // Excludes readOnly properties like 'id', 'createdAt'
478
+ }]
479
+ });
480
+ ```
481
+
482
+ **Example: Response schemas (exclude writeOnly)**
483
+ ```typescript
484
+ export default defineConfig({
485
+ specs: [{
486
+ input: 'openapi.yaml',
487
+ output: 'response-schemas.ts',
488
+ schemaType: 'response' // Excludes writeOnly properties like 'password'
489
+ }]
490
+ });
491
+ ```
492
+
493
+ **Example: Context-specific validation**
494
+ ```typescript
495
+ export default defineConfig({
496
+ specs: [{
497
+ input: 'openapi.yaml',
498
+ output: 'schemas.ts',
499
+ request: {
500
+ mode: 'strict', // Strict validation for incoming data
501
+ includeDescriptions: false
502
+ },
503
+ response: {
504
+ mode: 'loose', // Flexible validation for API responses
505
+ includeDescriptions: true
506
+ }
507
+ }]
508
+ });
509
+ ```
510
+
511
+ **OpenAPI Spec:**
512
+ ```yaml
513
+ User:
514
+ type: object
515
+ properties:
516
+ id:
517
+ type: string
518
+ readOnly: true # Excluded in 'request' mode
519
+ email:
520
+ type: string
521
+ password:
522
+ type: string
523
+ writeOnly: true # Excluded in 'response' mode
524
+ createdAt:
525
+ type: string
526
+ format: date-time
527
+ readOnly: true # Excluded in 'request' mode
528
+ ```
529
+
530
+ **Generated Request Schema** (`schemaType: 'request'`):
531
+ ```typescript
532
+ export const userSchema = z.object({
533
+ email: z.string(),
534
+ password: z.string(), // writeOnly included
535
+ // id and createdAt excluded (readOnly)
536
+ });
537
+ ```
538
+
539
+ **Generated Response Schema** (`schemaType: 'response'`):
540
+ ```typescript
541
+ export const userSchema = z.object({
542
+ id: z.string(), // readOnly included
543
+ email: z.string(),
544
+ createdAt: z.string().datetime(), // readOnly included
545
+ // password excluded (writeOnly)
546
+ });
547
+ ```
548
+
419
549
  ### String Constraints
420
550
 
421
551
  - `minLength` and `maxLength` are automatically applied
@@ -440,27 +570,27 @@ OpenAPI's `nullable: true` is converted to `.nullable()`
440
570
 
441
571
  ### Enums
442
572
 
443
- Enums are generated as TypeScript enums with:
444
- - PascalCase property names
445
- - Original string values
573
+ Enums are generated as Zod enums with:
574
+ - Proper string value handling
446
575
  - Zod schema using `z.enum()`
576
+ - TypeScript type inference from the Zod schema
447
577
 
448
578
  ## Schema Naming
449
579
 
450
580
  Customize schema names with prefixes and suffixes:
451
581
 
452
- ```bash
453
- # Add API prefix
454
- openapi-to-zod -i openapi.yaml -o schemas.ts -p api
455
- # Output: apiUserSchema, apiProductSchema, etc.
456
-
457
- # Add DTO suffix
458
- openapi-to-zod -i openapi.yaml -o schemas.ts --suffix dto
459
- # Output: userDtoSchema, productDtoSchema, etc.
460
-
461
- # Combine both
462
- openapi-to-zod -i openapi.yaml -o schemas.ts -p api --suffix dto
463
- # Output: apiUserDtoSchema, apiProductDtoSchema, etc.
582
+ ```typescript
583
+ // In your config file
584
+ export default defineConfig({
585
+ specs: [
586
+ {
587
+ input: 'openapi.yaml',
588
+ output: 'schemas.ts',
589
+ prefix: 'api', // Output: apiUserSchema, apiProductSchema
590
+ suffix: 'dto', // Output: userDtoSchema, productDtoSchema
591
+ },
592
+ ],
593
+ });
464
594
  ```
465
595
 
466
596
  This is useful when:
@@ -470,12 +600,11 @@ This is useful when:
470
600
 
471
601
  ## Generation Statistics
472
602
 
473
- Statistics are **included by default** in generated files. Use `--no-stats` to disable:
603
+ Statistics are **included by default** in generated files. Use `showStats: false` to disable:
474
604
 
475
605
  ```typescript
476
606
  // Generation Statistics:
477
607
  // Total schemas: 42
478
- // Enums: 8
479
608
  // Circular references: 3
480
609
  // Discriminated unions: 5
481
610
  // With constraints: 18
@@ -487,8 +616,6 @@ Helpful for:
487
616
  - Tracking changes over time
488
617
  - Debugging generation issues
489
618
 
490
- To disable: `openapi-to-zod -i openapi.yaml -o schemas.ts --no-stats`
491
-
492
619
  ## OpenAPI Features Supported
493
620
 
494
621
  ### Basic Types
@@ -832,6 +959,89 @@ All errors include:
832
959
  - Clear description of the problem
833
960
  - Context about what was expected
834
961
 
962
+ ## Public Utility Exports
963
+
964
+ Starting from **v0.7.0**, this package exports several utilities that can be used by other packages (like `@cerios/openapi-to-zod-playwright`):
965
+
966
+ ### `LRUCache<K, V>`
967
+
968
+ A Least Recently Used (LRU) cache implementation for efficient caching.
969
+
970
+ ```typescript
971
+ import { LRUCache } from '@cerios/openapi-to-zod';
972
+
973
+ const cache = new LRUCache<string, ParsedSpec>(50);
974
+ cache.set('spec-key', parsedSpec);
975
+ const spec = cache.get('spec-key');
976
+ ```
977
+
978
+ ### `toPascalCase(str: string | number): string`
979
+
980
+ Converts strings to PascalCase, handling kebab-case, snake_case, and special characters.
981
+
982
+ ```typescript
983
+ import { toPascalCase } from '@cerios/openapi-to-zod';
984
+
985
+ toPascalCase('my-api-client'); // => 'MyApiClient'
986
+ toPascalCase('user_name'); // => 'UserName'
987
+ ```
988
+
989
+ ### `escapeJSDoc(str: string): string`
990
+
991
+ Escapes JSDoc comment terminators to prevent injection.
992
+
993
+ ```typescript
994
+ import { escapeJSDoc } from '@cerios/openapi-to-zod';
995
+
996
+ escapeJSDoc('Comment with */ terminator'); // => 'Comment with *\\/ terminator'
997
+ ```
998
+
999
+ ### `executeBatch<T>()` and `Generator` Interface
1000
+
1001
+ Execute batch processing with custom generators.
1002
+
1003
+ ```typescript
1004
+ import { executeBatch, type Generator } from '@cerios/openapi-to-zod';
1005
+
1006
+ class MyGenerator implements Generator {
1007
+ generate(): void {
1008
+ // Your generation logic
1009
+ }
1010
+ }
1011
+
1012
+ await executeBatch(
1013
+ specs,
1014
+ 'sequential', // or 'parallel'
1015
+ spec => new MyGenerator(spec)
1016
+ );
1017
+ ```
1018
+
1019
+ ### Config Validation Utilities
1020
+
1021
+ Shared utilities for configuration file validation:
1022
+
1023
+ ```typescript
1024
+ import {
1025
+ createTypeScriptLoader,
1026
+ formatConfigValidationError,
1027
+ type RequestResponseOptions,
1028
+ type BaseOperationFilters
1029
+ } from '@cerios/openapi-to-zod';
1030
+
1031
+ // Create TypeScript config loader for cosmiconfig
1032
+ const loader = createTypeScriptLoader();
1033
+
1034
+ // Format Zod validation errors
1035
+ const errorMessage = formatConfigValidationError(
1036
+ zodError,
1037
+ filePath,
1038
+ configPath,
1039
+ ['Additional note 1', 'Additional note 2']
1040
+ );
1041
+ ```
1042
+
1043
+ These utilities are marked with `@shared` tags in the source code and are covered by comprehensive tests.
1044
+
835
1045
  ## API Reference
836
1046
 
837
1047
  ### `generateZodSchemas(options: OpenApiGeneratorOptions): void`
@@ -877,7 +1087,7 @@ interface OpenApiGeneratorOptions {
877
1087
  Comprehensive test suite with **364 passing tests** covering:
878
1088
 
879
1089
  - ✅ **Basic Schema Generation** (14 tests) - Core OpenAPI types, references, nested objects
880
- - ✅ **Enum Generation** (10 tests) - TypeScript enums, Zod enums, PascalCase conversion
1090
+ - ✅ **Enum Generation** (4 tests) - Zod enum generation and handling
881
1091
  - ✅ **Circular References** (5 tests) - Self-references, mutual references, validation
882
1092
  - ✅ **Format Support** (9 tests) - UUID, email, URL, date-time, and 15+ other formats
883
1093
  - ✅ **Validation Modes** (7 tests) - Strict, normal, loose object validation