From dd8d4fc29a78300d7598626825932f38f0bb9c38 Mon Sep 17 00:00:00 2001 From: Andrei L <1881266+unrevised6419@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:29:09 +0100 Subject: [PATCH 1/7] fix(imports): generate .d.ts file for eslint > 9 auto imports --- packages/wxt/src/builtin-modules/unimport.ts | 46 +++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index a0b72bc58..e8d6ed790 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -6,8 +6,9 @@ import type { WxtModule, WxtResolvedUnimportOptions, } from '../types'; -import { type Unimport, createUnimport, toExports } from 'unimport'; +import { createUnimport, toExports, type Unimport } from 'unimport'; import UnimportPlugin from 'unimport/unplugin'; +import { basename, dirname, extname, join } from 'node:path'; export default defineWxtModule({ name: 'wxt:built-in:unimport', @@ -51,14 +52,13 @@ export default defineWxtModule({ if (!wxt.config.imports.eslintrc.enabled) return; - // Only generate ESLint config if that feature is enabled - entries.push( - await getEslintConfigEntry( - unimport, - wxt.config.imports.eslintrc.enabled, - wxt.config.imports, - ), + const eslintConfigEntries = await getEslintConfigEntry( + unimport, + wxt.config.imports.eslintrc.enabled, + wxt.config.imports, ); + + entries.push(...eslintConfigEntries); }); // Add vite plugin @@ -105,7 +105,7 @@ async function getEslintConfigEntry( unimport: Unimport, version: 8 | 9, options: WxtResolvedUnimportOptions, -): Promise { +): Promise { const globals = (await unimport.getImports()) .map((i) => i.as ?? i.name) .filter(Boolean) @@ -115,7 +115,7 @@ async function getEslintConfigEntry( return globals; }, {}); - if (version <= 8) return getEslint8ConfigEntry(options, globals); + if (version <= 8) return [getEslint8ConfigEntry(options, globals)]; else return getEslint9ConfigEntry(options, globals); } @@ -132,8 +132,8 @@ export function getEslint8ConfigEntry( export function getEslint9ConfigEntry( options: WxtResolvedUnimportOptions, globals: Record, -): WxtDirFileEntry { - return { +): WxtDirFileEntry[] { + const javaScriptFileEntry: WxtDirFileEntry = { path: options.eslintrc.filePath, text: `const globals = ${JSON.stringify(globals, null, 2)} @@ -147,4 +147,26 @@ export default { }; `, }; + + const javaScriptFileDirname = dirname(options.eslintrc.filePath); + const javaScriptFileExtension = extname(options.eslintrc.filePath); + const javaScriptFileBasename = basename( + options.eslintrc.filePath, + javaScriptFileExtension, + ); + + const typeScriptFilePath = join( + javaScriptFileDirname, + `${javaScriptFileBasename}.d.ts`, + ); + + const typeScriptFileEntry: WxtDirFileEntry = { + path: typeScriptFilePath, + text: `import type { ConfigObject } from "@eslint/core"; +declare const config: ConfigObject; +export default config; +`, + }; + + return [javaScriptFileEntry, typeScriptFileEntry]; } From 9c7166f5f9a423904832559983de67a67cc660e6 Mon Sep 17 00:00:00 2001 From: PatrykKuniczak Date: Fri, 24 Apr 2026 11:55:08 +0200 Subject: [PATCH 2/7] Simplify getting typeScriptFilePath --- packages/wxt/src/builtin-modules/unimport.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index e8d6ed790..0433b39ac 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -148,17 +148,9 @@ export default { `, }; - const javaScriptFileDirname = dirname(options.eslintrc.filePath); - const javaScriptFileExtension = extname(options.eslintrc.filePath); - const javaScriptFileBasename = basename( - options.eslintrc.filePath, - javaScriptFileExtension, - ); - - const typeScriptFilePath = join( - javaScriptFileDirname, - `${javaScriptFileBasename}.d.ts`, - ); + const typeScriptFilePath = + options.eslintrc.filePath.slice(0, -extname(options.eslintrc.filePath)) + + '.d.ts'; const typeScriptFileEntry: WxtDirFileEntry = { path: typeScriptFilePath, From 839268dae6b4080a220a30cd1995358fd3a3178a Mon Sep 17 00:00:00 2001 From: PatrykKuniczak Date: Fri, 24 Apr 2026 15:40:35 +0200 Subject: [PATCH 3/7] fix: remove unused imports of unimport.ts --- packages/wxt/src/builtin-modules/unimport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index 0433b39ac..3f3b83596 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -8,7 +8,7 @@ import type { } from '../types'; import { createUnimport, toExports, type Unimport } from 'unimport'; import UnimportPlugin from 'unimport/unplugin'; -import { basename, dirname, extname, join } from 'node:path'; +import { extname } from 'node:path'; export default defineWxtModule({ name: 'wxt:built-in:unimport', From 37f9a78dbfe1d9707cfff73ced75639f9dd00697 Mon Sep 17 00:00:00 2001 From: PatrykKuniczak Date: Sat, 1 Aug 2026 21:20:04 +0200 Subject: [PATCH 4/7] refactor: simplify unimport.ts --- packages/wxt/src/builtin-modules/unimport.ts | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index ae239248a..264331752 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -116,18 +116,20 @@ async function getEslintConfigEntry( return globals; }, {}); - if (configVersion === 8) return [getEslint8ConfigEntry(options, globals)]; + if (configVersion === 8) return getEslint8ConfigEntry(options, globals); return getEslint9ConfigEntry(options, globals); } export function getEslint8ConfigEntry( options: WxtResolvedUnimportOptions, globals: Record, -): WxtDirFileEntry { - return { - path: options.eslintrc.filePath, - text: JSON.stringify({ globals }, null, 2) + '\n', - }; +): WxtDirFileEntry[] { + return [ + { + path: options.eslintrc.filePath, + text: JSON.stringify({ globals }, null, 2) + '\n', + }, + ]; } export function getEslint9ConfigEntry( @@ -149,9 +151,10 @@ export default { `, }; - const typeScriptFilePath = - options.eslintrc.filePath.slice(0, -extname(options.eslintrc.filePath)) + - '.d.ts'; + const typeScriptFilePath = options.eslintrc.filePath.replace( + extname(options.eslintrc.filePath), + '.d.ts', + ); const typeScriptFileEntry: WxtDirFileEntry = { path: typeScriptFilePath, From 1b8e72aa3d8e88fc9e3956ece343451779329a02 Mon Sep 17 00:00:00 2001 From: Patryk Kuniczak Date: Sun, 2 Aug 2026 10:00:48 +0200 Subject: [PATCH 5/7] fix: building ext for ts file path Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- packages/wxt/src/builtin-modules/unimport.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index 264331752..c2dda47fa 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -151,10 +151,10 @@ export default { `, }; - const typeScriptFilePath = options.eslintrc.filePath.replace( - extname(options.eslintrc.filePath), - '.d.ts', - ); + const ext = extname(options.eslintrc.filePath); + const declarationExt = ext === '.mjs' ? '.d.mts' : ext === '.cjs' ? '.d.cts' : '.d.ts'; + const typeScriptFilePath = + options.eslintrc.filePath.slice(0, -ext.length) + declarationExt; const typeScriptFileEntry: WxtDirFileEntry = { path: typeScriptFilePath, From e6f53ba6275bebbef7bf84fa11f0343aea92fee8 Mon Sep 17 00:00:00 2001 From: PatrykKuniczak Date: Sun, 2 Aug 2026 10:02:31 +0200 Subject: [PATCH 6/7] fix: formatting of unimport.ts --- packages/wxt/src/builtin-modules/unimport.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wxt/src/builtin-modules/unimport.ts b/packages/wxt/src/builtin-modules/unimport.ts index c2dda47fa..458cecf06 100644 --- a/packages/wxt/src/builtin-modules/unimport.ts +++ b/packages/wxt/src/builtin-modules/unimport.ts @@ -152,7 +152,8 @@ export default { }; const ext = extname(options.eslintrc.filePath); - const declarationExt = ext === '.mjs' ? '.d.mts' : ext === '.cjs' ? '.d.cts' : '.d.ts'; + const declarationExt = + ext === '.mjs' ? '.d.mts' : ext === '.cjs' ? '.d.cts' : '.d.ts'; const typeScriptFilePath = options.eslintrc.filePath.slice(0, -ext.length) + declarationExt; From 65afa0d33a157c7b2adf3be967982f69c95030b6 Mon Sep 17 00:00:00 2001 From: PatrykKuniczak Date: Sun, 2 Aug 2026 10:28:51 +0200 Subject: [PATCH 7/7] feat: add new tests for auto-import for eslint --- .../__snapshots__/auto-imports.test.ts.snap | 36 +++++++++++++++++++ packages/wxt/e2e/tests/auto-imports.test.ts | 7 ++++ 2 files changed, 43 insertions(+) diff --git a/packages/wxt/e2e/tests/__snapshots__/auto-imports.test.ts.snap b/packages/wxt/e2e/tests/__snapshots__/auto-imports.test.ts.snap index abd8c412e..177f1d7ef 100644 --- a/packages/wxt/e2e/tests/__snapshots__/auto-imports.test.ts.snap +++ b/packages/wxt/e2e/tests/__snapshots__/auto-imports.test.ts.snap @@ -119,6 +119,15 @@ export default { " `; +exports[`Auto Imports > eslint config > "enabled: 9" should output a flat config file compatible with ESLint >=9 2`] = ` +".wxt/eslint-auto-imports.d.mts +---------------------------------------- +import type { ConfigObject } from "@eslint/core"; +declare const config: ConfigObject; +export default config; +" +`; + exports[`Auto Imports > eslint config > "enabled: auto" should output a JSON config file compatible with ESLint of package.json 1`] = ` ".wxt/eslint-auto-imports.mjs ---------------------------------------- @@ -182,6 +191,15 @@ export default { " `; +exports[`Auto Imports > eslint config > "enabled: auto" should output a JSON config file compatible with ESLint of package.json 2`] = ` +".wxt/eslint-auto-imports.d.mts +---------------------------------------- +import type { ConfigObject } from "@eslint/core"; +declare const config: ConfigObject; +export default config; +" +`; + exports[`Auto Imports > eslint config > "enabled: true" should output a JSON config file compatible with ESLint of package.json 1`] = ` ".wxt/eslint-auto-imports.mjs ---------------------------------------- @@ -245,6 +263,15 @@ export default { " `; +exports[`Auto Imports > eslint config > "enabled: true" should output a JSON config file compatible with ESLint of package.json 2`] = ` +".wxt/eslint-auto-imports.d.mts +---------------------------------------- +import type { ConfigObject } from "@eslint/core"; +declare const config: ConfigObject; +export default config; +" +`; + exports[`Auto Imports > eslint config > should allow customizing the output 1`] = ` "example.json ---------------------------------------- @@ -307,3 +334,12 @@ export default { }; " `; + +exports[`Auto Imports > eslint config > should allow customizing the output 2`] = ` +"example.d.ts +---------------------------------------- +import type { ConfigObject } from "@eslint/core"; +declare const config: ConfigObject; +export default config; +" +`; diff --git a/packages/wxt/e2e/tests/auto-imports.test.ts b/packages/wxt/e2e/tests/auto-imports.test.ts index 2e4ad34ff..1c3c5b11c 100644 --- a/packages/wxt/e2e/tests/auto-imports.test.ts +++ b/packages/wxt/e2e/tests/auto-imports.test.ts @@ -235,6 +235,9 @@ describe('Auto Imports', () => { expect( await project.serializeFile('.wxt/eslint-auto-imports.mjs'), ).toMatchSnapshot(); + expect( + await project.serializeFile('.wxt/eslint-auto-imports.d.mts'), + ).toMatchSnapshot(); }, ); @@ -270,6 +273,9 @@ describe('Auto Imports', () => { expect( await project.serializeFile('.wxt/eslint-auto-imports.mjs'), ).toMatchSnapshot(); + expect( + await project.serializeFile('.wxt/eslint-auto-imports.d.mts'), + ).toMatchSnapshot(); }); it('"enabled: false" should NOT output an ESLint config file', async () => { @@ -307,6 +313,7 @@ describe('Auto Imports', () => { }); expect(await project.serializeFile('example.json')).toMatchSnapshot(); + expect(await project.serializeFile('example.d.ts')).toMatchSnapshot(); }); describe('Actual linting results', () => {