@@ -19,18 +19,26 @@ export function typesPlugin(): Plugin {
1919
2020 const ast = stringToAST ( code ) as ts . Node [ ] ;
2121
22+ // Collect names of all enum declarations to avoid generating duplicate type aliases
23+ const existingEnums = new Set (
24+ ast
25+ . filter ( node => ts . isEnumDeclaration ( node ) )
26+ . map ( node => ( node as ts . EnumDeclaration ) . name . text )
27+ ) ;
28+
2229 const componentsDeclaration = ast . find ( isComponentsInterfaceDeclaration ) ;
2330
2431 assert ( componentsDeclaration , "Missing components declaration" ) ;
2532 const schema = componentsDeclaration . members . find ( isComponentsSchema ) ;
2633 assert ( schema , "Missing components declaration" ) ;
2734 assert ( schema . type && ts . isTypeLiteralNode ( schema . type ) , "Invalid schema type" ) ;
28-
35+
2936 const typeNodes = schema . type . members
3037 . map ( member => member . name )
3138 . filter ( name => name !== undefined )
3239 . filter ( name => ts . isStringLiteral ( name ) || ts . isIdentifier ( name ) )
3340 . map ( name => name . text )
41+ . filter ( name => ! existingEnums . has ( toSafeName ( name ) ) )
3442 . map ( name => {
3543 if ( RESERVED_IDENTIFIERS . has ( name ) ) {
3644 throw new Error ( `Invalid schema name: ${ name } ` ) ;
@@ -68,33 +76,51 @@ export function isComponentsSchema(node: ts.Node): node is ts.PropertySignature
6876 * OpenAPI field names must match `^[a-zA-Z0-9\.\-_]+$` which allows names that
6977 * are not valid JavaScript/TypeScript identifiers. This function converts an
7078 * unsafe name into a safe name that can be used as a JavaScript/TypeScript
71- * identifier.
79+ * identifier using PascalCase transformation to match openapi-typescript's enum naming .
7280 */
7381export function toSafeName ( unsafeName : string ) : string {
7482 let safeName = "" ;
83+ let capitalizeNext = true ;
84+
7585 for ( const char of unsafeName ) {
7686 const charCode = char . charCodeAt ( 0 ) ;
7787
88+ // Special characters that should trigger capitalization of next char
89+ if ( char === "-" || char === "." || char === " " ) {
90+ capitalizeNext = true ;
91+ continue ;
92+ }
93+
7894 // A-Z
7995 if ( charCode >= 65 && charCode <= 90 ) {
8096 safeName += char ;
97+ capitalizeNext = false ;
98+ continue ;
8199 }
82100
83101 // a-z
84102 if ( charCode >= 97 && charCode <= 122 ) {
85- safeName += char ;
103+ safeName += capitalizeNext ? char . toUpperCase ( ) : char ;
104+ capitalizeNext = false ;
105+ continue ;
86106 }
87107
88- if ( char === "_" || char === "$" ) {
108+ // 0-9
109+ if ( safeName . length > 0 && charCode >= 48 && charCode <= 57 ) {
89110 safeName += char ;
111+ capitalizeNext = false ;
112+ continue ;
90113 }
91114
92- // 0-9
93- if ( safeName . length > 0 && charCode >= 48 && charCode <= 57 ) {
115+ // _ and $ are valid identifier characters
116+ if ( char === "_" || char === "$" ) {
94117 safeName += char ;
118+ capitalizeNext = false ;
119+ continue ;
95120 }
96121
97- continue ;
122+ // Any other character triggers capitalization of next char but is not included
123+ capitalizeNext = true ;
98124 }
99125
100126 return safeName ;
0 commit comments