diff --git a/playground/composables/index.ts b/playground/composables/index.ts index 6c8a0796..95cc1742 100644 --- a/playground/composables/index.ts +++ b/playground/composables/index.ts @@ -23,3 +23,5 @@ export type CustomType1 = string | number export interface CustomInterface1 { name: string } + +export enum CustomEnum {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c82d7230..0ff3e96a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,7 +50,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: ^2.17.0 - version: 2.17.0(@vue/compiler-sfc@3.4.26)(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0) + version: 2.17.0(@vue/compiler-sfc@3.4.27)(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0) '@types/estree': specifier: ^1.0.5 version: 1.0.5 @@ -125,7 +125,7 @@ packages: '@jridgewell/trace-mapping': 0.3.25 dev: true - /@antfu/eslint-config@2.17.0(@vue/compiler-sfc@3.4.26)(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0): + /@antfu/eslint-config@2.17.0(@vue/compiler-sfc@3.4.27)(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0): resolution: {integrity: sha512-OvLgETKfNTFD1PaGToM/Mu1A53lbMCXN4TLLL3QloGK3IkuSvNoGumLwkK1wQ1AsZAG+hfGoe+Rkd7V9Wv7MlA==} hasBin: true peerDependencies: @@ -193,7 +193,7 @@ packages: eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@7.8.0)(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0) eslint-plugin-vue: 9.25.0(eslint@8.57.0) eslint-plugin-yml: 1.14.0(eslint@8.57.0) - eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.26)(eslint@8.57.0) + eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.27)(eslint@8.57.0) globals: 15.2.0 jsonc-eslint-parser: 2.4.0 local-pkg: 0.5.0 @@ -1792,20 +1792,6 @@ packages: '@vue/compiler-core': 3.4.27 '@vue/shared': 3.4.27 - /@vue/compiler-sfc@3.4.26: - resolution: {integrity: sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==} - dependencies: - '@babel/parser': 7.24.4 - '@vue/compiler-core': 3.4.26 - '@vue/compiler-dom': 3.4.26 - '@vue/compiler-ssr': 3.4.26 - '@vue/shared': 3.4.26 - estree-walker: 2.0.2 - magic-string: 0.30.10 - postcss: 8.4.38 - source-map-js: 1.2.0 - dev: true - /@vue/compiler-sfc@3.4.27: resolution: {integrity: sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==} dependencies: @@ -1819,13 +1805,6 @@ packages: postcss: 8.4.38 source-map-js: 1.2.0 - /@vue/compiler-ssr@3.4.26: - resolution: {integrity: sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==} - dependencies: - '@vue/compiler-dom': 3.4.26 - '@vue/shared': 3.4.26 - dev: true - /@vue/compiler-ssr@3.4.27: resolution: {integrity: sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==} dependencies: @@ -2975,13 +2954,13 @@ packages: - supports-color dev: true - /eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.26)(eslint@8.57.0): + /eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.27)(eslint@8.57.0): resolution: {integrity: sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ==} peerDependencies: '@vue/compiler-sfc': ^3.3.0 eslint: ^8.50.0 || ^9.0.0 dependencies: - '@vue/compiler-sfc': 3.4.26 + '@vue/compiler-sfc': 3.4.27 eslint: 8.57.0 dev: true diff --git a/src/node/scan-dirs.ts b/src/node/scan-dirs.ts index 043b1230..18de3e6a 100644 --- a/src/node/scan-dirs.ts +++ b/src/node/scan-dirs.ts @@ -61,6 +61,10 @@ export function dedupeDtsExports(exports: Import[]) { if (!i.type) return true + // import enum as both value and type + if (i.declarationType === 'enum') + return true + return !exports.find(e => e.as === i.as && e.name === i.name && !e.type) }) } @@ -95,8 +99,11 @@ export async function scanExports(filepath: string, includeTypes: boolean, seen imports.push({ name, as: name, from: filepath, ...additional }) } else if (exp.type === 'declaration') { - if (exp.name) + if (exp.name) { imports.push({ name: exp.name, as: exp.name, from: filepath, ...additional }) + if (exp.declarationType === 'enum') + imports.push({ name: exp.name, as: exp.name, from: filepath, type: true, declarationType: exp.declarationType, ...additional }) + } } else if (exp.type === 'star' && exp.specifier) { if (exp.name) { diff --git a/src/types.ts b/src/types.ts index bbab842d..1962c17d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,5 @@ import type MagicString from 'magic-string' +import type { ESMExport } from 'mlly' import type { BuiltinPresetName } from './presets' export type ModuleId = string @@ -16,6 +17,8 @@ export interface ImportCommon { disabled?: boolean /** Won't output import in declaration file if true */ dtsDisabled?: boolean + /** Import declaration type like const / var / enum */ + declarationType?: ESMExport['declarationType'] /** * Metadata of the import */ diff --git a/src/utils.ts b/src/utils.ts index 703486cf..bd15f253 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -64,6 +64,9 @@ export function dedupeImports(imports: Import[], warn: (msg: string) => void) { const indexToRemove = new Set() imports.filter(i => !i.disabled).forEach((i, idx) => { + if (i.declarationType === 'enum') + return + const name = i.as ?? i.name if (!map.has(name)) { map.set(name, idx) @@ -71,6 +74,7 @@ export function dedupeImports(imports: Import[], warn: (msg: string) => void) { } const other = imports[map.get(name)!] + if (other.from === i.from) { indexToRemove.add(idx) return diff --git a/test/dts.test.ts b/test/dts.test.ts index f6d50e42..ba9f5de8 100644 --- a/test/dts.test.ts +++ b/test/dts.test.ts @@ -62,6 +62,7 @@ it('dts', async () => { "export {} declare global { const $: typeof import('jquery')['$'] + const CustomEnum: typeof import('/playground/composables/index')['CustomEnum'] const PascalCased: typeof import('/playground/composables/PascalCased')['PascalCased'] const THREE: typeof import('three') const bar: typeof import('/playground/composables/nested/bar/index')['bar'] @@ -100,7 +101,7 @@ it('dts', async () => { export type { JQuery } from 'jquery' import('jquery') // @ts-ignore - export type { CustomType1, CustomInterface1 } from '/playground/composables/index' + export type { CustomEnum, CustomType1, CustomInterface1 } from '/playground/composables/index' import('/playground/composables/index') // @ts-ignore export type { CustomType2 } from '/playground/composables/nested/bar/sub/index' diff --git a/test/scan-dirs.test.ts b/test/scan-dirs.test.ts index 67eec327..df388854 100644 --- a/test/scan-dirs.test.ts +++ b/test/scan-dirs.test.ts @@ -19,6 +19,18 @@ describe('scan-dirs', () => { "from": "index.ts", "name": "bump", }, + { + "as": "CustomEnum", + "from": "index.ts", + "name": "CustomEnum", + }, + { + "as": "CustomEnum", + "declarationType": "enum", + "from": "index.ts", + "name": "CustomEnum", + "type": true, + }, { "as": "CustomInterface1", "from": "index.ts",