@cerios/openapi-to-zod 0.6.0 → 1.1.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 +448 -51
- package/dist/cli.js +355 -186
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +418 -224
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +9 -344
- package/dist/index.d.ts +9 -344
- package/dist/index.js +156 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +155 -22
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.mts +257 -0
- package/dist/internal.d.ts +257 -0
- package/dist/internal.js +592 -0
- package/dist/internal.js.map +1 -0
- package/dist/internal.mjs +547 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/types-B7ePTDjr.d.mts +345 -0
- package/dist/types-B7ePTDjr.d.ts +345 -0
- package/package.json +102 -78
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { O as OpenApiGeneratorOptions } from './types-B7ePTDjr.js';
|
|
2
|
+
export { C as CommonSchemaOptions, a as ConfigFile, E as ExecutionMode, b as OpenAPISchema, c as OpenAPISpec, d as OperationFilters, R as RequestOptions, e as ResponseOptions, f as defineConfig } from './types-B7ePTDjr.js';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Custom error classes for better error handling and debugging
|
|
3
6
|
*/
|
|
@@ -50,298 +53,6 @@ declare class CliOptionsError extends GeneratorError {
|
|
|
50
53
|
constructor(message: string, context?: Record<string, unknown>);
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
/**
|
|
54
|
-
* Common options shared by both request and response contexts
|
|
55
|
-
*/
|
|
56
|
-
interface CommonSchemaOptions {
|
|
57
|
-
/**
|
|
58
|
-
* Object validation mode
|
|
59
|
-
* - 'strict': Uses z.strictObject() - no additional properties allowed
|
|
60
|
-
* - 'normal': Uses z.object() - additional properties allowed
|
|
61
|
-
* - 'loose': Uses z.looseObject() - explicitly allows additional properties
|
|
62
|
-
*/
|
|
63
|
-
mode?: "strict" | "normal" | "loose";
|
|
64
|
-
/**
|
|
65
|
-
* Whether to add .describe() calls for better error messages
|
|
66
|
-
* @default false
|
|
67
|
-
*/
|
|
68
|
-
useDescribe?: boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Whether to include descriptions as JSDoc comments
|
|
71
|
-
*/
|
|
72
|
-
includeDescriptions?: boolean;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Request-specific options that can override root-level options
|
|
76
|
-
*/
|
|
77
|
-
interface RequestOptions extends CommonSchemaOptions {
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Response-specific options that can override root-level options
|
|
81
|
-
*/
|
|
82
|
-
interface ResponseOptions extends CommonSchemaOptions {
|
|
83
|
-
}
|
|
84
|
-
interface OpenApiGeneratorOptions {
|
|
85
|
-
/**
|
|
86
|
-
* Object validation mode
|
|
87
|
-
* - 'strict': Uses z.strictObject() - no additional properties allowed
|
|
88
|
-
* - 'normal': Uses z.object() - additional properties allowed
|
|
89
|
-
* - 'loose': Uses z.looseObject() - explicitly allows additional properties
|
|
90
|
-
*/
|
|
91
|
-
mode?: "strict" | "normal" | "loose";
|
|
92
|
-
/**
|
|
93
|
-
* Input OpenAPI YAML file path
|
|
94
|
-
*/
|
|
95
|
-
input: string;
|
|
96
|
-
/**
|
|
97
|
-
* Output TypeScript file path
|
|
98
|
-
* Optional when using string generation methods (generateString)
|
|
99
|
-
* Required when calling generate() to write to a file
|
|
100
|
-
*/
|
|
101
|
-
output?: string;
|
|
102
|
-
/**
|
|
103
|
-
* Whether to include descriptions as JSDoc comments
|
|
104
|
-
*/
|
|
105
|
-
includeDescriptions?: boolean;
|
|
106
|
-
/**
|
|
107
|
-
* Whether to add .describe() calls for better error messages
|
|
108
|
-
* @default false
|
|
109
|
-
*/
|
|
110
|
-
useDescribe?: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* Schema filtering mode
|
|
113
|
-
* - 'all': Generate all schemas (default)
|
|
114
|
-
* - 'request': Only include schemas suitable for requests (excludes readOnly)
|
|
115
|
-
* - 'response': Only include schemas suitable for responses (excludes writeOnly)
|
|
116
|
-
*/
|
|
117
|
-
schemaType?: "all" | "request" | "response";
|
|
118
|
-
/**
|
|
119
|
-
* Prefix to add to all generated schema names
|
|
120
|
-
* @example "api" -> "apiUserSchema"
|
|
121
|
-
*/
|
|
122
|
-
prefix?: string;
|
|
123
|
-
/**
|
|
124
|
-
* Suffix to add before "Schema" in generated names
|
|
125
|
-
* @example "dto" -> "userDtoSchema"
|
|
126
|
-
*/
|
|
127
|
-
suffix?: string;
|
|
128
|
-
/**
|
|
129
|
-
* Whether to include generation statistics in output file
|
|
130
|
-
* @default true
|
|
131
|
-
*/
|
|
132
|
-
showStats?: boolean;
|
|
133
|
-
/**
|
|
134
|
-
* Request-specific options that override root-level options
|
|
135
|
-
* Applied when schemas are used in request contexts
|
|
136
|
-
*/
|
|
137
|
-
request?: RequestOptions;
|
|
138
|
-
/**
|
|
139
|
-
* Response-specific options that override root-level options
|
|
140
|
-
* Applied when schemas are used in response contexts
|
|
141
|
-
*/
|
|
142
|
-
response?: ResponseOptions;
|
|
143
|
-
/**
|
|
144
|
-
* Filter which operations to include/exclude from generation
|
|
145
|
-
* Useful for generating separate schemas for different API subsets
|
|
146
|
-
*
|
|
147
|
-
* Filtering logic:
|
|
148
|
-
* 1. If no filters specified, all operations are included
|
|
149
|
-
* 2. Empty arrays are treated as "no constraint" (not as "exclude all")
|
|
150
|
-
* 3. Include filters are applied first (allowlist)
|
|
151
|
-
* 4. Exclude filters are applied second (blocklist)
|
|
152
|
-
* 5. Exclude rules always win over include rules
|
|
153
|
-
*
|
|
154
|
-
* Supports glob patterns for paths and operationIds (e.g., "/api/v1/**", "get*")
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* // Only generate schemas for user-related endpoints
|
|
158
|
-
* operationFilters: {
|
|
159
|
-
* includeTags: ["users"]
|
|
160
|
-
* }
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* // Generate only GET endpoints, excluding deprecated ones
|
|
164
|
-
* operationFilters: {
|
|
165
|
-
* includeMethods: ["get"],
|
|
166
|
-
* excludeDeprecated: true
|
|
167
|
-
* }
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* // Generate only v1 API endpoints
|
|
171
|
-
* operationFilters: {
|
|
172
|
-
* includePaths: ["/api/v1/**"]
|
|
173
|
-
* }
|
|
174
|
-
*/
|
|
175
|
-
operationFilters?: OperationFilters;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Operation filtering options
|
|
179
|
-
* Controls which operations from the OpenAPI spec are included in generation
|
|
180
|
-
*/
|
|
181
|
-
interface OperationFilters {
|
|
182
|
-
/**
|
|
183
|
-
* Include only operations with these tags
|
|
184
|
-
* If specified, only operations with at least one matching tag are included
|
|
185
|
-
* Empty array = no constraint
|
|
186
|
-
*/
|
|
187
|
-
includeTags?: string[];
|
|
188
|
-
/**
|
|
189
|
-
* Exclude operations with these tags
|
|
190
|
-
* Operations with any matching tag are excluded
|
|
191
|
-
* Empty array = no constraint
|
|
192
|
-
*/
|
|
193
|
-
excludeTags?: string[];
|
|
194
|
-
/**
|
|
195
|
-
* Include only operations matching these path patterns
|
|
196
|
-
* Supports glob patterns (e.g., "/users/**", "/api/v1/*")
|
|
197
|
-
* Empty array = no constraint
|
|
198
|
-
*/
|
|
199
|
-
includePaths?: string[];
|
|
200
|
-
/**
|
|
201
|
-
* Exclude operations matching these path patterns
|
|
202
|
-
* Supports glob patterns (e.g., "/internal/**", "/admin/*")
|
|
203
|
-
* Empty array = no constraint
|
|
204
|
-
*/
|
|
205
|
-
excludePaths?: string[];
|
|
206
|
-
/**
|
|
207
|
-
* Include only these HTTP methods
|
|
208
|
-
* Valid values: "get", "post", "put", "patch", "delete", "head", "options"
|
|
209
|
-
* Empty array = no constraint
|
|
210
|
-
*/
|
|
211
|
-
includeMethods?: string[];
|
|
212
|
-
/**
|
|
213
|
-
* Exclude these HTTP methods
|
|
214
|
-
* Valid values: "get", "post", "put", "patch", "delete", "head", "options"
|
|
215
|
-
* Empty array = no constraint
|
|
216
|
-
*/
|
|
217
|
-
excludeMethods?: string[];
|
|
218
|
-
/**
|
|
219
|
-
* Include only operations matching these operationId patterns
|
|
220
|
-
* Supports glob patterns (e.g., "getUser*", "*Admin")
|
|
221
|
-
* Empty array = no constraint
|
|
222
|
-
*/
|
|
223
|
-
includeOperationIds?: string[];
|
|
224
|
-
/**
|
|
225
|
-
* Exclude operations matching these operationId patterns
|
|
226
|
-
* Supports glob patterns (e.g., "deleteUser*", "*Internal")
|
|
227
|
-
* Empty array = no constraint
|
|
228
|
-
*/
|
|
229
|
-
excludeOperationIds?: string[];
|
|
230
|
-
/**
|
|
231
|
-
* Whether to exclude deprecated operations
|
|
232
|
-
* @default false
|
|
233
|
-
*/
|
|
234
|
-
excludeDeprecated?: boolean;
|
|
235
|
-
}
|
|
236
|
-
interface OpenAPISchema {
|
|
237
|
-
type?: string | string[];
|
|
238
|
-
format?: string;
|
|
239
|
-
enum?: (string | number)[];
|
|
240
|
-
const?: string | number | boolean | null;
|
|
241
|
-
properties?: Record<string, OpenAPISchema>;
|
|
242
|
-
required?: string[];
|
|
243
|
-
items?: OpenAPISchema;
|
|
244
|
-
prefixItems?: OpenAPISchema[];
|
|
245
|
-
allOf?: OpenAPISchema[];
|
|
246
|
-
oneOf?: OpenAPISchema[];
|
|
247
|
-
anyOf?: OpenAPISchema[];
|
|
248
|
-
$ref?: string;
|
|
249
|
-
nullable?: boolean;
|
|
250
|
-
minLength?: number;
|
|
251
|
-
maxLength?: number;
|
|
252
|
-
minimum?: number;
|
|
253
|
-
maximum?: number;
|
|
254
|
-
exclusiveMinimum?: boolean | number;
|
|
255
|
-
exclusiveMaximum?: boolean | number;
|
|
256
|
-
multipleOf?: number;
|
|
257
|
-
pattern?: string;
|
|
258
|
-
description?: string;
|
|
259
|
-
title?: string;
|
|
260
|
-
example?: any;
|
|
261
|
-
examples?: any[];
|
|
262
|
-
additionalProperties?: boolean | OpenAPISchema;
|
|
263
|
-
minProperties?: number;
|
|
264
|
-
maxProperties?: number;
|
|
265
|
-
minItems?: number;
|
|
266
|
-
maxItems?: number;
|
|
267
|
-
uniqueItems?: boolean;
|
|
268
|
-
contains?: OpenAPISchema;
|
|
269
|
-
minContains?: number;
|
|
270
|
-
maxContains?: number;
|
|
271
|
-
discriminator?: {
|
|
272
|
-
propertyName: string;
|
|
273
|
-
mapping?: Record<string, string>;
|
|
274
|
-
};
|
|
275
|
-
readOnly?: boolean;
|
|
276
|
-
writeOnly?: boolean;
|
|
277
|
-
deprecated?: boolean;
|
|
278
|
-
dependentRequired?: Record<string, string[]>;
|
|
279
|
-
dependencies?: Record<string, string[] | OpenAPISchema>;
|
|
280
|
-
patternProperties?: Record<string, OpenAPISchema>;
|
|
281
|
-
propertyNames?: OpenAPISchema;
|
|
282
|
-
contentMediaType?: string;
|
|
283
|
-
contentEncoding?: string;
|
|
284
|
-
not?: OpenAPISchema;
|
|
285
|
-
if?: OpenAPISchema;
|
|
286
|
-
then?: OpenAPISchema;
|
|
287
|
-
else?: OpenAPISchema;
|
|
288
|
-
unevaluatedProperties?: boolean | OpenAPISchema;
|
|
289
|
-
unevaluatedItems?: boolean | OpenAPISchema;
|
|
290
|
-
}
|
|
291
|
-
interface OpenAPISpec {
|
|
292
|
-
components?: {
|
|
293
|
-
schemas?: Record<string, OpenAPISchema>;
|
|
294
|
-
};
|
|
295
|
-
paths?: Record<string, any>;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Execution mode for batch processing
|
|
299
|
-
* - 'parallel': Process all specs concurrently (default, faster)
|
|
300
|
-
* - 'sequential': Process specs one at a time (safer for resource constraints)
|
|
301
|
-
*/
|
|
302
|
-
type ExecutionMode = "parallel" | "sequential";
|
|
303
|
-
/**
|
|
304
|
-
* Root configuration file structure
|
|
305
|
-
*/
|
|
306
|
-
interface ConfigFile {
|
|
307
|
-
/**
|
|
308
|
-
* Global default options applied to all specs
|
|
309
|
-
* Can be overridden by individual spec configurations
|
|
310
|
-
*/
|
|
311
|
-
defaults?: Partial<Omit<OpenApiGeneratorOptions, "input" | "output">>;
|
|
312
|
-
/**
|
|
313
|
-
* Array of OpenAPI specifications to process
|
|
314
|
-
* Each spec must have input and output paths
|
|
315
|
-
*/
|
|
316
|
-
specs: OpenApiGeneratorOptions[];
|
|
317
|
-
/**
|
|
318
|
-
* Execution mode for batch processing
|
|
319
|
-
* @default "parallel"
|
|
320
|
-
*/
|
|
321
|
-
executionMode?: ExecutionMode;
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Helper function for type-safe config file creation
|
|
325
|
-
* Provides IDE autocomplete and type checking for config files
|
|
326
|
-
*
|
|
327
|
-
* @example
|
|
328
|
-
* ```typescript
|
|
329
|
-
* import { defineConfig } from '@cerios/openapi-to-zod';
|
|
330
|
-
*
|
|
331
|
-
* export default defineConfig({
|
|
332
|
-
* defaults: {
|
|
333
|
-
* mode: 'strict',
|
|
334
|
-
* includeDescriptions: true
|
|
335
|
-
* },
|
|
336
|
-
* specs: [
|
|
337
|
-
* { input: 'api-v1.yaml', output: 'schemas/v1.ts' },
|
|
338
|
-
* { input: 'api-v2.yaml', output: 'schemas/v2.ts', mode: 'normal' }
|
|
339
|
-
* ]
|
|
340
|
-
* });
|
|
341
|
-
* ```
|
|
342
|
-
*/
|
|
343
|
-
declare function defineConfig(config: ConfigFile): ConfigFile;
|
|
344
|
-
|
|
345
56
|
declare class OpenApiGenerator {
|
|
346
57
|
private schemas;
|
|
347
58
|
private types;
|
|
@@ -414,6 +125,11 @@ declare class OpenApiGenerator {
|
|
|
414
125
|
* Generate query parameter schemas for each operation
|
|
415
126
|
*/
|
|
416
127
|
private generateQueryParameterSchemas;
|
|
128
|
+
/**
|
|
129
|
+
* Check if a header should be ignored based on filter patterns
|
|
130
|
+
* @internal
|
|
131
|
+
*/
|
|
132
|
+
private shouldIgnoreHeader;
|
|
417
133
|
/**
|
|
418
134
|
* Generate header parameter schemas for each operation
|
|
419
135
|
* Header parameters are always string type (HTTP header semantics)
|
|
@@ -434,55 +150,4 @@ declare class OpenApiGenerator {
|
|
|
434
150
|
private generateStats;
|
|
435
151
|
}
|
|
436
152
|
|
|
437
|
-
|
|
438
|
-
* Filter statistics to track which operations were included/excluded
|
|
439
|
-
*/
|
|
440
|
-
interface FilterStatistics {
|
|
441
|
-
totalOperations: number;
|
|
442
|
-
includedOperations: number;
|
|
443
|
-
filteredByTags: number;
|
|
444
|
-
filteredByPaths: number;
|
|
445
|
-
filteredByMethods: number;
|
|
446
|
-
filteredByOperationIds: number;
|
|
447
|
-
filteredByDeprecated: number;
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Create a new filter statistics object with all counters initialized to zero
|
|
451
|
-
*/
|
|
452
|
-
declare function createFilterStatistics(): FilterStatistics;
|
|
453
|
-
/**
|
|
454
|
-
* Determine if an operation should be included based on filter criteria
|
|
455
|
-
*
|
|
456
|
-
* Filter logic:
|
|
457
|
-
* 1. If no filters specified, include all operations
|
|
458
|
-
* 2. Empty arrays are treated as "no constraint" (not as "exclude all")
|
|
459
|
-
* 3. Include filters are applied first (allowlist)
|
|
460
|
-
* 4. Exclude filters are applied second (blocklist)
|
|
461
|
-
* 5. Exclude rules always win over include rules
|
|
462
|
-
*
|
|
463
|
-
* @param operation - The OpenAPI operation object
|
|
464
|
-
* @param path - The operation path (e.g., "/users/{id}")
|
|
465
|
-
* @param method - The HTTP method (e.g., "get", "post")
|
|
466
|
-
* @param filters - Optional filter configuration
|
|
467
|
-
* @param stats - Optional statistics object to track filtering reasons
|
|
468
|
-
* @returns true if the operation should be included, false otherwise
|
|
469
|
-
*/
|
|
470
|
-
declare function shouldIncludeOperation(operation: any, path: string, method: string, filters?: OperationFilters, stats?: FilterStatistics): boolean;
|
|
471
|
-
/**
|
|
472
|
-
* Validate filter statistics and emit warnings for filters that matched nothing
|
|
473
|
-
* Helps users debug filter configurations that might be too restrictive or contain typos
|
|
474
|
-
*
|
|
475
|
-
* @param stats - Filter statistics object
|
|
476
|
-
* @param filters - The filter configuration to validate
|
|
477
|
-
*/
|
|
478
|
-
declare function validateFilters(stats: FilterStatistics, filters?: OperationFilters): void;
|
|
479
|
-
/**
|
|
480
|
-
* Format filter statistics for display in generated output
|
|
481
|
-
* Returns a formatted string suitable for inclusion in comments
|
|
482
|
-
*
|
|
483
|
-
* @param stats - Filter statistics object
|
|
484
|
-
* @returns Formatted statistics string
|
|
485
|
-
*/
|
|
486
|
-
declare function formatFilterStatistics(stats: FilterStatistics): string;
|
|
487
|
-
|
|
488
|
-
export { CircularReferenceError, CliOptionsError, type CommonSchemaOptions, type ConfigFile, ConfigValidationError, type ExecutionMode, FileOperationError, type FilterStatistics, GeneratorError, type OpenAPISchema, type OpenAPISpec, OpenApiGenerator, type OpenApiGeneratorOptions, type OperationFilters, type RequestOptions, type ResponseOptions, SchemaGenerationError, SpecValidationError, createFilterStatistics, defineConfig, formatFilterStatistics, shouldIncludeOperation, validateFilters };
|
|
153
|
+
export { CircularReferenceError, CliOptionsError, ConfigValidationError, FileOperationError, GeneratorError, OpenApiGenerator, OpenApiGeneratorOptions, SchemaGenerationError, SpecValidationError };
|
package/dist/index.js
CHANGED
|
@@ -28,11 +28,7 @@ __export(src_exports, {
|
|
|
28
28
|
OpenApiGenerator: () => OpenApiGenerator,
|
|
29
29
|
SchemaGenerationError: () => SchemaGenerationError,
|
|
30
30
|
SpecValidationError: () => SpecValidationError,
|
|
31
|
-
|
|
32
|
-
defineConfig: () => defineConfig,
|
|
33
|
-
formatFilterStatistics: () => formatFilterStatistics,
|
|
34
|
-
shouldIncludeOperation: () => shouldIncludeOperation,
|
|
35
|
-
validateFilters: () => validateFilters
|
|
31
|
+
defineConfig: () => defineConfig
|
|
36
32
|
});
|
|
37
33
|
module.exports = __toCommonJS(src_exports);
|
|
38
34
|
|
|
@@ -98,11 +94,24 @@ var ConfigurationError = class extends GeneratorError {
|
|
|
98
94
|
// src/openapi-generator.ts
|
|
99
95
|
var import_node_fs = require("fs");
|
|
100
96
|
var import_node_path = require("path");
|
|
97
|
+
var import_minimatch2 = require("minimatch");
|
|
101
98
|
var import_yaml = require("yaml");
|
|
102
99
|
|
|
103
100
|
// src/utils/name-utils.ts
|
|
101
|
+
function sanitizeIdentifier(str) {
|
|
102
|
+
return str.replace(/[^a-zA-Z0-9._\-\s]+/g, "_");
|
|
103
|
+
}
|
|
104
104
|
function toCamelCase(str, options) {
|
|
105
|
-
|
|
105
|
+
const sanitized = sanitizeIdentifier(str);
|
|
106
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
107
|
+
let name;
|
|
108
|
+
if (words.length === 0) {
|
|
109
|
+
name = str.charAt(0).toLowerCase() + str.slice(1);
|
|
110
|
+
} else if (words.length === 1) {
|
|
111
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1);
|
|
112
|
+
} else {
|
|
113
|
+
name = words[0].charAt(0).toLowerCase() + words[0].slice(1) + words.slice(1).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
114
|
+
}
|
|
106
115
|
if (options == null ? void 0 : options.prefix) {
|
|
107
116
|
const prefix = options.prefix.toLowerCase();
|
|
108
117
|
name = prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
|
@@ -115,12 +124,23 @@ function toCamelCase(str, options) {
|
|
|
115
124
|
}
|
|
116
125
|
function toPascalCase(str) {
|
|
117
126
|
const stringValue = String(str);
|
|
118
|
-
|
|
127
|
+
const isAlreadyValidCase = /^[a-zA-Z][a-zA-Z0-9]*$/.test(stringValue);
|
|
128
|
+
if (isAlreadyValidCase) {
|
|
129
|
+
return stringValue.charAt(0).toUpperCase() + stringValue.slice(1);
|
|
130
|
+
}
|
|
131
|
+
const sanitized = sanitizeIdentifier(stringValue);
|
|
132
|
+
const words = sanitized.split(/[.\-_\s]+/).filter((word) => word.length > 0);
|
|
133
|
+
let result;
|
|
134
|
+
if (words.length === 0) {
|
|
135
|
+
result = "Value";
|
|
136
|
+
} else {
|
|
137
|
+
result = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
138
|
+
}
|
|
119
139
|
if (/^\d/.test(result)) {
|
|
120
140
|
result = `N${result}`;
|
|
121
141
|
}
|
|
122
142
|
if (!result || /^_+$/.test(result)) {
|
|
123
|
-
|
|
143
|
+
return "Value";
|
|
124
144
|
}
|
|
125
145
|
return result;
|
|
126
146
|
}
|
|
@@ -132,9 +152,10 @@ function resolveRef(ref) {
|
|
|
132
152
|
// src/generators/enum-generator.ts
|
|
133
153
|
function generateEnum(name, values, options) {
|
|
134
154
|
const schemaName = `${toCamelCase(name, options)}Schema`;
|
|
155
|
+
const typeName = toPascalCase(name);
|
|
135
156
|
const enumValues = values.map((v) => `"${v}"`).join(", ");
|
|
136
157
|
const schemaCode = `export const ${schemaName} = z.enum([${enumValues}]);`;
|
|
137
|
-
const typeCode = `export type ${
|
|
158
|
+
const typeCode = `export type ${typeName} = z.infer<typeof ${schemaName}>;`;
|
|
138
159
|
return { schemaCode, typeCode };
|
|
139
160
|
}
|
|
140
161
|
|
|
@@ -234,6 +255,9 @@ var LRUCache = class {
|
|
|
234
255
|
this.cache = /* @__PURE__ */ new Map();
|
|
235
256
|
this.maxSize = maxSize;
|
|
236
257
|
}
|
|
258
|
+
get capacity() {
|
|
259
|
+
return this.maxSize;
|
|
260
|
+
}
|
|
237
261
|
get(key) {
|
|
238
262
|
if (!this.cache.has(key)) return void 0;
|
|
239
263
|
const value = this.cache.get(key);
|
|
@@ -264,6 +288,76 @@ var LRUCache = class {
|
|
|
264
288
|
}
|
|
265
289
|
};
|
|
266
290
|
|
|
291
|
+
// src/utils/pattern-utils.ts
|
|
292
|
+
function isRegexPattern(pattern) {
|
|
293
|
+
if (pattern.startsWith("^") || pattern.endsWith("$")) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
if (/\\[dDwWsS]/.test(pattern)) {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
if (/\.\*|\.\+/.test(pattern)) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (/[[\]()]/.test(pattern)) {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
if (/[^/][+?*]\{/.test(pattern)) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
function patternToRegex(pattern) {
|
|
311
|
+
if (pattern instanceof RegExp) {
|
|
312
|
+
return pattern;
|
|
313
|
+
}
|
|
314
|
+
if (isRegexPattern(pattern)) {
|
|
315
|
+
try {
|
|
316
|
+
return new RegExp(pattern);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.warn(`\u26A0\uFE0F Invalid regex pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
function stripPrefix(input, pattern, ensureLeadingChar) {
|
|
325
|
+
if (!pattern) {
|
|
326
|
+
return input;
|
|
327
|
+
}
|
|
328
|
+
const regex = patternToRegex(pattern);
|
|
329
|
+
if (regex) {
|
|
330
|
+
const match = input.match(regex);
|
|
331
|
+
if (match && match.index === 0) {
|
|
332
|
+
const stripped = input.substring(match[0].length);
|
|
333
|
+
if (ensureLeadingChar) {
|
|
334
|
+
if (stripped === "") {
|
|
335
|
+
return ensureLeadingChar;
|
|
336
|
+
}
|
|
337
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
338
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return stripped;
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
const stringPattern = pattern;
|
|
345
|
+
if (input.startsWith(stringPattern)) {
|
|
346
|
+
const stripped = input.substring(stringPattern.length);
|
|
347
|
+
if (ensureLeadingChar) {
|
|
348
|
+
if (stripped === "") {
|
|
349
|
+
return ensureLeadingChar;
|
|
350
|
+
}
|
|
351
|
+
if (!stripped.startsWith(ensureLeadingChar)) {
|
|
352
|
+
return `${ensureLeadingChar}${stripped}`;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return stripped;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return input;
|
|
359
|
+
}
|
|
360
|
+
|
|
267
361
|
// src/validators/array-validator.ts
|
|
268
362
|
function generateArrayValidation(schema, context) {
|
|
269
363
|
var _a;
|
|
@@ -783,6 +877,11 @@ ${properties.join(",\n")}
|
|
|
783
877
|
|
|
784
878
|
// src/validators/string-validator.ts
|
|
785
879
|
var PATTERN_CACHE = new LRUCache(1e3);
|
|
880
|
+
function configurePatternCache(size) {
|
|
881
|
+
if (size > 0 && size !== PATTERN_CACHE.capacity) {
|
|
882
|
+
PATTERN_CACHE = new LRUCache(size);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
786
885
|
var FORMAT_MAP = {
|
|
787
886
|
uuid: "z.uuid()",
|
|
788
887
|
email: "z.email()",
|
|
@@ -1115,8 +1214,9 @@ var _PropertyGenerator = class _PropertyGenerator {
|
|
|
1115
1214
|
}
|
|
1116
1215
|
(_a = this.context.schemaDependencies.get(currentSchema)) == null ? void 0 : _a.add(refName);
|
|
1117
1216
|
}
|
|
1118
|
-
const
|
|
1119
|
-
|
|
1217
|
+
const strippedRefName = stripPrefix(resolvedRefName, this.context.stripSchemaPrefix);
|
|
1218
|
+
const schemaName = `${toCamelCase(strippedRefName, this.context.namingOptions)}Schema`;
|
|
1219
|
+
if (currentSchema && (refName === currentSchema || this.isCircularThroughAlias(currentSchema, refName))) {
|
|
1120
1220
|
const lazySchema = `z.lazy((): z.ZodTypeAny => ${schemaName})`;
|
|
1121
1221
|
return wrapNullable(lazySchema, nullable);
|
|
1122
1222
|
}
|
|
@@ -1403,7 +1503,7 @@ var OpenApiGenerator = class {
|
|
|
1403
1503
|
this.schemaUsageMap = /* @__PURE__ */ new Map();
|
|
1404
1504
|
this.needsZodImport = true;
|
|
1405
1505
|
this.filterStats = createFilterStatistics();
|
|
1406
|
-
var _a, _b, _c;
|
|
1506
|
+
var _a, _b, _c, _d, _e;
|
|
1407
1507
|
if (!options.input) {
|
|
1408
1508
|
throw new ConfigurationError("Input path is required", { providedOptions: options });
|
|
1409
1509
|
}
|
|
@@ -1416,11 +1516,18 @@ var OpenApiGenerator = class {
|
|
|
1416
1516
|
schemaType: options.schemaType || "all",
|
|
1417
1517
|
prefix: options.prefix,
|
|
1418
1518
|
suffix: options.suffix,
|
|
1519
|
+
stripSchemaPrefix: options.stripSchemaPrefix,
|
|
1419
1520
|
showStats: (_c = options.showStats) != null ? _c : true,
|
|
1420
1521
|
request: options.request,
|
|
1421
1522
|
response: options.response,
|
|
1422
|
-
operationFilters: options.operationFilters
|
|
1523
|
+
operationFilters: options.operationFilters,
|
|
1524
|
+
ignoreHeaders: options.ignoreHeaders,
|
|
1525
|
+
cacheSize: (_d = options.cacheSize) != null ? _d : 1e3,
|
|
1526
|
+
batchSize: (_e = options.batchSize) != null ? _e : 10
|
|
1423
1527
|
};
|
|
1528
|
+
if (this.options.cacheSize) {
|
|
1529
|
+
configurePatternCache(this.options.cacheSize);
|
|
1530
|
+
}
|
|
1424
1531
|
try {
|
|
1425
1532
|
const fs = require("fs");
|
|
1426
1533
|
if (!fs.existsSync(this.options.input)) {
|
|
@@ -1486,7 +1593,8 @@ var OpenApiGenerator = class {
|
|
|
1486
1593
|
namingOptions: {
|
|
1487
1594
|
prefix: this.options.prefix,
|
|
1488
1595
|
suffix: this.options.suffix
|
|
1489
|
-
}
|
|
1596
|
+
},
|
|
1597
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
1490
1598
|
});
|
|
1491
1599
|
}
|
|
1492
1600
|
/**
|
|
@@ -1520,9 +1628,11 @@ var OpenApiGenerator = class {
|
|
|
1520
1628
|
const typeCode = this.types.get(name);
|
|
1521
1629
|
if (schemaCode) {
|
|
1522
1630
|
output.push(schemaCode);
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1631
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1632
|
+
const typeName = toPascalCase(strippedName);
|
|
1633
|
+
if (!schemaCode.includes(`export type ${typeName}`)) {
|
|
1634
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
1635
|
+
output.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
|
|
1526
1636
|
}
|
|
1527
1637
|
output.push("");
|
|
1528
1638
|
} else if (typeCode) {
|
|
@@ -1556,6 +1666,7 @@ var OpenApiGenerator = class {
|
|
|
1556
1666
|
const normalizedOutput = (0, import_node_path.normalize)(this.options.output);
|
|
1557
1667
|
this.ensureDirectoryExists(normalizedOutput);
|
|
1558
1668
|
(0, import_node_fs.writeFileSync)(normalizedOutput, output);
|
|
1669
|
+
console.log(` \u2713 Generated ${normalizedOutput}`);
|
|
1559
1670
|
}
|
|
1560
1671
|
/**
|
|
1561
1672
|
* Resolve options for a specific context (request or response)
|
|
@@ -1837,7 +1948,8 @@ var OpenApiGenerator = class {
|
|
|
1837
1948
|
const resolvedOptions = context === "response" ? this.responseOptions : this.requestOptions;
|
|
1838
1949
|
if (schema.enum) {
|
|
1839
1950
|
const jsdoc2 = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1840
|
-
const
|
|
1951
|
+
const strippedName2 = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1952
|
+
const { schemaCode, typeCode } = generateEnum(strippedName2, schema.enum, {
|
|
1841
1953
|
prefix: this.options.prefix,
|
|
1842
1954
|
suffix: this.options.suffix
|
|
1843
1955
|
});
|
|
@@ -1846,7 +1958,8 @@ ${typeCode}`;
|
|
|
1846
1958
|
this.schemas.set(name, enumSchemaCode);
|
|
1847
1959
|
return;
|
|
1848
1960
|
}
|
|
1849
|
-
const
|
|
1961
|
+
const strippedName = stripPrefix(name, this.options.stripSchemaPrefix);
|
|
1962
|
+
const schemaName = `${toCamelCase(strippedName, { prefix: this.options.prefix, suffix: this.options.suffix })}Schema`;
|
|
1850
1963
|
const jsdoc = generateJSDoc(schema, name, { includeDescriptions: resolvedOptions.includeDescriptions });
|
|
1851
1964
|
if (schema.allOf && schema.allOf.length === 1 && schema.allOf[0].$ref) {
|
|
1852
1965
|
const refName = resolveRef(schema.allOf[0].$ref);
|
|
@@ -1862,7 +1975,8 @@ ${typeCode}`;
|
|
|
1862
1975
|
namingOptions: {
|
|
1863
1976
|
prefix: this.options.prefix,
|
|
1864
1977
|
suffix: this.options.suffix
|
|
1865
|
-
}
|
|
1978
|
+
},
|
|
1979
|
+
stripSchemaPrefix: this.options.stripSchemaPrefix
|
|
1866
1980
|
});
|
|
1867
1981
|
const isAlias = !!(schema.$ref && !schema.properties && !schema.allOf && !schema.oneOf && !schema.anyOf);
|
|
1868
1982
|
const zodSchema = this.propertyGenerator.generatePropertySchema(schema, name, isAlias);
|
|
@@ -1966,6 +2080,24 @@ ${propsCode}
|
|
|
1966
2080
|
}
|
|
1967
2081
|
}
|
|
1968
2082
|
}
|
|
2083
|
+
/**
|
|
2084
|
+
* Check if a header should be ignored based on filter patterns
|
|
2085
|
+
* @internal
|
|
2086
|
+
*/
|
|
2087
|
+
shouldIgnoreHeader(headerName) {
|
|
2088
|
+
const ignorePatterns = this.options.ignoreHeaders;
|
|
2089
|
+
if (!ignorePatterns || ignorePatterns.length === 0) {
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
if (ignorePatterns.includes("*")) {
|
|
2093
|
+
return true;
|
|
2094
|
+
}
|
|
2095
|
+
const headerLower = headerName.toLowerCase();
|
|
2096
|
+
return ignorePatterns.some((pattern) => {
|
|
2097
|
+
const patternLower = pattern.toLowerCase();
|
|
2098
|
+
return (0, import_minimatch2.minimatch)(headerLower, patternLower);
|
|
2099
|
+
});
|
|
2100
|
+
}
|
|
1969
2101
|
/**
|
|
1970
2102
|
* Generate header parameter schemas for each operation
|
|
1971
2103
|
* Header parameters are always string type (HTTP header semantics)
|
|
@@ -1988,7 +2120,7 @@ ${propsCode}
|
|
|
1988
2120
|
continue;
|
|
1989
2121
|
}
|
|
1990
2122
|
const headerParams = operation.parameters.filter(
|
|
1991
|
-
(param) => param && typeof param === "object" && param.in === "header"
|
|
2123
|
+
(param) => param && typeof param === "object" && param.in === "header" && !this.shouldIgnoreHeader(param.name)
|
|
1992
2124
|
);
|
|
1993
2125
|
if (headerParams.length === 0) {
|
|
1994
2126
|
continue;
|
|
@@ -2046,7 +2178,8 @@ ${propsCode}
|
|
|
2046
2178
|
generateQueryParamType(schema, param) {
|
|
2047
2179
|
if (schema.$ref) {
|
|
2048
2180
|
const refName = resolveRef(schema.$ref);
|
|
2049
|
-
const
|
|
2181
|
+
const strippedRefName = stripPrefix(refName, this.options.stripSchemaPrefix);
|
|
2182
|
+
const schemaName = toCamelCase(strippedRefName, { prefix: this.options.prefix, suffix: this.options.suffix });
|
|
2050
2183
|
return `${schemaName}Schema`;
|
|
2051
2184
|
}
|
|
2052
2185
|
if (schema.enum) {
|
|
@@ -2199,10 +2332,6 @@ function defineConfig(config) {
|
|
|
2199
2332
|
OpenApiGenerator,
|
|
2200
2333
|
SchemaGenerationError,
|
|
2201
2334
|
SpecValidationError,
|
|
2202
|
-
|
|
2203
|
-
defineConfig,
|
|
2204
|
-
formatFilterStatistics,
|
|
2205
|
-
shouldIncludeOperation,
|
|
2206
|
-
validateFilters
|
|
2335
|
+
defineConfig
|
|
2207
2336
|
});
|
|
2208
2337
|
//# sourceMappingURL=index.js.map
|