@@ -6,16 +6,17 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
66 let declarations = ''
77 let exports = ''
88 const processedDeclarations = new Set ( )
9+ let pendingComment = ''
910
1011 // Function to extract the body of a function
11- const extractFunctionBody = ( funcName : string ) => {
12+ function extractFunctionBody ( funcName : string ) {
1213 const funcRegex = new RegExp ( `function\\s+${ funcName } \\s*\\([^)]*\\)\\s*{([\\s\\S]*?)}` , 'g' )
1314 const match = funcRegex . exec ( fileContent )
1415 return match ? match [ 1 ] : ''
1516 }
1617
1718 // Function to check if an identifier is used in a given content
18- const isIdentifierUsed = ( identifier : string , content : string ) => {
19+ function isIdentifierUsed ( identifier : string , content : string ) {
1920 const regex = new RegExp ( `\\b${ identifier } \\b` , 'g' )
2021 return regex . test ( content )
2122 }
@@ -48,7 +49,7 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
4849 }
4950
5051 // Function to parse object literal
51- const parseObjectLiteral = ( str : string ) => {
52+ function parseObjectLiteral ( str : string ) {
5253 const obj : Record < string , string > = { }
5354 str . split ( ',' ) . forEach ( ( pair ) => {
5455 const trimmedPair = pair . trim ( )
@@ -68,65 +69,90 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
6869 const declarationRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( e x p o r t \s + ( c o n s t | i n t e r f a c e | t y p e | f u n c t i o n | a s y n c f u n c t i o n ) \s + ( \w + ) [ \s \S ] * ?(? = e x p o r t \s | $ ) ) / g
6970 const declarationMatches = Array . from ( fileContent . matchAll ( declarationRegex ) )
7071 for ( const [ , comment , declaration , declType , name ] of declarationMatches ) {
71- if ( ! processedDeclarations . has ( name ) ) {
72- if ( comment )
73- declarations += `${ comment . trim ( ) } \n`
74-
75- if ( declType === 'const' ) {
76- const constMatch = declaration . match ( / e x p o r t \s + c o n s t \s + ( \w + ) ( \s * : \s * ( [ ^ = ] + ) ) ? \s * = \s * ( \{ [ ^ } ] + \} ) / )
77- if ( constMatch ) {
78- const [ , constName , , , constValue ] = constMatch
79- // Parse the object literal
80- const parsedValue = parseObjectLiteral ( constValue . slice ( 1 , - 1 ) )
81- const formattedValue = Object . entries ( parsedValue )
82- . map ( ( [ key , value ] ) => ` ${ key } : ${ value . includes ( '/' ) || value . includes ( '\'' ) ? value : `'${ value } '` } ` )
83- . join ( '\n' )
84-
85- declarations += `export declare const ${ constName } : {\n${ formattedValue } \n}\n\n`
72+ if ( comment ) {
73+ pendingComment = comment . trim ( )
74+ }
75+
76+ if ( declType === 'const' ) {
77+ const constMatch = declaration . match ( / e x p o r t \s + c o n s t \s + ( \w + ) ( \s * : \s * ( [ ^ = ] + ) ) ? \s * = \s * ( \{ [ ^ } ] + \} ) / )
78+ if ( constMatch ) {
79+ const [ , constName , , , constValue ] = constMatch
80+ // Parse the object literal
81+ const parsedValue = parseObjectLiteral ( constValue . slice ( 1 , - 1 ) )
82+ const formattedValue = Object . entries ( parsedValue )
83+ . map ( ( [ key , value ] ) => ` ${ key } : ${ value . includes ( '/' ) || value . includes ( '\'' ) ? value : `'${ value } '` } ` )
84+ . join ( '\n' )
85+
86+ if ( pendingComment ) {
87+ declarations += `${ pendingComment } \n`
88+ pendingComment = ''
89+ }
90+ declarations += `export declare const ${ constName } : {\n${ formattedValue } \n}\n\n`
91+ }
92+ else {
93+ // Handle constants initialized with function calls
94+ const constFuncMatch = declaration . match ( / e x p o r t \s + c o n s t \s + ( \w + ) \s * : \s * ( [ ^ = ] + ) \s * = \s * a w a i t \s + \w + \( [ ^ ) ] * \) / )
95+ if ( constFuncMatch ) {
96+ const [ , constName , constType ] = constFuncMatch
97+ if ( pendingComment ) {
98+ declarations += `${ pendingComment } \n`
99+ pendingComment = ''
100+ }
101+ declarations += `export declare const ${ constName } : ${ constType . trim ( ) } \n\n`
86102 }
87103 else {
88104 // Fallback to the original declaration if parsing fails
105+ if ( pendingComment ) {
106+ declarations += `${ pendingComment } \n`
107+ pendingComment = ''
108+ }
89109 declarations += `export declare ${ declaration . replace ( / e x p o r t \s + / , '' ) . trim ( ) } \n\n`
90110 }
91111 }
92- else if ( declType === 'interface' || declType === 'type' ) {
93- declarations += `${ declaration . trim ( ) } \n\n`
112+ }
113+ else if ( declType === 'interface' || declType === 'type' ) {
114+ if ( pendingComment ) {
115+ declarations += `${ pendingComment } \n`
116+ pendingComment = ''
117+ }
118+ declarations += `${ declaration . trim ( ) } \n\n`
119+ }
120+ else if ( declType === 'function' || declType === 'async function' ) {
121+ if ( pendingComment ) {
122+ declarations += `${ pendingComment } \n`
123+ pendingComment = ''
94124 }
95- else if ( declType === 'function' || declType === 'async function' ) {
96- const funcSignatureRegex = / e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n \s + ( \w + ) \s * \( ( [ ^ ) ] * ) \) \s * : \s * ( [ ^ { ] + ) /
97- const funcSignatureMatch = declaration . match ( funcSignatureRegex )
125+ const funcSignatureRegex = / e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n \s + ( \w + ) \s * \( ( [ ^ ) ] * ) \) \s * : \s * ( [ ^ { ] + ) /
126+ const funcSignatureMatch = declaration . match ( funcSignatureRegex )
98127
99- if ( funcSignatureMatch ) {
100- const [ , isAsync , funcName , params , returnType ] = funcSignatureMatch
101- declarations += `export declare ${ isAsync || '' } function ${ funcName } (${ params . trim ( ) } ): ${ returnType . trim ( ) } \n\n`
128+ if ( funcSignatureMatch ) {
129+ const [ , isAsync , funcName , params , returnType ] = funcSignatureMatch
130+ declarations += `export declare ${ isAsync || '' } function ${ funcName } (${ params . trim ( ) } ): ${ returnType . trim ( ) } \n\n`
131+ }
132+ else {
133+ // If we can't match the full signature, let's try to extract what we can
134+ const funcNameParamsRegex = / e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n \s + ( \w + ) \s * \( ( [ ^ ) ] * ) \) /
135+ const funcNameParamsMatch = declaration . match ( funcNameParamsRegex )
136+
137+ if ( funcNameParamsMatch ) {
138+ const [ , isAsync , funcName , params ] = funcNameParamsMatch
139+ // Try to find the return type
140+ const returnTypeRegex = / \) \s * : \s * ( [ ^ { ] + ) /
141+ const returnTypeMatch = declaration . match ( returnTypeRegex )
142+ const returnType = returnTypeMatch ? returnTypeMatch [ 1 ] . trim ( ) : 'any'
143+
144+ declarations += `export declare ${ isAsync || '' } function ${ funcName } (${ params . trim ( ) } ): ${ returnType } \n\n`
102145 }
103146 else {
104- // If we can't match the full signature, let's try to extract what we can
105- const funcNameParamsRegex = / e x p o r t \s + ( a s y n c \s + ) ? f u n c t i o n \s + ( \w + ) \s * \( ( [ ^ ) ] * ) \) /
106- const funcNameParamsMatch = declaration . match ( funcNameParamsRegex )
107-
108- if ( funcNameParamsMatch ) {
109- const [ , isAsync , funcName , params ] = funcNameParamsMatch
110- // Try to find the return type
111- const returnTypeRegex = / \) \s * : \s * ( [ ^ { ] + ) /
112- const returnTypeMatch = declaration . match ( returnTypeRegex )
113- const returnType = returnTypeMatch ? returnTypeMatch [ 1 ] . trim ( ) : 'any'
114-
115- declarations += `export declare ${ isAsync || '' } function ${ funcName } (${ params . trim ( ) } ): ${ returnType } \n\n`
116- }
117- else {
118- // If all else fails, just add 'declare' to the original export
119- const simplifiedDeclaration = declaration . replace ( / e x p o r t \s + / , '' ) . split ( '{' ) [ 0 ] . trim ( )
120- declarations += `export declare ${ simplifiedDeclaration } \n\n`
121- }
147+ // If all else fails, just add 'declare' to the original export
148+ const simplifiedDeclaration = declaration . replace ( / e x p o r t \s + / , '' ) . split ( '{' ) [ 0 ] . trim ( )
149+ declarations += `export declare ${ simplifiedDeclaration } \n\n`
122150 }
123151 }
124- else {
125- declarations += `${ declaration . trim ( ) } \n\n`
126- }
127-
128- processedDeclarations . add ( name )
129152 }
153+
154+ // Clear any remaining pending comment
155+ pendingComment = ''
130156 }
131157
132158 // Handle re-exports and standalone exports
@@ -157,6 +183,6 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
157183 exports += `\n\nexport default ${ defaultExportMatch [ 1 ] } `
158184 }
159185
160- const output = [ imports , declarations , exports ] . filter ( Boolean ) . join ( '\n' ) . trim ( )
186+ const output = [ imports , declarations . trim ( ) , exports . trim ( ) ] . filter ( Boolean ) . join ( '\n' ) . trim ( )
161187 return formatDeclarations ( output )
162188}
0 commit comments