A typesafe and promise-based messaging for the browser extension.
Supports Chrome, Firefox, and Safari.
Utilizes runtime.sendMessage
, runtime.onMessage.addListener
, and runtime.onMessageExternal.addListener
.
npm install --save @vocably/hermes
The @vocably/hermes
exports 2 methods: createMessage
and createExternalMessage
.
createMessage
could be used for messaging between content script and service worker when extension ID is not necessary.
const [messageSender, messageSubscriber] = createMessage<
PayloadType,
ResponseType
>('messageIdentifier');
messageSender
function expects PayloadType
as the only param. PayloadType
could be void
. Returns Promise<ResponseType>
;
messageSubscriber
function should be used in Service Worker to receive data of PayloadType
, asynchronously process it, and return value of ResponseType
.
createExternalMessage
could be used for messaging between externally_connectable
URLs and service worker when extension ID is necessary.
const [messageSender, messageSubscriber] = createExternalMessage<
PayloadType,
ResponseType
>('messageIdentifier');
messageSender
function expects extensionId: string
as the first parameter and PayloadType
as the second. PayloadType
could be void
. Returns Promise<ResponseType>
;
messageSubscriber
function should be used in Service Worker to receive data of PayloadType
, asynchronously process it, and return value of ResponseType
.
Let's imagine we need to create a user, pass it to a Service Worker and wait for the response from the Service Worker.
// save-user.ts
import { createMessage } from '@vocably/hermes';
type User = {
id?: string;
name: string;
email: string;
};
type SaveUserResponse = {
id: string;
};
export const [saveUser, onSaveUserRequest] = createMessage<
User,
SaveUserResponse
>('saveUser');
// content-script.ts
import { saveUser } from './save-user.ts';
saveUser({
name: 'Speedy Gonzales',
email: 'speedy@disney.com',
}).then(({ id }) => {
console.log(`The saved user ID is ${id}`);
});
// sevice-worker.ts
import { onSaveUserRequest } from './save-user.ts';
onSaveUserRequest(async (sendResponse, user) => {
let id: string;
if (user.id) {
// api.updateUser should be implemmented
// individually. It's not a part of @vocably/hermes
await api.updateUser(user);
id = user.id;
} else {
// api.createUser should be implemmented
// individually. It's not a part of @vocably/hermes
id = await api.createUser(user);
}
// The callback function must return sendResponse() with the message return value passed into it.
return sendResponse({
id,
});
});