Security News
Maven Central Adds Sigstore Signature Validation
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
@pubkeeper/client
Advanced tools
@pubkeeper/client
enables web browsers to join, consume, and produce content on a Pubkeeper network.
Brew
: A protocol/method of delivery, e.g. WebSocket, SocketIO, WebRTC, HTTPBrewer
: 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.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';
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
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);
};
});
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);
};
});
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.
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);
};
});
PubkeeperClient
ClassThe PubkeeperClient
manages the connection to a pubkeeper server.
new PubkeeperClient(options)
Name | Type | Description |
---|---|---|
options | ClientOptions | The options for this pubkeeper client |
ClientOptions
: object
These options can be given to a PubkeeperClient to customize its behavior.
Name | Type | Default | Description |
---|---|---|---|
server | string | - | Websocket URL of the pubkeeper server |
jwt | string | - | Auth token for the pubkeeper server |
brews | Array<Brew> | [] | Supported brews of this client |
crypto | Map<*,Crypto> | new Map | Supported crypto mappings for this client |
protocols | Map<*,Protocol> | new Map | Supported protocol mappings for this client. Defaults to the legacy protocol |
maxRetries | number | Infinity | Maximum number of connection retries |
maxTimeout | number | 10000 | Maximum timeout between retries (in milliseconds) |
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');
})();
.status
: string
Returns the status of this client. Can be one of the following:
Value | Description |
---|---|
'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 |
.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
.
Name | Type | Description |
---|---|---|
topic | string | The topic |
options | BrewerOptions | |
matched | Function | Callback 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.
Name | Type | Default | Description |
---|---|---|---|
autoRemoveListeners | boolean | false | Automatically remove all event listeners on unmatch |
brews | Array<(string|Brew)> | - | A subset of brews to use for this brewer, defaults to all registered brews. |
id | string | - | The UUID of this brewer, defaults to a random UUIDv4 |
waitForBrews | (number|boolean) | 250 | The maximum wait time to wait when brewing data for brew connections to stablize. |
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.
const ref = client.addBrewer('topic', matchedFn);
/* ...later */
client.removeBrewer(ref);
.addPatron(topic[,[ options,] matched])
: Patron
Create a new patron of topic
.
Name | Type | Description |
---|---|---|
topic | string | The topic |
options | PatronOptions | |
matched | Function | Callback 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.
Name | Type | Default | Description |
---|---|---|---|
autoRemoveListeners | boolean | false | Automatically remove all event listeners on unmatch |
brews | Array<(string|Brew)> | - | A subset of brews to use for this patron, defaults to all registered brews. |
id | string | - | The UUID of this patron, defaults to a random UUIDv4 |
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.
const ref = client.addPatron('topic', matchedFn);
/* ...later */
client.removePatron(ref);
Brewer
ClassA brewer is a publisher of information in a pubkeeper system.
.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
.brew(bytes[, options])
: Promise
Publish binary data to a brewer.
Name | Type | Description |
---|---|---|
bytes | (Uint8Array|Uint8ClampedArray) | Binary data to brew |
options | object | |
options.waitForBrews | number? | Override the brewers config |
.brewText(text[, options])
: Promise
Publish text
as a UTF-8 encoded byte array.
Name | Type | Description |
---|---|---|
text | string | text to brew |
options | object | |
options.waitForBrews | number? | Override the brewers config |
.brewJSON(value[, options])
: Promise
Publish value
using JSON.stringify
.
Name | Type | Description |
---|---|---|
value | * | value to serialize and brew |
options | object | |
options.waitForBrews | number? | 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.
added
Fired when a matched patron is added.
Name | Type | Description |
---|---|---|
e | object | |
e.id | string | UUID of the added patron |
e.topic | string | topic of the brewer |
removed
Fired when a matched patron is removed.
Name | Type | Description |
---|---|---|
e | object | |
e.id | string | UUID of the removed patron |
Patron
ClassA patron is a subscriber of information in a pubkeeper system.
.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
.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.
added
Fired when a matched brewer is added.
Name | Type | Description |
---|---|---|
e | object | |
e.id | string | UUID of the added brewer |
e.topic | string | topic of the brewer |
removed
Fired when a matched brewer is removed.
Name | Type | Description |
---|---|---|
e | object | |
e.id | string | UUID of the removed brewer |
message
Fired when a message is recieved from a brewer.
Name | Type | Description |
---|---|---|
data | Uint8Array | The binary data from the brewer |
meta | object | |
meta.topic | string | topic of the brewer that brewed this data |
meta.from | string | UUID of the brewer that brewed this data |
FAQs
Pubkeeper javascript SDK
We found that @pubkeeper/client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.