From c8034550087eeb518bc2c8d084bc13d0ea4ae664 Mon Sep 17 00:00:00 2001 From: NoTwoBoy <1244476905@qq.com> Date: Fri, 27 Dec 2024 19:03:45 +0800 Subject: [PATCH] feat(dts): introduce the `dtsMode` to control the behavior of generating dts file --- README.md | 6 ++ src/core/ctx.ts | 17 +++-- src/types.ts | 16 ++-- test/__snapshots__/dts.test.ts.snap | 2 +- test/dts.ignore.test.ts | 28 ------- test/dts.increase.test.ts | 21 ------ test/dts.test.ts | 113 ++++++++++++++++++++++------ 7 files changed, 117 insertions(+), 86 deletions(-) delete mode 100644 test/dts.ignore.test.ts delete mode 100644 test/dts.increase.test.ts diff --git a/README.md b/README.md index 56ccf54a..c05538c1 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,12 @@ AutoImport({ // Set `false` to disable. dts: './auto-imports.d.ts', + // The mode for generating the .d.ts file. + // 'overwrite': overwrite the whole existing .d.ts file with the new type definitions. + // 'append': only append the new type definitions to the existing .d.ts file, means the existing type definitions will be kept. + // Default to 'append' + dtsMode: 'append', + // Array of strings of regexes that contains imports meant to be ignored during // the declaration file generation. You may find this useful when you need to provide // a custom signature for a function. diff --git a/src/core/ctx.ts b/src/core/ctx.ts index 240b64e6..e858a66e 100644 --- a/src/core/ctx.ts +++ b/src/core/ctx.ts @@ -18,6 +18,7 @@ export function createContext(options: Options = {}, root = process.cwd()) { const { dts: preferDTS = isPackageExists('typescript'), + dtsMode = 'append', dirsScanOptions, dirs, vueDirectives, @@ -143,19 +144,21 @@ ${dts}`.trim()}\n` return i.from }, }) - const currentDTS = parseDTS(currentContent)! if (options.vueTemplate) { currentContent = currentContent.replace( componentCustomPropertiesReg, $1 => `interface GlobalComponents {}\n ${$1}`, ) } - if (originalDTS) { - Object.keys(currentDTS).forEach((key) => { - originalDTS[key] = currentDTS[key] - }) - const dtsList = Object.keys(originalDTS).sort().map(k => ` ${k}: ${originalDTS[k]}`) - return currentContent.replace(dtsReg, () => `declare global {\n${dtsList.join('\n')}\n}`) + + if (dtsMode === 'append') { + const currentDTS = parseDTS(currentContent)! + if (originalDTS) { + Object.assign(originalDTS, currentDTS) + + const dtsList = Object.keys(originalDTS).sort().map(k => ` ${k}: ${originalDTS[k]}`) + return currentContent.replace(dtsReg, () => `declare global {\n${dtsList.join('\n')}\n}`) + } } return currentContent diff --git a/src/types.ts b/src/types.ts index 60ab70e6..d8be06ff 100644 --- a/src/types.ts +++ b/src/types.ts @@ -163,14 +163,20 @@ export interface Options { parser?: UnimportOptions['parser'] /** - * Filepath to generate corresponding .d.ts file. - * Default enabled when `typescript` is installed locally. - * Set `false` to disable. - * - * @default './auto-imports.d.ts' + * Specifies the file path for generating the corresponding .d.ts file. + * This option is enabled by default when `typescript` is installed locally. + * Set to `false` to disable this feature. */ dts?: string | boolean + /** + * Mode for generating the .d.ts file. + * - `overwrite`: overwrite the whole existing .d.ts file with the new type definitions. + * - `append`: only append the new type definitions to the existing .d.ts file, means the existing type definitions will be kept. + * @default 'append' + */ + dtsMode?: 'overwrite' | 'append' + /** * Auto import inside Vue templates * diff --git a/test/__snapshots__/dts.test.ts.snap b/test/__snapshots__/dts.test.ts.snap index 380a7961..c29d0b18 100644 --- a/test/__snapshots__/dts.test.ts.snap +++ b/test/__snapshots__/dts.test.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`dts 1`] = ` +exports[`dts > normal 1`] = ` "/* eslint-disable */ /* prettier-ignore */ // @ts-nocheck diff --git a/test/dts.ignore.test.ts b/test/dts.ignore.test.ts deleted file mode 100644 index d6001cea..00000000 --- a/test/dts.ignore.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { join } from 'node:path' -import { expect, it } from 'vitest' -import { createContext } from '../src/core/ctx' - -it('dts ignore', async () => { - const cwd = process.cwd() - const ctx = createContext({ - imports: [{ - custom: [ - 'shouldBePresent', - 'shouldAlsoBePresent', - 'shouldBeIgnored', - 'ignoreme_shoudAlsoBeIgnored', - ], - }], - ignoreDts: [ - 'shouldBeIgnored', - /^ignoreme_/, - ], - }) - - const dtsContent = await ctx.generateDTS(join(cwd, 'index.d.ts')) - - expect(dtsContent).toContain('shouldBePresent') - expect(dtsContent).toContain('shouldAlsoBePresent') - expect(dtsContent).not.toContain('shouldBeIgnored') - expect(dtsContent).not.toContain('ignoreme_shoudAlsoBeIgnored') -}) diff --git a/test/dts.increase.test.ts b/test/dts.increase.test.ts deleted file mode 100644 index 8a6c1e59..00000000 --- a/test/dts.increase.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { join } from 'node:path' -import process from 'node:process' -import { expect, it } from 'vitest' -import { createContext } from '../src/core/ctx' - -it('dts', async () => { - const cwd = process.cwd() - const dts = join(cwd, './test/tmp/dts.increase.d.ts') - const ctx = createContext({ - ignore: ['h'], - imports: ['vue'], - dts, - }) - - const dtsContent = await ctx.generateDTS(dts) - expect(dtsContent).toContain('AAA') - expect(dtsContent).toContain('BBB') - expect(dtsContent).toContain('$$') - expect(dtsContent).toContain('customFile') - expect(dtsContent).toContain('customFile1') -}) diff --git a/test/dts.test.ts b/test/dts.test.ts index 57338d01..fc28b197 100644 --- a/test/dts.test.ts +++ b/test/dts.test.ts @@ -3,32 +3,97 @@ import process from 'node:process' import { expect, it } from 'vitest' import { createContext } from '../src/core/ctx' -it('dts', async () => { - const cwd = process.cwd() - const ctx = createContext({ - packagePresets: ['magic-string'], - imports: [ - 'vue-demi', - 'react', - 'svelte', - 'svelte/animate', - 'svelte/easing', - 'svelte/motion', - 'svelte/store', - 'svelte/transition', - { +describe('dts', () => { + it('normal', async () => { + const cwd = process.cwd() + const ctx = createContext({ + packagePresets: ['magic-string'], + imports: [ + 'vue-demi', + 'react', + 'svelte', + 'svelte/animate', + 'svelte/easing', + 'svelte/motion', + 'svelte/store', + 'svelte/transition', + { + custom: [ + 'customNamed', + ['default', 'customDefault'], + ], + custom2: [ + ['*', 'custom2'], + ], + [join(cwd, 'foo.ts')]: ['foo'], + }, + 'vue/macros', + ], + }) + + expect(await ctx.generateDTS(join(cwd, 'index.d.ts'))).toMatchSnapshot() + }) + + it('dts ignore', async () => { + const cwd = process.cwd() + const ctx = createContext({ + imports: [{ custom: [ - 'customNamed', - ['default', 'customDefault'], + 'shouldBePresent', + 'shouldAlsoBePresent', + 'shouldBeIgnored', + 'ignoreme_shoudAlsoBeIgnored', ], - custom2: [ - ['*', 'custom2'], - ], - [join(cwd, 'foo.ts')]: ['foo'], - }, - 'vue/macros', - ], + }], + ignoreDts: [ + 'shouldBeIgnored', + /^ignoreme_/, + ], + }) + + const dtsContent = await ctx.generateDTS(join(cwd, './test/tmp/dts.ignore.d.ts')) + + expect(dtsContent).toContain('shouldBePresent') + expect(dtsContent).toContain('shouldAlsoBePresent') + expect(dtsContent).not.toContain('shouldBeIgnored') + expect(dtsContent).not.toContain('ignoreme_shoudAlsoBeIgnored') }) - expect(await ctx.generateDTS(join(cwd, 'index.d.ts'))).toMatchSnapshot() + it('dts in append mode', async () => { + const cwd = process.cwd() + const dts = join(cwd, './test/tmp/dts.increase.d.ts') + const ctx = createContext({ + imports: ['vue'], + dts, + }) + + const dtsContent = await ctx.generateDTS(dts) + expect(dtsContent).toContain('AAA') + expect(dtsContent).toContain('BBB') + expect(dtsContent).toContain('$$') + expect(dtsContent).toContain('customFile') + expect(dtsContent).toContain('customFile1') + }) + + it('dts in overwrite mode', async () => { + const cwd = process.cwd() + const dts = join(cwd, './test/tmp/dts.increase.d.ts') + const ctx = createContext({ + imports: ['vue'], + dts, + dtsMode: 'overwrite', + }) + + const dtsContent = await ctx.generateDTS(dts) + expect(dtsContent).not.toContain('AAA') + expect(dtsContent).not.toContain('BBB') + expect(dtsContent).not.toContain('$$') + expect(dtsContent).not.toContain('customFile') + expect(dtsContent).not.toContain('customFile1') + + expect(dtsContent).toContain('ref') + expect(dtsContent).toContain('reactive') + expect(dtsContent).toContain('watch') + expect(dtsContent).toContain('computed') + }) })