Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,11 @@ export interface MagicStringResult {
export interface ImportInjectionResult extends MagicStringResult {
imports: Import[]
}

export interface ToExportsOptions {
/**
* Whether to retrieve module names from imports' `typeFrom` property when provided
* @default false
*/
declaration?: boolean
}
15 changes: 8 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { StaticImport } from 'mlly'
import type { Import, InlinePreset, MagicStringResult, PathFromResolver, TypeDeclarationOptions } from './types'
import type { Import, InlinePreset, MagicStringResult, PathFromResolver, ToExportsOptions, TypeDeclarationOptions } from './types'
import MagicString from 'magic-string'
import { findStaticImports, parseStaticImport, resolvePathSync } from 'mlly'
import { isAbsolute, relative } from 'pathe'
Expand Down Expand Up @@ -147,8 +147,8 @@ export function dedupeImports(imports: Import[], warn: (msg: string) => void) {
return imports.filter((_, idx) => !indexToRemove.has(idx))
}

export function toExports(imports: Import[], fileDir?: string, includeType = false) {
const map = toImportModuleMap(imports, includeType)
export function toExports(imports: Import[], fileDir?: string, includeType = false, options: ToExportsOptions = {}) {
const map = toImportModuleMap(imports, includeType, options)
return Object.entries(map)
.flatMap(([name, imports]) => {
if (isFilePath(name))
Expand Down Expand Up @@ -282,16 +282,17 @@ function stringifyImportAlias(item: Import, isCJS = false) {
: `${item.name} as ${item.as}`
}

function toImportModuleMap(imports: Import[], includeType = false) {
function toImportModuleMap(imports: Import[], includeType = false, options: ToExportsOptions = {}) {
const map: Record<string, Set<Import>> = {}
for (const _import of imports) {
if (_import.type && !includeType)
continue

if (!map[_import.from])
map[_import.from] = new Set()
const from = (options.declaration && _import.typeFrom) || _import.from
if (!map[from])
map[from] = new Set()

map[_import.from].add(_import)
map[from].add(_import)
}
return map
}
Expand Down
9 changes: 9 additions & 0 deletions test/to-export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,13 @@ describe('toExports', () => {
expect(toExports(imports, root, true))
.toMatchInlineSnapshot('"export { ref, Ref } from \'vue\';"')
})

it('declaration file support', () => {
const imports: Import[] = [
{ from: 'pkg/src', typeFrom: 'pkg/dts', name: 'foo' },
]
expect(
toExports(imports, undefined, false, { declaration: true }),
).toMatchInlineSnapshot(`"export { foo } from 'pkg/dts';"`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
).toMatchInlineSnapshot(`"export { foo } from 'pkg/dts';"`)
).toMatchInlineSnapshot(`"export type { foo } from 'pkg/dts';"`)

Should it be like this as well?

Copy link
Contributor Author

@8ctavio 8ctavio Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that toExports does not currently emmit export type, and typeFrom is only concerned with the specifier; but since declaration: true is supposed to be used for declaration files, generating type-only exports with the export type {} from syntax may also be supported.

Imports, however, are "marked" as type-only with the Import.type option. Perhaps when includeType and declaration are set to true, toExports should use export type {} for type-only imports (those with type: true). For reference, generateTypeDeclarations uses toTypeReExports for type-only imports.

})
})