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

@wbet/message-api

v1.0.14

Published

Overcharged wrapper over the functions of chrome's/browser's message APIs

Downloads

23

Readme

Message API

Message API is a strongly typed wrapper that provides a modern API based on promises, compatible with both Chromium and Firefox Message API, while keeping their native performance.

It can be used with both the chrome and the browser namespace. If both are found the browser namespace takes priority to provide the best performance.

Regardless of the available namespace, all of the functions will return a promise if possible. For example runtime.sendMessage on Chrome uses a callback while on Firefox returns a promise, this library will return a promise for both of them.

It also provides easy to use functions specifically created to remove the clutter of manually crafted filters for the messages used to get to that specific one that triggers the desired functions. Lastly, it takes care of edge cases and errors like The message port closed before a response was received..

How to use

Interfaces

All the available interfaces will be presented bellow in an explicit way. For Typescript users all the generics have 'any' the default so no explicit declaration is actually needed.

interface Message<T> {
    data: T;
    source?: 'Content' | 'Background' | 'Popup' | 'Options';
    destination?: 'Content' | 'Background' | 'Popup' | 'Options';
    filters?: MessagePathFilter; //contains key value pairs with custom properties to filter on while receiving the message
}

interface MessagePath {
    source?: 'Content' | 'Background' | 'Popup' | 'Options';
    destination?: 'Content' | 'Background' | 'Popup' | 'Options';
    filters?: MessagePathFilter; //contains key value pairs with custom properties to filter on while receiving the message
}

interface MessagePathFilter {
    [filterName: string]: string | number | boolean;
}

interface MessageOptions {
    extensionId?: string; // required while sending a message to an extension (if not filled in it will send to your extension)
    options?:
        | {
              /** Whether the TLS channel ID will be passed into onMessageExternal for processes that are listening for the connection event. */
              includeTlsChannelId?: boolean;
          }
        | {
              /** Optional. Send a message to a specific frame identified by frameId instead of all frames in the tab. */
              frameId?: number;
          };
}
export type MessageReceivedCallback<TData = any, TResponseData = any> = (data: TData, sender: chrome.runtime.MessageSender | browser.runtime.MessageSender) => TResponseData | Promise<TResponseData> | undefined;

Enums

All the available enums will be presented bellow:

export enum MessageLocation {
    Content = 'Content',
    Background = 'Background',
    Popup = 'Popup',
    Options = 'Options'
}
// used as a normal object with properties

MessageLocation.Popup;

Send message

These functions wraps both runtime.sendMessage and tabs.sendMessage APIs. They are used to send a message to content and background scripts or to different extensions or to different parts of your extension such as popup and options pages:

Typescript

function sendMessageToBackground<TData = any, TResponseData = any>(data: TData, source: MessageLocation, messageOptions?: MessageOptions, filters?: MessagePathFilter): Promise<TResponseData>;

function sendMessageToOptions<TData = any, TResponseData = any>(data: TData, source: MessageLocation, messageOptions?: MessageOptions, filters?: MessagePathFilter): Promise<TResponseData>;

function sendMessageToPopup<TData = any, TResponseData = any>(data: TData, source: MessageLocation, messageOptions?: MessageOptions, filters?: MessagePathFilter): Promise<TResponseData>;

function sendMessageToContentScript<TData = any, TResponseData = any>(tabId: number, data: TData, source: MessageLocation, messageOptions?: MessageOptions, filters?: MessagePathFilter): Promise<TResponseData>;

function sendMessageToCurrentWebPage<TData = any, TResponseData = any>(data: TData, source: MessageLocation, messageOptions?: MessageOptions, filters?: MessagePathFilter): Promise<TResponseData>;

function sendMessageTo<TData = any, TResponseData = any>(message: Message<TData>, messageOptions?: MessageOptions, tabId?: number): Promise<TResponseData>;

Javascript

function sendMessageToBackground(data, source, messageOptions, filters)

function sendMessageToOptions(data, source, messageOptions, filters)

function sendMessageToPopup(data, source, messageOptions, filters)

function sendMessageToContentScript(tabId, data, source, messageOptions, filters)

function sendMessageToCurrentWebPage(data, source, messageOptions, filters)

function sendMessageTo(message, messageOptions, tabId)

Example

//simple use case
sendMessageToBackground('message', MessageLocation.Popup);
// or
sendMessageToBackground('message', 'Popup');

// more complex use case
sendMessageToBackground('message', MessageLocation.Popup, {}, { name: 'messageForSpecificCase', numberFilter: 30, isFiltered: true });

// with response handle
sendMessageToBackground('message', 'Popup').then((response) => {
    // processing response
});

// with response handle of known type
sendMessageToBackground<{ name: string; age: number }>('message', 'Popup').then((response) => {
    // processing response of type {name:string, age:number}
});

// custom use case - where we can set no source or destination and just use specific custom filters
sendMessageTo({ data: 'message' }, {}, { filter: 'filter data' });

// custom use case - where we can set a source or destination if we want
sendMessageTo({ data: 'message' }, {}, { filter: 'filter data' });

//others
sendMessageTo({ data: 'message' }, { extensionId: 'id' }, { filter: 'filter data' });
sendMessageTo({ data: 'message' }, { extensionId: 'id', options: { frameId: 'frameId' } }, { filter: 'filter data' });
sendMessageTo({ data: 'message' }, { extensionId: 'id', options: { includeTlsChannelId: 'true' } }, { filter: 'filter data' });

