The general idea behind Rempl
is to simplify moderated remote access to JavaScript runtime. Rempl
provides a transport between environments and a set of UI hosts.
Built on Rempl
:
- shower-remote-control – Shower plugin for remote controlling of presentation
- webpack-runtime-analyzer – Webpack plugin for analyzing internal processes, state and structure of bundles
npm install rempl
<script src="node_modules/rempl/dist/rempl.js"></script>
<script>
var myTool = rempl.createPublisher('myTool', function(settings, callback) {
/* return a UI bundle or url */
});
// ...
</script>
By default publisher attempts to connect to WS server with the same hostname
as page but 8177
as port. There are some options to specify rempl end point:
- using
<meta name="rempl:server" content="{rempl server host}">
:<meta name="rempl:server" content="//1.2.3.4:1234"> <!-- or content="none" to disable connection to WS server -->
- using
ws
option onPublisher
create:new Publisher('name', function() { ... }, { ws: '//1.2.3.4:1234' // set false to disable connection to WS server });
- using
connectWS()
method ofPulisher
's instancevar myPublisher = new Publisher('name', function() { ... }); myPublisher.connectWs('//1.2.3.4:1234')
var rempl = require('rempl');
var myTool = rempl.createPublisher('myTool', function(settings, callback) {
/* return a UI bundle or url */
});
// ...
When publisher is running on Node.js, it doesn't connect to WS server until WS server is not specified (there is no location
object available like in browser's environment). There some options to specify server host:
- using environment variable
REMPL_SERVER
when start a script or before rempl is required for a first time. Example for MacOS:> REMPL_SERVER=//1.2.3.4:1234 node my-script.js
- using
ws
option onPublisher
create:new Publisher('name', function() { ... }, { ws: '//1.2.3.4:1234' // set false to disable connection to WS server });
- using
connectWS()
method ofPulisher
's instancevar myPublisher = new Publisher('name', function() { ... }); myPublisher.connectWs('//1.2.3.4:1234')
Subject
– something to be inspected, i.e. app, page, environment etc.Publisher
– monitors asubject
, collects data and publishes it forsubscribers
Subscriber
– consumer ofpublisher
's data, provides an UI for received dataTransport
– channels and protocols betweenpublisher
andsubscriber
; WebSocket (socket.io) or DOM Event-based communication may to be used between endpointsHost
– integrates in some environment (app), allows to choose a publisher and creates asandbox
for itssubscriber
; usually it's a plugin for something like browser, editor etc.Sandbox
– creates asubscriber
, request an UI and activate it when received
Publisher and subscriber are two parts of single app (tool). Transports, hosts and sandboxes are parts of rempl
.
For most cases you need a WebSocket transport. In this case a WS server is required. Rempl provides
- rempl-cli – command line app to launch a server
- menubar-server – an Electron app that launchs an
rempl
server instance and provide easy control over it; allows forget about command line
Rempl
server provides web interface to monitor list of publishers and to launch selected publisher's UI in sandbox. Just open server's origin (by default http://localhost:8177
) in your browser.
- Browsers
- Google Chrome [repo]
- Firefox (planned)
- Editors
Publisher doesn't depends hard on environment. It's mostly limited by transports allowed to process. Currently rempl
publisher works well in:
- Browser's regular page
- Node.js process
Planned (not tested yet):
- WebWorker
- ServiceWorker
Publisher can theoretically be created in non-JavaScript environment. In this case publisher interface and socket.io client should be implemented in language you use.
For tools based on rempl
, a publisher is a source of UI. When new sandbox for subscriber is created, it sends a request to publisher to provide an UI. Publisher should provide UI in some way:
script
– JavaScript bundle that includes everything is needed to build an UI (i.e. JavaScript, CSS, templates etc.). Whenscript
type is using,rempl
injects itself before script evaluation. Therefore no need to include rempl source to subscriber.url
– url of page subscriber. In this caserempl
should be included to page by author.
var rempl = require('rempl');
var myTool = rempl.createPublisher('myTool', function(settings, callback) {
callback(null, 'script', 'alert("myTool UI inited")');
});
setInterval(function() {
myTool.publish(Date.now());
}, 1000);
myTool.provide({
pong: function() {
console.log('Remote subscriber invoke `pong`');
}
});
publish(data)
pipe(fn[, init])
provide(methodName, fn)
orprovide(methods)
isMethodProvided(method)
revoke(methodName)
orrevoke(methodNamesArray)
callRemote(method, ...args, callback)
ns(namespace)
- publish/pipe/provide/revoke/isMethodProvided/callRemote
var myTool = rempl.getSubscriber();
myTool.subscribe(function(data) {
console.log('Receive data from publisher:', data);
myTool.callRemote('pong');
});
subscribe(callback)
provide(methodName, fn)
orprovide(methods)
isMethodProvided(methodName)
revoke(methodName)
orrevoke(methodNamesArray)
callRemote(methodName, ...args, callback)
getRemoteMethod(methodName)
isRemoteMethodExists(methodName)
onRemoteMethodsChanged(callback)
ns(namespace)
- subscribe/provide/revoke/isMethodProvided/callRemote
Rempl provides a host that can be injected right in the inspecting page, so called in-page
host. To get that host use rempl.getHost()
method.
var inpageHost = rempl.getHost();
inpageHost.activate();
inpageHost.activate(publisherName);
inpageHost.deactivate();
inpageHost.deactivate(publisherName);
Host has two methods activate()
and deactivate()
.
activate([publisherName])
- uses to add host's view to page. When used with no argument method show UI and selects a first publisher. When argument is passed, it selects publisher with specified name.deactivate([publisherName])
- hide host's view if it showed. WhenpublisherName
is passed, method deactivates view only if publisher with passed name is selected.
Publishers and Subcribers can provide methods for remote side invocation and invoke methods of other side. API of both sides is symetric. Every namespace have the same RPC API as Publisher or Subscriber have.
NOTE: Examples are given for a Publisher, but the same API is available for any Subscriber since API is symetric.
Method to provide a method(s) for remote side. It allows to provide a single method or batch of methods.
publisher.provide('foo', function() {
console.log('Method `foo` was invoked by subscriber');
});
publisher.ns('something').provide({
method1: function() { /* do something */ },
method2: function() { /* do something */ }
});
Method to revoke a method(s) that was provided before. It allows to revoke a single method or several methods at once.
publisher.revoke('foo');
publisher.ns('something').revoke(['method1', 'method2']);
Invoke remote side method with given arguments. All arguments should be a transferable through JSON data types, i.e. number
, string
, boolean
, Array
, plain object or null. The last argument can be a function that remote side can use to send data back.
publisher.callRemote('methodName', 1, 2, function(res) {
console.log('response from subscriber');
});
Returns true
when own method is provided for remote side by provide()
method.
publisher.isMethodProvided('test'); // false
publisher.provide('test', function() {});
publisher.isMethodProvided('test'); // true
publisher.revoke('test');
publisher.isMethodProvided('test'); // false
Returns true
when remote method is available to be invoked.
Currently method doesn't work for publisher since there can be several subscribers with different method set provided.
if (subscriber.isRemoteMethodExists('test')) {
subscriber.callRemote('test');
}
Allows to subscribe to remote side API state of namespace. Method invoke passed callback on subscription and return a function to unsubscribe.
Currently method doesn't work for publisher since there can be several subscribers with different method set provided.
var unsubscribeDefaultNsMethodsLogging = subscriber.onRemoteMethodsChanged(function(methods) {
console.log(methods);
});
// call returned function when need to stop listen for API changes
unsubscribeDefaultNsMethodsLogging();
Returns a function that invokes callRemote
with specified methodName
. This function is context free (namespace is binded) and invokes callRemote
only when remote method is available, otherwise it outputs a warning. available
property of function can be used to check a remote method is available.
Currently method doesn't work for publisher since there can be several subscribers with different method set provided.
var fooMethod = subscriber.getRemoteMethod('foo');
var nsBarBazMethod = subscriber.ns('bar').getRemoteMethod('baz');
if (fooMethod.available) {
fooMethod(1, 2, 3);
}
nsBarBazMethod();
// with no check a warning message might to be outputed