4.0.7 • Published 5 years ago

@pubkeeper/client v4.0.7

Weekly downloads
4
License
UNLICENSED
Repository
github
Last release
5 years ago

Pubkeeper Client

@pubkeeper/client enables web browsers to join, consume, and produce content on a Pubkeeper network.

Concepts & Terms

  • Brew : A protocol/method of delivery, e.g. WebSocket, SocketIO, WebRTC, HTTP
  • Brewer : An object bound to a specific topic that accepts a data transports it to matched patrons.
  • Patron : A consumer bound to one or more topics, it receives data from matched brewers.

Installation

In a browser:

<script src="pubkeeper-client.js"></script>

Using npm:

$ npm install --save @pubkeeper/client

Then, load using ES5 require() syntax…

var PubkeeperClient = require('@pubkeeper/client').PubkeeperClient;

…or with ES2015+ import syntax:

import { PubkeeperClient } from '@pubkeeper/client';

Basic Syntax

Client Configuration

import { PubkeeperClient } from '@pubkeeper/client';
import { WebSocketBrew } from '@pubkeeper/brew-websocket';
import { PubkeeperAesCbcCrypto } from '@pubkeeper/crypto-cjs-aes-cbc';

// Create a client
const client = new PubkeeperClient({
  server: 'wss://192.168.100.191:9898/ws',
  jwt: "[your JWT]",
  crypto: new Map([
    PubkeeperAesCbcCrypto,
  ]),
  brews: [
    new WebSocketBrew({
      brewerConfig: {
        hostname: '192.168.100.191',
        port: 8000,
        secure: true,
      },
    }),
  ],
});

client.connect();

Note: This client is the core pubkeeper client, as such it does not include any crypto or brews. If you want a pre-packaged version suitable for general usage see @pubkeeper/browser-client

Brewing Setup

To produce data into the Pubkeeper network you will need to create a brewer. The example below will setup a Brewer with the topic of topic.information

client.addBrewer('topic.information', (brewer) => {
  // brewer has been *matched* by pubkeeper, i.e. there is
  // at least one patron of this topic.
  let counter = 0;

  const id = setInterval(() => {
    brewer.brewJSON({ counter });
    counter += 1;
  }, 1000);

  return function teardown() {
    // teardown function will be called when there are
    // _no_ more patrons or this brewer has been removed.
    clearInterval(id);
  };
});

Patron Setup

To listen to someone who is brewing information, you need to subscribe to the topic, and configure a callback to occur when there is data available for processing.

client.addPatron('weather.*', (patron) => {
  // patron has been *matched* by pubkeeper, i.e. there is
  // at least one brewer of this topic.
  function handler(bytes, meta) {
    console.log(meta.from, meta.topic, patron.id, bytes);
  };

  patron.on('message', handler);

  return function teardown() {
    // teardown function will be called when there are
    // _no_ more brewers or this patron has been removed.
    patron.off('message', handler);
  };
});

Brewer/Patron Connections

The Patron message event is always fired with a Uint8Array as data, no matter which brew*() method was called on the brewing side. You need to handle parsing/casting those bytes.

For instance, given a brewer:

client.addBrewer('tick', (b) => {
  let id, count = 0;
  (function tick() {
    id = setTimeout(tick, 1000);
    b.brewJSON({ count });
  })();
  return () => { clearTimeout(id); };
});

Then on the patron side, it would look like this;

client.addPatron('tick', (p) => {
  const handler = (bytes) => {
    const text = new TextDecoder().decode(bytes);
    const value = JSON.parse(text);
    console.log(value.count);
  };
  p.on('message', handler);
  return () => { p.off('message', handler); };
});

NOTE This will be resolved in future versions of the protocol.

State Change Events

Brewers and Patrons will be notified when thier couterparts are added or removed:

client.addBrewer('topic.information', (brewer) => {
  const handleAdded = ({ id, topic }) => {
    console.log('patron (%s) added', id);
  };

  const handleRemoved = ({ id }) => {
    console.log('patron (%s) removed', id);
  };

  // setup
  brewer.on('added', handleAdded);
  brewer.on('removed', handleRemoved);

  return function teardown() {
    // cleanup
    brewer.off('added', handleAdded);
    brewer.off('removed', handleRemoved);
  };
});

Legacy/Deprecated API

The legacy (<=2.0.0) API is now deprecated/obsolete depending on how it is invoked. The objects returned by client.addBrewer() and client.addPatron() are place-holders/identifiers for the actual implementation that is resolved by the version of the protocol that gets negotiated with the server.

