webext-core

website·Indexed 32 days ago

https://webext-core.aklinker1.io/

A collection of utilities for web extension development. The ecosystem includes @webext-core/fake-browser for unit testing with frameworks like Vitest, Jest, Bun, and Mocha, as well as @webext-core/proxy-service for defining services and protocol maps for type-safe messaging in TypeScript projects. Supports Manifest V2 and V3 across Chrome, Firefox, Safari, and Edge.

Tokens
10.7K
Snippets
71
Records
85
Agent score
61%

What's inside webext-core

  1. Overview of webext-core utility packages

    webext-core provides a suite of utilities designed to simplify the development and testing of web extensions across different browsers. Available packages include:

    • @webext-core/storage: A type-safe alternative to local storage for extension storage.
    • @webext-core/messaging: A simplified, type-safe API for message passing.
    • @webext-core/job-scheduler: Tools for scheduling and managing recurring jobs.
    • @webext-core/match-patterns: Utilities for handling extension match patterns.
    • @webext-core/proxy-service: Allows executing functions in different JavaScript contexts (e.g., calling a function from a content script that executes in the background).
    • @webext-core/isolated-element: Creates UI containers with styles isolated from the host page's CSS.
    • @webext-core/fake-browser: An in-memory implementation of web extension APIs used for testing purposes.
  2. Overview of @webext-core/isolated-element

    @webext-core/isolated-element provides a way to load UIs from content scripts without using iframes. It leverages the ShadowRoot API to ensure that the injected UI's CSS is completely separate from the host page and allows for control over event bubbling from the isolated element to the host page.
  3. Webext-core contribution guidelines and goals

    The project aims to provide quality utilities for web extensions across all browsers and manifest versions.

    Key requirements for new code:

    • Written in TypeScript with strong TS support.
    • Cross-browser compatibility.
    • High unit test coverage (near 100%).

    Contribution Process:

    • Bug fixes and doc improvements: Open a PR directly.
    • New packages or features: Open an issue first to ensure alignment with project goals before submitting a PR.
  4. Initialize @webext-core/fake-browser in a testing environment

    @webext-core/fake-browser is framework-agnostic and works with any testing framework. To set it up, import @webext-core/fake-browser/auto before using any browser APIs. This import assigns the global chrome and browser variables to fakeBrowser, which prevents polyfills from attempting to run and ensures the environment is recognized as a browser environment.
    import '@webext-core/fake-browser/auto';
  5. Send extension messages to specific tabs or frames

    When sending messages from a background script to a tab, you can target all frames in a tab by providing the tabId, or a specific frame by providing an object containing both tabId and frameId.
    import { sendMessage } from './messaging';
    
    // Send to all frames in the tab
    const length = await sendMessage('getStringLength', 'hello world', tabId);
    
    // Send to a specific frame in the tab
    const length = await sendMessage('getStringLength', 'hello world', { tabId, frameId });
  6. Install @webext-core without a bundler

    For projects not using a bundler, packages must be downloaded locally and shipped with the extension. This is required for Manifest V3 (MV3) because Google prohibits remotely hosted code (CDN URLs) for security reasons.

    Each package provides a minified IIFE build at dist/index.iife.js which creates a global variable to access the APIs. For example, @webext-core/storage provides the webExtCoreStorage global variable.

    # Create vendor directory and download the IIFE build
    mkdir -p vendor/webext-core
    curl -o vendor/webext-core/storage.js https://cdn.jsdelivr.net/npm/@webext-core/storage/dist/index.iife.js
  7. Install @webext-core/isolated-element via NPM or CDN

    You can install @webext-core/isolated-element using a package manager or by downloading the IIFE bundle from a CDN.
    # NPM
    pnpm i @webext-core/isolated-element
    
    # CDN
    curl -o isolated-element.js https://cdn.jsdelivr.net/npm/@webext-core/isolated-element/dist/index.iife.js
  8. Remove a scheduled job

    Use removeJob(id) to stop a job from running. This is critical when releasing updates where a job is no longer needed; if removeJob is not called, the internal alarm will persist even if scheduleJob is no longer called in the code.
    jobs.removeJob('some-old-job');
  9. Communicate via CustomEvents with defineCustomEventMessaging

    Use defineCustomEventMessaging to create a messenger backed by the CustomEvent API. This is primarily used for communication between a content script and a website, or between a content script and an injected script. Note that sendMessage for this messenger does not accept additional arguments.
    interface WebsiteMessengerSchema {
      initInjectedScript(data: any): void;
    }
    
    export const websiteMessenger = defineCustomEventMessaging<WebsiteMessengerSchema>({
      namespace: 'my-app-namespace' // Required via CustomEventMessagingConfig
    });
    
    // Content script
    websiteMessenger.sendMessage("initInjectedScript", { foo: 'bar' });
    
    // Injected script
    websiteMessenger.onMessage("initInjectedScript", (message) => {
      console.log(message.data);
    });
  10. Define type-safe service keys using ProxyServiceKey

    To ensure type-safety between a registered service and its proxy, cast the service key to a ProxyServiceKey<T> branded type. This removes the need to manually provide a type argument to createProxyService and guarantees that the registered service matches the expected type. It is highly recommended to store these keys as shared constants in a separate file.
    import type { ProxyServiceKey } from '@webext-core/proxy-service';
    
    // Define the key as a branded type
    const key = 'math-service' as ProxyServiceKey<MathService>;
    
    // Register the service
    registerService(key, new MathService());
    
    // Create the proxy (type is automatically inferred as MathService)
    const proxy = createProxyService(key);
  11. Set up development environment for webext-core

    To contribute to webext-core, you must have Bun installed. After forking the repository, initialize the project by installing dependencies and running the initial build.
    git clone {your-fork}
    cd webext-core
    bun i
    bun run build
  12. Install @webext-core/job-scheduler

    The @webext-core/job-scheduler library is compatible with Manifest V2 (MV2) and V3 (MV3) across Chrome, Firefox, and Safari. It can be installed via NPM or included via CDN.
    # NPM installation
    pnpm i @webext-core/job-scheduler
    
    # CDN installation
    curl -o job-scheduler.js https://cdn.jsdelivr.net/npm/@webext-core/job-scheduler/dist/index.iife.js