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.2.1 to 0.3.0

dist/dispatcher.d.ts

4

dist/common.d.ts
export declare type IdType = number;
export declare type KeyType = string | number;
export declare type MethodsType = Record<KeyType, Callable<any[], ValueOrPromise<any>>>;
export declare type EventsType = Record<KeyType, any>;
export declare type Callable<A extends Array<any>, R> = (...args: A) => R;

@@ -9,1 +12,2 @@ export declare type ValueOrPromise<T> = T | Promise<T>;

export declare type ItemArgs<T> = T extends (...args: infer A) => ValueOrPromise<unknown> ? A : [];
export declare function createUniqueIdFn(): () => number;

41

dist/connection.d.ts

@@ -1,32 +0,21 @@

import { IdType } from './common';
import { Messenger } from './messenger';
import { LocalHandle, RemoteHandle, MethodsType, EventsType } from './handle';
export interface Connection<E0 extends EventsType = {}, M1 extends MethodsType = {}, E1 extends EventsType = {}> {
sessionId: () => IdType;
import { MethodsType, EventsType } from './common';
import { Dispatcher } from './dispatcher';
import { LocalHandle, RemoteHandle, ConcreteRemoteHandle, ConcreteLocalHandle } from './handle';
export interface Connection<E0 extends EventsType = EventsType, M1 extends MethodsType = MethodsType, E1 extends EventsType = EventsType> {
localHandle: () => LocalHandle<E0>;
remoteHandle: () => RemoteHandle<M1, E1>;
destroy: () => void;
close: () => void;
}
export declare class ConcreteConnection<M0 extends MethodsType> implements Connection {
private _localMethods;
private _messenger;
private _removeMainListener;
private _sessionId;
private dispatcher;
private methods;
private _remoteHandle;
private _localHandle;
private _remoteHandle;
private _requests;
private _eventListeners;
constructor(localMethods: M0, messenger: Messenger, sessionId: number);
localHandle(): LocalHandle<{}>;
remoteHandle(): RemoteHandle<{}, {}>;
sessionId(): number;
destroy(): void;
private onMessage;
private localEmit;
private remoteCall;
private localCall;
private remoteAddEventListener;
private remoteRemoveEventListener;
private sendMessage;
private uniqueRequestId;
constructor(dispatcher: Dispatcher, localMethods: M0);
close(): void;
localHandle(): ConcreteLocalHandle<Record<string | number, any>>;
remoteHandle(): ConcreteRemoteHandle<Record<string | number, import("./common").Callable<any[], any>>, Record<string | number, any>>;
private handleCall;
private handleEvent;
private callRemoteMethod;
}

@@ -1,11 +0,16 @@

import { Callable, ValueOrPromise, InnerType } from './common';
export declare type MethodsType = Required<Record<string, Callable<any[], ValueOrPromise<any>>>>;
export declare type EventsType = Record<string, any>;
export interface RemoteHandle<M extends MethodsType = {}, E extends EventsType = {}> {
import { InnerType, MethodsType, EventsType } from './common';
import { Emitter, IEmitter } from './emitter';
export interface RemoteHandle<M extends MethodsType = MethodsType, E extends EventsType = EventsType> extends IEmitter<E> {
call: <K extends keyof M>(methodName: K, ...args: Parameters<M[K]>) => Promise<InnerType<ReturnType<M[K]>>>;
addEventListener: <K extends keyof E>(eventName: K, callback: (data: E[K]) => void) => void;
removeEventListener: <K extends keyof E>(eventName: K, callback: (data: E[K]) => void) => void;
}
export interface LocalHandle<E extends EventsType = {}> {
export declare class ConcreteRemoteHandle<M extends MethodsType = MethodsType, E extends EventsType = EventsType> extends Emitter<E> implements RemoteHandle<M, E> {
call: <K extends keyof M>(methodName: K, ...args: Parameters<M[K]>) => Promise<InnerType<ReturnType<M[K]>>>;
constructor(callFn: RemoteHandle<M, E>['call']);
}
export interface LocalHandle<E extends EventsType = EventsType> {
emit: <K extends keyof E>(eventName: K, data: E[K]) => void;
}
export declare class ConcreteLocalHandle<E extends EventsType = EventsType> implements LocalHandle<E> {
emit: <K extends keyof E>(eventName: K, data: E[K]) => void;
constructor(emitFn: LocalHandle<E>['emit']);
}

@@ -1,6 +0,5 @@

import { MethodsType } from './handle';
import { MethodsType } from './common';
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, messenger: Messenger, maxAttempts?: number, attemptsInterval?: number): Promise<Connection>;
export declare function ChildHandshake<M0 extends MethodsType>(localMethods: M0, messenger: Messenger): Promise<Connection>;
export declare function ParentHandshake<M0 extends MethodsType>(messenger: Messenger, localMethods?: M0, maxAttempts?: number, attemptsInterval?: number): Promise<Connection>;
export declare function ChildHandshake<M extends MethodsType>(messenger: Messenger, localMethods?: M): Promise<Connection>;

@@ -0,47 +1,112 @@

function createUniqueIdFn() {
let __id = 0;
return function () {
const id = __id;
__id += 1;
return id;
};
}
class Emitter {
constructor() {
this.listeners = {};
}
addEventListener(eventName, listener) {
let listeners = this.listeners[eventName];
if (!listeners) {
listeners = new Set();
this.listeners[eventName] = listeners;
}
listeners.add(listener);
}
removeEventListener(eventName, listener) {
let listeners = this.listeners[eventName];
if (!listeners) {
return;
}
listeners.delete(listener);
}
once(eventName) {
return new Promise((resolve) => {
const listener = (data) => {
this.removeEventListener(eventName, listener);
resolve(data);
};
this.addEventListener(eventName, listener);
});
}
emit(eventName, data) {
let listeners = this.listeners[eventName];
if (!listeners) {
return;
}
listeners.forEach((listener) => {
listener(data);
});
}
removeAllListeners() {
Object.values(this.listeners).forEach((listeners) => {
if (listeners) {
listeners.clear();
}
});
}
}
const MARKER = '@post-me';
var MessageType;
(function (MessageType) {
MessageType["Handshake"] = "@post-me/handshake";
MessageType["Call"] = "@post-me/call";
MessageType["Response"] = "@post-me/response";
MessageType["Error"] = "@post-me/error";
MessageType["Event"] = "@post-me/event";
MessageType["HandshakeRequest"] = "handshake-request";
MessageType["HandshakeResponse"] = "handshake-response";
MessageType["Call"] = "call";
MessageType["Response"] = "response";
MessageType["Error"] = "error";
MessageType["Event"] = "event";
})(MessageType || (MessageType = {}));
// Message Creators
function createHandshakeMessage(sessionId) {
function createHandshakeRequestMessage(sessionId) {
return {
type: MessageType.Handshake,
type: MARKER,
action: MessageType.HandshakeRequest,
sessionId,
requestId: sessionId,
};
}
function createCallMessage(sessionId, requestId, name, ...args) {
function createHandshakeResponseMessage(sessionId) {
return {
type: MessageType.Call,
type: MARKER,
action: MessageType.HandshakeResponse,
sessionId,
requestId,
name,
args,
};
}
function createResponsMessage(sessionId, requestId, result) {
function createCallMessage(sessionId, requestId, methodName, ...args) {
return {
type: MessageType.Response,
type: MARKER,
action: MessageType.Call,
sessionId,
requestId,
result,
methodName,
args,
};
}
function createErrorMessage(sessionId, requestId, error) {
return {
type: MessageType.Error,
function createResponsMessage(sessionId, requestId, result, error) {
const message = {
type: MARKER,
action: MessageType.Response,
sessionId,
requestId,
error,
};
if (result !== undefined) {
message.result = result;
}
if (error !== undefined) {
message.error = error;
}
return message;
}
function createEventMessage(sessionId, name, payload) {
function createEventMessage(sessionId, eventName, payload) {
return {
type: MessageType.Event,
type: MARKER,
action: MessageType.Event,
sessionId,
name,
eventName,
payload,

@@ -52,148 +117,141 @@ };

function isMessage(m) {
return (m.type !== undefined &&
m.sessionId !== undefined);
return m.type === MARKER;
}
function isHandshakeMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Handshake &&
m.requestId !== undefined);
function isHandshakeRequestMessage(m) {
return isMessage(m) && m.action === MessageType.HandshakeRequest;
}
function isHandshakeResponseMessage(m) {
return isMessage(m) && m.action === MessageType.HandshakeResponse;
}
function isCallMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Call &&
m.requestId !== undefined &&
m.name !== undefined &&
Array.isArray(m.args));
return isMessage(m) && m.action === MessageType.Call;
}
function isResponseMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Response &&
m.requestId !== undefined);
return isMessage(m) && m.action === MessageType.Response;
}
function isErrorMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Error &&
m.requestId !== undefined &&
m.error !== undefined);
}
function isEventMessage(m) {
return isMessage(m) && m.type === MessageType.Event;
return isMessage(m) && m.action === MessageType.Event;
}
class Dispatcher extends Emitter {
constructor(messenger, sessionId) {
super();
this.uniqueId = createUniqueIdFn();
this.messenger = messenger;
this.sessionId = sessionId;
this.removeMessengerListener = this.messenger.addMessageListener(this.messengerListener.bind(this));
}
messengerListener(event) {
const { data } = event;
if (!isMessage(data)) {
return;
}
if (this.sessionId !== data.sessionId) {
return;
}
if (isCallMessage(data)) {
this.emit(MessageType.Call, data);
}
else if (isResponseMessage(data)) {
this.emit(data.requestId, data);
}
else if (isEventMessage(data)) {
this.emit(MessageType.Event, data);
}
}
callOnRemote(methodName, ...args) {
const requestId = this.uniqueId();
const message = createCallMessage(this.sessionId, requestId, methodName, ...args);
this.messenger.postMessage(message);
return requestId;
}
respondToRemote(requestId, value, error) {
const message = createResponsMessage(this.sessionId, requestId, value, error);
this.messenger.postMessage(message);
}
emitToRemote(eventName, payload) {
const message = createEventMessage(this.sessionId, eventName, payload);
this.messenger.postMessage(message);
}
close() {
this.removeMessengerListener();
this.removeAllListeners();
}
}
class ParentHandshakeDispatcher extends Emitter {
constructor(messenger, sessionId) {
super();
this.messenger = messenger;
this.sessionId = sessionId;
this.removeMessengerListener = this.messenger.addMessageListener(this.messengerListener.bind(this));
}
messengerListener(event) {
const { data } = event;
if (!isMessage(data)) {
return;
}
if (this.sessionId !== data.sessionId) {
return;
}
if (isHandshakeResponseMessage(data)) {
this.emit(data.sessionId, data);
}
}
initiateHandshake() {
const message = createHandshakeRequestMessage(this.sessionId);
this.messenger.postMessage(message);
return this.sessionId;
}
close() {
this.removeMessengerListener();
this.removeAllListeners();
}
}
class ChildHandshakeDispatcher extends Emitter {
constructor(messenger) {
super();
this.messenger = messenger;
this.removeMessengerListener = this.messenger.addMessageListener(this.messengerListener.bind(this));
}
messengerListener(event) {
const { data } = event;
if (isHandshakeRequestMessage(data)) {
this.emit(MessageType.HandshakeRequest, data);
}
}
acceptHandshake(sessionId) {
const message = createHandshakeResponseMessage(sessionId);
this.messenger.postMessage(message);
}
close() {
this.removeMessengerListener();
this.removeAllListeners();
}
}
class ConcreteRemoteHandle extends Emitter {
constructor(callFn) {
super();
this.call = callFn;
}
}
class ConcreteLocalHandle {
constructor(emitFn) {
this.emit = emitFn;
}
}
class ConcreteConnection {
constructor(localMethods, messenger, sessionId) {
this.onMessage = (ev) => {
const { data } = ev;
if (!isMessage(data)) {
return;
}
if (data.sessionId !== this.sessionId()) {
return;
}
if (isCallMessage(data)) {
const { requestId, name, args } = data;
this.localCall(name, ...args)
.then((value) => {
const message = createResponsMessage(this.sessionId(), requestId, value);
this.sendMessage(message);
})
.catch((e) => {
const message = createErrorMessage(this.sessionId(), requestId, e);
this.sendMessage(message);
});
}
else if (isResponseMessage(data)) {
const { requestId, result } = data;
const promiseMethods = this._requests[requestId];
if (!promiseMethods) {
return;
}
promiseMethods.resolve(result);
delete this._requests[requestId];
return;
}
else if (isEventMessage(data)) {
const { name, payload } = data;
const listeners = this._eventListeners[name];
if (!listeners) {
return;
}
listeners.forEach((listener) => {
listener(payload);
});
return;
}
else if (isErrorMessage(data)) {
const { requestId, error } = data;
const promiseMethods = this._requests[requestId];
if (!promiseMethods) {
return;
}
promiseMethods.reject(error);
delete this._requests[requestId];
return;
}
};
this.localEmit = (eventName, data) => {
const message = createEventMessage(this.sessionId(), eventName, data);
this.sendMessage(message);
};
this.remoteCall = (methodName, ...args) => {
return new Promise((resolve, reject) => {
const requestId = this.uniqueRequestId();
this._requests[requestId] = { resolve, reject };
const message = createCallMessage(this.sessionId(), requestId, methodName, ...args);
this.sendMessage(message);
});
};
this.localCall = (methodName, ...args) => {
return new Promise((resolve, reject) => {
const method = this._localMethods[methodName];
if (!method) {
reject(new Error(`The method "${methodName}" has not been implemented.`));
return;
}
Promise.resolve(method(...args))
.then((val) => resolve(val))
.catch((e) => reject(e));
});
};
this.remoteAddEventListener = (eventName, callback) => {
let listeners = this._eventListeners[eventName];
if (!listeners) {
listeners = new Set();
this._eventListeners[eventName] = listeners;
}
listeners.add(callback);
};
this.remoteRemoveEventListener = (eventName, callback) => {
let listeners = this._eventListeners[eventName];
if (!listeners) {
return;
}
listeners.delete(callback);
};
this.uniqueRequestId = (() => {
let __requestId = 0;
return () => {
const requestId = __requestId;
__requestId += 1;
return requestId;
};
})();
this._localMethods = localMethods;
this._messenger = messenger;
this._sessionId = sessionId;
this._requests = {};
this._eventListeners = {};
this._localHandle = {
emit: this.localEmit,
};
this._remoteHandle = {
call: this.remoteCall,
addEventListener: this.remoteAddEventListener,
removeEventListener: this.remoteRemoveEventListener,
};
this._removeMainListener = this._messenger.addMessageListener(this.onMessage);
constructor(dispatcher, localMethods) {
this.dispatcher = dispatcher;
this.methods = localMethods;
this._remoteHandle = new ConcreteRemoteHandle(this.callRemoteMethod.bind(this));
this._localHandle = new ConcreteLocalHandle(this.dispatcher.emitToRemote.bind(this.dispatcher));
this.dispatcher.addEventListener(MessageType.Call, this.handleCall.bind(this));
this.dispatcher.addEventListener(MessageType.Event, this.handleEvent.bind(this));
}
close() {
this.dispatcher.close();
this._remoteHandle['removeAllListeners']();
}
localHandle() {

@@ -205,23 +263,44 @@ return this._localHandle;

}
sessionId() {
return this._sessionId;
handleCall(data) {
const { requestId, methodName, args } = data;
const callMethod = new Promise((resolve, reject) => {
const method = this.methods[methodName];
if (typeof method !== 'function') {
reject(new Error(`The method "${methodName}" has not been implemented.`));
return;
}
Promise.resolve(method(...args))
.then(resolve)
.catch(reject);
});
callMethod
.then((value) => {
this.dispatcher.respondToRemote(requestId, value);
})
.catch((error) => {
this.dispatcher.respondToRemote(requestId, undefined, error);
});
}
destroy() {
this._removeMainListener();
handleEvent(data) {
const { eventName, payload } = data;
this._remoteHandle['emit'](eventName, payload);
}
sendMessage(message) {
this._messenger.postMessage(message);
callRemoteMethod(methodName, ...args) {
return new Promise((resolve, reject) => {
const responseEvent = this.dispatcher.callOnRemote(methodName, ...args);
this.dispatcher.once(responseEvent).then((response) => {
const { result, error } = response;
if (error !== undefined) {
reject(error);
}
else {
resolve(result);
}
});
});
}
}
const uniqueSessionId = (() => {
let __sessionId = 0;
return () => {
const sessionId = __sessionId;
__sessionId += 1;
return sessionId;
};
})();
const HANDSHAKE_SUCCESS = '@post-me/handshake-success';
const runUntil = (worker, condition, maxAttempts, attemptInterval) => {
const uniqueSessionId = createUniqueIdFn();
const runUntil = (worker, condition, unfulfilled, maxAttempts, attemptInterval) => {
let attempt = 0;

@@ -234,44 +313,35 @@ const fn = () => {

}
else if (!condition() && attempt >= maxAttempts && maxAttempts >= 1) {
unfulfilled();
}
};
fn();
};
function ParentHandshake(localMethods, messenger, maxAttempts = 5, attemptsInterval = 50) {
function ParentHandshake(messenger, localMethods = {}, maxAttempts = 5, attemptsInterval = 100) {
const thisSessionId = uniqueSessionId();
let connected = false;
return new Promise((resolve, reject) => {
let removeHandshakeListener;
let connected = false;
const handshakeListener = (event) => {
const { data } = event;
if (isResponseMessage(data)) {
const { sessionId, requestId, result } = data;
if (sessionId === thisSessionId &&
requestId === thisSessionId &&
result === HANDSHAKE_SUCCESS) {
connected = true;
removeHandshakeListener();
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
}
};
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
runUntil(() => {
const message = createHandshakeMessage(thisSessionId);
messenger.postMessage(message);
}, () => connected, maxAttempts, attemptsInterval);
const handshakeDispatcher = new ParentHandshakeDispatcher(messenger, thisSessionId);
handshakeDispatcher.once(thisSessionId).then((response) => {
connected = true;
handshakeDispatcher.close();
const { sessionId } = response;
const dispatcher = new Dispatcher(messenger, sessionId);
const connection = new ConcreteConnection(dispatcher, localMethods);
resolve(connection);
});
runUntil(() => handshakeDispatcher.initiateHandshake(), () => connected, () => reject(new Error(`Handshake failed, reached maximum number of attempts`)), maxAttempts, attemptsInterval);
});
}
function ChildHandshake(localMethods, messenger) {
function ChildHandshake(messenger, localMethods = {}) {
return new Promise((resolve, reject) => {
let removeHandshakeListener;
const handshakeListener = (event) => {
const { data } = event;
if (isHandshakeMessage(data)) {
removeHandshakeListener();
const { sessionId, requestId } = data;
const message = createResponsMessage(sessionId, requestId, HANDSHAKE_SUCCESS);
messenger.postMessage(message);
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
};
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
const handshakeDispatcher = new ChildHandshakeDispatcher(messenger);
handshakeDispatcher.once(MessageType.HandshakeRequest).then((response) => {
const { sessionId } = response;
handshakeDispatcher.acceptHandshake(sessionId);
handshakeDispatcher.close();
const dispatcher = new Dispatcher(messenger, sessionId);
const connection = new ConcreteConnection(dispatcher, localMethods);
resolve(connection);
});
});

@@ -278,0 +348,0 @@ }

@@ -7,2 +7,11 @@ (function (global, factory) {

function createUniqueIdFn() {
var __id = 0;
return function () {
var id = __id;
__id += 1;
return id;
};
}
/*! *****************************************************************************

@@ -22,3 +31,17 @@ Copyright (c) Microsoft Corporation.

***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __spreadArrays() {

@@ -32,19 +55,76 @@ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;

var Emitter = /** @class */ (function () {
function Emitter() {
this.listeners = {};
}
Emitter.prototype.addEventListener = function (eventName, listener) {
var listeners = this.listeners[eventName];
if (!listeners) {
listeners = new Set();
this.listeners[eventName] = listeners;
}
listeners.add(listener);
};
Emitter.prototype.removeEventListener = function (eventName, listener) {
var listeners = this.listeners[eventName];
if (!listeners) {
return;
}
listeners.delete(listener);
};
Emitter.prototype.once = function (eventName) {
var _this = this;
return new Promise(function (resolve) {
var listener = function (data) {
_this.removeEventListener(eventName, listener);
resolve(data);
};
_this.addEventListener(eventName, listener);
});
};
Emitter.prototype.emit = function (eventName, data) {
var listeners = this.listeners[eventName];
if (!listeners) {
return;
}
listeners.forEach(function (listener) {
listener(data);
});
};
Emitter.prototype.removeAllListeners = function () {
Object.values(this.listeners).forEach(function (listeners) {
if (listeners) {
listeners.clear();
}
});
};
return Emitter;
}());
var MARKER = '@post-me';
var MessageType;
(function (MessageType) {
MessageType["Handshake"] = "@post-me/handshake";
MessageType["Call"] = "@post-me/call";
MessageType["Response"] = "@post-me/response";
MessageType["Error"] = "@post-me/error";
MessageType["Event"] = "@post-me/event";
MessageType["HandshakeRequest"] = "handshake-request";
MessageType["HandshakeResponse"] = "handshake-response";
MessageType["Call"] = "call";
MessageType["Response"] = "response";
MessageType["Error"] = "error";
MessageType["Event"] = "event";
})(MessageType || (MessageType = {}));
// Message Creators
function createHandshakeMessage(sessionId) {
function createHandshakeRequestMessage(sessionId) {
return {
type: MessageType.Handshake,
type: MARKER,
action: MessageType.HandshakeRequest,
sessionId: sessionId,
requestId: sessionId,
};
}
function createCallMessage(sessionId, requestId, name) {
function createHandshakeResponseMessage(sessionId) {
return {
type: MARKER,
action: MessageType.HandshakeResponse,
sessionId: sessionId,
};
}
function createCallMessage(sessionId, requestId, methodName) {
var args = [];

@@ -55,30 +135,31 @@ for (var _i = 3; _i < arguments.length; _i++) {

return {
type: MessageType.Call,
type: MARKER,
action: MessageType.Call,
sessionId: sessionId,
requestId: requestId,
name: name,
methodName: methodName,
args: args,
};
}
function createResponsMessage(sessionId, requestId, result) {
return {
type: MessageType.Response,
function createResponsMessage(sessionId, requestId, result, error) {
var message = {
type: MARKER,
action: MessageType.Response,
sessionId: sessionId,
requestId: requestId,
result: result,
};
if (result !== undefined) {
message.result = result;
}
if (error !== undefined) {
message.error = error;
}
return message;
}
function createErrorMessage(sessionId, requestId, error) {
function createEventMessage(sessionId, eventName, payload) {
return {
type: MessageType.Error,
type: MARKER,
action: MessageType.Event,
sessionId: sessionId,
requestId: requestId,
error: error,
};
}
function createEventMessage(sessionId, name, payload) {
return {
type: MessageType.Event,
sessionId: sessionId,
name: name,
eventName: eventName,
payload: payload,

@@ -89,157 +170,160 @@ };

function isMessage(m) {
return (m.type !== undefined &&
m.sessionId !== undefined);
return m.type === MARKER;
}
function isHandshakeMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Handshake &&
m.requestId !== undefined);
function isHandshakeRequestMessage(m) {
return isMessage(m) && m.action === MessageType.HandshakeRequest;
}
function isHandshakeResponseMessage(m) {
return isMessage(m) && m.action === MessageType.HandshakeResponse;
}
function isCallMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Call &&
m.requestId !== undefined &&
m.name !== undefined &&
Array.isArray(m.args));
return isMessage(m) && m.action === MessageType.Call;
}
function isResponseMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Response &&
m.requestId !== undefined);
return isMessage(m) && m.action === MessageType.Response;
}
function isErrorMessage(m) {
return (isMessage(m) &&
m.type === MessageType.Error &&
m.requestId !== undefined &&
m.error !== undefined);
}
function isEventMessage(m) {
return isMessage(m) && m.type === MessageType.Event;
return isMessage(m) && m.action === MessageType.Event;
}
var Dispatcher = /** @class */ (function (_super) {
__extends(Dispatcher, _super);
function Dispatcher(messenger, sessionId) {
var _this = _super.call(this) || this;
_this.uniqueId = createUniqueIdFn();
_this.messenger = messenger;
_this.sessionId = sessionId;
_this.removeMessengerListener = _this.messenger.addMessageListener(_this.messengerListener.bind(_this));
return _this;
}
Dispatcher.prototype.messengerListener = function (event) {
var data = event.data;
if (!isMessage(data)) {
return;
}
if (this.sessionId !== data.sessionId) {
return;
}
if (isCallMessage(data)) {
this.emit(MessageType.Call, data);
}
else if (isResponseMessage(data)) {
this.emit(data.requestId, data);
}
else if (isEventMessage(data)) {
this.emit(MessageType.Event, data);
}
};
Dispatcher.prototype.callOnRemote = function (methodName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var requestId = this.uniqueId();
var message = createCallMessage.apply(void 0, __spreadArrays([this.sessionId,
requestId,
methodName], args));
this.messenger.postMessage(message);
return requestId;
};
Dispatcher.prototype.respondToRemote = function (requestId, value, error) {
var message = createResponsMessage(this.sessionId, requestId, value, error);
this.messenger.postMessage(message);
};
Dispatcher.prototype.emitToRemote = function (eventName, payload) {
var message = createEventMessage(this.sessionId, eventName, payload);
this.messenger.postMessage(message);
};
Dispatcher.prototype.close = function () {
this.removeMessengerListener();
this.removeAllListeners();
};
return Dispatcher;
}(Emitter));
var ParentHandshakeDispatcher = /** @class */ (function (_super) {
__extends(ParentHandshakeDispatcher, _super);
function ParentHandshakeDispatcher(messenger, sessionId) {
var _this = _super.call(this) || this;
_this.messenger = messenger;
_this.sessionId = sessionId;
_this.removeMessengerListener = _this.messenger.addMessageListener(_this.messengerListener.bind(_this));
return _this;
}
ParentHandshakeDispatcher.prototype.messengerListener = function (event) {
var data = event.data;
if (!isMessage(data)) {
return;
}
if (this.sessionId !== data.sessionId) {
return;
}
if (isHandshakeResponseMessage(data)) {
this.emit(data.sessionId, data);
}
};
ParentHandshakeDispatcher.prototype.initiateHandshake = function () {
var message = createHandshakeRequestMessage(this.sessionId);
this.messenger.postMessage(message);
return this.sessionId;
};
ParentHandshakeDispatcher.prototype.close = function () {
this.removeMessengerListener();
this.removeAllListeners();
};
return ParentHandshakeDispatcher;
}(Emitter));
var ChildHandshakeDispatcher = /** @class */ (function (_super) {
__extends(ChildHandshakeDispatcher, _super);
function ChildHandshakeDispatcher(messenger) {
var _this = _super.call(this) || this;
_this.messenger = messenger;
_this.removeMessengerListener = _this.messenger.addMessageListener(_this.messengerListener.bind(_this));
return _this;
}
ChildHandshakeDispatcher.prototype.messengerListener = function (event) {
var data = event.data;
if (isHandshakeRequestMessage(data)) {
this.emit(MessageType.HandshakeRequest, data);
}
};
ChildHandshakeDispatcher.prototype.acceptHandshake = function (sessionId) {
var message = createHandshakeResponseMessage(sessionId);
this.messenger.postMessage(message);
};
ChildHandshakeDispatcher.prototype.close = function () {
this.removeMessengerListener();
this.removeAllListeners();
};
return ChildHandshakeDispatcher;
}(Emitter));
var ConcreteRemoteHandle = /** @class */ (function (_super) {
__extends(ConcreteRemoteHandle, _super);
function ConcreteRemoteHandle(callFn) {
var _this = _super.call(this) || this;
_this.call = callFn;
return _this;
}
return ConcreteRemoteHandle;
}(Emitter));
var ConcreteLocalHandle = /** @class */ (function () {
function ConcreteLocalHandle(emitFn) {
this.emit = emitFn;
}
return ConcreteLocalHandle;
}());
var ConcreteConnection = /** @class */ (function () {
function ConcreteConnection(localMethods, messenger, sessionId) {
var _this = this;
this.onMessage = function (ev) {
var data = ev.data;
if (!isMessage(data)) {
return;
}
if (data.sessionId !== _this.sessionId()) {
return;
}
if (isCallMessage(data)) {
var requestId_1 = data.requestId, name_1 = data.name, args = data.args;
_this.localCall.apply(_this, __spreadArrays([name_1], args)).then(function (value) {
var message = createResponsMessage(_this.sessionId(), requestId_1, value);
_this.sendMessage(message);
})
.catch(function (e) {
var message = createErrorMessage(_this.sessionId(), requestId_1, e);
_this.sendMessage(message);
});
}
else if (isResponseMessage(data)) {
var requestId = data.requestId, result = data.result;
var promiseMethods = _this._requests[requestId];
if (!promiseMethods) {
return;
}
promiseMethods.resolve(result);
delete _this._requests[requestId];
return;
}
else if (isEventMessage(data)) {
var name_2 = data.name, payload_1 = data.payload;
var listeners = _this._eventListeners[name_2];
if (!listeners) {
return;
}
listeners.forEach(function (listener) {
listener(payload_1);
});
return;
}
else if (isErrorMessage(data)) {
var requestId = data.requestId, error = data.error;
var promiseMethods = _this._requests[requestId];
if (!promiseMethods) {
return;
}
promiseMethods.reject(error);
delete _this._requests[requestId];
return;
}
};
this.localEmit = function (eventName, data) {
var message = createEventMessage(_this.sessionId(), eventName, data);
_this.sendMessage(message);
};
this.remoteCall = function (methodName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return new Promise(function (resolve, reject) {
var requestId = _this.uniqueRequestId();
_this._requests[requestId] = { resolve: resolve, reject: reject };
var message = createCallMessage.apply(void 0, __spreadArrays([_this.sessionId(),
requestId, methodName], args));
_this.sendMessage(message);
});
};
this.localCall = function (methodName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return new Promise(function (resolve, reject) {
var method = _this._localMethods[methodName];
if (!method) {
reject(new Error("The method \"" + methodName + "\" has not been implemented."));
return;
}
Promise.resolve(method.apply(void 0, args))
.then(function (val) { return resolve(val); })
.catch(function (e) { return reject(e); });
});
};
this.remoteAddEventListener = function (eventName, callback) {
var listeners = _this._eventListeners[eventName];
if (!listeners) {
listeners = new Set();
_this._eventListeners[eventName] = listeners;
}
listeners.add(callback);
};
this.remoteRemoveEventListener = function (eventName, callback) {
var listeners = _this._eventListeners[eventName];
if (!listeners) {
return;
}
listeners.delete(callback);
};
this.uniqueRequestId = (function () {
var __requestId = 0;
return function () {
var requestId = __requestId;
__requestId += 1;
return requestId;
};
})();
this._localMethods = localMethods;
this._messenger = messenger;
this._sessionId = sessionId;
this._requests = {};
this._eventListeners = {};
this._localHandle = {
emit: this.localEmit,
};
this._remoteHandle = {
call: this.remoteCall,
addEventListener: this.remoteAddEventListener,
removeEventListener: this.remoteRemoveEventListener,
};
this._removeMainListener = this._messenger.addMessageListener(this.onMessage);
function ConcreteConnection(dispatcher, localMethods) {
this.dispatcher = dispatcher;
this.methods = localMethods;
this._remoteHandle = new ConcreteRemoteHandle(this.callRemoteMethod.bind(this));
this._localHandle = new ConcreteLocalHandle(this.dispatcher.emitToRemote.bind(this.dispatcher));
this.dispatcher.addEventListener(MessageType.Call, this.handleCall.bind(this));
this.dispatcher.addEventListener(MessageType.Event, this.handleEvent.bind(this));
}
ConcreteConnection.prototype.close = function () {
this.dispatcher.close();
this._remoteHandle['removeAllListeners']();
};
ConcreteConnection.prototype.localHandle = function () {

@@ -251,10 +335,46 @@ return this._localHandle;

};
ConcreteConnection.prototype.sessionId = function () {
return this._sessionId;
ConcreteConnection.prototype.handleCall = function (data) {
var _this = this;
var requestId = data.requestId, methodName = data.methodName, args = data.args;
var callMethod = new Promise(function (resolve, reject) {
var method = _this.methods[methodName];
if (typeof method !== 'function') {
reject(new Error("The method \"" + methodName + "\" has not been implemented."));
return;
}
Promise.resolve(method.apply(void 0, args))
.then(resolve)
.catch(reject);
});
callMethod
.then(function (value) {
_this.dispatcher.respondToRemote(requestId, value);
})
.catch(function (error) {
_this.dispatcher.respondToRemote(requestId, undefined, error);
});
};
ConcreteConnection.prototype.destroy = function () {
this._removeMainListener();
ConcreteConnection.prototype.handleEvent = function (data) {
var eventName = data.eventName, payload = data.payload;
this._remoteHandle['emit'](eventName, payload);
};
ConcreteConnection.prototype.sendMessage = function (message) {
this._messenger.postMessage(message);
ConcreteConnection.prototype.callRemoteMethod = function (methodName) {
var _this = this;
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return new Promise(function (resolve, reject) {
var _a;
var responseEvent = (_a = _this.dispatcher).callOnRemote.apply(_a, __spreadArrays([methodName], args));
_this.dispatcher.once(responseEvent).then(function (response) {
var result = response.result, error = response.error;
if (error !== undefined) {
reject(error);
}
else {
resolve(result);
}
});
});
};

@@ -264,12 +384,4 @@ return ConcreteConnection;

var uniqueSessionId = (function () {
var __sessionId = 0;
return function () {
var sessionId = __sessionId;
__sessionId += 1;
return sessionId;
};
})();
var HANDSHAKE_SUCCESS = '@post-me/handshake-success';
var runUntil = function (worker, condition, maxAttempts, attemptInterval) {
var uniqueSessionId = createUniqueIdFn();
var runUntil = function (worker, condition, unfulfilled, maxAttempts, attemptInterval) {
var attempt = 0;

@@ -282,46 +394,41 @@ var fn = function () {

}
else if (!condition() && attempt >= maxAttempts && maxAttempts >= 1) {
unfulfilled();
}
};
fn();
};
function ParentHandshake(localMethods, messenger, maxAttempts, attemptsInterval) {
function ParentHandshake(messenger, localMethods, maxAttempts, attemptsInterval) {
if (localMethods === void 0) { localMethods = {}; }
if (maxAttempts === void 0) { maxAttempts = 5; }
if (attemptsInterval === void 0) { attemptsInterval = 50; }
if (attemptsInterval === void 0) { attemptsInterval = 100; }
var thisSessionId = uniqueSessionId();
var connected = false;
return new Promise(function (resolve, reject) {
var removeHandshakeListener;
var connected = false;
var handshakeListener = function (event) {
var data = event.data;
if (isResponseMessage(data)) {
var sessionId = data.sessionId, requestId = data.requestId, result = data.result;
if (sessionId === thisSessionId &&
requestId === thisSessionId &&
result === HANDSHAKE_SUCCESS) {
connected = true;
removeHandshakeListener();
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
}
};
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
runUntil(function () {
var message = createHandshakeMessage(thisSessionId);
messenger.postMessage(message);
}, function () { return connected; }, maxAttempts, attemptsInterval);
var handshakeDispatcher = new ParentHandshakeDispatcher(messenger, thisSessionId);
handshakeDispatcher.once(thisSessionId).then(function (response) {
connected = true;
handshakeDispatcher.close();
var sessionId = response.sessionId;
var dispatcher = new Dispatcher(messenger, sessionId);
var connection = new ConcreteConnection(dispatcher, localMethods);
resolve(connection);
});
runUntil(function () { return handshakeDispatcher.initiateHandshake(); }, function () { return connected; }, function () {
return reject(new Error("Handshake failed, reached maximum number of attempts"));
}, maxAttempts, attemptsInterval);
});
}
function ChildHandshake(localMethods, messenger) {
function ChildHandshake(messenger, localMethods) {
if (localMethods === void 0) { localMethods = {}; }
return new Promise(function (resolve, reject) {
var removeHandshakeListener;
var handshakeListener = function (event) {
var data = event.data;
if (isHandshakeMessage(data)) {
removeHandshakeListener();
var sessionId = data.sessionId, requestId = data.requestId;
var message = createResponsMessage(sessionId, requestId, HANDSHAKE_SUCCESS);
messenger.postMessage(message);
resolve(new ConcreteConnection(localMethods, messenger, sessionId));
}
};
removeHandshakeListener = messenger.addMessageListener(handshakeListener);
var handshakeDispatcher = new ChildHandshakeDispatcher(messenger);
handshakeDispatcher.once(MessageType.HandshakeRequest).then(function (response) {
var sessionId = response.sessionId;
handshakeDispatcher.acceptHandshake(sessionId);
handshakeDispatcher.close();
var dispatcher = new Dispatcher(messenger, sessionId);
var connection = new ConcreteConnection(dispatcher, localMethods);
resolve(connection);
});
});

@@ -328,0 +435,0 @@ }

@@ -1,1 +0,1 @@

(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,factory(global["post-me"]={}))})(this,function(exports){"use strict";function __spreadArrays(){for(var s=0,i=0,il=arguments.length;i<il;i++)s+=arguments[i].length;for(var r=Array(s),k=0,i=0;i<il;i++)for(var a=arguments[i],j=0,jl=a.length;j<jl;j++,k++)r[k]=a[j];return r}var MessageType;(function(MessageType){MessageType["Handshake"]="@post-me/handshake";MessageType["Call"]="@post-me/call";MessageType["Response"]="@post-me/response";MessageType["Error"]="@post-me/error";MessageType["Event"]="@post-me/event"})(MessageType||(MessageType={}));function createHandshakeMessage(sessionId){return{type:MessageType.Handshake,sessionId:sessionId,requestId:sessionId}}function createCallMessage(sessionId,requestId,name){var args=[];for(var _i=3;_i<arguments.length;_i++){args[_i-3]=arguments[_i]}return{type:MessageType.Call,sessionId:sessionId,requestId:requestId,name:name,args:args}}function createResponsMessage(sessionId,requestId,result){return{type:MessageType.Response,sessionId:sessionId,requestId:requestId,result:result}}function createErrorMessage(sessionId,requestId,error){return{type:MessageType.Error,sessionId:sessionId,requestId:requestId,error:error}}function createEventMessage(sessionId,name,payload){return{type:MessageType.Event,sessionId:sessionId,name:name,payload:payload}}function isMessage(m){return m.type!==undefined&&m.sessionId!==undefined}function isHandshakeMessage(m){return isMessage(m)&&m.type===MessageType.Handshake&&m.requestId!==undefined}function isCallMessage(m){return isMessage(m)&&m.type===MessageType.Call&&m.requestId!==undefined&&m.name!==undefined&&Array.isArray(m.args)}function isResponseMessage(m){return isMessage(m)&&m.type===MessageType.Response&&m.requestId!==undefined}function isErrorMessage(m){return isMessage(m)&&m.type===MessageType.Error&&m.requestId!==undefined&&m.error!==undefined}function isEventMessage(m){return isMessage(m)&&m.type===MessageType.Event}var ConcreteConnection=function(){function ConcreteConnection(localMethods,messenger,sessionId){var _this=this;this.onMessage=function(ev){var data=ev.data;if(!isMessage(data)){return}if(data.sessionId!==_this.sessionId()){return}if(isCallMessage(data)){var requestId_1=data.requestId,name_1=data.name,args=data.args;_this.localCall.apply(_this,__spreadArrays([name_1],args)).then(function(value){var message=createResponsMessage(_this.sessionId(),requestId_1,value);_this.sendMessage(message)}).catch(function(e){var message=createErrorMessage(_this.sessionId(),requestId_1,e);_this.sendMessage(message)})}else if(isResponseMessage(data)){var requestId=data.requestId,result=data.result;var promiseMethods=_this._requests[requestId];if(!promiseMethods){return}promiseMethods.resolve(result);delete _this._requests[requestId];return}else if(isEventMessage(data)){var name_2=data.name,payload_1=data.payload;var listeners=_this._eventListeners[name_2];if(!listeners){return}listeners.forEach(function(listener){listener(payload_1)});return}else if(isErrorMessage(data)){var requestId=data.requestId,error=data.error;var promiseMethods=_this._requests[requestId];if(!promiseMethods){return}promiseMethods.reject(error);delete _this._requests[requestId];return}};this.localEmit=function(eventName,data){var message=createEventMessage(_this.sessionId(),eventName,data);_this.sendMessage(message)};this.remoteCall=function(methodName){var args=[];for(var _i=1;_i<arguments.length;_i++){args[_i-1]=arguments[_i]}return new Promise(function(resolve,reject){var requestId=_this.uniqueRequestId();_this._requests[requestId]={resolve:resolve,reject:reject};var message=createCallMessage.apply(void 0,__spreadArrays([_this.sessionId(),requestId,methodName],args));_this.sendMessage(message)})};this.localCall=function(methodName){var args=[];for(var _i=1;_i<arguments.length;_i++){args[_i-1]=arguments[_i]}return new Promise(function(resolve,reject){var method=_this._localMethods[methodName];if(!method){reject(new Error('The method "'+methodName+'" has not been implemented.'));return}Promise.resolve(method.apply(void 0,args)).then(function(val){return resolve(val)}).catch(function(e){return reject(e)})})};this.remoteAddEventListener=function(eventName,callback){var listeners=_this._eventListeners[eventName];if(!listeners){listeners=new Set;_this._eventListeners[eventName]=listeners}listeners.add(callback)};this.remoteRemoveEventListener=function(eventName,callback){var listeners=_this._eventListeners[eventName];if(!listeners){return}listeners.delete(callback)};this.uniqueRequestId=function(){var __requestId=0;return function(){var requestId=__requestId;__requestId+=1;return requestId}}();this._localMethods=localMethods;this._messenger=messenger;this._sessionId=sessionId;this._requests={};this._eventListeners={};this._localHandle={emit:this.localEmit};this._remoteHandle={call:this.remoteCall,addEventListener:this.remoteAddEventListener,removeEventListener:this.remoteRemoveEventListener};this._removeMainListener=this._messenger.addMessageListener(this.onMessage)}ConcreteConnection.prototype.localHandle=function(){return this._localHandle};ConcreteConnection.prototype.remoteHandle=function(){return this._remoteHandle};ConcreteConnection.prototype.sessionId=function(){return this._sessionId};ConcreteConnection.prototype.destroy=function(){this._removeMainListener()};ConcreteConnection.prototype.sendMessage=function(message){this._messenger.postMessage(message)};return ConcreteConnection}();var uniqueSessionId=function(){var __sessionId=0;return function(){var sessionId=__sessionId;__sessionId+=1;return sessionId}}();var HANDSHAKE_SUCCESS="@post-me/handshake-success";var runUntil=function(worker,condition,maxAttempts,attemptInterval){var attempt=0;var fn=function(){if(!condition()&&(attempt<maxAttempts||maxAttempts<1)){worker();attempt+=1;setTimeout(fn,attemptInterval)}};fn()};function ParentHandshake(localMethods,messenger,maxAttempts,attemptsInterval){if(maxAttempts===void 0){maxAttempts=5}if(attemptsInterval===void 0){attemptsInterval=50}var thisSessionId=uniqueSessionId();return new Promise(function(resolve,reject){var removeHandshakeListener;var connected=false;var handshakeListener=function(event){var data=event.data;if(isResponseMessage(data)){var sessionId=data.sessionId,requestId=data.requestId,result=data.result;if(sessionId===thisSessionId&&requestId===thisSessionId&&result===HANDSHAKE_SUCCESS){connected=true;removeHandshakeListener();resolve(new ConcreteConnection(localMethods,messenger,sessionId))}}};removeHandshakeListener=messenger.addMessageListener(handshakeListener);runUntil(function(){var message=createHandshakeMessage(thisSessionId);messenger.postMessage(message)},function(){return connected},maxAttempts,attemptsInterval)})}function ChildHandshake(localMethods,messenger){return new Promise(function(resolve,reject){var removeHandshakeListener;var handshakeListener=function(event){var data=event.data;if(isHandshakeMessage(data)){removeHandshakeListener();var sessionId=data.sessionId,requestId=data.requestId;var message=createResponsMessage(sessionId,requestId,HANDSHAKE_SUCCESS);messenger.postMessage(message);resolve(new ConcreteConnection(localMethods,messenger,sessionId))}};removeHandshakeListener=messenger.addMessageListener(handshakeListener)})}var acceptableMessageEvent=function(event,remoteWindow,acceptedOrigin){var source=event.source,origin=event.origin;if(source!==remoteWindow){return false}if(origin!==acceptedOrigin&&acceptedOrigin!=="*"){return false}return true};var WindowMessenger=function(){function WindowMessenger(_a){var localWindow=_a.localWindow,remoteWindow=_a.remoteWindow,remoteOrigin=_a.remoteOrigin;localWindow=localWindow||window;this.postMessage=function(message){remoteWindow.postMessage(message,remoteOrigin)};this.addMessageListener=function(listener){var outerListener=function(event){if(acceptableMessageEvent(event,remoteWindow,remoteOrigin)){listener(event)}};localWindow.addEventListener("message",outerListener);var removeListener=function(){localWindow.removeEventListener("message",outerListener)};return removeListener}}return WindowMessenger}();var WorkerMessenger=function(){function WorkerMessenger(_a){var worker=_a.worker;this.postMessage=function(message){worker.postMessage(message)};this.addMessageListener=function(listener){var outerListener=function(event){listener(event)};worker.addEventListener("message",outerListener);var removeListener=function(){worker.removeEventListener("message",outerListener)};return removeListener}}return WorkerMessenger}();var debug=function(namespace,log){log=log||console.debug||console.log||function(){};return function(){var data=[];for(var _i=0;_i<arguments.length;_i++){data[_i]=arguments[_i]}log.apply(void 0,__spreadArrays([namespace],data))}};function DebugMessenger(messenger,log){log=log||debug("post-me");var debugListener=function(event){var data=event.data;log("⬅️ received message",data)};messenger.addMessageListener(debugListener);return{postMessage:function(message){log("➡️ sending message",message);messenger.postMessage(message)},addMessageListener:function(listener){return messenger.addMessageListener(listener)}}}exports.ChildHandshake=ChildHandshake;exports.DebugMessenger=DebugMessenger;exports.ParentHandshake=ParentHandshake;exports.WindowMessenger=WindowMessenger;exports.WorkerMessenger=WorkerMessenger;exports.debug=debug;Object.defineProperty(exports,"__esModule",{value:true})});
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,factory(global["post-me"]={}))})(this,function(exports){"use strict";function createUniqueIdFn(){var __id=0;return function(){var id=__id;__id+=1;return id}}var extendStatics=function(d,b){extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b}||function(d,b){for(var p in b)if(Object.prototype.hasOwnProperty.call(b,p))d[p]=b[p]};return extendStatics(d,b)};function __extends(d,b){extendStatics(d,b);function __(){this.constructor=d}d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __)}function __spreadArrays(){for(var s=0,i=0,il=arguments.length;i<il;i++)s+=arguments[i].length;for(var r=Array(s),k=0,i=0;i<il;i++)for(var a=arguments[i],j=0,jl=a.length;j<jl;j++,k++)r[k]=a[j];return r}var Emitter=function(){function Emitter(){this.listeners={}}Emitter.prototype.addEventListener=function(eventName,listener){var listeners=this.listeners[eventName];if(!listeners){listeners=new Set;this.listeners[eventName]=listeners}listeners.add(listener)};Emitter.prototype.removeEventListener=function(eventName,listener){var listeners=this.listeners[eventName];if(!listeners){return}listeners.delete(listener)};Emitter.prototype.once=function(eventName){var _this=this;return new Promise(function(resolve){var listener=function(data){_this.removeEventListener(eventName,listener);resolve(data)};_this.addEventListener(eventName,listener)})};Emitter.prototype.emit=function(eventName,data){var listeners=this.listeners[eventName];if(!listeners){return}listeners.forEach(function(listener){listener(data)})};Emitter.prototype.removeAllListeners=function(){Object.values(this.listeners).forEach(function(listeners){if(listeners){listeners.clear()}})};return Emitter}();var MARKER="@post-me";var MessageType;(function(MessageType){MessageType["HandshakeRequest"]="handshake-request";MessageType["HandshakeResponse"]="handshake-response";MessageType["Call"]="call";MessageType["Response"]="response";MessageType["Error"]="error";MessageType["Event"]="event"})(MessageType||(MessageType={}));function createHandshakeRequestMessage(sessionId){return{type:MARKER,action:MessageType.HandshakeRequest,sessionId:sessionId}}function createHandshakeResponseMessage(sessionId){return{type:MARKER,action:MessageType.HandshakeResponse,sessionId:sessionId}}function createCallMessage(sessionId,requestId,methodName){var args=[];for(var _i=3;_i<arguments.length;_i++){args[_i-3]=arguments[_i]}return{type:MARKER,action:MessageType.Call,sessionId:sessionId,requestId:requestId,methodName:methodName,args:args}}function createResponsMessage(sessionId,requestId,result,error){var message={type:MARKER,action:MessageType.Response,sessionId:sessionId,requestId:requestId};if(result!==undefined){message.result=result}if(error!==undefined){message.error=error}return message}function createEventMessage(sessionId,eventName,payload){return{type:MARKER,action:MessageType.Event,sessionId:sessionId,eventName:eventName,payload:payload}}function isMessage(m){return m.type===MARKER}function isHandshakeRequestMessage(m){return isMessage(m)&&m.action===MessageType.HandshakeRequest}function isHandshakeResponseMessage(m){return isMessage(m)&&m.action===MessageType.HandshakeResponse}function isCallMessage(m){return isMessage(m)&&m.action===MessageType.Call}function isResponseMessage(m){return isMessage(m)&&m.action===MessageType.Response}function isEventMessage(m){return isMessage(m)&&m.action===MessageType.Event}var Dispatcher=function(_super){__extends(Dispatcher,_super);function Dispatcher(messenger,sessionId){var _this=_super.call(this)||this;_this.uniqueId=createUniqueIdFn();_this.messenger=messenger;_this.sessionId=sessionId;_this.removeMessengerListener=_this.messenger.addMessageListener(_this.messengerListener.bind(_this));return _this}Dispatcher.prototype.messengerListener=function(event){var data=event.data;if(!isMessage(data)){return}if(this.sessionId!==data.sessionId){return}if(isCallMessage(data)){this.emit(MessageType.Call,data)}else if(isResponseMessage(data)){this.emit(data.requestId,data)}else if(isEventMessage(data)){this.emit(MessageType.Event,data)}};Dispatcher.prototype.callOnRemote=function(methodName){var args=[];for(var _i=1;_i<arguments.length;_i++){args[_i-1]=arguments[_i]}var requestId=this.uniqueId();var message=createCallMessage.apply(void 0,__spreadArrays([this.sessionId,requestId,methodName],args));this.messenger.postMessage(message);return requestId};Dispatcher.prototype.respondToRemote=function(requestId,value,error){var message=createResponsMessage(this.sessionId,requestId,value,error);this.messenger.postMessage(message)};Dispatcher.prototype.emitToRemote=function(eventName,payload){var message=createEventMessage(this.sessionId,eventName,payload);this.messenger.postMessage(message)};Dispatcher.prototype.close=function(){this.removeMessengerListener();this.removeAllListeners()};return Dispatcher}(Emitter);var ParentHandshakeDispatcher=function(_super){__extends(ParentHandshakeDispatcher,_super);function ParentHandshakeDispatcher(messenger,sessionId){var _this=_super.call(this)||this;_this.messenger=messenger;_this.sessionId=sessionId;_this.removeMessengerListener=_this.messenger.addMessageListener(_this.messengerListener.bind(_this));return _this}ParentHandshakeDispatcher.prototype.messengerListener=function(event){var data=event.data;if(!isMessage(data)){return}if(this.sessionId!==data.sessionId){return}if(isHandshakeResponseMessage(data)){this.emit(data.sessionId,data)}};ParentHandshakeDispatcher.prototype.initiateHandshake=function(){var message=createHandshakeRequestMessage(this.sessionId);this.messenger.postMessage(message);return this.sessionId};ParentHandshakeDispatcher.prototype.close=function(){this.removeMessengerListener();this.removeAllListeners()};return ParentHandshakeDispatcher}(Emitter);var ChildHandshakeDispatcher=function(_super){__extends(ChildHandshakeDispatcher,_super);function ChildHandshakeDispatcher(messenger){var _this=_super.call(this)||this;_this.messenger=messenger;_this.removeMessengerListener=_this.messenger.addMessageListener(_this.messengerListener.bind(_this));return _this}ChildHandshakeDispatcher.prototype.messengerListener=function(event){var data=event.data;if(isHandshakeRequestMessage(data)){this.emit(MessageType.HandshakeRequest,data)}};ChildHandshakeDispatcher.prototype.acceptHandshake=function(sessionId){var message=createHandshakeResponseMessage(sessionId);this.messenger.postMessage(message)};ChildHandshakeDispatcher.prototype.close=function(){this.removeMessengerListener();this.removeAllListeners()};return ChildHandshakeDispatcher}(Emitter);var ConcreteRemoteHandle=function(_super){__extends(ConcreteRemoteHandle,_super);function ConcreteRemoteHandle(callFn){var _this=_super.call(this)||this;_this.call=callFn;return _this}return ConcreteRemoteHandle}(Emitter);var ConcreteLocalHandle=function(){function ConcreteLocalHandle(emitFn){this.emit=emitFn}return ConcreteLocalHandle}();var ConcreteConnection=function(){function ConcreteConnection(dispatcher,localMethods){this.dispatcher=dispatcher;this.methods=localMethods;this._remoteHandle=new ConcreteRemoteHandle(this.callRemoteMethod.bind(this));this._localHandle=new ConcreteLocalHandle(this.dispatcher.emitToRemote.bind(this.dispatcher));this.dispatcher.addEventListener(MessageType.Call,this.handleCall.bind(this));this.dispatcher.addEventListener(MessageType.Event,this.handleEvent.bind(this))}ConcreteConnection.prototype.close=function(){this.dispatcher.close();this._remoteHandle["removeAllListeners"]()};ConcreteConnection.prototype.localHandle=function(){return this._localHandle};ConcreteConnection.prototype.remoteHandle=function(){return this._remoteHandle};ConcreteConnection.prototype.handleCall=function(data){var _this=this;var requestId=data.requestId,methodName=data.methodName,args=data.args;var callMethod=new Promise(function(resolve,reject){var method=_this.methods[methodName];if(typeof method!=="function"){reject(new Error('The method "'+methodName+'" has not been implemented.'));return}Promise.resolve(method.apply(void 0,args)).then(resolve).catch(reject)});callMethod.then(function(value){_this.dispatcher.respondToRemote(requestId,value)}).catch(function(error){_this.dispatcher.respondToRemote(requestId,undefined,error)})};ConcreteConnection.prototype.handleEvent=function(data){var eventName=data.eventName,payload=data.payload;this._remoteHandle["emit"](eventName,payload)};ConcreteConnection.prototype.callRemoteMethod=function(methodName){var _this=this;var args=[];for(var _i=1;_i<arguments.length;_i++){args[_i-1]=arguments[_i]}return new Promise(function(resolve,reject){var _a;var responseEvent=(_a=_this.dispatcher).callOnRemote.apply(_a,__spreadArrays([methodName],args));_this.dispatcher.once(responseEvent).then(function(response){var result=response.result,error=response.error;if(error!==undefined){reject(error)}else{resolve(result)}})})};return ConcreteConnection}();var uniqueSessionId=createUniqueIdFn();var runUntil=function(worker,condition,unfulfilled,maxAttempts,attemptInterval){var attempt=0;var fn=function(){if(!condition()&&(attempt<maxAttempts||maxAttempts<1)){worker();attempt+=1;setTimeout(fn,attemptInterval)}else if(!condition()&&attempt>=maxAttempts&&maxAttempts>=1){unfulfilled()}};fn()};function ParentHandshake(messenger,localMethods,maxAttempts,attemptsInterval){if(localMethods===void 0){localMethods={}}if(maxAttempts===void 0){maxAttempts=5}if(attemptsInterval===void 0){attemptsInterval=100}var thisSessionId=uniqueSessionId();var connected=false;return new Promise(function(resolve,reject){var handshakeDispatcher=new ParentHandshakeDispatcher(messenger,thisSessionId);handshakeDispatcher.once(thisSessionId).then(function(response){connected=true;handshakeDispatcher.close();var sessionId=response.sessionId;var dispatcher=new Dispatcher(messenger,sessionId);var connection=new ConcreteConnection(dispatcher,localMethods);resolve(connection)});runUntil(function(){return handshakeDispatcher.initiateHandshake()},function(){return connected},function(){return reject(new Error("Handshake failed, reached maximum number of attempts"))},maxAttempts,attemptsInterval)})}function ChildHandshake(messenger,localMethods){if(localMethods===void 0){localMethods={}}return new Promise(function(resolve,reject){var handshakeDispatcher=new ChildHandshakeDispatcher(messenger);handshakeDispatcher.once(MessageType.HandshakeRequest).then(function(response){var sessionId=response.sessionId;handshakeDispatcher.acceptHandshake(sessionId);handshakeDispatcher.close();var dispatcher=new Dispatcher(messenger,sessionId);var connection=new ConcreteConnection(dispatcher,localMethods);resolve(connection)})})}var acceptableMessageEvent=function(event,remoteWindow,acceptedOrigin){var source=event.source,origin=event.origin;if(source!==remoteWindow){return false}if(origin!==acceptedOrigin&&acceptedOrigin!=="*"){return false}return true};var WindowMessenger=function(){function WindowMessenger(_a){var localWindow=_a.localWindow,remoteWindow=_a.remoteWindow,remoteOrigin=_a.remoteOrigin;localWindow=localWindow||window;this.postMessage=function(message){remoteWindow.postMessage(message,remoteOrigin)};this.addMessageListener=function(listener){var outerListener=function(event){if(acceptableMessageEvent(event,remoteWindow,remoteOrigin)){listener(event)}};localWindow.addEventListener("message",outerListener);var removeListener=function(){localWindow.removeEventListener("message",outerListener)};return removeListener}}return WindowMessenger}();var WorkerMessenger=function(){function WorkerMessenger(_a){var worker=_a.worker;this.postMessage=function(message){worker.postMessage(message)};this.addMessageListener=function(listener){var outerListener=function(event){listener(event)};worker.addEventListener("message",outerListener);var removeListener=function(){worker.removeEventListener("message",outerListener)};return removeListener}}return WorkerMessenger}();var debug=function(namespace,log){log=log||console.debug||console.log||function(){};return function(){var data=[];for(var _i=0;_i<arguments.length;_i++){data[_i]=arguments[_i]}log.apply(void 0,__spreadArrays([namespace],data))}};function DebugMessenger(messenger,log){log=log||debug("post-me");var debugListener=function(event){var data=event.data;log("⬅️ received message",data)};messenger.addMessageListener(debugListener);return{postMessage:function(message){log("➡️ sending message",message);messenger.postMessage(message)},addMessageListener:function(listener){return messenger.addMessageListener(listener)}}}exports.ChildHandshake=ChildHandshake;exports.DebugMessenger=DebugMessenger;exports.ParentHandshake=ParentHandshake;exports.WindowMessenger=WindowMessenger;exports.WorkerMessenger=WorkerMessenger;exports.debug=debug;Object.defineProperty(exports,"__esModule",{value:true})});
{
"name": "post-me",
"version": "0.2.1",
"version": "0.3.0",
"description": "A library to facilitate communication between windows (iframe, worker, popup, ...)",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -58,3 +58,3 @@ [![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)

});
ParentHandshake(methods, messenger);
ParentHandshake(messenger, methods)
.then((connection) => {

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

const messenger = new WindowMessenger({ remoteOrigin: '*' });
ChildHandshake(methods, messenger)
ChildHandshake(messenger, methods)
.then((connection) => {

@@ -120,5 +120,10 @@ const localHandle = connection.localHandle();

## Typescript
Thanks to `post-me` typescript support, the correctness of the methods call arguments and event payloads can be statically enforced during development.
Thanks to `post-me` extensive typescript support, the correctness of the following items can be statically checked during development:
- Method names
- Argument number and types
- Return values type
- Event names
- Event payload type
Ideally methods and events types should be defined in a third package that will be imported by both the parent and the child. This way, it will be ensured that both applications are working with up to date type definition.
Ideally methods and events types should be defined in a place accessible to the code of both parent and child, so that they can both import the same type definition. This way, it will be ensured that the contract between the parties will be enforced.

@@ -151,3 +156,3 @@ Below a modified version of the previous example using typescript.

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

@@ -174,6 +179,6 @@ import { ParentMethods, ParentEvents, ChildMethods, ChildEvents} from '/path/to/common';

});
ParentHandshake(methods, messenger);
.then((connection: Connection<ParentEvents, ChildMethods, ChildEvents>) => {
const localHandle = connection.localHandle();
const remoteHandle = connection.remoteHandle();
ParentHandshake(messenger, methods)
.then((connection) => {
const localHandle: LocalHandle<ParentEvents> = connection.localHandle();
const remoteHandle: RemoteHandle<ChildMethods, ChildEvents> = connection.remoteHandle();

@@ -198,3 +203,3 @@ // Call a method on the child

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

@@ -215,6 +220,6 @@ import { ParentMethods, ParentEvents, ChildMethods, ChildEvents} from '/path/to/common';

});
ChildHandshake(methods, messenger)
.then((connection: Connection<ChildEvents, ParentMethods, ParentEvents>) => {
const localHandle = connection.localHandle();
const remoteHandle = connection.remoteHandle();
ChildHandshake(messenger, methods)
.then((connection) => {
const localHandle: LocalHandle<ChildEvents> = connection.localHandle();
const remoteHandle: RemoteHandle<ParentMethods, ParentEvents> = connection.remoteHandle();

@@ -251,5 +256,4 @@ // Call a method on the parent

const messenger = new WorkerMessenger({ worker });
const methods = {};
ParentHandshake(methods, messenger).then((connection) => {
ParentHandshake(messenger).then((connection) => {
const remoteHandle = connection.remoteHandle();

@@ -281,3 +285,3 @@

const messenger = new PostMe.WorkerMessenger({ worker: self });
PostMe.ChildHandshake(methods, messenger).then((_connection) => {
PostMe.ChildHandshake(messenger, methods).then((_connection) => {
console.log('Worker successfully connected');

@@ -311,3 +315,3 @@ });

ParentHandshake({}, messenger).then((connection) => {
ParentHandshake(messenger).then((connection) => {
// ...

@@ -314,0 +318,0 @@ });

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