From 99d558f33c1d23d7ccf024d8d2f6c96369683836 Mon Sep 17 00:00:00 2001 From: Aaron Date: Sun, 8 Feb 2026 15:21:45 -0600 Subject: [PATCH] refactor: Standardize file existence checks to `pathExists` (#2083) Co-authored-by: Patryk Kuniczak --- packages/auto-icons/src/index.ts | 4 +-- packages/runner/src/options.ts | 4 +-- packages/wxt/e2e/tests/analysis.test.ts | 18 +++++----- packages/wxt/e2e/tests/auto-imports.test.ts | 6 ++-- packages/wxt/e2e/tests/modules.test.ts | 6 ++-- .../wxt/e2e/tests/output-structure.test.ts | 16 ++++----- packages/wxt/e2e/tests/react.test.ts | 2 +- packages/wxt/e2e/tests/remote-code.test.ts | 2 +- packages/wxt/e2e/tests/user-config.test.ts | 6 ++-- packages/wxt/e2e/tests/zip.test.ts | 36 +++++++++---------- packages/wxt/e2e/utils.ts | 4 +-- .../builders/vite/plugins/resolveAppConfig.ts | 4 +-- packages/wxt/src/core/generate-wxt-dir.ts | 2 +- .../package-managers/__tests__/npm.test.ts | 4 +-- packages/wxt/src/core/resolve-config.ts | 2 +- packages/wxt/src/core/utils/fs.ts | 2 +- packages/wxt/vitest.globalSetup.ts | 4 +-- 17 files changed, 61 insertions(+), 61 deletions(-) diff --git a/packages/auto-icons/src/index.ts b/packages/auto-icons/src/index.ts index a97aeede..b13616e5 100644 --- a/packages/auto-icons/src/index.ts +++ b/packages/auto-icons/src/index.ts @@ -3,7 +3,7 @@ import { defineWxtModule } from 'wxt/modules'; import { resolve, relative } from 'node:path'; import defu from 'defu'; import sharp from 'sharp'; -import { ensureDir, exists } from 'fs-extra'; +import { ensureDir, pathExists } from 'fs-extra'; export default defineWxtModule({ name: '@wxt-dev/auto-icons', @@ -37,7 +37,7 @@ export default defineWxtModule({ if (!parsedOptions.enabled) return wxt.logger.warn(`\`[auto-icons]\` ${this.name} disabled`); - if (!(await exists(resolvedPath))) { + if (!(await pathExists(resolvedPath))) { return wxt.logger.warn( `\`[auto-icons]\` Skipping icon generation, no base icon found at ${relative(process.cwd(), resolvedPath)}`, ); diff --git a/packages/runner/src/options.ts b/packages/runner/src/options.ts index 9aab2bf5..4fad6731 100644 --- a/packages/runner/src/options.ts +++ b/packages/runner/src/options.ts @@ -114,7 +114,7 @@ async function findBrowserBinary(target: string): Promise { for (const target of targets) { const potentialPaths = KNOWN_BROWSER_PATHS[target]?.[platform] ?? []; for (const path of potentialPaths) { - if (await exists(path)) return path; + if (await pathExists(path)) return path; } } } @@ -207,7 +207,7 @@ function deduplicateArgs( return args; } -async function exists(path: string): Promise { +async function pathExists(path: string): Promise { try { await open(path, 'r'); return true; diff --git a/packages/wxt/e2e/tests/analysis.test.ts b/packages/wxt/e2e/tests/analysis.test.ts index 0ba662f9..b78f44f3 100644 --- a/packages/wxt/e2e/tests/analysis.test.ts +++ b/packages/wxt/e2e/tests/analysis.test.ts @@ -30,8 +30,8 @@ describe('Analysis', () => { }, }); - expect(await project.fileExists('stats.html')).toBe(true); - expect(await project.fileExists('.output/chrome-mv3/stats-0.json')).toBe( + expect(await project.pathExists('stats.html')).toBe(true); + expect(await project.pathExists('.output/chrome-mv3/stats-0.json')).toBe( false, ); }); @@ -52,9 +52,9 @@ describe('Analysis', () => { }, }); - expect(await project.fileExists('stats.html')).toBe(true); - expect(await project.fileExists('stats-0.json')).toBe(true); - expect(await project.fileExists('stats-1.json')).toBe(true); + expect(await project.pathExists('stats.html')).toBe(true); + expect(await project.pathExists('stats-0.json')).toBe(true); + expect(await project.pathExists('stats-1.json')).toBe(true); }); it('should support customizing the stats output directory', async () => { @@ -73,7 +73,7 @@ describe('Analysis', () => { }, }); - expect(await project.fileExists('stats/bundle.html')).toBe(true); + expect(await project.pathExists('stats/bundle.html')).toBe(true); }); it('should place artifacts next to the custom output file', async () => { @@ -93,9 +93,9 @@ describe('Analysis', () => { }, }); - expect(await project.fileExists('stats/bundle.html')).toBe(true); - expect(await project.fileExists('stats/bundle-0.json')).toBe(true); - expect(await project.fileExists('stats/bundle-1.json')).toBe(true); + expect(await project.pathExists('stats/bundle.html')).toBe(true); + expect(await project.pathExists('stats/bundle-0.json')).toBe(true); + expect(await project.pathExists('stats/bundle-1.json')).toBe(true); }); it('should open the stats in the browser when requested', async () => { diff --git a/packages/wxt/e2e/tests/auto-imports.test.ts b/packages/wxt/e2e/tests/auto-imports.test.ts index daa0427a..5d1cb143 100644 --- a/packages/wxt/e2e/tests/auto-imports.test.ts +++ b/packages/wxt/e2e/tests/auto-imports.test.ts @@ -142,7 +142,7 @@ describe('Auto Imports', () => { await project.prepare(); - expect(await project.fileExists('.wxt/types/imports.d.ts')).toBe(false); + expect(await project.pathExists('.wxt/types/imports.d.ts')).toBe(false); }); it('should only include imports-module.d.ts in the the project', async () => { @@ -280,10 +280,10 @@ describe('Auto Imports', () => { }, }); - expect(await project.fileExists('.wxt/eslint-auto-imports.mjs')).toBe( + expect(await project.pathExists('.wxt/eslint-auto-imports.mjs')).toBe( false, ); - expect(await project.fileExists('.wxt/eslintrc-auto-import.json')).toBe( + expect(await project.pathExists('.wxt/eslintrc-auto-import.json')).toBe( false, ); }); diff --git a/packages/wxt/e2e/tests/modules.test.ts b/packages/wxt/e2e/tests/modules.test.ts index eb36eea6..1a24efc1 100644 --- a/packages/wxt/e2e/tests/modules.test.ts +++ b/packages/wxt/e2e/tests/modules.test.ts @@ -77,7 +77,7 @@ describe('Module Helpers', () => { await project.build(config); - expect(await project.fileExists('.output/chrome-mv3/injected.js')).toBe( + expect(await project.pathExists('.output/chrome-mv3/injected.js')).toBe( true, ); }); @@ -118,10 +118,10 @@ describe('Module Helpers', () => { fileName: 'module.txt', }); await expect( - project.fileExists('.output/chrome-mv3/module.txt'), + project.pathExists('.output/chrome-mv3/module.txt'), ).resolves.toBe(true); await expect( - project.fileExists('.output/chrome-mv3/example/generated.txt'), + project.pathExists('.output/chrome-mv3/example/generated.txt'), ).resolves.toBe(true); }); diff --git a/packages/wxt/e2e/tests/output-structure.test.ts b/packages/wxt/e2e/tests/output-structure.test.ts index 0db84f04..7b5f31f0 100644 --- a/packages/wxt/e2e/tests/output-structure.test.ts +++ b/packages/wxt/e2e/tests/output-structure.test.ts @@ -126,7 +126,7 @@ describe('Output Directory Structure', () => { await project.build({ browser: 'firefox' }); - expect(await project.fileExists('.output/firefox-mv2/background.js')).toBe( + expect(await project.pathExists('.output/firefox-mv2/background.js')).toBe( false, ); }); @@ -146,7 +146,7 @@ describe('Output Directory Structure', () => { await project.build({ browser: 'chrome' }); - expect(await project.fileExists('.output/firefox-mv2/background.js')).toBe( + expect(await project.pathExists('.output/firefox-mv2/background.js')).toBe( false, ); }); @@ -174,7 +174,7 @@ describe('Output Directory Structure', () => { await project.build(); - expect(await project.fileExists('stats.html')).toBe(true); + expect(await project.pathExists('stats.html')).toBe(true); }); it('should support JavaScript entrypoints', async () => { @@ -210,14 +210,14 @@ describe('Output Directory Structure', () => { ---------------------------------------- {"manifest_version":3,"name":"E2E Extension","description":"Example description","version":"0.0.0","background":{"service_worker":"background.js"},"content_scripts":[{"matches":["*://*.google.com/*"],"js":["content-scripts/content.js"]},{"matches":["*://*.duckduckgo.com/*"],"js":["content-scripts/named.js"]}]}" `); - expect(await project.fileExists('.output/chrome-mv3/background.js')); + expect(await project.pathExists('.output/chrome-mv3/background.js')); expect( - await project.fileExists('.output/chrome-mv3/content-scripts/content.js'), + await project.pathExists('.output/chrome-mv3/content-scripts/content.js'), ); expect( - await project.fileExists('.output/chrome-mv3/content-scripts/named.js'), + await project.pathExists('.output/chrome-mv3/content-scripts/named.js'), ); - expect(await project.fileExists('.output/chrome-mv3/unlisted.js')); + expect(await project.pathExists('.output/chrome-mv3/unlisted.js')); }); it('should support CSS entrypoints', async () => { @@ -300,7 +300,7 @@ describe('Output Directory Structure', () => { await project.build(); - expect(await project.fileExists('dist/chrome-mv3/manifest.json')).toBe( + expect(await project.pathExists('dist/chrome-mv3/manifest.json')).toBe( true, ); }); diff --git a/packages/wxt/e2e/tests/react.test.ts b/packages/wxt/e2e/tests/react.test.ts index 4e016723..f22e23fc 100644 --- a/packages/wxt/e2e/tests/react.test.ts +++ b/packages/wxt/e2e/tests/react.test.ts @@ -31,7 +31,7 @@ describe('React', () => { await project.build(); expect( - await project.fileExists('.output/chrome-mv3/content-scripts/demo.js'), + await project.pathExists('.output/chrome-mv3/content-scripts/demo.js'), ).toBe(true); expect(await project.serializeFile('.output/chrome-mv3/manifest.json')) .toMatchInlineSnapshot(` diff --git a/packages/wxt/e2e/tests/remote-code.test.ts b/packages/wxt/e2e/tests/remote-code.test.ts index c445cc56..a328e954 100644 --- a/packages/wxt/e2e/tests/remote-code.test.ts +++ b/packages/wxt/e2e/tests/remote-code.test.ts @@ -20,7 +20,7 @@ describe('Remote Code', () => { ); expect(output).not.toContain(url); expect( - await project.fileExists(`.wxt/cache/${encodeURIComponent(url)}`), + await project.pathExists(`.wxt/cache/${encodeURIComponent(url)}`), ).toBe(true); }); }); diff --git a/packages/wxt/e2e/tests/user-config.test.ts b/packages/wxt/e2e/tests/user-config.test.ts index 7eecaae4..9677a7a9 100644 --- a/packages/wxt/e2e/tests/user-config.test.ts +++ b/packages/wxt/e2e/tests/user-config.test.ts @@ -108,7 +108,7 @@ describe('User Config', () => { await project.build({ configFile: 'test.config.ts' }); expect( - await project.fileExists('.custom-output/chrome-mv3/background.js'), + await project.pathExists('.custom-output/chrome-mv3/background.js'), ).toBe(true); }); @@ -129,13 +129,13 @@ describe('User Config', () => { await project.build(); expect( - await project.fileExists('.output/test-chrome-mv3-production-build'), + await project.pathExists('.output/test-chrome-mv3-production-build'), ).toBe(true); await project.build({ mode: 'development' }); expect( - await project.fileExists('.output/test-chrome-mv3-development-dev-build'), + await project.pathExists('.output/test-chrome-mv3-development-dev-build'), ).toBe(true); }); diff --git a/packages/wxt/e2e/tests/zip.test.ts b/packages/wxt/e2e/tests/zip.test.ts index c370097b..5a721e84 100644 --- a/packages/wxt/e2e/tests/zip.test.ts +++ b/packages/wxt/e2e/tests/zip.test.ts @@ -26,7 +26,7 @@ describe('Zipping', () => { browser: 'firefox', zip: { downloadPackages: ['flatten'] }, }); - expect(await project.fileExists('.output/')).toBe(true); + expect(await project.pathExists('.output/')).toBe(true); await extract(sourcesZip, { dir: unzipDir }); // Update package json wxt path @@ -51,7 +51,7 @@ describe('Zipping', () => { }), ).resolves.not.toHaveProperty('exitCode'); - await expect(project.fileExists(unzipDir, '.output')).resolves.toBe(true); + await expect(project.pathExists(unzipDir, '.output')).resolves.toBe(true); expect( await project.serializeFile( project.resolvePath(unzipDir, 'package.json'), @@ -95,8 +95,8 @@ describe('Zipping', () => { }, }); - expect(await project.fileExists(artifactZip)).toBe(true); - expect(await project.fileExists(sourcesZip)).toBe(true); + expect(await project.pathExists(artifactZip)).toBe(true); + expect(await project.pathExists(sourcesZip)).toBe(true); }); it('should not zip hidden files into sources by default', async () => { @@ -117,8 +117,8 @@ describe('Zipping', () => { browser: 'firefox', }); await extract(sourcesZip, { dir: unzipDir }); - expect(await project.fileExists(unzipDir, '.env')).toBe(false); - expect(await project.fileExists(unzipDir, '.hidden-dir/file')).toBe(false); + expect(await project.pathExists(unzipDir, '.env')).toBe(false); + expect(await project.pathExists(unzipDir, '.hidden-dir/file')).toBe(false); }); it('should not zip files inside hidden directories if only the directory is specified', async () => { @@ -142,8 +142,8 @@ describe('Zipping', () => { }, }); await extract(sourcesZip, { dir: unzipDir }); - expect(await project.fileExists(unzipDir, '.hidden-dir/file')).toBe(false); - expect(await project.fileExists(unzipDir, '.hidden-dir/nested/file')).toBe( + expect(await project.pathExists(unzipDir, '.hidden-dir/file')).toBe(false); + expect(await project.pathExists(unzipDir, '.hidden-dir/nested/file')).toBe( false, ); }); @@ -171,12 +171,12 @@ describe('Zipping', () => { }, }); await extract(sourcesZip, { dir: unzipDir }); - expect(await project.fileExists(unzipDir, '.env')).toBe(true); - expect(await project.fileExists(unzipDir, '.hidden-dir/file')).toBe(true); - expect(await project.fileExists(unzipDir, '.hidden-dir/nested/file1')).toBe( + expect(await project.pathExists(unzipDir, '.env')).toBe(true); + expect(await project.pathExists(unzipDir, '.hidden-dir/file')).toBe(true); + expect(await project.pathExists(unzipDir, '.hidden-dir/nested/file1')).toBe( true, ); - expect(await project.fileExists(unzipDir, '.hidden-dir/nested/file2')).toBe( + expect(await project.pathExists(unzipDir, '.hidden-dir/nested/file2')).toBe( true, ); }); @@ -210,10 +210,10 @@ describe('Zipping', () => { }); await extract(sourcesZip, { dir: unzipDir }); expect( - await project.fileExists(unzipDir, 'entrypoints/not-firefox.content.ts'), + await project.pathExists(unzipDir, 'entrypoints/not-firefox.content.ts'), ).toBe(false); expect( - await project.fileExists(unzipDir, 'entrypoints/all.content.ts'), + await project.pathExists(unzipDir, 'entrypoints/all.content.ts'), ).toBe(true); }); @@ -234,7 +234,7 @@ describe('Zipping', () => { browser, }); - expect(await project.fileExists(sourcesZip)).toBe(true); + expect(await project.pathExists(sourcesZip)).toBe(true); }, ); @@ -258,7 +258,7 @@ describe('Zipping', () => { }, }); - expect(await project.fileExists(sourcesZip)).toBe(true); + expect(await project.pathExists(sourcesZip)).toBe(true); }, ); @@ -282,7 +282,7 @@ describe('Zipping', () => { }, }); - expect(await project.fileExists(sourcesZip)).toBe(false); + expect(await project.pathExists(sourcesZip)).toBe(false); }, ); @@ -305,6 +305,6 @@ describe('Zipping', () => { }); await extract(sourcesZip, { dir: unzipDir }); - expect(await project.fileExists(unzipDir, 'manifest.json')).toBe(true); + expect(await project.pathExists(unzipDir, 'manifest.json')).toBe(true); }); }); diff --git a/packages/wxt/e2e/utils.ts b/packages/wxt/e2e/utils.ts index 8a44c985..9d2394af 100644 --- a/packages/wxt/e2e/utils.ts +++ b/packages/wxt/e2e/utils.ts @@ -185,8 +185,8 @@ export class TestProject { ].join(`\n${''.padEnd(40, '-')}\n`); } - fileExists(...path: string[]): Promise { - return fs.exists(this.resolvePath(...path)); + pathExists(...path: string[]): Promise { + return fs.pathExists(this.resolvePath(...path)); } async getOutputManifest( diff --git a/packages/wxt/src/core/builders/vite/plugins/resolveAppConfig.ts b/packages/wxt/src/core/builders/vite/plugins/resolveAppConfig.ts index e2b4e670..a76c2c3d 100644 --- a/packages/wxt/src/core/builders/vite/plugins/resolveAppConfig.ts +++ b/packages/wxt/src/core/builders/vite/plugins/resolveAppConfig.ts @@ -1,4 +1,4 @@ -import { exists } from 'fs-extra'; +import { pathExists } from 'fs-extra'; import { resolve } from 'node:path'; import type * as vite from 'vite'; import { ResolvedConfig } from '../../../../types'; @@ -25,7 +25,7 @@ export function resolveAppConfig(config: ResolvedConfig): vite.Plugin { async resolveId(id) { if (id !== virtualModuleId) return; - return (await exists(appConfigFile)) + return (await pathExists(appConfigFile)) ? appConfigFile : resolvedVirtualModuleId; }, diff --git a/packages/wxt/src/core/generate-wxt-dir.ts b/packages/wxt/src/core/generate-wxt-dir.ts index ad7aeb2e..921f1c13 100644 --- a/packages/wxt/src/core/generate-wxt-dir.ts +++ b/packages/wxt/src/core/generate-wxt-dir.ts @@ -136,7 +136,7 @@ declare module "wxt/browser" { 'messages.json', ); let messages: Message[]; - if (await fs.exists(defaultLocalePath)) { + if (await fs.pathExists(defaultLocalePath)) { const content = JSON.parse(await fs.readFile(defaultLocalePath, 'utf-8')); messages = parseI18nMessages(content); } else { diff --git a/packages/wxt/src/core/package-managers/__tests__/npm.test.ts b/packages/wxt/src/core/package-managers/__tests__/npm.test.ts index de2e8e2a..6117d946 100644 --- a/packages/wxt/src/core/package-managers/__tests__/npm.test.ts +++ b/packages/wxt/src/core/package-managers/__tests__/npm.test.ts @@ -2,7 +2,7 @@ import { beforeAll, describe, expect, it } from 'vitest'; import path from 'node:path'; import { npm } from '../npm'; import spawn from 'nano-spawn'; -import { exists } from 'fs-extra'; +import { pathExists } from 'fs-extra'; describe('NPM Package Management Utils', () => { describe('listDependencies', () => { @@ -41,7 +41,7 @@ describe('NPM Package Management Utils', () => { const actual = await npm.downloadDependency(id, downloadDir); expect(actual).toEqual(expected); - expect(await exists(actual)).toBe(true); + expect(await pathExists(actual)).toBe(true); }); }); }); diff --git a/packages/wxt/src/core/resolve-config.ts b/packages/wxt/src/core/resolve-config.ts index 5e14b4e8..574d535e 100644 --- a/packages/wxt/src/core/resolve-config.ts +++ b/packages/wxt/src/core/resolve-config.ts @@ -550,7 +550,7 @@ function resolveWxtModuleDir() { } async function isDirMissing(dir: string) { - return !(await fs.exists(dir)); + return !(await fs.pathExists(dir)); } function logMissingDir(logger: Logger, name: string, expected: string) { diff --git a/packages/wxt/src/core/utils/fs.ts b/packages/wxt/src/core/utils/fs.ts index ff9cdfdc..3d3f2887 100644 --- a/packages/wxt/src/core/utils/fs.ts +++ b/packages/wxt/src/core/utils/fs.ts @@ -28,7 +28,7 @@ export async function writeFileIfDifferent( * `config.publicDir`. */ export async function getPublicFiles(): Promise { - if (!(await fs.exists(wxt.config.publicDir))) return []; + if (!(await fs.pathExists(wxt.config.publicDir))) return []; const files = await glob('**/*', { cwd: wxt.config.publicDir }); return files.map(unnormalizePath); diff --git a/packages/wxt/vitest.globalSetup.ts b/packages/wxt/vitest.globalSetup.ts index 3847f26a..df29b053 100644 --- a/packages/wxt/vitest.globalSetup.ts +++ b/packages/wxt/vitest.globalSetup.ts @@ -1,4 +1,4 @@ -import { exists, rm } from 'fs-extra'; +import { pathExists, rm } from 'fs-extra'; let setupHappened = false; @@ -13,7 +13,7 @@ export async function setup() { globalThis.__ENTRYPOINT__ = 'test'; const e2eDistPath = './e2e/dist/'; - if (await exists(e2eDistPath)) { + if (await pathExists(e2eDistPath)) { await rm(e2eDistPath, { recursive: true, force: true }); } }