Receive message

These functions wraps both runtime.sendMessage and tabs.sendMessage APIs. They are used to send a message to content and background scripts or to different extensions or to different parts of your extension such as popup and options pages:

Typescript

function onMessageFromBackground<TData = any, TResponseData = any>(currentLocation: MessageLocation, filters: MessagePathFilter, callback: MessageReceivedCallback<TData, TResponseData>): void;

function onMessageFromOptions<TData = any, TResponseData = any>(currentLocation: MessageLocation, filters: MessagePathFilter, callback: MessageReceivedCallback<TData, TResponseData>): void;

function onMessageFromPopup<TData = any, TResponseData = any>(currentLocation: MessageLocation, filters: MessagePathFilter, callback: MessageReceivedCallback<TData, TResponseData>): void;

function onMessageFromContentScript<TData = any, TResponseData = any>(currentLocation: MessageLocation, filters: MessagePathFilter, callback: MessageReceivedCallback<TData, TResponseData>): void;

function onMessageAnywhere<TData = any, TResponseData = any>(filters: MessagePathFilter, callback: MessageReceivedCallback<TData, TResponseData>): void;

function onMessage<TData = any, TResponseData = any>(messagePath: MessagePath, callback: MessageReceivedCallback<TData, TResponseData>): void;

Javascript

function onMessageFromBackground(currentLocation, filters, callback)

function onMessageFromOptions(currentLocation, filters, callback)

function onMessageFromPopup(currentLocation, filters, callback)

function onMessageFromContentScript(currentLocation, filters, callback)

function onMessageAnywhere(filters, callback)

function onMessage(messagePath, callback)

Example

// default use case where no type is defined - assumptions currentLocation is the popup page and no filters
onMessageFromBackground(MessageLocation.Popup, {}, (data, sender, sendResponse) => {
    // sender has the sender info
    // data has the any type
    // sendResponse can be called to return a response to the sender
    // e.g
    const modifiedData = data.age + 1;
    sendResponse(modifiedData);
});

// use case with type definitions
onMessageFromBackground<{ name: string; age: number }, number>(MessageLocation.Popup, {}, (data, sender, sendResponse) => {
    // sender has the sender info
    // data has the {name:string, age:number} type
    // sendResponse can be called to return a response to the sender with the number type
    // e.g
    const modifiedData = data.age + 1;
    sendResponse(modifiedData);
});

// use case with type definitions and filters
onMessageFromBackground<{ name: string; age: number }, number>(MessageLocation.Popup, { name: 'AgentX' }, (data, sender, sendResponse) => {
    // only messages sent to the popup from the background script coming from 'AgentX' will pass through
});

//simple use case - only process the data
onMessageFromBackground(MessageLocation.Popup, {}, (data: TData) => {
    // process data
});

//custom use case - similar with the ones above
onMessage({ source: MessageLocation.Background, destination: MessageLocation.Popup, filters: { name: 'AgentX' } }, (data, sender, sendResponse) => {
    // sender has the sender info
    // data has the {name:string, age:number} type
    // sendResponse can be called to return a response to the sender with the number type
    // e.g
    const modifiedData = data.age + 1;
    sendResponse(modifiedData);
});

//custom use case - similar with the ones above but with no source or destination
onMessage({ filters: { name: 'AgentX' } }, (data, sender, sendResponse) => {
    // sender has the sender info
    // data has the {name:string, age:number} type
    // sendResponse can be called to return a response to the sender with the number type
    // e.g
    const modifiedData = data.age + 1;
    sendResponse(modifiedData);
});

Importing the library

This library is available both as an unminified ES6 module and as a minfied libraries created by webpack.

  • Using the unminified ES6 module each individual functions can be imported own their own. This is very useful if you use modern TS/JS, especially with a bundling system that can remove unused functions.
import { onMessage } from '@wbet/message-api/message-receiver';
  • The minified libraries are compatible with ES6, AMD, CommonJS and the script tag.
// import using CommonJS(in nodeJS)
const messageApi = require('@wbet/message-api');

// import using AMD
require(['messageApi'], (messageApi) => {
    // ...
});

// import using ES6 modules
import * as messageApi from '@wbet/message-api';
// import using the script tag - importing minified UML - I will use relative paths to exemplify
<script src="./dist/umd/index.min.js"></script>
<script>
    // The 'messageApi' library is added as a property to the window object
    window.messageApi.sendMessage(...)
    // ...
</script>

// import using the script tag - importing minified script from the Web folder - I will use relative paths to exemplify
<script src="./dist/web/index.min.js"></script>
<script>
     // The 'messageApi' library is saved in a global variable
    messageApi.sendMessage(...)
</script>

// if you want to load the script from a CDN you can use
<script src="https://unpkg.com/@wbet/message-api/dist/umd/index.min.js"></script>

// or
<script src="https://unpkg.com/@wbet/message-api/dist/web/index.min.js"></script>

Final note

This library will be improved over time with APIs like connect and sendNativeMessage.

If you found any bug please open an issue and it will be addressed as soon as humanly possible.

Changelog

1.0.10

  • Added actions and action types. Actions are a map of functions to trigger as callback if the type is matched. Actions are optional.
  • Small fixes

1.0.5