11import type { DevupApiTypeGeneratorOptions } from '@devup-api/core'
22import type { OpenAPIV3_1 } from 'openapi-types'
33import { convertCase } from './convert-case'
4+ import {
5+ CONTENT_TYPE_PRIORITY ,
6+ extractSchemaNameFromRef ,
7+ isErrorStatusCode ,
8+ normalizeServerName ,
9+ resolveRef ,
10+ } from './openapi-utils'
411import { wrapInterfaceKeyGuard } from './wrap-interface-key-guard'
512
6- // =============================================================================
7- // Helper Functions
8- // =============================================================================
9-
10- /**
11- * Normalize server name by removing ./ prefix
12- */
13- function normalizeServerName ( serverName : string ) : string {
14- return serverName . replace ( / ^ \. \/ / , '' )
15- }
16-
17- /**
18- * Resolve $ref reference in OpenAPI schema
19- */
20- function resolveSchemaRef <
21- T extends OpenAPIV3_1 . SchemaObject | OpenAPIV3_1 . ParameterObject ,
22- > ( ref : string , document : OpenAPIV3_1 . Document ) : T | null {
23- if ( ! ref . startsWith ( '#/' ) ) {
24- return null
25- }
26-
27- const parts = ref . slice ( 2 ) . split ( '/' )
28- let current : unknown = document
29-
30- for ( const part of parts ) {
31- if ( current && typeof current === 'object' && part in current ) {
32- current = ( current as Record < string , unknown > ) [ part ]
33- } else {
34- return null
35- }
36- }
37-
38- if ( current && typeof current === 'object' && ! ( '$ref' in current ) ) {
39- return current as T
40- }
41-
42- return null
43- }
44-
45- /**
46- * Extract schema name from $ref
47- */
48- function extractSchemaNameFromRef ( ref : string ) : string | null {
49- if ( ref . startsWith ( '#/components/schemas/' ) ) {
50- return ref . replace ( '#/components/schemas/' , '' )
51- }
52- return null
53- }
54-
55- /**
56- * Check if status code is an error response
57- */
58- function isErrorStatusCode ( statusCode : string ) : boolean {
59- if ( statusCode === 'default' ) return true
60- const code = parseInt ( statusCode , 10 )
61- return code >= 400 && code < 600
62- }
63-
6413// =============================================================================
6514// OpenAPI to Zod Conversion
6615// =============================================================================
@@ -83,10 +32,7 @@ function schemaToZod(
8332 // Return lazy reference for circular dependencies
8433 return `z.lazy(() => ${ schemaRefs . get ( schemaName ) } )`
8534 }
86- const resolved = resolveSchemaRef < OpenAPIV3_1 . SchemaObject > (
87- schema . $ref ,
88- document ,
89- )
35+ const resolved = resolveRef < OpenAPIV3_1 . SchemaObject > ( schema . $ref , document )
9036 if ( resolved ) {
9137 return schemaToZod ( resolved , document , schemaRefs , options )
9238 }
@@ -262,7 +208,7 @@ function schemaToZod(
262208 // Check for default value
263209 let hasDefault = false
264210 if ( '$ref' in value ) {
265- const resolved = resolveSchemaRef < OpenAPIV3_1 . SchemaObject > (
211+ const resolved = resolveRef < OpenAPIV3_1 . SchemaObject > (
266212 value . $ref ,
267213 document ,
268214 )
@@ -328,10 +274,7 @@ function schemaToZodType(
328274 // Return a lazy type reference
329275 return `z.ZodLazy<z.ZodTypeAny>`
330276 }
331- const resolved = resolveSchemaRef < OpenAPIV3_1 . SchemaObject > (
332- schema . $ref ,
333- document ,
334- )
277+ const resolved = resolveRef < OpenAPIV3_1 . SchemaObject > ( schema . $ref , document )
335278 if ( resolved ) {
336279 return schemaToZodType ( resolved , document , options )
337280 }
@@ -442,7 +385,7 @@ function schemaToZodType(
442385 // Check for default value
443386 let hasDefault = false
444387 if ( '$ref' in value ) {
445- const resolved = resolveSchemaRef < OpenAPIV3_1 . SchemaObject > (
388+ const resolved = resolveRef < OpenAPIV3_1 . SchemaObject > (
446389 value . $ref ,
447390 document ,
448391 )
@@ -572,11 +515,7 @@ function collectSchemaUsage(
572515 return extractSchemaNameFromRef ( requestBody . $ref )
573516 }
574517 const content = requestBody . content
575- for ( const ct of [
576- 'application/json' ,
577- 'application/x-www-form-urlencoded' ,
578- 'multipart/form-data' ,
579- ] ) {
518+ for ( const ct of CONTENT_TYPE_PRIORITY ) {
580519 const bodyContent = content ?. [ ct ]
581520 if ( bodyContent ?. schema && '$ref' in bodyContent . schema ) {
582521 return extractSchemaNameFromRef ( bodyContent . schema . $ref )
@@ -618,11 +557,7 @@ function collectSchemaUsage(
618557 }
619558 } else {
620559 const content = operation . requestBody . content
621- for ( const ct of [
622- 'application/json' ,
623- 'application/x-www-form-urlencoded' ,
624- 'multipart/form-data' ,
625- ] ) {
560+ for ( const ct of CONTENT_TYPE_PRIORITY ) {
626561 const bodyContent = content ?. [ ct ]
627562 if ( bodyContent ?. schema ) {
628563 collectSchemaNames ( bodyContent . schema , requestSchemaNames )
0 commit comments