From 6a52bb22a343b5149429f9a3497898d67385e0cd Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 2 May 2025 08:41:02 -0500 Subject: [PATCH] fix: Use `@wxt-dev/browser` instead of `@types/chrome` (#1645) --- .../analytics/modules/analytics/client.ts | 15 ++++++----- packages/analytics/package.json | 2 +- packages/analytics/tsconfig.json | 3 +-- packages/i18n/package.json | 2 +- packages/i18n/src/__tests__/index.test.ts | 17 +++++++----- packages/i18n/src/__tests__/types.test.ts | 17 +++++++----- packages/i18n/src/index.ts | 5 ++-- packages/i18n/tsconfig.json | 2 +- packages/storage/package.json | 2 +- packages/storage/src/__tests__/index.test.ts | 7 ++--- packages/storage/src/index.ts | 11 ++------ packages/storage/tsconfig.json | 3 +-- pnpm-lock.yaml | 26 +++++++------------ 13 files changed, 54 insertions(+), 58 deletions(-) diff --git a/packages/analytics/modules/analytics/client.ts b/packages/analytics/modules/analytics/client.ts index f97457a5..7eae5923 100644 --- a/packages/analytics/modules/analytics/client.ts +++ b/packages/analytics/modules/analytics/client.ts @@ -9,11 +9,12 @@ import type { AnalyticsEventMetadata, AnalyticsProvider, } from './types'; +import { browser } from '@wxt-dev/browser'; const ANALYTICS_PORT = '@wxt-dev/analytics'; export function createAnalytics(config?: AnalyticsConfig): Analytics { - if (typeof chrome === 'undefined' || !chrome?.runtime?.id) + if (!browser?.runtime?.id) throw Error( 'Cannot use WXT analytics in contexts without access to the browser.runtime APIs', ); @@ -51,13 +52,13 @@ function createBackgroundAnalytics( defineStorageItem('local:wxt-analytics:enabled', false); // Cached values - const platformInfo = chrome.runtime.getPlatformInfo(); + const platformInfo = browser.runtime.getPlatformInfo(); const userAgent = UAParser(); let userId = Promise.resolve(userIdStorage.getValue()).then( (id) => id ?? globalThis.crypto.randomUUID(), ); let userProperties = userPropertiesStorage.getValue(); - const manifest = chrome.runtime.getManifest(); + const manifest = browser.runtime.getManifest(); const getBackgroundMeta = () => ({ timestamp: Date.now(), @@ -178,7 +179,7 @@ function createBackgroundAnalytics( config?.providers?.map((provider) => provider(analytics, config)) ?? []; // Listen for messages from the rest of the extension - chrome.runtime.onConnect.addListener((port) => { + browser.runtime.onConnect.addListener((port) => { if (port.name === ANALYTICS_PORT) { port.onMessage.addListener(({ fn, args }) => { // @ts-expect-error: Untyped fn key @@ -194,7 +195,7 @@ function createBackgroundAnalytics( * Creates an analytics client for non-background contexts. */ function createFrontendAnalytics(): Analytics { - const port = chrome.runtime.connect({ name: ANALYTICS_PORT }); + const port = browser.runtime.connect({ name: ANALYTICS_PORT }); const sessionId = Date.now(); const getFrontendMetadata = (): AnalyticsEventMetadata => ({ sessionId, @@ -252,8 +253,8 @@ function defineStorageItem( ): AnalyticsStorageItem { return { getValue: async () => - (await chrome.storage.local.get(key))[key] ?? defaultValue, - setValue: (newValue) => chrome.storage.local.set({ [key]: newValue }), + (await browser.storage.local.get(key))[key] ?? defaultValue, + setValue: (newValue) => browser.storage.local.set({ [key]: newValue }), }; } diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 355e13d1..1e48c27d 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -52,7 +52,6 @@ }, "devDependencies": { "@aklinker1/check": "2.0.0", - "@types/chrome": "^0.0.313", "@types/ua-parser-js": "^0.7.39", "publint": "^0.3.12", "typescript": "^5.8.3", @@ -60,6 +59,7 @@ "wxt": "workspace:*" }, "dependencies": { + "@wxt-dev/browser": "workspace:*", "ua-parser-js": "^1.0.40" } } diff --git a/packages/analytics/tsconfig.json b/packages/analytics/tsconfig.json index 9d173da1..75b85ae5 100644 --- a/packages/analytics/tsconfig.json +++ b/packages/analytics/tsconfig.json @@ -3,8 +3,7 @@ "compilerOptions": { "paths": { "#analytics": ["./.wxt/analytics/index.ts"] - }, - "types": ["chrome"] + } }, "exclude": ["node_modules", "dist"] } diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 8418f501..32754d18 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -26,6 +26,7 @@ "test": "buildc --deps-only -- vitest" }, "dependencies": { + "@wxt-dev/browser": "workspace:*", "chokidar": "^4.0.3", "confbox": "^0.1.8 || ^0.2.2", "fast-glob": "^3.3.3" @@ -40,7 +41,6 @@ }, "devDependencies": { "@aklinker1/check": "2.0.0", - "@types/chrome": "^0.0.313", "@types/node": "^20.17.6", "oxlint": "^0.16.8", "publint": "^0.3.12", diff --git a/packages/i18n/src/__tests__/index.test.ts b/packages/i18n/src/__tests__/index.test.ts index 2ffc37f6..11ed8d60 100644 --- a/packages/i18n/src/__tests__/index.test.ts +++ b/packages/i18n/src/__tests__/index.test.ts @@ -1,13 +1,18 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { createI18n } from '../index'; +import { browser } from '@wxt-dev/browser'; -const getMessageMock = vi.fn(); - -vi.stubGlobal('chrome', { - i18n: { - getMessage: getMessageMock, - }, +vi.mock('@wxt-dev/browser', async () => { + const { vi } = await import('vitest'); + return { + browser: { + i18n: { + getMessage: vi.fn(), + }, + }, + }; }); +const getMessageMock = vi.mocked(browser.i18n.getMessage); describe('createI18n', () => { beforeEach(() => { diff --git a/packages/i18n/src/__tests__/types.test.ts b/packages/i18n/src/__tests__/types.test.ts index 6c7999bc..54073209 100644 --- a/packages/i18n/src/__tests__/types.test.ts +++ b/packages/i18n/src/__tests__/types.test.ts @@ -1,13 +1,18 @@ import { beforeEach, describe, it, vi } from 'vitest'; import { createI18n } from '..'; +import { browser } from '@wxt-dev/browser'; -const getMessageMock = vi.fn(); - -vi.stubGlobal('chrome', { - i18n: { - getMessage: getMessageMock, - }, +vi.mock('@wxt-dev/browser', async () => { + const { vi } = await import('vitest'); + return { + browser: { + i18n: { + getMessage: vi.fn(), + }, + }, + }; }); +const getMessageMock = vi.mocked(browser.i18n.getMessage); const n: number = 1; diff --git a/packages/i18n/src/index.ts b/packages/i18n/src/index.ts index b5b01b9a..559083b0 100644 --- a/packages/i18n/src/index.ts +++ b/packages/i18n/src/index.ts @@ -7,6 +7,7 @@ import { I18n, Substitution, } from './types'; +import { browser } from '@wxt-dev/browser'; export function createI18n< T extends I18nStructure = DefaultI18nStructure, @@ -39,9 +40,9 @@ export function createI18n< if (sub?.length) { // Convert all substitutions to strings const stringSubs = sub?.map((sub) => String(sub)); - message = chrome.i18n.getMessage(key.replaceAll('.', '_'), stringSubs); + message = browser.i18n.getMessage(key.replaceAll('.', '_'), stringSubs); } else { - message = chrome.i18n.getMessage(key.replaceAll('.', '_')); + message = browser.i18n.getMessage(key.replaceAll('.', '_')); } if (!message) { console.warn(`[i18n] Message not found: "${key}"`); diff --git a/packages/i18n/tsconfig.json b/packages/i18n/tsconfig.json index 7d7d8a78..46e1f61f 100644 --- a/packages/i18n/tsconfig.json +++ b/packages/i18n/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "types": ["chrome", "node"] + "types": ["node"] }, "exclude": ["node_modules/**", "dist/**"] } diff --git a/packages/storage/package.json b/packages/storage/package.json index ca704c12..0835e37d 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -30,12 +30,12 @@ "test": "buildc --deps-only -- vitest" }, "dependencies": { + "@wxt-dev/browser": "workspace:*", "async-mutex": "^0.5.0", "dequal": "^2.0.3" }, "devDependencies": { "@aklinker1/check": "2.0.0", - "@types/chrome": "^0.0.313", "@webext-core/fake-browser": "^1.3.2", "oxlint": "^0.16.8", "publint": "^0.3.12", diff --git a/packages/storage/src/__tests__/index.test.ts b/packages/storage/src/__tests__/index.test.ts index faa1bc5a..200de6aa 100644 --- a/packages/storage/src/__tests__/index.test.ts +++ b/packages/storage/src/__tests__/index.test.ts @@ -1,6 +1,7 @@ import { fakeBrowser } from '@webext-core/fake-browser'; import { describe, it, expect, beforeEach, vi, expectTypeOf } from 'vitest'; import { MigrationError, type WxtStorageItem, storage } from '../index'; +import { browser } from '@wxt-dev/browser'; /** * This works because fakeBrowser is synchronous, and is will finish any number of chained @@ -222,7 +223,7 @@ describe('Storage Utils', () => { describe('setMeta', () => { it('should set metadata at key+$', async () => { const existing = { v: 1 }; - await chrome.storage[storageArea].set({ count$: existing }); + await browser.storage[storageArea].set({ count$: existing }); const newValues = { date: Date.now(), }; @@ -238,7 +239,7 @@ describe('Storage Utils', () => { 'should remove any properties set to %s', async (version) => { const existing = { v: 1 }; - await chrome.storage[storageArea].set({ count$: existing }); + await browser.storage[storageArea].set({ count$: existing }); const expected = {}; await storage.setMeta(`${storageArea}:count`, { v: version }); @@ -1265,7 +1266,7 @@ describe('Storage Utils', () => { await item.removeValue(); // Make sure it's actually blank before running the test - expect(await chrome.storage.local.get()).toEqual({}); + expect(await browser.storage.local.get()).toEqual({}); init.mockClear(); const [value1, value2] = await Promise.all([ diff --git a/packages/storage/src/index.ts b/packages/storage/src/index.ts index fe2d66c3..76e43825 100644 --- a/packages/storage/src/index.ts +++ b/packages/storage/src/index.ts @@ -1,4 +1,3 @@ -/// /** * Simplified storage APIs with support for versioned fields, snapshots, metadata, and item definitions. * @@ -7,13 +6,7 @@ */ import { dequal } from 'dequal/lite'; import { Mutex } from 'async-mutex'; - -const browser: typeof chrome = - // @ts-expect-error - globalThis.browser?.runtime?.id == null - ? globalThis.chrome - : // @ts-expect-error - globalThis.browser; +import { browser, type Browser } from '@wxt-dev/browser'; export const storage = createStorage(); @@ -897,7 +890,7 @@ export interface WxtStorageItemOptions { } export type StorageAreaChanges = { - [key: string]: chrome.storage.StorageChange; + [key: string]: Browser.storage.StorageChange; }; /** diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json index 1d1ddb7f..0b19846f 100644 --- a/packages/storage/tsconfig.json +++ b/packages/storage/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "verbatimModuleSyntax": true, - "types": ["chrome"] + "verbatimModuleSyntax": true }, "exclude": ["node_modules/**", "dist/**"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfab4c3b..7af7c095 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,6 +100,9 @@ importers: packages/analytics: dependencies: + '@wxt-dev/browser': + specifier: workspace:* + version: link:../browser ua-parser-js: specifier: ^1.0.40 version: 1.0.40 @@ -107,9 +110,6 @@ importers: '@aklinker1/check': specifier: 2.0.0 version: 2.0.0 - '@types/chrome': - specifier: ^0.0.313 - version: 0.0.313 '@types/ua-parser-js': specifier: ^0.7.39 version: 0.7.39 @@ -187,6 +187,9 @@ importers: packages/i18n: dependencies: + '@wxt-dev/browser': + specifier: workspace:* + version: link:../browser chokidar: specifier: ^4.0.3 version: 4.0.3 @@ -200,9 +203,6 @@ importers: '@aklinker1/check': specifier: 2.0.0 version: 2.0.0 - '@types/chrome': - specifier: ^0.0.313 - version: 0.0.313 '@types/node': specifier: ^20.17.6 version: 20.17.30 @@ -336,6 +336,9 @@ importers: packages/storage: dependencies: + '@wxt-dev/browser': + specifier: workspace:* + version: link:../browser async-mutex: specifier: ^0.5.0 version: 0.5.0 @@ -346,9 +349,6 @@ importers: '@aklinker1/check': specifier: 2.0.0 version: 2.0.0 - '@types/chrome': - specifier: ^0.0.313 - version: 0.0.313 '@webext-core/fake-browser': specifier: ^1.3.2 version: 1.3.2 @@ -1866,9 +1866,6 @@ packages: '@types/babel__traverse@7.20.6': resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - '@types/chrome@0.0.313': - resolution: {integrity: sha512-9R5T7gTaYZhkxlu+Ho4wk9FL+y/werWQY2yjGWSqCuiTsqS7nL/BE5UMTP6rU7J+oIG2FRKqrEycHhJATeltVA==} - '@types/chrome@0.0.318': resolution: {integrity: sha512-rrtyYQ1t+g7EyG0FejE+UXQBjSGUHGh0RIdXwUT/laPo9T724NOIgXA94ns6ewmNauwijYa5ck3+dBxWnHcynQ==} @@ -5917,11 +5914,6 @@ snapshots: dependencies: '@babel/types': 7.27.0 - '@types/chrome@0.0.313': - dependencies: - '@types/filesystem': 0.0.36 - '@types/har-format': 1.2.15 - '@types/chrome@0.0.318': dependencies: '@types/filesystem': 0.0.36