This means that trying to access a brewer or patron at the top-level before you have established a connection to a Pubkeeper server will throw an exception:

const client = new PubkeeperClient(config);
const p = client.addPatron('topic');
// OBSOLETE exception
p.on('message', (data) => { /* ... */ });
client.connect();

You can still access the deprecated interface, as long as you wait until after you have connected to the pubkeeper server:

const client = new PubkeeperClient(config);
const p = client.addPatron('topic');
client.connect().then(() => {
  // DEPRECATED warning
  p.on('message', (data) => { /* ... */ });
});

However, this exhibit undesirable behavior if the connection to the server is lost/reconnected. Use at your own risk.

The correct way is to use the matcher callback, which will give you actual implementation:

const client = new PubkeeperClient(config);
client.addPatron('topic', (patron) => {
  p.on('message', (data) => { /* ... */ });
  return () => p.removeAllListeners();
});
client.connect();

PubkeeperClient Class

The PubkeeperClient manages the connection to a pubkeeper server.

new PubkeeperClient(options)

NameTypeDescription
optionsClientOptionsThe options for this pubkeeper client
ClientOptions : object

These options can be given to a PubkeeperClient to customize its behavior.

NameTypeDefaultDescription
serverstring-Websocket URL of the pubkeeper server
jwtstring-Auth token for the pubkeeper server
brewsArray<Brew>[]Supported brews of this client
cryptoMap<*,Crypto>new MapSupported crypto mappings for this client
protocolsMap<*,Protocol>new MapSupported protocol mappings for this client. Defaults to the legacy protocol
maxRetriesnumberInfinityMaximum number of connection retries
maxTimeoutnumber10000Maximum timeout between retries (in milliseconds)
Examples

Using ES2015 Promise:

const client = new PubkeeperClient(config)

client.connect().then(() => {
  console.log('ready');
});

Using ES2017 async/await:

(async () => {
  const client = new PubkeeperClient(config)
  await client.connect();
  console.log('ready');
})();

Members

.status : string

Returns the status of this client. Can be one of the following:

ValueDescription
'connecting'Attempting to connect.
'connected'Connected
'reconnecting'Has lost the connection, and has queued a reconnection attempt.
'disconnected'Disconnected
'dead'Given up retrying to connect

Methods

.connect({ wait = true } = {}) : Promise?

Connect to the configured pubkeeper server. If { wait: true } is specified, this function will return a Promise that will be resolved when the connection to the pubkeeper server has been finalized. Passing { wait: false } will immediately return undefined and the server may or may not be connected yet.


.disconnect()

Disconnect from the server.


.addBrewer(topic[,[ options,] matched]) : Brewer

Create a new brewer of topic.

NameTypeDescription
topicstringThe topic
optionsBrewerOptions
matchedFunctionCallback that is invoked when the brewer has been matched with a patron
BrewerOptions : object

These options can be given to the PubkeeperClient#addBrewer method to customize the brewers behavior.

NameTypeDefaultDescription
autoRemoveListenersbooleanfalseAutomatically remove all event listeners on unmatch
brewsArray<(string\|Brew)>-A subset of brews to use for this brewer, defaults to all registered brews.
idstring-The UUID of this brewer, defaults to a random UUIDv4
waitForBrews(number\|boolean)250The maximum wait time to wait when brewing data for brew connections to stablize.
Examples

Using the matched callback:

client.addBrewer('topic', (brewer) => {
  brewer.brewText('somebody is out there!');
});

With extended options:

// Do not wait for brew connections to stablize before sending.
client.addBrewer(
  'topic',
  { waitForBrews: false },
  (brewer) => {
    brewer.brewText('somebody is out there!');
  },
);

Managing resources with teardown function:

client.addBrewer(
  'device.motion',
  (brewer) => {
    const handler = ({ acceleration }) => {
      brewer.brewJSON(acceleration);
    };
    window.addEventListener('devicemotion', handler);
    return () => {
      window.removeEventListener('devicemotion', handler);
    };
  },
);

.removeBrewer(brewer)

Remove a brewer from this client.

Examples
const ref = client.addBrewer('topic', matchedFn);
/* ...later */
client.removeBrewer(ref);

.addPatron(topic[,[ options,] matched]) : Patron

Create a new patron of topic.

NameTypeDescription
topicstringThe topic
optionsPatronOptions
matchedFunctionCallback that is invoked when the patron has been matched with a brewer
PatronOptions : object

These options can be given to the PubkeeperClient#addPatron method to customize the patrons behavior.

