Load the module "node-jet":
var jet = require('node-jet');
The Jet Peer is able to to consume content provided by (other) peers:
- set States to new values, see
peer.set
- call Methods, see
peer.call
- fetch States and Methods as a realtime query, see
jet.Fetcher
The Jet Peer is also able to create content:
- add States , see
jet.State
- add Methods , see
jet.Method
Creates and returns a new Jet Peer instance with the specified connection config. The supported config fields are:
url
: {String} The Jet Daemon Websocket URL, e.g.ws://localhost:11123
ip
: {String} The Jet Daemon TCP trivial protocol ip (default:localhost
)port
: {String} The Jet Daemon TCP trivial protocol port (default:11122
)user
: {String, Optional} The user name used for authenticationpassword
: {String, Optional} The password used for authenticationrejectUnauthorized
: {Boolean, Optional} Allow self signed server certificates, when using wss:// (default:false
)headers
: {Object, Optional} Pass additional headers (cookies, bearer etc) to the WebSocket upgrade request
The peer uses either the Websocket protocol or the TCP trivial protocol (default) as transport.
When specifying the url
field, the peer uses the Websocket protocol as transport.
If no config
is provided, the Peer connects to the local ('localhost') Daemon using the trivial protocol.
Browsers do only support the Websocket transport and must be provided with a config
with url
field.
Authentication is optional and is explained separately.
var jet = require('node-jet');
var peer = new jet.Peer({
url: 'ws://jet.nodejitsu.com:80'
});
peer.connect().then(function() {
console.log('connection to Daemon established');
console.log('Daemon Info: ', peer.daemonInfo);
});
Connects to the Daemon and returns a Promise which gets resolved as the connection is established.
After the connect Promise has been resolved, the peer provides peer.daemonInfo
.
peer.connect().then(function() {
var daemonInfo = peer.daemonInfo;
console.log('name', daemonInfo.name); // string
console.log('version', daemonInfo.version); // string
console.log('protocolVersion', daemonInfo.protocolVersion); // number
console.log('can process JSON-RPC batches', daemonInfo.features.batches); // boolean
console.log('supports authentication', daemonInfo.features.authentication); // boolean
console.log('fetch-mode', daemonInfo.features.fetch); // string: 'full' or 'simple'
});
The returned Promise may be rejected with:
Closes the connection to the Daemon. Returns a promise which resolves as the connection has been closed.
Returns a promise which gets resolved when the connection to the Daemon has been closed.
Tries to set the Jet State specified by path
to value
. Returns a Promise which gets resolved as
the specified state has been setted successfully to the specified value.
peer.set('foo', 123)
.then(function() {
console.log('set finished successfully');
}).catch(function(err) {
console.log('set failed', err);
});
// dont care about the result
peer.set('foo', 12341);
options
is an optional argument, which supports the following fields:
timeout
in seconds. Time to wait before rejecting with a timeout errorvalueAsResult
boolean flag. If settrue
the returned Promise get the "real" new value as argument.
peer.set('magic', 123, {
timeout: 7,
valueAsResult: true
}).then(function(realNewValue) {
console.log('magic is now', realNewValue);
}).catch(function(err) {
console.log('set failed', err);
});
The returned Promise may be rejected with:
jet.ConnectionClosed
jet.Unauthorized
jet.FetchOnly
jet.NotFound
jet.PeerError
jet.PeerTimeout
jet.InvalidArgument
Calls the Jet Method specified by path
with args
as arguments. Returns a Promise which may get resolved with the
Method call's result
. An options
object may be specified which may define a
timeout
in seconds. Time to wait before rejecting with a timeout error
peer.call('sum', [1,2,3,4,5]).then(function(result) {
console.log('sum is', result);
}).catch(function(err) {
console.log('could not calc the sum', e);
});
// dont care about the result
peer.call('greet', {first: 'John', last: 'Mitchell'});
The returned Promise may be rejected with:
jet.ConnectionClosed
jet.Unauthorized
jet.NotFound
jet.PeerError
jet.PeerTimeout
jet.InvalidArgument
Registers a jet.State
or a jet.Method
instance at the Daemon. The returned Promise gets resolved
when the Daemon has accepted the request and set
(States) or call
(Methods) events may be emitted.
var jim = new jet.State('persons/a4362d', {name: 'jim'});
peer.add(jim).then(function() {
console.log('jim has been added');
});
The returned Promise may be rejected with:
Unregisters a jet.State
or a jet.Method
instance at the Daemon.
As soon as the returned Promise gets resolved, no set
or call
events for the state/method are emitted anymore.
var jim = new jet.State('persons/a4362d', {name: 'jim'});
peer.add(jim).then(function() {
console.log('jim has been added');
peer.remove(jim).then(function() {
console.log('jim has been removed');
});
});
The returned Promise may be rejected with:
Registers the fetcher at the Daemon. A jet.Fetcher
must be created first. The returned Promise gets resolved
when the Daemon has accepted the fetcher and data
event may be emitted.
var topPlayers = new jet.Fetcher()
.path('startsWith', 'players/')
.sortByKey('score', 'number')
.range(1, 10)
.on('data', function(playersArray) {
});
peer.fetch(topPlayers);
The returned Promise may be rejected with:
Unregisters the fetcher at the Daemon.
As soon as the returned Promise gets resolved, no data
events for the fetcher are emitted anymore.
path
: {String} The unique path of the Statevalue
: {Any} The initial value of the Stateaccess
: {Object, Optional} ContainingfetchGroups
andsetGroups
Creates a new State (but does NOT register it at the Daemon).
To register the State call peer.add
!
var john = new jet.State('peoples/25261', {age: 43, name: 'john'}, {
fetchGroups: ['public'],
setGroups: ['admin']
});
peer.add(john).then(function() {
});
Registers a set
event handler. Should be called before the state is actually added (peer.add(state)
).
The cb
callback gets the new requested value passed in.
The function is free to:
- return nothing, a State change is posted automatically with the
newValue
- throw an Error, the Error should be a String or an Object with
code
andmessage
- return on Object with the supported fields:
value
: {Any, Optional} the "real/adjusted" new value. This is posted as the new value.dontNotify
: {Boolean, Optional} Don't auto-send a change Notification
john.on('set', function(newValue) {
var prev = this.value();
if (newValue.age < prev.age){
throw 'invalid age';
}
return {
value: {
age: newValue.age,
name: newValue.name || prev.name
}
};
});
To provide an async set
event handler, provide two arguments to the callback.
- The requested
newValue
reply
: {Function} Method for sending the result/error.
john.on('set', function(newValue, reply) {
setTimeout(function() {
var prev = this.value();
if (newValue.age < prev.age){
reply({
error: 'invalid age'
});
} else {
reply({
value: {
age: newValue.age,
name: newValue.name || prev.name
}});
}
}, 200);
});
The arguments to reply
can be:
value
: {Any} The new value of the state.dontNotify
: {Boolean} Dont auto notify a state change.error
: {String/Error, Optional} Operation failed
If newValue
is undefined
, returns the current value. Else posts a value
change Notification that the State's value is now newValue
.
Use this for spontaneouos changes of a State which were not initially triggered
by the set
event handler invokation.
var ticker = new jet.State('ticker', 1);
peer.add(ticker).then(function() {
setTimeout(function() {
var old = ticker.value();
ticker.value(++old);
},1000);
});
Register the state from the Daemon convenience function. peer.add(state)
must have been called before to initially bind the state
to the respective peer!
The returned Promise may be rejected with:
Unregister the state from the Daemon. Is the same as calling peer.remove(state)
.
The returned Promise may be rejected with:
Creates a new fetcher. All fetcher calls are chainable.
Register the fetcher instance with a call to peer.fetch(fetcher)
.
Installs a callback handler for the data
event.
The fetchCb
argument for non-sorting fetches is an Object with:
path
: {String} The path of the State / Method which triggered the Fetch Notificationevent
: {String} The event which triggered the Fetch Notification ('add', 'remove', 'change')value
: {Any | undefined} The current value of the State orundefined
for Methods
var movies = new Fetcher()
.path('startsWith', 'movies')
.on('data', function(data) {
console.log(data.path, data.event, data.value);
});
peer.fetch(movies);
For sorting fetch rules, the fetchCb
arguments are:
sortedStatesArray
: {Array} The sorted states/methods
var topTenPlayers = new jet.Fetcher()
.path('startsWith', 'players/')
.sortByKey('score', 'number')
.range(1, 10)
.on('data', function(topTenPlayersArray) {
});
peer.fetch(topTenPlayers);
Adds a path matching rule to the fetcher.
Implemented path
predicates are:
startsWith
{String}startsNotWith
{String}endsWith
{String}endsNotWith
{String}contains
{String}containsNot
{String}containsOneOf
{Array of Strings}containsAllOf
{Array of Strings}containsOneOf
{Array of Strings}equals
{String}equalsOneOf
{Array of Strings}equalsNotOneOf
{Array of Strings}
Makes path matching case insensitive.
Directly sets the fetch expression rule object. This call overwrite all previously set (chained) rules.
// The expression may contain the following entries
var expr = {
path: { // path based matches
caseInsensitive: true,
startsWith: 'foo',
contains: ['bar', 'test']
// and all other path based match rules
},
value: { // value based matches
equals: 3
// and other value based match rules
},
valueField: {
'sub.object.path': {
isType: 'string'
// and other value/key based match rules
},
'another.sub.object.path': {
lessThan: 5
// and other value/key based match rules
}
},
sort: {
asArray: true, // pass items as sorted array to data callback. See fetcher.differential doc
byPath: true, // either this
byValue: 'number', // or this (needs supposed js type)
byValueFiels: { // or this
'sub.object.path': 'string'
},
descending: true,
from: 1, // starts with index 1 (inclusive range)
to: 100 // last index 100 (inclusive range)
}
}
Adds a value matching rule for primitive type values to the fetcher.
Implemented predicates are:
lessThan
{any less than comparable}greaterThan
{any greater than comparable}equals
{any primitive type}equalsNot
{any primitive type}isType
{String}
Adds a key matching rule for Object type values to the fetcher.
Nested keys can be specified like this: relatives.father.age
.
Implemented predicates are:
lessThan
{any less than comparable}greaterThan
{any greater than comparable}equals
{any primitive type}equalsNot
{any primitive type}isType
{String}
Adds a sort by path rule to the fetcher.
Adds a sort by value for primitive types to the fetcher. Type can be either:
number
string
Adds a sort by key for Object types to the fetcher. Type can be either:
number
string
Nested keys can be specified like this: relatives.father.age
.
Adds a sort range to the fetcher. Note that the first index is 1. from-to is a closed interval, that
means fetcher.range(1,10)
gives you up to ten matching states/methods.
Adds a sort descending rule to the fetcher.
Adds a sort ascending rule to the fetcher.
Unfetches (removes) the Fetcher. callbacks
is optional.
// setup some fetcher
var fetcher = new jet.Fetcher();
fetcher.on('data', function(path, event, value) {
if (event === 'remove') {
this.unfetch();
}
});
peer.fetch(fetcher);
The returned Promise may be rejected with:
Creates and returns a Jet Method. To register the Method at the Daemon call peer.add(method)
.
path
: {String} The unique path of the Methodaccess
: {Object, Optional} ContainingfetchGroups
andcallGroups
var greet = new jet.Method('greet', {
fetchGroups: ['public'],
callGroups: ['public']
});
peer.add(greet).then(function() {
});
Installs a call
event handler, which gets executed whenever some peer issues a call request (peer.call
).
The arguments to the call
Function are the forwarded "args" field from of original "call" Request.
Either an Array or an Object.
The call
method can return anything or throw an Error (String/JSON-RPC error)
if required.
greet.on('call', function(who) {
if (who.first === 'John') {
throw 'John is dismissed';
}
var greeting = 'Hello Mr. ' + who.last;
console.log(greeting);
return greeting;
});
To provide an async call
event handler, provide two arguments to the callback.
- The forwarded args (Array or Object)
reply
: {Function} Method for sending the result/error.
greet.on('call', function(who, reply) {
if (who.first === 'John') {
throw 'John is dismissed';
}
setTimeout(function() {
var greeting = 'Hello Mr. ' + who.last;
console.log(greeting);
reply({
result: greeting
});
}, 100);
});
The arguments to reply
can be:
result
: {Truish, Optional} Operation was successerror
: {String/Error, Optional} Operation failed
Register the method from the Daemon convenience function. peer.add(method)
must have been called before to initially bind the method
to the respective peer!
The returned Promise may be rejected with:
Unregister the method from the Daemon. Is the same as calling peer.remove(method)
.
The returned Promise may be rejected with:
All Peer methods which return a Promise maybe rejected with a typed error. See the doc of each method to see, which
error types this can be for each respective method. For instance the peer.add
method
may throw jet.ConnectionClosed
, jet.Unauthorized
or jet.Occupied
.
There are three recommended strategies for handling different errors:
- Using
err.name
to distinguish between the types - Using
instanceof
operator
// by err.name
peer.set('foo', {age: 3, name: 'bar'})
.then(function() {})
.catch(function(err) {
if (err.name === 'NotFound') {
console.log('foo was not found');
} else if (err.name === 'PeerTimeout') {
console.log('foo is not responding fast enough');
} ...
});
// by instanceof
peer.set('foo', {age: 3, name: 'bar'})
.then(function() {})
.catch(function(err) {
if (err instanceof jet.NotFound) {
console.log('foo was not found');
} else if (err instanceof jet.PeerTimeout) {
console.log('foo is not responding fast enough');
} ...
});
Base class for all jet Error types. For all error instances err instanceof Error
and err instanceof jet.BaseError
is true
.
The connection to the specified endpoint could not be established or has been closed.
The user (name) provided is not registered at the Daemon.
The password provided for the user is not correct.
The State or Method specified by path
has not been added to the Daemon.
One could fetch
the respective State or Method to wait until it becomes available.
A State or Method with the specified path
can not be added, because another
State/Method with the same path
already has been added.
The Peer processing the set
or get
request has not answered within the specified timeout.
The Peer processing the set
ot get
request threw an error during dispatching the request.
The State specified by path
cannot be changed. Some States have strict "monitor" characteristics, as they can be observed
(by fetched), but not changed by calling peer.set
.
The peer instance (user/password) is not authorized to perform the requested action.