@@ -6,53 +6,58 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
6
6
let usedTypes = new Set < string > ( )
7
7
let importMap = new Map < string , Set < string > > ( )
8
8
9
- // Capture all imported types
10
- const importRegex = / i m p o r t \s + t y p e \s * \{ ( [ ^ } ] + ) \} \s * f r o m \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
9
+ // Capture all imports
10
+ const importRegex = / i m p o r t \s + (?: ( t y p e ) \s + ) ? (?: ( \{ [ ^ } ] + \} ) | ( \w + ) ) (?: \s * , \s * (?: ( \{ [ ^ } ] + \} ) | ( \w + ) ) ) ? \s + f r o m \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
11
11
let importMatch
12
12
while ( ( importMatch = importRegex . exec ( fileContent ) ) !== null ) {
13
- const types = importMatch [ 1 ] . split ( ',' ) . map ( t => t . trim ( ) )
14
- const from = importMatch [ 2 ]
15
- if ( ! importMap . has ( from ) ) importMap . set ( from , new Set ( ) )
16
- types . forEach ( type => importMap . get ( from ) ! . add ( type ) )
17
- }
18
-
19
- // Function to add used types
20
- const addUsedType = ( type : string ) => {
21
- const cleanType = type . replace ( / [ \[ \] ? ] / g, '' ) . trim ( ) // Remove brackets and question marks
22
- if ( / ^ [ A - Z ] / . test ( cleanType ) ) { // Only add if it starts with a capital letter (likely a type)
23
- usedTypes . add ( cleanType )
13
+ const [ , isTypeImport , namedImports1 , defaultImport1 , namedImports2 , defaultImport2 , from ] = importMatch
14
+ const processImports = ( imports : string | undefined , isType : boolean ) => {
15
+ if ( imports ) {
16
+ const types = imports . replace ( / [ { } ] / g, '' ) . split ( ',' ) . map ( t => {
17
+ const [ name , alias ] = t . split ( ' as ' ) . map ( s => s . trim ( ) )
18
+ return { name : name . replace ( / ^ t y p e \s + / , '' ) , alias : alias || name . replace ( / ^ t y p e \s + / , '' ) }
19
+ } )
20
+ if ( ! importMap . has ( from ) ) importMap . set ( from , new Set ( ) )
21
+ types . forEach ( ( { name, alias } ) => {
22
+ importMap . get ( from ) ! . add ( name )
23
+ } )
24
+ }
24
25
}
26
+
27
+ processImports ( namedImports1 , ! ! isTypeImport )
28
+ processImports ( namedImports2 , ! ! isTypeImport )
29
+ if ( defaultImport1 ) importMap . get ( from ) ! . add ( defaultImport1 )
30
+ if ( defaultImport2 ) importMap . get ( from ) ! . add ( defaultImport2 )
25
31
}
26
32
27
33
// Handle exported functions with comments
28
- const exportedFunctionRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( 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 * ( [ ^ { ] + ) ) / g
34
+ const exportedFunctionRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( 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 * ( [ ^ { ] + ) ) / g
29
35
let match
30
36
while ( ( match = exportedFunctionRegex . exec ( fileContent ) ) !== null ) {
31
- const [ , comment , , isAsync , name , params , returnType ] = match
37
+ const [ , comment , exportKeyword , isAsync , , name , params , returnType ] = match
32
38
const cleanParams = params . replace ( / \s * = \s * [ ^ , ) ] + / g, '' )
33
- const declaration = `${ comment || '' } export declare ${ isAsync || '' } function ${ name } (${ cleanParams } ): ${ returnType . trim ( ) } `
34
- declarations += `${ declaration } \n\n`
39
+ let cleanReturnType = returnType . trim ( )
35
40
36
- // Check for types used in parameters
37
- const paramTypes = params . match ( / : \s * ( [ ^ , ) = ] + ) / g ) || [ ]
38
- paramTypes . forEach ( type => addUsedType ( type . slice ( 1 ) . trim ( ) ) )
41
+ if ( isAsync && ! cleanReturnType . startsWith ( 'Promise' ) ) {
42
+ cleanReturnType = `Promise< ${ cleanReturnType } >`
43
+ }
39
44
40
- // Check for return type
41
- addUsedType ( returnType . trim ( ) )
45
+ const declaration = `${ comment || '' } ${ exportKeyword } declare function ${ name } (${ cleanParams } ): ${ cleanReturnType } `
46
+ declarations += `${ declaration } \n\n`
47
+
48
+ // Add parameter types and return type to usedTypes
49
+ params . match ( / : \s * ( \w + ) / g) ?. forEach ( type => usedTypes . add ( type . slice ( 1 ) . trim ( ) ) )
50
+ cleanReturnType . match ( / \b ( [ A - Z ] \w + ) \b / g) ?. forEach ( type => usedTypes . add ( type ) )
42
51
}
43
52
44
53
// Handle other exports (interface, type, const)
45
54
const otherExportRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( e x p o r t \s + ( (?: i n t e r f a c e | t y p e | c o n s t ) \s + \w + (?: \s * = \s * [ ^ ; ] + | \s * \{ [ ^ } ] * \} ) ) ) ; ? / gs
46
55
while ( ( match = otherExportRegex . exec ( fileContent ) ) !== null ) {
47
- const [ , comment , exportStatement , declaration ] = match
56
+ const [ , comment , exportStatement ] = match
48
57
declarations += `${ comment || '' } ${ exportStatement } \n\n`
49
58
50
- // Check for types used in the declaration
51
- const typeRegex = / \b ( [ A - Z ] \w + ) \b / g
52
- let typeMatch
53
- while ( ( typeMatch = typeRegex . exec ( declaration ) ) !== null ) {
54
- addUsedType ( typeMatch [ 1 ] )
55
- }
59
+ // Add types used in the export to usedTypes
60
+ exportStatement . match ( / \b ( [ A - Z ] \w + ) \b / g) ?. forEach ( type => usedTypes . add ( type ) )
56
61
}
57
62
58
63
// Generate import statements for used types
0 commit comments