@wix/duplexer-js
v2.0.6
Published
browser & react-naitve client for Duplexer
Maintainers
Keywords
Readme
@wix/duplexer-js
Establish a connection to wix-duplexer-sockets-server, subscribe and listen to channels & events from the browser.
Requirements
| Environment | Minimum version | | --- | --- | | Node.js | 18.0.0 | | Chrome | 42 | | Firefox | 39 | | Safari | 10.1 | | Edge | 14 |
The following Web APIs must be available at runtime:
fetch/ResponseAbortController/AbortSignal(for request cancellation)
Testing in Node.js
Node 18+ includes a global fetch (based on undici). If your test framework intercepts HTTP with nock, ensure you are using nock v13+ which supports intercepting native fetch.
Features
Send events
Send event directly from the client (browser). Read more about sending client event.
Private channels
Allow authorized-only clients to subscribe specific channels. Read more about private channels.
Multiplexing
It means that N different clients can utilize/share same the physical socket while having a full isolation and, hence, improve general performance.
Environments
- Browser (default).
- React Native.
Install
npm install @wix/duplexer-jsUsage
import { Duplexer } from '@wix/duplexer-js';
const instanceUpdater = {
getInstance() {
return window.__APP_INSTANCE__;
}
};
const siteRevision = '1';
const duplexer = new Duplexer('duplexer.wix.com', {
instanceUpdater,
siteRevision,
});
const connection = duplexer.connect({
appDefId: '224b330b-f3dc-4898-8876-d177ab3877ca'
});
const channel = connection.subscribe('some-channel');
connection.on('@duplexer:connected', () => {
// connection established
})
channel.on('some-event', payload => {
// do something with your payload
});Note: in case you use jsdom, you must specify its url with http:// protocol in order to make Duplexer testkit to work properly (exposed websocket & http server are not under SSL).
require('jsdom-global)('', { url: 'http://localhost:7000' });Note: in case you run Duplexer in a Node.js environment (e.g. testing with Jest/Mocha), you need:
- Node.js 18+ (provides global
fetch,AbortController). - A WebSocket implementation on the
globalobject. You can installws:
global.WebSocket = require('ws');API
new Duplexer(opts): Duplexer
Create a new Duplexer instance that will open socket against url. It must be provided with duplexer.wix.com as the url, as it communicates with the sockets server directly (opens a connection, send commands etc.).
Parameters:
- opts (Object):
url(String) - url to wix-duplexer-sockets-server service, must be protocol-less.siteRevision(String) - the site's revision number.instanceUpdater(InstanceUpdater) - an object that exposesgetInstance: () => stringmember that is responsible of retrieving Wix's instance.autoConnect(Boolean, default: true) - whether to enable auto reconnect when a sudden disconnection accurs. Used for testing purposes.
Duplexer.connect(opts): VirtualSocket
Establish a connection according to given opts.appDefId.
Parameters:
- opts
appDefId(String)
Duplexer.getConnectionServerTime(): Promise
Retrieves the server time that the connection was established with. Promise is getting resolved upon successful connect.
Note: it refers to the physical connection establishment (connection_establish packet).
Duplexer.triggerInstanceChanged(): void
In case the signed instance is no longer valid (say, expired) and connection closed with status 401, you should make the instance updater to return a new valid signed instance. After you do that, you can call triggerInstanceChanged(), so Duplexer will try to reconnect (... and resubscribe).
VirtualSocket.disconnect(): void
Closes namespace (might close the entire underlying connection or not, depends if pool contains more namespaces or not).
VirtualSocket.subscribe(channel, opts): Channel
Subscribe to channel and start getting emitted events.
Note: current limitation is up to 10 different subscriptions (channels) per api key.
Parameters:
- channel (String)
- opts (Object) (Optional)
- restoreStrategy (Object) - custom restore strategy taht will be attached to the subscribe command, see RestoreStrategyBuilderFactory for more information about possible restore strategies.
- resourceId - if you have a specific channel for each resource, like
scores/1andscores/2.
VirtualSocket.subscribeToUserChannel(): Channel
Subscribe to user's dedicated channel. This channel acts like his own inbox, so nobody else can listen to.
In order to publish to user channel (backend perspective), the USER context should be used along with the recipients field (that represents the user IDs that should receive the message).
VirtualSocket.unsubscribe(channel): void
Unsubscribe channel, stop getting emitted events.
Parameters:
- channel (String)
VirtualSocket.on(event, handler)
Listen to event and execute handler on every event that emitted on this connection.
Parameters:
- event (String)
- handler (Function: payload? => void)
Reserved events
| Event | Description |
| -------------------------- | ----------- |
| @duplexer:connected | Emitted on connection successfully established |
| @duplexer:disconnected | Emitted on connection closed, either intentionally or caused by error. If connection was closed due to error, a TransportError instance will be passed. In case TransportError contains { recoverable: false }, you will have to conneect manually (you should check the status and act accordingly; for instance, in case it's 401 - the provided signed instance is invalid) |
| @duplexer:connect_error | Emitted on every connect try error, a TransportError instance will be passed. In case error is unrecoverable, @duplexer:connect_error won't be thrown, but @duplexer:diconnected with TransportError that contains { recoverable: false } |
Note: all above events might be called multiple times, for instance:
connected -> disconnected (with error) -> connect_erorr -> connect_erorr -> connected
This happens because duplexer client tries to recover itself in case of unexpected disconnection.
VirtualSocket.off(event, handler?)
Remove handler from being executed on event. In case no handler passed, all handlers will be removed.
Parameters:
- event (String)
- handler (Optional) (Function)
Channel.on(event, handler): Channel
Listen to event and execute handler on every event that emitted on this channel.
Parameters:
- event (String)
- handler (Function: (payload?, attachments?) => void) - handler that will be executed every time an event received:
- payload (any)
- attachments (Object)
- user (Object) - user informartion that was attached to event (from signed subscription token).
channel.on('client-typing', (_, {user}) => {
// ${user.info.name} is typing!
})Reserved events
| Event | Description |
| -------------------------------- | ----------- |
| @duplexer:subscription_succeeded | Subscription established successfully and from now on messages will be delivered. Note: will be called on every resubscribe (in case of reconnect for instance), so make sure your handler is idempotent.Payload is an object that contains:- isSynced (Boolean) - determines if app server should resync (possibly) missed messages. Will always return false at the beginning, and app server might needs to fetch its recent messages in this phase. |
| @duplexer:subscription_failed | Emitted on authorization failure - in case request returns status other than 2xx.Payload is an object that contains:- status (Boolean) - status code the request returned with.- message (String) - detailed message about the error |
| @duplexer:unsubscribe_succeeded | Unsubscribed successfully from channel and messages will stop being delivered. |
Channel.off(event, handler?)
Remove handler from being executed on event. In case no handler passed, all handlers will be removed.
Parameters:
- event (String)
- handler (Optional) (Function)
Channel.send(event, payload): void
Send a client event. User is implicitly attached.
Parameters:
- event (String)
- payload (Object)
RestoreStrategyBuilderFactory
Possible restore strategies, see wix-duplexer-protocol#RestoreStrategyBuilderFactory
