@@ -91,9 +91,12 @@ function getModuleExports(filepath, stack = new Set()) {
9191 return null ;
9292 }
9393
94+ const localImports = collectLocalImports ( ast . body ) ;
95+
9496 const exports = new Map ( ) ;
9597 for ( const stmt of ast . body ) {
96- if ( stmt . type === 'ExportNamedDeclaration' ) collectNamedExports ( stmt , exports , filepath , stack ) ;
98+ if ( stmt . type === 'ExportNamedDeclaration' )
99+ collectNamedExports ( stmt , exports , filepath , stack , localImports ) ;
97100 else if ( stmt . type === 'ExportAllDeclaration' )
98101 collectStarExports ( stmt , exports , filepath , stack ) ;
99102 else if ( stmt . type === 'ExportDefaultDeclaration' ) {
@@ -111,10 +114,91 @@ function getModuleExports(filepath, stack = new Set()) {
111114 return exports ;
112115}
113116
114- function collectNamedExports ( stmt , exports , filepath , stack ) {
117+ // Collect value-level named/default imports so that `export const X = Y`
118+ // can be resolved as a re-export of Y's original source. We skip type-only
119+ // imports (they can't legally appear in a value-position initializer).
120+ function collectLocalImports ( body ) {
121+ const map = new Map ( ) ;
122+ for ( const stmt of body ) {
123+ if ( stmt . type !== 'ImportDeclaration' ) continue ;
124+ if ( stmt . importKind === 'type' ) continue ;
125+ const sourceSpec = stmt . source . value ;
126+ for ( const spec of stmt . specifiers ) {
127+ if ( spec . importKind === 'type' ) continue ;
128+ if ( spec . type === 'ImportSpecifier' ) {
129+ map . set ( spec . local . name , { sourceSpec, importedName : idOrStr ( spec . imported ) } ) ;
130+ } else if ( spec . type === 'ImportDefaultSpecifier' ) {
131+ map . set ( spec . local . name , { sourceSpec, importedName : 'default' } ) ;
132+ }
133+ }
134+ }
135+ return map ;
136+ }
137+
138+ // Strip TS `as`/type-assertion wrappers from an initializer and return the
139+ // inner identifier name if the whole expression is just `Ident (as T)*`.
140+ function unwrapAliasInit ( node ) {
141+ let cur = node ;
142+ while ( cur && ( cur . type === 'TSAsExpression' || cur . type === 'TSTypeAssertion' ) ) {
143+ cur = cur . expression ;
144+ }
145+ return cur && cur . type === 'Identifier' ? cur . name : null ;
146+ }
147+
148+ function buildAliasExport ( importEntry , fromFile , stack , stmtIsType ) {
149+ const { sourceSpec, importedName } = importEntry ;
150+ const targetFile = resolveImportSource ( sourceSpec , fromFile ) ;
151+ const isBare = ! sourceSpec . startsWith ( '.' ) ;
152+ let source = targetFile ;
153+ let bareSource = ! targetFile && isBare ? sourceSpec : null ;
154+ let local = importedName ;
155+
156+ if ( targetFile ) {
157+ const nested = getModuleExports ( targetFile , stack ) ;
158+ const nestedEntry = nested ?. get ( importedName ) ;
159+ if ( nestedEntry && nestedEntry . kind !== 'namespace' ) {
160+ if ( nestedEntry . source ) {
161+ source = nestedEntry . source ;
162+ bareSource = null ;
163+ local = nestedEntry . localName ;
164+ } else if ( nestedEntry . bareSource ) {
165+ source = null ;
166+ bareSource = nestedEntry . bareSource ;
167+ local = nestedEntry . localName ;
168+ }
169+ }
170+ }
171+
172+ return { source, bareSource, localName : local , isType : stmtIsType , kind : 'named' } ;
173+ }
174+
175+ function collectNamedExports ( stmt , exports , filepath , stack , localImports ) {
115176 const stmtIsType = stmt . exportKind === 'type' ;
116177
117178 if ( stmt . declaration ) {
179+ // `export const X = Y [as T]` where Y is a top-level imported binding is
180+ // treated as a re-export of Y's original source. This intentionally drops
181+ // any branding/cast type — internal call sites don't need it, and it lets
182+ // consumers import the implementation directly for tree-shaking.
183+ if ( stmt . declaration . type === 'VariableDeclaration' ) {
184+ for ( const v of stmt . declaration . declarations ) {
185+ if ( v . id ?. type !== 'Identifier' ) continue ;
186+ const name = v . id . name ;
187+ const aliased = v . init ? unwrapAliasInit ( v . init ) : null ;
188+ const importEntry = aliased ? localImports . get ( aliased ) : null ;
189+ if ( importEntry ) {
190+ setExport ( exports , name , buildAliasExport ( importEntry , filepath , stack , stmtIsType ) ) ;
191+ } else {
192+ setExport ( exports , name , {
193+ source : filepath ,
194+ localName : name ,
195+ isType : stmtIsType ,
196+ kind : 'local' ,
197+ } ) ;
198+ }
199+ }
200+ return ;
201+ }
118202 for ( const { name, isType } of declarationNames ( stmt . declaration ) ) {
119203 setExport ( exports , name , {
120204 source : filepath ,
0 commit comments