diff --git a/docs/guide/essentials/config/environment-variables.md b/docs/guide/essentials/config/environment-variables.md index e287b34a..35453433 100644 --- a/docs/guide/essentials/config/environment-variables.md +++ b/docs/guide/essentials/config/environment-variables.md @@ -42,6 +42,8 @@ WXT provides some custom environment variables based on the current command: | `import.meta.env.EDGE` | `boolean` | Equivalent to `import.meta.env.BROWSER === "edge"` | | `import.meta.env.OPERA` | `boolean` | Equivalent to `import.meta.env.BROWSER === "opera"` | +You can set the [`targetBrowsers`](/api/reference/wxt/interfaces/InlineConfig#targetbrowsers) option to make the `BROWSER` variable a more specific type, like `"chrome" | "firefox"`. + You can also access all of [Vite's environment variables](https://vite.dev/guide/env-and-mode.html#env-variables): | Usage | Type | Description | diff --git a/packages/wxt-demo/wxt.config.ts b/packages/wxt-demo/wxt.config.ts index eee9f5d3..d52e05bf 100644 --- a/packages/wxt-demo/wxt.config.ts +++ b/packages/wxt-demo/wxt.config.ts @@ -3,6 +3,7 @@ import { presetUno } from 'unocss'; export default defineConfig({ srcDir: 'src', + targetBrowsers: ['chrome', 'firefox', 'safari'], manifest: { permissions: ['storage'], default_locale: 'en', diff --git a/packages/wxt/e2e/tests/typescript-project.test.ts b/packages/wxt/e2e/tests/typescript-project.test.ts index de933ce7..4e32a383 100644 --- a/packages/wxt/e2e/tests/typescript-project.test.ts +++ b/packages/wxt/e2e/tests/typescript-project.test.ts @@ -396,6 +396,19 @@ describe('TypeScript Project', () => { expect(output).toContain('./example.ts'); }); + it('should set correct import.meta.env.BROWSER type based on targetBrowsers', async () => { + const project = new TestProject(); + project.addFile('entrypoints/unlisted.html', ''); + project.setConfigFileConfig({ + targetBrowsers: ['firefox', 'chrome'], + }); + + await project.prepare(); + + const output = await project.serializeFile('.wxt/types/globals.d.ts'); + expect(output).toContain('readonly BROWSER: "firefox" | "chrome";'); + }); + // TODO: Once a module has been published, use it here for testing - local files are never added to the .wxt/wxt.d.ts file it.todo( 'should add modules from NPM to the TS project if they have a configKey', diff --git a/packages/wxt/src/core/resolve-config.ts b/packages/wxt/src/core/resolve-config.ts index c062aa96..001884f9 100644 --- a/packages/wxt/src/core/resolve-config.ts +++ b/packages/wxt/src/core/resolve-config.ts @@ -70,6 +70,12 @@ export async function resolveConfig( if (debug) logger.level = LogLevels.debug; const browser = mergedConfig.browser ?? 'chrome'; + const targetBrowsers = mergedConfig.targetBrowsers ?? []; + if (targetBrowsers.length > 0 && !targetBrowsers.includes(browser)) { + throw new Error( + `Current target browser \`${browser}\` is not in your \`targetBrowsers\` list!`, + ); + } const manifestVersion = mergedConfig.manifestVersion ?? (browser === 'firefox' || browser === 'safari' ? 2 : 3); @@ -197,6 +203,7 @@ export async function resolveConfig( return { browser, + targetBrowsers, command, debug, entrypointsDir, diff --git a/packages/wxt/src/core/utils/globals.ts b/packages/wxt/src/core/utils/globals.ts index b5ff5fa8..5eeaecfe 100644 --- a/packages/wxt/src/core/utils/globals.ts +++ b/packages/wxt/src/core/utils/globals.ts @@ -12,7 +12,10 @@ export function getGlobals( { name: 'BROWSER', value: config.browser, - type: `string`, + type: + config.targetBrowsers.length === 0 + ? 'string' + : config.targetBrowsers.map((browser) => `"${browser}"`).join(' | '), }, { name: 'CHROME', diff --git a/packages/wxt/src/core/utils/testing/fake-objects.ts b/packages/wxt/src/core/utils/testing/fake-objects.ts index 46a75dd5..923113d3 100644 --- a/packages/wxt/src/core/utils/testing/fake-objects.ts +++ b/packages/wxt/src/core/utils/testing/fake-objects.ts @@ -235,6 +235,7 @@ export const fakeResolvedConfig = fakeObjectCreator(() => { return { browser, + targetBrowsers: [], command, entrypointsDir: fakeDir(), modulesDir: fakeDir(), diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index c4c3cbc6..7d394aa7 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -108,6 +108,12 @@ export interface InlineConfig { * "chrome" */ browser?: TargetBrowser; + /** + * Target browsers to support. When set, `import.meta.env.BROWSER` will be narrowed to a string literal type containing only the specified browser names. + * + * @default [] + */ + targetBrowsers?: TargetBrowser[]; /** * Explicitly set a manifest version to target. This will override the default manifest version * for each command, and can be overridden by the command line `--mv2` or `--mv3` option. @@ -1311,6 +1317,7 @@ export interface ResolvedConfig { mode: string; command: WxtCommand; browser: TargetBrowser; + targetBrowsers: TargetBrowser[]; manifestVersion: TargetManifestVersion; env: ConfigEnv; logger: Logger;