Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

phoenix-socket

Package Overview
Dependencies
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

phoenix-socket - npm Package Compare versions

Comparing version 1.1.3 to 1.2.3

362

dist/socket.js
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
Object.defineProperty(exports, "__esModule", {

@@ -9,4 +7,8 @@ value: true

function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; }
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -19,3 +21,3 @@

// A single connection is established to the server and
// channels are mulitplexed over the connection.
// channels are multiplexed over the connection.
// Connect to the server using the `Socket` class:

@@ -40,3 +42,3 @@ //

//
// let channel = socket.channel("rooms:123", {token: roomToken})
// let channel = socket.channel("room:123", {token: roomToken})
// channel.on("new_msg", msg => console.log("Got message", msg) )

@@ -64,3 +66,12 @@ // $input.onEnter( e => {

//
// ## Duplicate Join Subscriptions
//
// While the client may join any number of topics on any number of channels,
// the client may only hold a single subscription for each unique topic at any
// given time. When attempting to create a duplicate subscription,
// the server will close the existing channel, log a warning, and
// spawn a new channel for the topic. The client will have their
// `channel.onClose` callbacks fired for the existing channel, and the new
// channel join will have its receive hooks processed as normal.
//
// ## Pushing Messages

@@ -95,3 +106,3 @@ //

// `onError` hooks are invoked if the socket connection drops, or the channel
// crashes on the server. In either case, a channel rejoin is attemtped
// crashes on the server. In either case, a channel rejoin is attempted
// automatically in an exponential backoff manner.

@@ -105,3 +116,74 @@ //

//
//
// ## Presence
//
// The `Presence` object provides features for syncing presence information
// from the server with the client and handling presences joining and leaving.
//
// ### Syncing initial state from the server
//
// `Presence.syncState` is used to sync the list of presences on the server
// with the client's state. An optional `onJoin` and `onLeave` callback can
// be provided to react to changes in the client's local presences across
// disconnects and reconnects with the server.
//
// `Presence.syncDiff` is used to sync a diff of presence join and leave
// events from the server, as they happen. Like `syncState`, `syncDiff`
// accepts optional `onJoin` and `onLeave` callbacks to react to a user
// joining or leaving from a device.
//
// ### Listing Presences
//
// `Presence.list` is used to return a list of presence information
// based on the local state of metadata. By default, all presence
// metadata is returned, but a `listBy` function can be supplied to
// allow the client to select which metadata to use for a given presence.
// For example, you may have a user online from different devices with a
// a metadata status of "online", but they have set themselves to "away"
// on another device. In this case, they app may choose to use the "away"
// status for what appears on the UI. The example below defines a `listBy`
// function which prioritizes the first metadata which was registered for
// each user. This could be the first tab they opened, or the first device
// they came online from:
//
// let state = {}
// state = Presence.syncState(state, stateFromServer)
// let listBy = (id, {metas: [first, ...rest]}) => {
// first.count = rest.length + 1 // count of this user's presences
// first.id = id
// return first
// }
// let onlineUsers = Presence.list(state, listBy)
//
//
// ### Example Usage
//
// // detect if user has joined for the 1st time or from another tab/device
// let onJoin = (id, current, newPres) => {
// if(!current){
// console.log("user has entered for the first time", newPres)
// } else {
// console.log("user additional presence", newPres)
// }
// }
// // detect if user has left from all tabs/devices, or is still present
// let onLeave = (id, current, leftPres) => {
// if(current.metas.length === 0){
// console.log("user has left from all devices", leftPres)
// } else {
// console.log("user left from a device", leftPres)
// }
// }
// let presences = {} // client's initial empty presence state
// // receive initial presence data from server, sent after join
// myChannel.on("presences", state => {
// presences = Presence.syncState(presences, state, onJoin, onLeave)
// displayUsers(Presence.list(presences))
// })
// // receive "presence_diff" from server, containing join/leave events
// myChannel.on("presence_diff", diff => {
// presences = Presence.syncDiff(presences, diff, onJoin, onLeave)
// this.setState({users: Presence.list(room.presences, listBy)})
// })
//
var VSN = "1.0.0";

@@ -114,3 +196,4 @@ var SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 };

joined: "joined",
joining: "joining"
joining: "joining",
leaving: "leaving"
};