NameTypeDefaultDescription
autoRemoveListenersbooleanfalseAutomatically remove all event listeners on unmatch
brewsArray<(string\|Brew)>-A subset of brews to use for this patron, defaults to all registered brews.
idstring-The UUID of this patron, defaults to a random UUIDv4
Examples

Using the matched callback:

client.addBrewer('topic', (patron) => {
  const handler = (data, meta) => { /* process data */ };
  patron.on('message', hanlder);
  return () => { patron.off('message', handler); };
});

.removePatron(brewer)

Remove a patron from this client.

Examples
const ref = client.addPatron('topic', matchedFn);
/* ...later */
client.removePatron(ref);

Brewer Class

A brewer is a publisher of information in a pubkeeper system.

Members

.id : string

the uuid of this brewer


.brews : Array<string>?

the subset of brew names that this brewer is using.


.topic : string

the topic this brewer is bound to


.count : number

current count of matched patrons


.isMatched : boolean

Is the brewer currently matched with any patrons

Methods

.brew(bytes[, options]) : Promise

Publish binary data to a brewer.

NameTypeDescription
bytes(Uint8Array\|Uint8ClampedArray)Binary data to brew
optionsobject
options.waitForBrewsnumber?Override the brewers config

.brewText(text[, options]) : Promise

Publish text as a UTF-8 encoded byte array.

NameTypeDescription
textstringtext to brew
optionsobject
options.waitForBrewsnumber?Override the brewers config

.brewJSON(value[, options]) : Promise

Publish value using JSON.stringify.

NameTypeDescription
value*value to serialize and brew
optionsobject
options.waitForBrewsnumber?Override the brewers config

.on(event, fn[, context]) : this
.addListener(event, fn[, context]) : this

Add a listener for a given event.


.off(event, fn[, context[, once]]) : this
.removeListener(event, fn[, context[, once]]) : this

Remove the listeners of a given event.

Events

added

Fired when a matched patron is added.

NameTypeDescription
eobject
e.idstringUUID of the added patron
e.topicstringtopic of the brewer

removed

Fired when a matched patron is removed.

NameTypeDescription
eobject
e.idstringUUID of the removed patron

Patron Class

A patron is a subscriber of information in a pubkeeper system.

Members

.id : string

the uuid of this patron


.brews : Array<string>?

the subset of brew names that this patron is using.


.topic : string

the topic this patron is bound to


.count : number

current count of matched brewers


.isMatched : boolean

Is the patron currently matched with any brewers

Methods

.on(event, fn[, context]) : this
.addListener(event, fn[, context]) : this

Add a listener for a given event.


.off(event, fn[, context[, once]]) : this
.removeListener(event, fn[, context[, once]]) : this

Remove the listeners of a given event.

Events

added

Fired when a matched brewer is added.

NameTypeDescription
eobject
e.idstringUUID of the added brewer
e.topicstringtopic of the brewer

removed

Fired when a matched brewer is removed.

NameTypeDescription
eobject
e.idstringUUID of the removed brewer

message

Fired when a message is recieved from a brewer.

NameTypeDescription
dataUint8ArrayThe binary data from the brewer
metaobject
meta.topicstringtopic of the brewer that brewed this data
meta.fromstringUUID of the brewer that brewed this data
5.0.0

5 years ago

4.0.7

5 years ago

4.0.6

5 years ago

4.0.5

5 years ago

4.0.4

5 years ago

4.0.3

5 years ago

4.0.2

5 years ago

4.0.1

5 years ago

4.0.0

5 years ago

4.0.0-rc.4

5 years ago

4.0.0-rc.3

5 years ago

4.0.0-rc.2

5 years ago

4.0.0-rc.1

5 years ago

4.0.0-rc.0

6 years ago

4.0.0-alpha.2

6 years ago

4.0.0-alpha.1

6 years ago

3.2.0

6 years ago

3.1.0

6 years ago

3.0.0

6 years ago

3.0.0-rc.3

6 years ago

3.0.0-rc.2

6 years ago

3.0.0-rc.1

7 years ago

3.0.0-rc.0

7 years ago

3.0.0-beta.4

7 years ago

3.0.0-beta.3

7 years ago

3.0.0-beta.2

7 years ago

3.0.0-beta.1

7 years ago

3.0.0-alpha.6

7 years ago

3.0.0-alpha.5

7 years ago

3.0.0-alpha.4

7 years ago

3.0.0-alpha.3

7 years ago

3.0.0-alpha.2

7 years ago

3.0.0-alpha.1

7 years ago

2.0.0

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago