1
1
import { readFile } from 'node:fs/promises'
2
- import { formatComment } from './utils'
2
+ import { formatComment , formatDeclarations } from './utils'
3
3
4
4
export async function extractTypeFromSource ( filePath : string ) : Promise < string > {
5
5
const fileContent = await readFile ( filePath , 'utf-8' )
@@ -12,13 +12,16 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
12
12
let importMatch
13
13
while ( ( importMatch = importRegex . exec ( fileContent ) ) !== null ) {
14
14
const [ , isTypeImport , namedImports1 , defaultImport1 , namedImports2 , defaultImport2 , from ] = importMatch
15
+ if ( ! importMap . has ( from ) ) {
16
+ importMap . set ( from , new Set ( ) )
17
+ }
18
+
15
19
const processImports = ( imports : string | undefined , isType : boolean ) => {
16
20
if ( imports ) {
17
21
const types = imports . replace ( / [ { } ] / g, '' ) . split ( ',' ) . map ( t => {
18
22
const [ name , alias ] = t . split ( ' as ' ) . map ( s => s . trim ( ) )
19
23
return { name : name . replace ( / ^ t y p e \s + / , '' ) , alias : alias || name . replace ( / ^ t y p e \s + / , '' ) }
20
24
} )
21
- if ( ! importMap . has ( from ) ) importMap . set ( from , new Set ( ) )
22
25
types . forEach ( ( { name, alias } ) => {
23
26
importMap . get ( from ) ! . add ( name )
24
27
} )
@@ -32,11 +35,11 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
32
35
}
33
36
34
37
// Handle exports with comments
35
- const exportRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ ) ? \s * ( e x p o r t \s + (?: a s y n c \s + ) ? (?: f u n c t i o n | c o n s t | l e t | v a r | c l a s s | i n t e r f a c e | t y p e ) \s + \w + [ \s \S ] * ?) (? = \n \s * (?: \/ \* \* | e x p o r t | $ ) ) / g;
38
+ const exportRegex = / ( \/ \* \* [ \s \S ] * ?\* \/ \s * ) ? ( e x p o r t \s + (?: a s y n c \s + ) ? (?: f u n c t i o n | c o n s t | l e t | v a r | c l a s s | i n t e r f a c e | t y p e ) \s + \w + [ \s \S ] * ?) (? = \n \s * (?: \/ \* \* | e x p o r t | $ ) ) / g;
36
39
let match
37
40
while ( ( match = exportRegex . exec ( fileContent ) ) !== null ) {
38
41
const [ , comment , exportStatement ] = match
39
- const formattedComment = comment ? formatComment ( comment ) : ''
42
+ const formattedComment = comment ? formatComment ( comment . trim ( ) ) : ''
40
43
let formattedExport = exportStatement . trim ( )
41
44
42
45
if ( formattedExport . startsWith ( 'export function' ) || formattedExport . startsWith ( 'export async function' ) ) {
@@ -51,17 +54,9 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
51
54
} else if ( formattedExport . startsWith ( 'export const' ) || formattedExport . startsWith ( 'export let' ) || formattedExport . startsWith ( 'export var' ) ) {
52
55
formattedExport = formattedExport . replace ( / ^ e x p o r t \s + ( c o n s t | l e t | v a r ) / , 'export declare $1' )
53
56
formattedExport = formattedExport . split ( '=' ) [ 0 ] . trim ( ) + ';'
54
- } else if ( formattedExport . startsWith ( 'export interface' ) ) {
55
- // Keep interface declarations as they are, including their content
56
- formattedExport = formattedExport . replace ( / \s * \{ \s * $ / m, ' {' )
57
- . replace ( / ^ \s * } / m, '}' )
58
- . replace ( / ; \s * $ / g, '' )
59
- } else if ( formattedExport . startsWith ( 'export type' ) ) {
60
- // Keep type declarations as they are
61
- formattedExport = formattedExport . replace ( / ; \s * $ / , '' )
62
57
}
63
58
64
- declarations += `${ formattedComment } ${ formattedExport } \n\n`
59
+ declarations += `${ formattedComment } \n ${ formattedExport } \n\n`
65
60
66
61
// Add types used in the export to usedTypes
67
62
const typeRegex = / \b ( [ A - Z ] \w + ) (?: < [ ^ > ] * > ) ? / g
@@ -76,39 +71,55 @@ export async function extractTypeFromSource(filePath: string): Promise<string> {
76
71
importMap . forEach ( ( types , path ) => {
77
72
const usedTypesFromPath = [ ...types ] . filter ( type => usedTypes . has ( type ) )
78
73
if ( usedTypesFromPath . length > 0 ) {
79
- importDeclarations += `import type { ${ usedTypesFromPath . join ( ', ' ) } } from '${ path } '; \n`
74
+ importDeclarations += `import type { ${ usedTypesFromPath . join ( ', ' ) } } from '${ path } '\n`
80
75
}
81
76
} )
82
77
83
78
if ( importDeclarations ) {
84
79
declarations = importDeclarations + '\n' + declarations
85
80
}
86
81
87
- return declarations . trim ( ) + '\n'
82
+ // Apply final formatting
83
+ const formattedDeclarations = formatDeclarations ( declarations , false )
84
+
85
+ console . log ( `Unformatted declarations for ${ filePath } :` , declarations )
86
+ console . log ( `Extracted declarations for ${ filePath } :` , formattedDeclarations )
87
+
88
+ return formattedDeclarations
88
89
}
89
90
90
91
export async function extractConfigTypeFromSource ( filePath : string ) : Promise < string > {
91
92
const fileContent = await readFile ( filePath , 'utf-8' )
92
93
let declarations = ''
93
94
94
- // Handle type imports
95
- const importRegex = / i m p o r t \s + t y p e \s * \{ ( [ ^ } ] + ) \} \s * f r o m \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
96
- let importMatch
97
- while ( ( importMatch = importRegex . exec ( fileContent ) ) !== null ) {
98
- const types = importMatch [ 1 ] . split ( ',' ) . map ( t => t . trim ( ) )
99
- const from = importMatch [ 2 ]
100
- declarations += `import type { ${ types . join ( ', ' ) } } from '${ from } '\n\n` // Add two newlines here
101
- }
95
+ try {
96
+ // Handle type imports
97
+ const importRegex = / i m p o r t \s + t y p e \s * \{ ( [ ^ } ] + ) \} \s * f r o m \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g
98
+ let importMatch
99
+ while ( ( importMatch = importRegex . exec ( fileContent ) ) !== null ) {
100
+ const [ , types , from ] = importMatch
101
+ const typeList = types . split ( ',' ) . map ( t => t . trim ( ) )
102
+ declarations += `import type { ${ typeList . join ( ', ' ) } } from '${ from } '\n`
103
+ }
102
104
103
- // Handle exports
104
- const exportRegex = / e x p o r t \s + c o n s t \s + ( \w + ) \s * : \s * ( [ ^ = ] + ) \s * = / g
105
- let exportMatch
106
- while ( ( exportMatch = exportRegex . exec ( fileContent ) ) !== null ) {
107
- const [ , name , type ] = exportMatch
108
- declarations += `export declare const ${ name } : ${ type . trim ( ) } \n`
109
- }
105
+ if ( declarations ) {
106
+ declarations += '\n'
107
+ }
110
108
111
- return declarations . trim ( ) + '\n'
109
+ // Handle exports
110
+ const exportRegex = / e x p o r t \s + c o n s t \s + ( \w + ) \s * : \s * ( [ ^ = ] + ) \s * = / g
111
+ let exportMatch
112
+ while ( ( exportMatch = exportRegex . exec ( fileContent ) ) !== null ) {
113
+ const [ , name , type ] = exportMatch
114
+ declarations += `export declare const ${ name } : ${ type . trim ( ) } \n`
115
+ }
116
+
117
+ console . log ( `Extracted config declarations for ${ filePath } :` , declarations )
118
+ return declarations . trim ( ) + '\n'
119
+ } catch ( error ) {
120
+ console . error ( `Error extracting config declarations from ${ filePath } :` , error )
121
+ return ''
122
+ }
112
123
}
113
124
114
125
export async function extractIndexTypeFromSource ( filePath : string ) : Promise < string > {
@@ -122,5 +133,6 @@ export async function extractIndexTypeFromSource(filePath: string): Promise<stri
122
133
declarations += `${ match [ 0 ] } \n`
123
134
}
124
135
136
+ console . log ( `Extracted index declarations for ${ filePath } :` , declarations )
125
137
return declarations . trim ( ) + '\n'
126
138
}
0 commit comments