@@ -129,3 +212,3 @@ var CHANNEL_EVENTS = {

var Push = (function () {
var Push = function () {

@@ -139,3 +222,2 @@ // Initializes the Push

//
function Push(channel, event, payload, timeout) {

@@ -196,5 +278,5 @@ _classCallCheck(this, Push);

value: function matchReceive(_ref) {
var status = _ref.status;
var response = _ref.response;
var ref = _ref.ref;
var status = _ref.status,
response = _ref.response,
ref = _ref.ref;

@@ -256,5 +338,5 @@ this.recHooks.filter(function (h) {

return Push;
})();
}();
var Channel = exports.Channel = (function () {
var Channel = exports.Channel = function () {
function Channel(topic, params, socket) {

@@ -286,3 +368,4 @@ var _this2 = this;

this.onClose(function () {
_this2.socket.log("channel", "close " + _this2.topic);
_this2.rejoinTimer.reset();
_this2.socket.log("channel", "close " + _this2.topic + " " + _this2.joinRef());
_this2.state = CHANNEL_STATES.closed;

@@ -292,2 +375,5 @@ _this2.socket.remove(_this2);

this.onError(function (reason) {
if (_this2.isLeaving() || _this2.isClosed()) {
return;
}
_this2.socket.log("channel", "error " + _this2.topic, reason);

@@ -298,6 +384,5 @@ _this2.state = CHANNEL_STATES.errored;

this.joinPush.receive("timeout", function () {
if (_this2.state !== CHANNEL_STATES.joining) {
if (!_this2.isJoining()) {
return;
}
_this2.socket.log("channel", "timeout " + _this2.topic, _this2.joinPush.timeout);

@@ -323,3 +408,3 @@ _this2.state = CHANNEL_STATES.errored;

value: function join() {
var timeout = arguments.length <= 0 || arguments[0] === undefined ? this.timeout : arguments[0];
var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.timeout;

@@ -330,5 +415,5 @@ if (this.joinedOnce) {

this.joinedOnce = true;
this.rejoin(timeout);
return this.joinPush;
}
this.rejoin(timeout);
return this.joinPush;
}

@@ -362,3 +447,3 @@ }, {

value: function canPush() {
return this.socket.isConnected() && this.state === CHANNEL_STATES.joined;
return this.socket.isConnected() && this.isJoined();
}

@@ -368,3 +453,3 @@ }, {

value: function push(event, payload) {
var timeout = arguments.length <= 2 || arguments[2] === undefined ? this.timeout : arguments[2];
var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.timeout;

@@ -403,7 +488,8 @@ if (!this.joinedOnce) {

var timeout = arguments.length <= 0 || arguments[0] === undefined ? this.timeout : arguments[0];
var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.timeout;
this.state = CHANNEL_STATES.leaving;
var onClose = function onClose() {
_this3.socket.log("channel", "leave " + _this3.topic);
_this3.trigger(CHANNEL_EVENTS.close, "leave");
_this3.trigger(CHANNEL_EVENTS.close, "leave", _this3.joinRef());
};

@@ -427,6 +513,11 @@ var leavePush = new Push(this, CHANNEL_EVENTS.leave, {}, timeout);

// Receives all events for specialized message handling
// before dispatching to the channel callbacks.
//
// Must return the payload, modified or unmodified
}, {
key: "onMessage",
value: function onMessage(event, payload, ref) {}
value: function onMessage(event, payload, ref) {
return payload;
}

@@ -441,2 +532,7 @@ // private

}, {
key: "joinRef",
value: function joinRef() {
return this.joinPush.ref;
}
}, {
key: "sendJoin",

@@ -450,3 +546,6 @@ value: function sendJoin(timeout) {

value: function rejoin() {
var timeout = arguments.length <= 0 || arguments[0] === undefined ? this.timeout : arguments[0];
var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.timeout;
if (this.isLeaving()) {
return;
}
this.sendJoin(timeout);

@@ -456,8 +555,20 @@ }

key: "trigger",
value: function trigger(triggerEvent, payload, ref) {
this.onMessage(triggerEvent, payload, ref);
value: function trigger(event, payload, ref) {
var close = CHANNEL_EVENTS.close,
error = CHANNEL_EVENTS.error,
leave = CHANNEL_EVENTS.leave,
join = CHANNEL_EVENTS.join;
if (ref && [close, error, leave, join].indexOf(event) >= 0 && ref !== this.joinRef()) {
return;
}
var handledPayload = this.onMessage(event, payload, ref);
if (payload && !handledPayload) {
throw "channel onMessage callbacks must return the payload, modified or unmodified";
}
this.bindings.filter(function (bind) {
return bind.event === triggerEvent;
return bind.event === event;
}).map(function (bind) {
return bind.callback(payload, ref);
return bind.callback(handledPayload, ref);
});

@@ -470,8 +581,33 @@ }

}
}, {
key: "isClosed",
value: function isClosed() {
return this.state === CHANNEL_STATES.closed;
}
}, {
key: "isErrored",
value: function isErrored() {
return this.state === CHANNEL_STATES.errored;
}
}, {
key: "isJoined",
value: function isJoined() {
return this.state === CHANNEL_STATES.joined;
}
}, {
key: "isJoining",
value: function isJoining() {
return this.state === CHANNEL_STATES.joining;
}
}, {
key: "isLeaving",
value: function isLeaving() {
return this.state === CHANNEL_STATES.leaving;
}
}]);
return Channel;
})();
}();
var Socket = exports.Socket = (function () {
var Socket = exports.Socket = function () {

@@ -506,7 +642,6 @@ // Initializes the Socket

//
function Socket(endPoint) {
var _this4 = this;
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

@@ -703,3 +838,3 @@ _classCallCheck(this, Socket);

this.channels = this.channels.filter(function (c) {
return !c.isMember(channel.topic);
return c.joinRef() !== channel.joinRef();
});

@@ -710,3 +845,3 @@ }

value: function channel(topic) {
var chanParams = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var chanParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

@@ -722,6 +857,6 @@ var chan = new Channel(topic, chanParams, this);

var topic = data.topic;
var event = data.event;
var payload = data.payload;
var ref = data.ref;
var topic = data.topic,
event = data.event,
payload = data.payload,
ref = data.ref;

@@ -775,6 +910,6 @@ var callback = function callback() {

var msg = JSON.parse(rawMessage.data);
var topic = msg.topic;
var event = msg.event;
var payload = msg.payload;
var ref = msg.ref;
var topic = msg.topic,
event = msg.event,
payload = msg.payload,
ref = msg.ref;

@@ -794,5 +929,5 @@ this.log("receive", (payload.status || "") + " " + topic + " " + event + " " + (ref && "(" + ref + ")" || ""), payload);

return Socket;
})();
}();
var LongPoll = exports.LongPoll = (function () {
var LongPoll = exports.LongPoll = function () {
function LongPoll(endPoint) {

@@ -847,5 +982,5 @@ _classCallCheck(this, LongPoll);

if (resp) {
var status = resp.status;
var token = resp.token;
var messages = resp.messages;
var status = resp.status,
token = resp.token,
messages = resp.messages;

@@ -903,5 +1038,5 @@ _this8.token = token;

return LongPoll;
})();
}();
var Ajax = exports.Ajax = (function () {
var Ajax = exports.Ajax = function () {
function Ajax() {

@@ -918,5 +1053,5 @@ _classCallCheck(this, Ajax);

} else {
var req = window.XMLHttpRequest ? new XMLHttpRequest() : // IE7+, Firefox, Chrome, Opera, Safari
var _req = window.XMLHttpRequest ? new XMLHttpRequest() : // IE7+, Firefox, Chrome, Opera, Safari
new ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5
this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback);
this.xhrRequest(_req, method, endPoint, accept, body, timeout, ontimeout, callback);
}

@@ -1003,6 +1138,113 @@ }

return Ajax;
})();
}();
Ajax.states = { complete: 4 };
var Presence = exports.Presence = {
syncState: function syncState(currentState, newState, onJoin, onLeave) {
var _this12 = this;
var state = this.clone(currentState);
var joins = {};
var leaves = {};
this.map(state, function (key, presence) {
if (!newState[key]) {
leaves[key] = presence;
}
});
this.map(newState, function (key, newPresence) {
var currentPresence = state[key];
if (currentPresence) {
var newRefs = newPresence.metas.map(function (m) {
return m.phx_ref;
});
var curRefs = currentPresence.metas.map(function (m) {
return m.phx_ref;
});
var joinedMetas = newPresence.metas.filter(function (m) {
return curRefs.indexOf(m.phx_ref) < 0;
});
var leftMetas = currentPresence.metas.filter(function (m) {
return newRefs.indexOf(m.phx_ref) < 0;
});
if (joinedMetas.length > 0) {
joins[key] = newPresence;
joins[key].metas = joinedMetas;
}
if (leftMetas.length > 0) {
leaves[key] = _this12.clone(currentPresence);
leaves[key].metas = leftMetas;
}
} else {
joins[key] = newPresence;
}
});
return this.syncDiff(state, { joins: joins, leaves: leaves }, onJoin, onLeave);
},
syncDiff: function syncDiff(currentState, _ref2, onJoin, onLeave) {
var joins = _ref2.joins,
leaves = _ref2.leaves;
var state = this.clone(currentState);
if (!onJoin) {
onJoin = function onJoin() {};
}
if (!onLeave) {
onLeave = function onLeave() {};
}
this.map(joins, function (key, newPresence) {
var currentPresence = state[key];
state[key] = newPresence;
if (currentPresence) {
var _state$key$metas;
(_state$key$metas = state[key].metas).unshift.apply(_state$key$metas, _toConsumableArray(currentPresence.metas));
}
onJoin(key, currentPresence, newPresence);
});
this.map(leaves, function (key, leftPresence) {
var currentPresence = state[key];
if (!currentPresence) {
return;
}
var refsToRemove = leftPresence.metas.map(function (m) {
return m.phx_ref;
});
currentPresence.metas = currentPresence.metas.filter(function (p) {
return refsToRemove.indexOf(p.phx_ref) < 0;
});
onLeave(key, currentPresence, leftPresence);
if (currentPresence.metas.length === 0) {
delete state[key];
}
});
return state;
},
list: function list(presences, chooser) {
if (!chooser) {
chooser = function chooser(key, pres) {
return pres;
};
}
return this.map(presences, function (key, presence) {
return chooser(key, presence);
});
},
// private
map: function map(obj, func) {
return Object.getOwnPropertyNames(obj).map(function (key) {
return func(key, obj[key]);
});
},
clone: function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}
};
// Creates a timer that accepts a `timerCalc` function to perform

@@ -1022,3 +1264,3 @@ // calculated timeout retries, such as exponential backoff.

var Timer = (function () {
var Timer = function () {
function Timer(callback, timerCalc) {

@@ -1045,3 +1287,3 @@ _classCallCheck(this, Timer);

value: function scheduleTimeout() {
var _this12 = this;
var _this13 = this;

@@ -1051,4 +1293,4 @@ clearTimeout(this.timer);

this.timer = setTimeout(function () {
_this12.tries = _this12.tries + 1;
_this12.callback();
_this13.tries = _this13.tries + 1;
_this13.callback();
}, this.timerCalc(this.tries + 1));

@@ -1059,2 +1301,2 @@ }

return Timer;
})();
}();

2

package.json
{
"name": "phoenix-socket",
"version": "1.1.3",
"version": "1.2.3",
"description": "Socket API for accessing Phoenix Framework's Channels",

@@ -5,0 +5,0 @@ "main": "dist/socket.js",

@@ -6,3 +6,3 @@ // Phoenix Channels JavaScript client

// A single connection is established to the server and
// channels are mulitplexed over the connection.
// channels are multiplexed over the connection.
// Connect to the server using the `Socket` class:

@@ -27,3 +27,3 @@ //

//
// let channel = socket.channel("rooms:123", {token: roomToken})
// let channel = socket.channel("room:123", {token: roomToken})
// channel.on("new_msg", msg => console.log("Got message", msg) )

@@ -51,3 +51,12 @@ // $input.onEnter( e => {

//
// ## Duplicate Join Subscriptions
//
// While the client may join any number of topics on any number of channels,
// the client may only hold a single subscription for each unique topic at any
// given time. When attempting to create a duplicate subscription,
// the server will close the existing channel, log a warning, and
// spawn a new channel for the topic. The client will have their
// `channel.onClose` callbacks fired for the existing channel, and the new
// channel join will have its receive hooks processed as normal.
//
// ## Pushing Messages

@@ -82,3 +91,3 @@ //

// `onError` hooks are invoked if the socket connection drops, or the channel
// crashes on the server. In either case, a channel rejoin is attemtped
// crashes on the server. In either case, a channel rejoin is attempted
// automatically in an exponential backoff manner.

@@ -92,3 +101,74 @@ //

//
//
// ## Presence
//
// The `Presence` object provides features for syncing presence information
// from the server with the client and handling presences joining and leaving.
//
// ### Syncing initial state from the server
//
// `Presence.syncState` is used to sync the list of presences on the server
// with the client's state. An optional `onJoin` and `onLeave` callback can
// be provided to react to changes in the client's local presences across
// disconnects and reconnects with the server.
//
// `Presence.syncDiff` is used to sync a diff of presence join and leave
// events from the server, as they happen. Like `syncState`, `syncDiff`
// accepts optional `onJoin` and `onLeave` callbacks to react to a user
// joining or leaving from a device.
//
// ### Listing Presences
//
// `Presence.list` is used to return a list of presence information
// based on the local state of metadata. By default, all presence
// metadata is returned, but a `listBy` function can be supplied to
// allow the client to select which metadata to use for a given presence.
// For example, you may have a user online from different devices with a
// a metadata status of "online", but they have set themselves to "away"
// on another device. In this case, they app may choose to use the "away"
// status for what appears on the UI. The example below defines a `listBy`
// function which prioritizes the first metadata which was registered for
// each user. This could be the first tab they opened, or the first device
// they came online from:
//
// let state = {}
// state = Presence.syncState(state, stateFromServer)
// let listBy = (id, {metas: [first, ...rest]}) => {
// first.count = rest.length + 1 // count of this user's presences
// first.id = id
// return first
// }
// let onlineUsers = Presence.list(state, listBy)
//
//
// ### Example Usage
//
// // detect if user has joined for the 1st time or from another tab/device
// let onJoin = (id, current, newPres) => {
// if(!current){
// console.log("user has entered for the first time", newPres)
// } else {
// console.log("user additional presence", newPres)
// }
// }
// // detect if user has left from all tabs/devices, or is still present
// let onLeave = (id, current, leftPres) => {
// if(current.metas.length === 0){
// console.log("user has left from all devices", leftPres)
// } else {
// console.log("user left from a device", leftPres)
// }
// }
// let presences = {} // client's initial empty presence state
// // receive initial presence data from server, sent after join
// myChannel.on("presences", state => {
// presences = Presence.syncState(presences, state, onJoin, onLeave)
// displayUsers(Presence.list(presences))
// })
// // receive "presence_diff" from server, containing join/leave events
// myChannel.on("presence_diff", diff => {
// presences = Presence.syncDiff(presences, diff, onJoin, onLeave)
// this.setState({users: Presence.list(room.presences, listBy)})
// })
//
const VSN = "1.0.0"

@@ -102,2 +182,3 @@ const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}

joining: "joining",
leaving: "leaving",
}

@@ -230,7 +311,8 @@ const CHANNEL_EVENTS = {

this.onClose( () => {
this.socket.log("channel", `close ${this.topic}`)
this.rejoinTimer.reset()
this.socket.log("channel", `close ${this.topic} ${this.joinRef()}`)
this.state = CHANNEL_STATES.closed
this.socket.remove(this)
})
this.onError( reason => {
this.onError( reason => { if(this.isLeaving() || this.isClosed()){ return }
this.socket.log("channel", `error ${this.topic}`, reason)

@@ -240,5 +322,3 @@ this.state = CHANNEL_STATES.errored

})
this.joinPush.receive("timeout", () => {
if(this.state !== CHANNEL_STATES.joining){ return }
this.joinPush.receive("timeout", () => { if(!this.isJoining()){ return }
this.socket.log("channel", `timeout ${this.topic}`, this.joinPush.timeout)

@@ -265,5 +345,5 @@ this.state = CHANNEL_STATES.errored

this.joinedOnce = true
this.rejoin(timeout)
return this.joinPush
}
this.rejoin(timeout)
return this.joinPush
}

@@ -281,3 +361,3 @@

canPush(){ return this.socket.isConnected() && this.state === CHANNEL_STATES.joined }
canPush(){ return this.socket.isConnected() && this.isJoined() }

@@ -312,5 +392,6 @@ push(event, payload, timeout = this.timeout){

leave(timeout = this.timeout){
this.state = CHANNEL_STATES.leaving
let onClose = () => {
this.socket.log("channel", `leave ${this.topic}`)
this.trigger(CHANNEL_EVENTS.close, "leave")
this.trigger(CHANNEL_EVENTS.close, "leave", this.joinRef())
}

@@ -329,3 +410,6 @@ let leavePush = new Push(this, CHANNEL_EVENTS.leave, {}, timeout)

// Receives all events for specialized message handling
onMessage(event, payload, ref){}
// before dispatching to the channel callbacks.
//
// Must return the payload, modified or unmodified
onMessage(event, payload, ref){ return payload }

@@ -336,2 +420,4 @@ // private

joinRef(){ return this.joinPush.ref }
sendJoin(timeout){

@@ -342,11 +428,25 @@ this.state = CHANNEL_STATES.joining

rejoin(timeout = this.timeout){ this.sendJoin(timeout) }
rejoin(timeout = this.timeout){ if(this.isLeaving()){ return }
this.sendJoin(timeout)
}
trigger(triggerEvent, payload, ref){
this.onMessage(triggerEvent, payload, ref)
this.bindings.filter( bind => bind.event === triggerEvent )
.map( bind => bind.callback(payload, ref) )
trigger(event, payload, ref){
let {close, error, leave, join} = CHANNEL_EVENTS
if(ref && [close, error, leave, join].indexOf(event) >= 0 && ref !== this.joinRef()){
return
}
let handledPayload = this.onMessage(event, payload, ref)
if(payload && !handledPayload){ throw("channel onMessage callbacks must return the payload, modified or unmodified") }
this.bindings.filter( bind => bind.event === event)
.map( bind => bind.callback(handledPayload, ref))
}
replyEventName(ref){ return `chan_reply_${ref}` }
isClosed() { return this.state === CHANNEL_STATES.closed }
isErrored(){ return this.state === CHANNEL_STATES.errored }
isJoined() { return this.state === CHANNEL_STATES.joined }
isJoining(){ return this.state === CHANNEL_STATES.joining }
isLeaving(){ return this.state === CHANNEL_STATES.leaving }
}

@@ -495,3 +595,3 @@

remove(channel){
this.channels = this.channels.filter( c => !c.isMember(channel.topic) )
this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())
}

@@ -710,2 +810,83 @@

export var Presence = {
syncState(currentState, newState, onJoin, onLeave){
let state = this.clone(currentState)
let joins = {}
let leaves = {}
this.map(state, (key, presence) => {
if(!newState[key]){
leaves[key] = presence
}
})
this.map(newState, (key, newPresence) => {
let currentPresence = state[key]
if(currentPresence){
let newRefs = newPresence.metas.map(m => m.phx_ref)
let curRefs = currentPresence.metas.map(m => m.phx_ref)
let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)
let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)
if(joinedMetas.length > 0){
joins[key] = newPresence
joins[key].metas = joinedMetas
}
if(leftMetas.length > 0){
leaves[key] = this.clone(currentPresence)
leaves[key].metas = leftMetas
}
} else {
joins[key] = newPresence
}
})
return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)
},
syncDiff(currentState, {joins, leaves}, onJoin, onLeave){
let state = this.clone(currentState)
if(!onJoin){ onJoin = function(){} }
if(!onLeave){ onLeave = function(){} }
this.map(joins, (key, newPresence) => {
let currentPresence = state[key]
state[key] = newPresence
if(currentPresence){
state[key].metas.unshift(...currentPresence.metas)
}
onJoin(key, currentPresence, newPresence)
})
this.map(leaves, (key, leftPresence) => {
let currentPresence = state[key]
if(!currentPresence){ return }
let refsToRemove = leftPresence.metas.map(m => m.phx_ref)
currentPresence.metas = currentPresence.metas.filter(p => {
return refsToRemove.indexOf(p.phx_ref) < 0
})
onLeave(key, currentPresence, leftPresence)
if(currentPresence.metas.length === 0){
delete state[key]
}
})
return state
},
list(presences, chooser){
if(!chooser){ chooser = function(key, pres){ return pres } }
return this.map(presences, (key, presence) => {
return chooser(key, presence)
})
},
// private
map(obj, func){
return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))
},
clone(obj){ return JSON.parse(JSON.stringify(obj)) }
}
// Creates a timer that accepts a `timerCalc` function to perform

@@ -712,0 +893,0 @@ // calculated timeout retries, such as exponential backoff.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc