Awesome Open Source
Awesome Open Source

Wormhole

It's better EventEmitter for communication between tabs with supporting Master/Slave.

npm i --save-dev wormhole.js

Features


Basic example

import wormhole from 'wormhole.js'; // yes, with ".js", it's not mistake

// All tabs
wormhole().on('coords', (x, y) => {
	console.log(x, y);
});

// Some tab
wormhole().emit('coords', [5, 10]);

// Master tab
if (wormhole().master) {
	// ..
}

wormhole().on('master', () => {
	console.log('Wow!');
});

One connection on WebSocket for all tabs

Module wormhole.js/ws implements WebSocket-like interface: https://rubaxa.github.io/wormhole/?ws=y

import WS from 'wormhole.js/ws';

// Create WebScoket (wormhole-socket)
const socket = new WS('ws://echo.websocket.org'); // OR new WS('...', null, hole);

socket.onopen = () => console.log('Connected');
socket.onmessage = ({data}) => console.log('Received:', data);

// Unique event
socket.onmaster = () => {
	console.log('Yes, I\'m master!');
};

// Some tab
socket.send({foo: 'bar'})

// All tabs:
//  "Received:" {foo: 'bar'}

CORS example

  1. Create a subdomain, ex.: http://wormhole.youdomain.com/;
  2. Copy-paste universal.html and wormhole.js into root;
  3. Check access http://wormhole.youdomain.com/universal.html;
  4. Profit:
// http://foo.youdomain.com/
import {Universal} from 'wormhole.js';
const hole = new Universal('http://wormhole.youdomain.com/universal.html');

hole.on('data', (data) => {
	console.log(data);
});


// http://bar.youdomain.com/
import {Universal} from 'wormhole.js';
const hole = new Universal('http://wormhole.youdomain.com/universal.html');

hole.emit('data', 'any data');

Master/slave example

import wormhole from 'wormhole.js';

// All tabs (main.js)
// Define remote command (master)
wormhole()['get-data'] = (function (_cache) {
	return function getData(req, callback) {
		if (!_cache.hasOwnProperty(req.url)) {
			_cache[req.url] = fetch(req.url).then(res => res.json());
		}

		return _cache[key];
	};
})({});

// Get remote data method
function getData(url) {
	return new Promise((resolve, reject) => {
		// Calling command on master (from slave... or the master, is not important)
		wormhole().call(
			'get-data', // command
			{url}, // arguments
			(err, json) => err ? reject(err) : resolve(json) // callback(err, result)
		);
	});
};

// I'm master!
wormhole().on('master', () => {
	// some code
});

// Tab #X
getData('/path/to/api').then((json) => {
	// Send ajax request
	console.log(result);
});

// Tab #Y
getData('/path/to/api').then((result) => {
	// From master cache
	console.log(result);
});

Peers

wormhole()
	.on('peers', (peers) => {
		console.log('ids:', peers); // ['tab-id-1', 'tab-id-2', ..]
	})
	.on('peers:add', (id) => {
		// ..
	})
	.on('peers:remove', (id) => {
		// ..
	})
;

Executing the command on master

// Register command (all tabs)
wormhole()['foo'] = (data, next) => {
	// bla-bla-bla
	next(null, data.reverse()); // or `next('error')`
};


// Calling the command (some tab)
wormhole().call('foo', [1, 2, 3], (err, results) => {
	console.log(results); // [3, 2, 1]
})

Modules

  • Emitter — Micro event emitter
  • cors — Handy wrapper over postMessage.
  • store — Safe and a handy wrapper over localStorage.

wormhole.Emitter

Micro event emitter.

  • on(type:String, fn:Function):this
  • off(type:String, fn:Function):this
  • emit(type:String[, args:*|Array]):this
import {Emitter} from 'wormhole.js';

const obj = Emitter.apply({}); // or new wormhole.Emitter();

obj.on('foo', () => {
  console.log(arguments);
});

obj.emit('foo'); // []
obj.emit('foo', 1); // [1]
obj.emit('foo', [1, 2, 3]); // [1, 2, 3]

wormhole.cors

Handy wrapper over postMessage.

import {cors} from 'wormhole.js';

// Main-document
cors.on('data', (data) => {
	console.log('Received:', data);
});

cors['some:command'] = (value) => value * 2;

// IFrame
cors(parent).send({foo: 'bar'});
// [main-document] "Received:" {foo: 'bar'}

cors(parent).call('some:command', 3, (err, result) => {
	console.log('Error:', err, 'Result:', result);
	// [iframe] "Error:" null "Result:" 6
});

wormhole.store

Safe and a handy wrapper over localStorage.

  • get(key:String):*
  • set(key:String, value:*)
  • remove(key:String)
  • on(type:String, fn:Function)
  • off(type:String, fn:Function)
import {store} from 'wormhole.js';

store.on('change', (key, data) => {
	console.log('change -> ', key, data);
});

store.on('change:prop', (key, value) => {
	console.log('change:prop -> ', key, value);
});

store.set('foo', {bar: 'baz'});
// change -> foo {bar: 'baz'}

store.set('prop', {qux: 'ok'});
// change -> prop {qux: 'ok'}
// change:prop -> prop {qux: 'ok'}

Utils


wormhole.uuid():String

A universally unique identifier (UUID) is an identifier standard used in software construction, standardized by the Open Software Foundation (OSF) as part of the Distributed Computing Environment (DCE) (c) wiki.


wormhole.debounce(fn:Function, delay:Number[, immediate:Boolean]):Function

Creates and returns a new debounced version of the passed function that will postpone its execution until after wait milliseconds have elapsed since the last time it was invoked.


Development

  • npm test
  • npm run dev — run dev watcher
  • npm run build

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
javascript (68,071
websocket (438
communication (81
cors (50
persistent (18

Find Open Source By Browsing 7,000 Topics Across 59 Categories