Primus Client
=============
.. note:: We recommend using Feathers and the
``@feathersjs/primus-client`` module on the client if possible. To
use a direct Primus connection without using Feathers on the client
however see the `Direct connection <#direct-connection>`_ section.
Loading the Primus client library
---------------------------------
In the browser the Primus client library (usually at
``primus/primus.js``) always has to be loaded using a ``
.. important::
This will make the ``Primus`` object globally
available. Module loader options are currently not available.
Client use in NodeJS
--------------------
In NodeJS a Primus client can be initialized as follows:
.. code:: js
const Primus = require('primus');
const Emitter = require('primus-emitter');
const Socket = Primus.createSocket({
transformer: 'websockets',
plugin: {
'emitter': Emitter
}
});
const socket = new Socket('http://api.feathersjs.com');
@feathersjs/primus-client
-------------------------
|GitHub stars| |npm version| |Changelog|
.. code-block:: sh
$ npm install @feathersjs/primus-client --save
The ``@feathersjs/primus-client`` module allows to connect to services
exposed through the :doc:`primus` via the configured
websocket library.
.. important:: Primus sockets are also used to *call* service
methods. Using sockets for both, calling methods and receiving
real-time events is generally faster than using
:doc:`./rest` and there is no need to use both, REST and
websockets in the same client application at the same time.
``primus(socket)``
~~~~~~~~~~~~~~~~~~
Initialize the Primus client using a given socket and the default options.
.. code-block:: js
const feathers = require(‘@feathersjs/feathers’);
const primusClient = require(‘@feathersjs/primus-client’);
const socket = new Primus(‘http://api.my-feathers-server.com’);
const app = feathers();
app.configure(primusClient(socket));
// Receive real-time events through Primus
app.service(‘messages’).on(‘created’, message => console.log(‘New message created’, message));
// Call the ``messages``
service app.service(‘messages’).create({ text: ‘A message from a REST client’ });
.. code-block:: html
``primus(socket, options)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Initialize the Primus client using a given socket and the given options.
Options can be:
- ``timeout`` (default: 5000ms) - The time after which a method call
fails and times out. This usually happens when calling a service or
service method that does not exist.
.. code:: js
const feathers = require('@feathersjs/feathers');
const Primus = require('@feathersjs/primus-client');
const socket = new Primus('http://api.my-feathers-server.com');
const app = feathers();
app.configure(primus(socket, { timeout: 2000 }));
The timeout per service can be changed like this:
.. code:: js
app.service('messages').timeout = 3000;
Direct connection
-----------------
In the browser, the connection can be established by loading the client
from ``primus/primus.js`` and instantiating a new ``Primus`` instance.
Unlike HTTP calls, websockets do not have a cross-origin restriction in
the browser so it is possible to connect to any Feathers server.
See the `Primus docs `_
for more details.
.. tip:: The socket connection URL has to point to the server root
which is where Feathers will set up Primus.
.. code:: html
Service methods can be called by emitting a
``::`` event with the method parameters.
``servicepath`` is the name the service has been registered with (in
``app.use``) without leading or trailing slashes. An optional callback
following the ``function(error, data)`` Node convention will be called
with the result of the method call or any errors that might have
occurred.
``params`` will be set as ``params.query`` in the service method call.
Other service parameters can be set through a :doc:`primus`.
Authentication
~~~~~~~~~~~~~~
Sockets can be authenticated by sending the ``authenticate`` event with
the ``strategy`` and the payload. For specific examples see the “Direct
Connection” section in the :doc:`../authentication/jwt`
authentication chapters.
.. code:: js
socket.send('authenticate', {
strategy: 'strategyname',
... otherData
}, function(message, data) {
console.log(message); // message will be null
console.log(data); // data will be {"accessToken": "your token"}
// You can now send authenticated messages to the server
});
``find``
~~~~~~~~
Retrieves a list of all matching resources from the service
.. code:: js
socket.send('find', 'messages', { status: 'read', user: 10 }, (error, data) => {
console.log('Found all messages', data);
});
Will call
``app.service('messages').find({ query: { status: 'read', user: 10 } })``
on the server.
get
~~~
Retrieve a single resource from the service.
.. code:: js
socket.send('get', 'messages', 1, (error, message) => {
console.log('Found message', message);
});
Will call ``app.service('messages').get(1, {})`` on the server.
.. code:: js
socket.send('get', 'messages', 1, { fetch: 'all' }, (error, message) => {
console.log('Found message', message);
});
Will call
``app.service('messages').get(1, { query: { fetch: 'all' } })`` on the
server.
create
~~~~~~
Create a new resource with ``data`` which may also be an array.
.. code:: js
socket.send('create', 'messages', {
text: 'I really have to iron'
}, (error, message) => {
console.log('Message created', message);
});
Will call
``app.service('messages').create({ "text": "I really have to iron" }, {})``
on the server.
.. code:: js
socket.send('create', 'messages', [
{ text: 'I really have to iron' },
{ text: 'Do laundry' }
]);
Will call ``app.service('messages').create`` on the server with the
array.
update
~~~~~~
Completely replace a single or multiple resources.
.. code:: js
socket.send('update', 'messages', 2, {
text: 'I really have to do laundry'
}, (error, message) => {
console.log('Message updated', message);
});
Will call
``app.service('messages').update(2, { "text": "I really have to do laundry" }, {})``
on the server. The ``id`` can also be ``null`` to update multiple
resources:
.. code:: js
socket.send('update', 'messages', null, {
complete: true
}, { complete: false });
Will call
``app.service('messages').update(null, { complete: true }, { query: { complete: false } })``
on the server.
.. tip:: ``update`` is normally expected to replace an entire
resource which is why the database adapters only support ``patch``
for multiple records.
patch
~~~~~
Merge the existing data of a single or multiple resources with the new
``data``.
.. code:: js
socket.send('patch', 'messages', 2, {
read: true
}, (error, message) => {
console.log('Patched message', message);
});
Will call ``app.service('messages').patch(2, { "read": true }, {})`` on
the server. The ``id`` can also be ``null`` to update multiple
resources:
.. code:: js
socket.send('patch', 'messages', null, {
complete: true
}, {
complete: false
}, (error, message) => {
console.log('Patched message', message);
});
Will call
``app.service('messages').patch(null, { complete: true }, { query: { complete: false } })``
on the server to change the status for all read app.service(‘messages’).
This is supported out of the box by the Feathers :doc:`../readme`
remove
~~~~~~
Remove a single or multiple resources:
.. code:: js
socket.send('remove', 'messages', 2, { cascade: true }, (error, message) => {
console.log('Removed a message', message);
});
Will call
``app.service('messages').remove(2, { query: { cascade: true } })`` on
the server. The ``id`` can also be ``null`` to remove multiple
resources:
.. code:: js
socket.send('remove', 'messages', null, { read: true });
Will call
``app.service('messages').remove(null, { query: { read: 'true' } })`` on
the server to delete all read app.service(‘messages’).
Listening to events
~~~~~~~~~~~~~~~~~~~
Listening to service events allows real-time behaviour in an
application. :doc:`../events` are sent to the socket in
the form of ``servicepath eventname``.
created
^^^^^^^
The ``created`` event will be published with the callback data when a
service ``create`` returns successfully.
.. code:: js
socket.on('messages created', function(message) {
console.log('Got a new Message!', message);
});
updated, patched
^^^^^^^^^^^^^^^^
The ``updated`` and ``patched`` events will be published with the
callback data when a service ``update`` or ``patch`` method calls back
successfully.
.. code:: js
socket.on('my/messages updated', function(message) {
console.log('Got an updated Message!', message);
});
socket.send('update', 'my/messages', 1, {
text: 'Updated text'
}, {}, function(error, callback) {
// Do something here
});
removed
^^^^^^^
The ``removed`` event will be published with the callback data when a
service ``remove`` calls back successfully.
.. code:: js
socket.on('messages removed', function(message) {
// Remove element showing the Message from the page
$('#message-' + message.id).remove();
});
.. |GitHub stars| image:: https://img.shields.io/github/stars/feathersjs/primus-client.png?style=social&label=Star
:target: https://github.com/feathersjs/primus-client/
.. |npm version| image:: https://img.shields.io/npm/v/@feathersjs/primus-client.png?style=flat-square
:target: https://www.npmjs.com/package/@feathersjs/primus-client
.. |Changelog| image:: https://img.shields.io/badge/changelog-.md-blue.png?style=flat-square
:target: https://github.com/feathersjs/primus-client/blob/master/CHANGELOG.md