Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

post-me

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

post-me - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

dist/messenger.d.ts

7

dist/connection.d.ts
import { IdType } from './common';
import { Messenger } from './messenger';
import { LocalHandle, RemoteHandle, MethodsType, EventsType } from './handle';
import { Message } from './message';
export interface Connection<E0 extends EventsType = {}, M1 extends MethodsType = {}, E1 extends EventsType = {}> {

@@ -12,4 +12,3 @@ sessionId: () => IdType;

private _localMethods;
private _postMessage;
private _addMessageListener;
private _messenger;
private _removeMainListener;

@@ -21,3 +20,3 @@ private _sessionId;

private _eventListeners;
constructor(localMethods: M0, postMessage: (message: Message<any>) => void, addMessageListener: (listener: (event: MessageEvent) => void) => () => void, sessionId: number);
constructor(localMethods: M0, messenger: Messenger, sessionId: number);
localHandle(): LocalHandle<{}>;

@@ -24,0 +23,0 @@ remoteHandle(): RemoteHandle<{}, {}>;

import { MethodsType } from './handle';
import { Messenger } from './messenger';
import { Connection } from './connection';
export declare const HANDSHAKE_SUCCESS = "@post-me/handshake-success";
export declare function ParentHandshake<M0 extends MethodsType>(localMethods: M0, otherWindow: Window | Worker, acceptedOrigin: string, _thisWindow?: Window | DedicatedWorkerGlobalScope): Promise<Connection>;
export declare function ChildHandshake<M0 extends MethodsType>(localMethods: M0, acceptedOrigin: string, _thisWindow?: Window | DedicatedWorkerGlobalScope): Promise<Connection>;
export declare function ParentHandshake<M0 extends MethodsType>(localMethods: M0, messenger: Messenger, maxAttempts?: number, attemptsInterval?: number): Promise<Connection>;
export declare function ChildHandshake<M0 extends MethodsType>(localMethods: M0, messenger: Messenger): Promise<Connection>;
import { ParentHandshake, ChildHandshake } from './handshake';
import { Connection } from './connection';
import { Messenger, WindowMessenger, WorkerMessenger } from './messenger';
import { RemoteHandle, LocalHandle } from './handle';
export { ParentHandshake, ChildHandshake, Connection, RemoteHandle, LocalHandle, };
export { ParentHandshake, ChildHandshake, Connection, RemoteHandle, LocalHandle, Messenger, WindowMessenger, WorkerMessenger, };

@@ -83,3 +83,3 @@ var MessageType;

class ConcreteConnection {
constructor(localMethods, postMessage, addMessageListener, sessionId) {
constructor(localMethods, messenger, sessionId) {
this.onMessage = (ev) => {

@@ -185,4 +185,3 @@ const { data } = ev;

this._localMethods = localMethods;
this._postMessage = postMessage;
this._addMessageListener = addMessageListener;
this._messenger = messenger;
this._sessionId = sessionId;

@@ -199,3 +198,3 @@ this._requests = {};

};
this._removeMainListener = this._addMessageListener(this.onMessage);
this._removeMainListener = this._messenger.addMessageListener(this.onMessage);
}

@@ -215,12 +214,6 @@ localHandle() {

sendMessage(message) {
this._postMessage(message);
this._messenger.postMessage(message);
}
}
function isWindow(w) {
return globalThis.Window
? w.constructor.name === globalThis.Window.name
: false;
}
const uniqueSessionId = (() => {

@@ -235,70 +228,18 @@ let __sessionId = 0;

const HANDSHAKE_SUCCESS = '@post-me/handshake-success';
const makeWindowPostMessage = (w, origin) => {
return (message) => {
w.postMessage(message, origin);
};
};
const makeWorkerPostMessage = (w) => {
return (message) => {
w.postMessage(message);
};
};
const makeWindowAddMessageListener = (w, acceptedOrigin) => {
const acceptEvent = (event) => {
const { origin } = event;
if (origin !== acceptedOrigin && acceptedOrigin !== '*') {
return false;
const runUntil = (worker, condition, maxAttempts, attemptInterval) => {
let attempt = 0;
const fn = () => {
if (!condition() && (attempt < maxAttempts || maxAttempts < 1)) {
worker();
attempt += 1;
setTimeout(fn, attemptInterval);
}
return true;
};
return (listener) => {
const outerListener = (event) => {
if (acceptEvent(event)) {
listener(event);
}
};
w.addEventListener('message', outerListener);
const removeListener = () => {
w.removeEventListener('message', outerListener);
};
return removeListener;
};
fn();
};
const makeWorkerAddMessageListener = (w) => {
return (listener) => {
const outerListener = (event) => {
{
listener(event);
}
};
w.addEventListener('message', outerListener);
const removeListener = () => {
w.removeEventListener('message', outerListener);
};
return removeListener;
};
};
function ParentHandshake(localMethods, otherWindow, acceptedOrigin, _thisWindow) {
const thisWindow = _thisWindow || window;
function ParentHandshake(localMethods, messenger, maxAttempts = 5, attemptsInterval = 50) {
const thisSessionId = uniqueSessionId();
return new Promise((resolve, reject) => {
let postMessage;
let addMessageListener;
if (isWindow(otherWindow)) {
postMessage = makeWindowPostMessage(otherWindow, acceptedOrigin);
}
else {
postMessage = makeWorkerPostMessage(otherWindow);
}
if (isWindow(thisWindow) && isWindow(otherWindow)) {
addMessageListener = makeWindowAddMessageListener(thisWindow, acceptedOrigin);
}
if (isWindow(thisWindow) && !isWindow(otherWindow)) {
addMessageListener = makeWorkerAddMessageListener(otherWindow);
}
if (postMessage === undefined || addMessageListener === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
let removeHandshakeListener;
let connected = false;
const handshakeListener = (event) => {

@@ -311,52 +252,80 @@ const { data } = event;

result === HANDSHAKE_SUCCESS) {
connected = true;
removeHandshakeListener();
resolve(new ConcreteConnection(localMethods, postMessage, addMessageListener, sessionId));
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
}
};
removeHandshakeListener = addMessageListener(handshakeListener);
const message = createHandshakeMessage(thisSessionId);
postMessage(message);
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
runUntil(() => {
const message = createHandshakeMessage(thisSessionId);
messenger.postMessage(message);
}, () => connected, maxAttempts, attemptsInterval);
});
}
function ChildHandshake(localMethods, acceptedOrigin, _thisWindow) {
const thisWindow = _thisWindow || window;
function ChildHandshake(localMethods, messenger) {
return new Promise((resolve, reject) => {
let postMessage;
let addMessageListener;
if (isWindow(thisWindow)) {
addMessageListener = makeWindowAddMessageListener(thisWindow, acceptedOrigin);
}
else {
addMessageListener = makeWorkerAddMessageListener(thisWindow);
}
if (addMessageListener === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
let removeHandshakeListener;
const handshakeListener = (event) => {
const { source, data } = event;
const { data } = event;
if (isHandshakeMessage(data)) {
removeHandshakeListener();
if (source && isWindow(source)) {
postMessage = makeWindowPostMessage(source, acceptedOrigin);
}
else if (!source && !isWindow(thisWindow)) {
postMessage = makeWorkerPostMessage(thisWindow);
}
if (postMessage === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
const { sessionId, requestId } = data;
const message = createResponsMessage(sessionId, requestId, HANDSHAKE_SUCCESS);
postMessage(message);
resolve(new ConcreteConnection(localMethods, postMessage, addMessageListener, sessionId));
messenger.postMessage(message);
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
};
removeHandshakeListener = addMessageListener(handshakeListener);
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
});
}
export { ChildHandshake, ParentHandshake };
const acceptableMessageEvent = (event, remoteWindow, acceptedOrigin) => {
const { source, origin } = event;
if (source !== remoteWindow) {
return false;
}
if (origin !== acceptedOrigin && acceptedOrigin !== '*') {
return false;
}
return true;
};
class WindowMessenger {
constructor({ localWindow, remoteWindow, remoteOrigin, }) {
localWindow = localWindow || window;
this.postMessage = (message) => {
remoteWindow.postMessage(message, remoteOrigin);
};
this.addMessageListener = (listener) => {
const outerListener = (event) => {
if (acceptableMessageEvent(event, remoteWindow, remoteOrigin)) {
listener(event);
}
};
localWindow.addEventListener('message', outerListener);
const removeListener = () => {
localWindow.removeEventListener('message', outerListener);
};
return removeListener;
};
}
}
class WorkerMessenger {
constructor({ worker }) {
this.postMessage = (message) => {
worker.postMessage(message);
};
this.addMessageListener = (listener) => {
const outerListener = (event) => {
listener(event);
};
worker.addEventListener('message', outerListener);
const removeListener = () => {
worker.removeEventListener('message', outerListener);
};
return removeListener;
};
}
}
export { ChildHandshake, ParentHandshake, WindowMessenger, WorkerMessenger };

@@ -89,3 +89,3 @@ (function (global, factory) {

class ConcreteConnection {
constructor(localMethods, postMessage, addMessageListener, sessionId) {
constructor(localMethods, messenger, sessionId) {
this.onMessage = (ev) => {

@@ -191,4 +191,3 @@ const { data } = ev;

this._localMethods = localMethods;
this._postMessage = postMessage;
this._addMessageListener = addMessageListener;
this._messenger = messenger;
this._sessionId = sessionId;

@@ -205,3 +204,3 @@ this._requests = {};

};
this._removeMainListener = this._addMessageListener(this.onMessage);
this._removeMainListener = this._messenger.addMessageListener(this.onMessage);
}

@@ -221,12 +220,6 @@ localHandle() {

sendMessage(message) {
this._postMessage(message);
this._messenger.postMessage(message);
}
}
function isWindow(w) {
return globalThis.Window
? w.constructor.name === globalThis.Window.name
: false;
}
const uniqueSessionId = (() => {

@@ -241,70 +234,18 @@ let __sessionId = 0;

const HANDSHAKE_SUCCESS = '@post-me/handshake-success';
const makeWindowPostMessage = (w, origin) => {
return (message) => {
w.postMessage(message, origin);
};
};
const makeWorkerPostMessage = (w) => {
return (message) => {
w.postMessage(message);
};
};
const makeWindowAddMessageListener = (w, acceptedOrigin) => {
const acceptEvent = (event) => {
const { origin } = event;
if (origin !== acceptedOrigin && acceptedOrigin !== '*') {
return false;
const runUntil = (worker, condition, maxAttempts, attemptInterval) => {
let attempt = 0;
const fn = () => {
if (!condition() && (attempt < maxAttempts || maxAttempts < 1)) {
worker();
attempt += 1;
setTimeout(fn, attemptInterval);
}
return true;
};
return (listener) => {
const outerListener = (event) => {
if (acceptEvent(event)) {
listener(event);
}
};
w.addEventListener('message', outerListener);
const removeListener = () => {
w.removeEventListener('message', outerListener);
};
return removeListener;
};
fn();
};
const makeWorkerAddMessageListener = (w) => {
return (listener) => {
const outerListener = (event) => {
{
listener(event);
}
};
w.addEventListener('message', outerListener);
const removeListener = () => {
w.removeEventListener('message', outerListener);
};
return removeListener;
};
};
function ParentHandshake(localMethods, otherWindow, acceptedOrigin, _thisWindow) {
const thisWindow = _thisWindow || window;
function ParentHandshake(localMethods, messenger, maxAttempts = 5, attemptsInterval = 50) {
const thisSessionId = uniqueSessionId();
return new Promise((resolve, reject) => {
let postMessage;
let addMessageListener;
if (isWindow(otherWindow)) {
postMessage = makeWindowPostMessage(otherWindow, acceptedOrigin);
}
else {
postMessage = makeWorkerPostMessage(otherWindow);
}
if (isWindow(thisWindow) && isWindow(otherWindow)) {
addMessageListener = makeWindowAddMessageListener(thisWindow, acceptedOrigin);
}
if (isWindow(thisWindow) && !isWindow(otherWindow)) {
addMessageListener = makeWorkerAddMessageListener(otherWindow);
}
if (postMessage === undefined || addMessageListener === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
let removeHandshakeListener;
let connected = false;
const handshakeListener = (event) => {

@@ -317,54 +258,84 @@ const { data } = event;

result === HANDSHAKE_SUCCESS) {
connected = true;
removeHandshakeListener();
resolve(new ConcreteConnection(localMethods, postMessage, addMessageListener, sessionId));
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
}
};
removeHandshakeListener = addMessageListener(handshakeListener);
const message = createHandshakeMessage(thisSessionId);
postMessage(message);
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
runUntil(() => {
const message = createHandshakeMessage(thisSessionId);
messenger.postMessage(message);
}, () => connected, maxAttempts, attemptsInterval);
});
}
function ChildHandshake(localMethods, acceptedOrigin, _thisWindow) {
const thisWindow = _thisWindow || window;
function ChildHandshake(localMethods, messenger) {
return new Promise((resolve, reject) => {
let postMessage;
let addMessageListener;
if (isWindow(thisWindow)) {
addMessageListener = makeWindowAddMessageListener(thisWindow, acceptedOrigin);
}
else {
addMessageListener = makeWorkerAddMessageListener(thisWindow);
}
if (addMessageListener === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
let removeHandshakeListener;
const handshakeListener = (event) => {
const { source, data } = event;
const { data } = event;
if (isHandshakeMessage(data)) {
removeHandshakeListener();
if (source && isWindow(source)) {
postMessage = makeWindowPostMessage(source, acceptedOrigin);
}
else if (!source && !isWindow(thisWindow)) {
postMessage = makeWorkerPostMessage(thisWindow);
}
if (postMessage === undefined) {
reject(new Error('post-me does not work yet with this type of worker.'));
return;
}
const { sessionId, requestId } = data;
const message = createResponsMessage(sessionId, requestId, HANDSHAKE_SUCCESS);
postMessage(message);
resolve(new ConcreteConnection(localMethods, postMessage, addMessageListener, sessionId));
messenger.postMessage(message);
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
};
removeHandshakeListener = addMessageListener(handshakeListener);
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
});
}
const acceptableMessageEvent = (event, remoteWindow, acceptedOrigin) => {
const { source, origin } = event;
if (source !== remoteWindow) {
return false;
}
if (origin !== acceptedOrigin && acceptedOrigin !== '*') {
return false;
}
return true;
};
class WindowMessenger {
constructor({ localWindow, remoteWindow, remoteOrigin, }) {
localWindow = localWindow || window;
this.postMessage = (message) => {
remoteWindow.postMessage(message, remoteOrigin);
};
this.addMessageListener = (listener) => {
const outerListener = (event) => {
if (acceptableMessageEvent(event, remoteWindow, remoteOrigin)) {
listener(event);
}
};
localWindow.addEventListener('message', outerListener);
const removeListener = () => {
localWindow.removeEventListener('message', outerListener);
};
return removeListener;
};
}
}
class WorkerMessenger {
constructor({ worker }) {
this.postMessage = (message) => {
worker.postMessage(message);
};
this.addMessageListener = (listener) => {
const outerListener = (event) => {
listener(event);
};
worker.addEventListener('message', outerListener);
const removeListener = () => {
worker.removeEventListener('message', outerListener);
};
return removeListener;
};
}
}
exports.ChildHandshake = ChildHandshake;
exports.ParentHandshake = ParentHandshake;
exports.WindowMessenger = WindowMessenger;
exports.WorkerMessenger = WorkerMessenger;

@@ -371,0 +342,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

{
"name": "post-me",
"version": "0.1.0",
"version": "0.2.0",
"description": "A library to facilitate communication between windows (iframe, worker, popup, ...)",

@@ -15,2 +15,3 @@ "main": "dist/index.umd.js",

"demo": "npm run build:demo && npx serve www",
"deploy:demo": "npm run build:demo && gh-pages -d www",
"test": "jest --coverage tests",

@@ -39,2 +40,3 @@ "prettier:check-staged": "pretty-quick --staged --check --pattern '**/*.{js,jsx,ts,tsx,css,html}'",

"@types/jsdom": "^16.2.5",
"gh-pages": "^3.1.0",
"husky": "^4.3.0",

@@ -41,0 +43,0 @@ "jest": "^26.6.3",

@@ -1,3 +0,4 @@

![workflow status](https://github.com/alesgenova/post-me/workflows/main/badge.svg?branch=main)
[![workflow status](https://github.com/alesgenova/post-me/workflows/main/badge.svg?branch=main)](https://github.com/alesgenova/post-me/actions?query=workflow%3Amain+branch%3Amain)
[![npm package](https://img.shields.io/npm/v/post-me.svg)](https://www.npmjs.com/package/post-me)
[![codecov](https://codecov.io/gh/alesgenova/post-me/branch/main/graph/badge.svg)](https://codecov.io/gh/alesgenova/post-me)
# post-me

@@ -18,3 +19,3 @@

## Demo
In this [live demo]() a parent window achieves two-way communication with its 5 children (4 iframes and 1 web worker).
In this [live demo](https://alesgenova.github.io/post-me/) a parent window achieves two-way communication with its 5 children (4 iframes and 1 web worker).

@@ -37,3 +38,3 @@ ## Usage

```typescript
import { ParentHandshake } from 'post-me';
import { ParentHandshake, WindowMessenger } from 'post-me';

@@ -53,3 +54,8 @@ // Create the child window any way you like (iframe here, but could be popup or tab too)

// Start the handshake
ParentHandshake(methods, childWindow, childWindow.origin);
// For safety it is strongly adviced to pass the explicit child origin instead of '*'
const messenger = new WindowMessenger({
remoteWindow: childWindow,
remoteOrigin: '*'
});
ParentHandshake(methods, messenger);
.then((connection) => {

@@ -77,3 +83,3 @@ const localHandle = connection.localHandle();

```typescript
import { ChildHandshake } from 'post-me';
import { ChildHandshake, WindowMessenger } from 'post-me';

@@ -88,4 +94,8 @@ // Define the methods you want to expose to the other window.

// For safety it is strongly adviced to pass the explicit parent origin instead of '*'
const parentOrigin = '*';
ChildHandshake(methods, parentOrigin)
const messenger = new WindowMessenger({
remoteWindow: window.parent,
remoteOrigin: '*'
});
const messenger = new WindowMessenger({ remoteOrigin: '*' });
ChildHandshake(methods, messenger)
.then((connection) => {

@@ -142,3 +152,3 @@ const localHandle = connection.localHandle();

```typescript
import { ParentHandshake, Connection } from 'post-me';
import { ParentHandshake, WindowMessenger, Connection } from 'post-me';

@@ -160,3 +170,8 @@ import { ParentMethods, ParentEvents, ChildMethods, ChildEvents} from '/path/to/common';

// Start the handshake
ParentHandshake(methods, childWindow, childWindow.origin);
// For safety it is strongly adviced to pass the explicit child origin instead of '*'
const messenger = new WindowMessenger({
remoteWindow: childWindow,
remoteOrigin: '*'
});
ParentHandshake(methods, messenger);
.then((connection: Connection<ParentEvents, ChildMethods, ChildEvents>) => {

@@ -184,3 +199,3 @@ const localHandle = connection.localHandle();

```typescript
import { ChildHandshake, Connection } from 'post-me';
import { ChildHandshake, WindowMessenger, Connection } from 'post-me';

@@ -197,4 +212,7 @@ import { ParentMethods, ParentEvents, ChildMethods, ChildEvents} from '/path/to/common';

// For safety it is strongly adviced to pass the explicit parent origin instead of '*'
const parentOrigin = '*';
ChildHandshake(methods, parentOrigin)
const messenger = new WindowMessenger({
remoteWindow: window.parent,
remoteOrigin: '*'
});
ChildHandshake(methods, messenger)
.then((connection: Connection<ChildEvents, ParentMethods, ParentEvents>) => {

@@ -224,1 +242,44 @@ const localHandle = connection.localHandle();

- Worker: [source](https://github.com/alesgenova/post-me/blob/main/demo/worker.js)
### Parent code
```typescript
import { ParentHandshake, WorkerMessenger } from 'post-me';
// Create a dedicated web worker.
const worker = new Worker('./worker.js');
// Start the handshake
const messenger = new WorkerMessenger({ worker });
const methods = {};
ParentHandshake(methods, messenger).then((connection) => {
const remoteHandle = connection.remoteHandle();
// Call a method on the worker
remoteHandle.call('sum', 3, 4)
.then((value) => {
console.log(value); // 7
});
remoteHandle.call('mul', 3, 4)
.then((value) => {
console.log(value); // 12
});
})
```
### Worker code
```typescript
importScripts('./post-me.umd.js');
const PostMe = self['post-me'];
const methods = {
sum: (x, y) => x + y,
mul: (x, y) => x * y,
};
const messenger = new PostMe.WorkerMessenger({ worker: self });
PostMe.ChildHandshake(methods, messenger).then((_connection) => {
console.log('Worker successfully connected');
});
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc