npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@webext-pegasus/transport

v0.3.6

Published

Turns surface specific browser APIs into unified transport layer

Downloads

2,795

Readme

webext-pegasus Logo

@webext-pegasus/transport

License GitHub Actions Workflow Status Package version

Sending messages and events in web extensions has never been easier. Batteries included 🔋🔋🔋

Turns surface specific browser APIs into unified transport layer. So you can seamlessly communicate between all extension contexts (including injected script/window). Promotes code reusability by enabling reuse of the components that rely on messages/events between dfferent extension contexts.

No more chrome.runtime.sendMessage or chrome.runtime.onConnect or window.dispatchEvent

This library provides two communication patterns:

  • One-on-one messaging with optional replies – via definePegasusMessageBus API. Resilient way of communication between any 2 contexts. Ex: DevTools panel and injected script within instected tab.
  • Event broadcasting – via definePegasusEventBus API. This allows you to inform other extension contexts about certains events. Ex: broadcast changes to all open tabs

Supports

  • Runtime contexts: window (injected script), popup, devtools, content script, background, options, sidepanel (planned)
  • Browsers: Chrome, Firefox, Safari, Opera, Edge + others supported by webextension-polyfill

Comparison to other libraries

| | @webext-pegasus/transport | webext-bridge| @webext-core/messaging | |----------------------------------|-----------------------------|----------------|--------------------------| | Injected script (window) support | ✅ | ✅ | 🌦️ | | One-on-one messaging | ✅ | ✅ | ✅ | | Event Broadcasting | ✅ | ❌ | ❌ | | Context agnostic APIs | ✅ | ❌ | 🌦️ | | Type Safety | ✅ | 🌦️ | ✅ |

🚀 Quick Start

npm install -S @webext-pegasus/transport

Initialize Pegasus transport layer once for every runtime context you use in your extension.

// background.ts + once per all other extension contexts
import { initPegasusTransport } from '@webext-pegasus/transport/background';

initPegasusTransport();
// You can use all other Pegasus packages after it

As soon as Pegasus Transport was initialized - all other code that relies on transport layer may simply do the following:

import {definePegasusEventBus, definePegasusMessageBus} from '@webext-pegasus/transport';

// Message Bus
interface ITestMessageBus {
  stringLength(data: string): number;
}
const messageBus = definePegasusMessageBus<ITestEventBus>();
messageBus.onMessage('stringLength', (message) => {
  return message.data.length;
});
messageBus.sendMessage(
  'stringLength',
  'some string',
  'background', // Destination of the message
);

// Event Bus
interface ITestEventBus {
  testEvent: string;
}
const eventBus = definePegasusEventBus<ITestEventBus>();
eventBus.onBroadcastEvent('testEvent', (message) => {
  console.log('received test-event with', message.data, 'from', message.sender);
});
eventBus.emitBroadcastEvent(
  'testEvent',
  'Hello world from background script!',
);

Available entrypoints:

  • @webext-pegasus/transport/background
  • @webext-pegasus/transport/content-script
  • @webext-pegasus/transport/devtools
  • @webext-pegasus/transport/options
  • @webext-pegasus/transport/popup
  • @webext-pegasus/transport/window (for injected scripts)

Troubleshooting

  • Doesn't work?

    If window contexts are not part of the puzzle, it shall out of the box for messaging between devtools <-> background <-> content-script(s). If even that is not working, it's likely that @webext-pegasus/transport hasn't been initialized in background page of your extension, which is used as a relay for all events/messages. If you don't need a background page for yourself, here's bare minimum to get Pegasus flying.

// background.js (requires transpilation/bundling using webpack(recommended))

import { initPegasusTransport } from '@webext-pegasus/transport/background';
initPegasusTransport();
// manifest.json

{
  "background": {
    "scripts": ["path/to/transpiled/background.js"]
  }
}
  • Can't send messages to / receive from window?

    Sending or receiving messages from or to window requires you to open the messaging gateway in content script(s) for that particular tab. Call initPegasusTransport({allowWindowMessagingForNamespace: '...'}) while passing allowWindowMessagingForNamespace option in any of your content script(s) in that tab and call initPegasusTransport({namespace: '...'}) in the script loaded in top frame i.e the window context. Make sure that namespaceA === namespaceB. If you're doing this, read the security note below

Security risks while communicating with injected script

The following note only applies if and only if, you will be sending/receiving messages to/from window contexts. There's no security concern if you will be only working with content-script, background, popup, options, or devtools scope, which is the default setting.

window context(s) in tab A get unlocked the moment you call initPegasusTransport({allowWindowMessagingForNamespace: 'TEST'}) in your extension's content script AND initPegasusTransport({namespace: 'TEST'}) in your injected script.

Unlike chrome.runtime.sendMessage and chrome.runtime.connect, which requires extension's manifest to specify sites allowed to talk with the extension, this package has no such measure by design, which means any webpage whether you intended or not, can do sendMessage(msgId, data, 'background') or something similar that produces same effect, as long as it uses same protocol used by this library and namespace set to same as yours.

So to be safe, if you will be interacting with window contexts, treat incoming data as you would treat user input.

As an example if you plan on having something critical, always verify the sender before responding:

// background.js

import { onMessage } from '@webext-pegasus/transport/background';

onMessage("getUserBrowsingHistory", (message) => {
  const { data, sender } = message;
  // Respond only if request is from 'devtools', 'content-script', 'popup', 'options', or 'background' endpoint
});

Credits

This library is based on the Server Side Up's implementation of the webext-bridge in context of RPC stack. However it simplifies use of the sendMessage/onMessage APIs in conponents that may be present within different runtime contexts.