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

ddp.js

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ddp.js - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

.eslintrc

7

bower.json
{
"name": "ddp.js",
"main": "dist/ddp.js",
"version": "1.0.0-rc1",
"version": "1.1.0",
"homepage": "https://github.com/mondora/ddp.js",

@@ -11,2 +11,3 @@ "authors": [

"moduleType": [
"amd",
"globals",

@@ -24,6 +25,4 @@ "node"

"node_modules",
"bower_components",
"test",
"tests"
"test"
]
}

@@ -0,1 +1,16 @@

##1.1.0 (July 11, 2015)
Moved the code to use ES6. In the process, I also refactored it a bit to use
less "exotic" patterns, but there _should be_ no breaking changes to the public
API.
Two enhancements:
1. a `status` property (`connected` / `disconnected`) is now available on the
instance
1. it's now possible to call methods `sub`, `unsub`, and `method` right after
creating the instance. Calls are queued and performed after the `connected`
event
##1.0.0 (January 11, 2015)

@@ -2,0 +17,0 @@

@@ -1,13 +0,22 @@

var DDP =
/******/ (function(modules) { // webpackBootstrap
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("wolfy87-eventemitter"));
else if(typeof define === 'function' && define.amd)
define(["wolfy87-eventemitter"], factory);
else if(typeof exports === 'object')
exports["DDP"] = factory(require("wolfy87-eventemitter"));
else
root["DDP"] = factory(root["wolfy87-eventemitter"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)

@@ -19,23 +28,23 @@ /******/ var module = installedModules[moduleId] = {

/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports

@@ -51,267 +60,343 @@ /******/ return __webpack_require__(0);

var EventEmitter = __webpack_require__(1);
Object.defineProperty(exports, "__esModule", {
value: true
});
var DDP = function (options) {
// Configuration
this._endpoint = options.endpoint;
this._SocketConstructor = options.SocketConstructor;
// Init
this._init();
};
DDP.prototype = Object.create(EventEmitter.prototype);
DDP.prototype.constructor = DDP;
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; }; })();
DDP.prototype._init = function () {
__webpack_require__(2).call(this);
__webpack_require__(3).call(this);
__webpack_require__(4).call(this);
__webpack_require__(5).call(this);
__webpack_require__(6).call(this);
};
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
DDP.prototype.connect = function () {
var c = __webpack_require__(7);
this._socket.send({
msg: "connect",
version: c.DDP_VERSION,
support: [c.DDP_VERSION]
});
};
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
DDP.prototype.method = function (name, params) {
var id = __webpack_require__(8).uniqueId();
this._socket.send({
msg: "method",
id: id,
method: name,
params: params
});
return id;
};
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
DDP.prototype.ping = function () {
var id = __webpack_require__(8).uniqueId();
this._socket.send({
msg: "ping",
id: id
});
return id;
};
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
DDP.prototype.pong = function (id) {
this._socket.send({
msg: "pong",
id: id
});
return id;
};
var _wolfy87Eventemitter = __webpack_require__(1);
DDP.prototype.sub = function (name, params) {
var id = __webpack_require__(8).uniqueId();
this._socket.send({
msg: "sub",
id: id,
name: name,
params: params
});
return id;
};
var _wolfy87Eventemitter2 = _interopRequireDefault(_wolfy87Eventemitter);
DDP.prototype.unsub = function (id) {
this._socket.send({
msg: "unsub",
id: id
});
return id;
};
var _queue = __webpack_require__(2);
module.exports = DDP;
var _queue2 = _interopRequireDefault(_queue);
var _socket = __webpack_require__(3);
var _socket2 = _interopRequireDefault(_socket);
var _utils = __webpack_require__(4);
var DDP_VERSION = "1";
var PUBLIC_EVENTS = [
// Subscription messages
"ready", "nosub", "added", "changed", "removed",
// Method messages
"result", "updated",
// Error messages
"error"];
var RECONNECT_INTERVAL = 10000;
var DDP = (function (_EventEmitter) {
_inherits(DDP, _EventEmitter);
_createClass(DDP, [{
key: "emit",
value: function emit() {
var _this = this;
var args = arguments;
setTimeout(function () {
_get(Object.getPrototypeOf(DDP.prototype), "emit", _this).apply(_this, args);
}, 0);
}
}]);
function DDP(options) {
var _this2 = this;
_classCallCheck(this, DDP);
_get(Object.getPrototypeOf(DDP.prototype), "constructor", this).call(this);
this.status = "disconnected";
this.messageQueue = new _queue2["default"](function (message) {
if (_this2.status === "connected") {
_this2.socket.send(message);
return true;
} else {
return false;
}
});
this.socket = new _socket2["default"](options.SocketConstructor, options.endpoint);
this.socket.on("open", function () {
// When the socket opens, send the `connect` message
// to establish the DDP connection
_this2.socket.send({
msg: "connect",
version: DDP_VERSION,
support: [DDP_VERSION]
});
});
this.socket.on("close", function () {
_this2.status = "disconnected";
_this2.messageQueue.empty();
_this2.emit("disconnected");
// Schedule a reconnection
setTimeout(_this2.socket.connect.bind(_this2.socket), RECONNECT_INTERVAL);
});
this.socket.on("message:in", function (message) {
if (message.msg === "connected") {
_this2.status = "connected";
_this2.messageQueue.process();
_this2.emit("connected");
} else if (message.msg === "ping") {
// Reply with a `pong` message to prevent the server from
// closing the connection
_this2.socket.send({ msg: "pong", id: message.id });
} else if ((0, _utils.contains)(PUBLIC_EVENTS, message.msg)) {
_this2.emit(message.msg, message);
}
});
this.socket.connect();
}
_createClass(DDP, [{
key: "method",
value: function method(name, params) {
var id = (0, _utils.uniqueId)();
this.messageQueue.push({
msg: "method",
id: id,
method: name,
params: params
});
return id;
}
}, {
key: "sub",
value: function sub(name, params) {
var id = (0, _utils.uniqueId)();
this.messageQueue.push({
msg: "sub",
id: id,
name: name,
params: params
});
return id;
}
}, {
key: "unsub",
value: function unsub(id) {
this.messageQueue.push({
msg: "unsub",
id: id
});
return id;
}
}]);
return DDP;
})(_wolfy87Eventemitter2["default"]);
exports["default"] = DDP;
module.exports = exports["default"];
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
/***/ function(module, exports) {
module.exports = EventEmitter;
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {
/***/ function(module, exports) {
/*
* Set up the _socket proxy
*/
"use strict";
module.exports = function () {
// _socket is a proxy for the _rawSocket, with the purpose of exposing a
// more consistent event api
var EventEmitter = __webpack_require__(1);
this._socket = new EventEmitter();
this._socket.send = (function (object) {
var message = JSON.stringify(object);
this._rawSocket.send(message);
// Emit a copy of the object, as we don't know who might be listening
this._socket.emit("message:out", JSON.parse(message));
}).bind(this);
};
Object.defineProperty(exports, "__esModule", {
value: true
});
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; }; })();
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/*
* Maintain a DDP connection with the server
*/
var Queue = (function () {
"use strict";
/*
* As the name implies, `consumer` is the (sole) consumer of the queue.
* It gets called with each element of the queue and its return value
* serves as a ack, determining whether the element is removed or not from
* the queue, allowing then subsequent elements to be processed.
*/
module.exports = function () {
// Register handlers for the `_socket` events that are responsible for
// establishing and maintaining the DDP connection
this._socket.on("open", (function () {
// When the socket opens, send the `connect` message
// to establish the DDP connection
this.connect();
}).bind(this));
this._socket.on("close", (function () {
// When the socket closes, emit the `disconnected` event to the DDP
// connection, and try reconnecting after a timeout
this.emit("disconnected");
setTimeout(
__webpack_require__(6).bind(this),
__webpack_require__(7).RECONNECT_INTERVAL
);
}).bind(this));
this._socket.on("message:in", (function (message) {
// When the `connected` message is received, emit the `connected` event
// to the DDP connection
if (message.msg === "connected") {
this.emit("connected");
function Queue(consumer) {
_classCallCheck(this, Queue);
this.consumer = consumer;
this.queue = [];
}
_createClass(Queue, [{
key: "push",
value: function push(element) {
this.queue.push(element);
this.process();
}
}).bind(this));
};
}, {
key: "process",
value: function process() {
var _this = this;
setTimeout(function () {
if (_this.queue.length !== 0) {
var ack = _this.consumer(_this.queue[0]);
if (ack) {
_this.queue.shift();
_this.process();
}
}
}, 0);
}
}, {
key: "empty",
value: function empty() {
this.queue = [];
}
}]);
return Queue;
})();
exports["default"] = Queue;
module.exports = exports["default"];
/***/ },
/* 4 */
/* 3 */
/***/ function(module, exports, __webpack_require__) {
/*
* Emits subscription and method related events
*/
"use strict";
module.exports = function () {
this._socket.on("message:in", (function (message) {
var msgs = [
// Subscription messages
"ready",
"nosub",
"added",
"changed",
"removed",
// Method messages
"result",
"updated"
];
if (__webpack_require__(8).contains(msgs, message.msg)) {
this.emit(message.msg, message);
}
}).bind(this));
};
Object.defineProperty(exports, "__esModule", {
value: true
});
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; }; })();
/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
/*
* Responds to ping messages
*/
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
module.exports = function () {
this._socket.on("message:in", (function (message) {
if (message.msg === "ping") {
this.pong(message.id);
}
}).bind(this));
};
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }
var _wolfy87Eventemitter = __webpack_require__(1);
/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {
var _wolfy87Eventemitter2 = _interopRequireDefault(_wolfy87Eventemitter);
/*
* Create the socket instance and register event listeners
*/
var Socket = (function (_EventEmitter) {
_inherits(Socket, _EventEmitter);
"use strict";
_createClass(Socket, [{
key: "emit",
value: function emit() {
var _this = this;
module.exports = function () {
// The `open`, `error` and `close` events are simply proxy-ed to `_socket`.
// The `message` event is instead parsed into a js object (if possible) and
// then passed as a parameter of the `message:in` event
this._rawSocket = new this._SocketConstructor(this._endpoint);
this._rawSocket.onopen = this._socket.emit.bind(this._socket, "open");
this._rawSocket.onerror = this._socket.emit.bind(this._socket, "error");
this._rawSocket.onclose = this._socket.emit.bind(this._socket, "close");
this._rawSocket.onmessage = (function (message) {
var object;
try {
object = JSON.parse(message.data);
} catch (ignore) {
// Simply ignore the malformed message and return
return;
var args = arguments;
setTimeout(function () {
_get(Object.getPrototypeOf(Socket.prototype), "emit", _this).apply(_this, args);
}, 0);
}
// Outside the try-catch block as it must only catch JSON parsing
// errors, not errors that may occur inside a "message:in" event handler
this._socket.emit("message:in", object);
}).bind(this);
};
}]);
function Socket(SocketConstructor, endpoint) {
_classCallCheck(this, Socket);
/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {
_get(Object.getPrototypeOf(Socket.prototype), "constructor", this).call(this);
this.SocketConstructor = SocketConstructor;
this.endpoint = endpoint;
}
"use strict";
_createClass(Socket, [{
key: "send",
value: function send(object) {
var message = JSON.stringify(object);
this.rawSocket.send(message);
// Emit a copy of the object, as the listener might mutate it.
this.emit("message:out", JSON.parse(message));
}
}, {
key: "connect",
value: function connect() {
var _this2 = this;
module.exports = {
DDP_VERSION: "1",
DEFAULT_PING_INTERVAL: 10000,
RECONNECT_INTERVAL: 10000
};
this.rawSocket = new this.SocketConstructor(this.endpoint);
/*
* The `open`, `error` and `close` events are simply proxy-ed to `_socket`.
* The `message` event is instead parsed into a js object (if possible) and
* then passed as a parameter of the `message:in` event
*/
this.rawSocket.onopen = function () {
return _this2.emit("open");
};
this.rawSocket.onerror = function (error) {
return _this2.emit("error", error);
};
this.rawSocket.onclose = function () {
return _this2.emit("close");
};
this.rawSocket.onmessage = function (message) {
var object;
try {
object = JSON.parse(message.data);
} catch (ignore) {
// Simply ignore the malformed message and return
return;
}
// Outside the try-catch block as it must only catch JSON parsing
// errors, not errors that may occur inside a "message:in" event handler
_this2.emit("message:in", object);
};
}
}]);
return Socket;
})(_wolfy87Eventemitter2["default"]);
exports["default"] = Socket;
module.exports = exports["default"];
/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {
/* 4 */
/***/ function(module, exports) {
"use strict";
var uniqueId = (function () {
var i = 0;
return function () {
return (i++).toString();
};
})();
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.uniqueId = uniqueId;
exports.contains = contains;
var i = 0;
var contains = function (array, element) {
function uniqueId() {
return (i++).toString();
}
function contains(array, element) {
return array.indexOf(element) !== -1;
};
}
module.exports = {
uniqueId: uniqueId,
contains: contains
};
/***/ }
/******/ ])
/******/ ])
});
;
{
"name": "ddp.js",
"version": "1.0.0",
"version": "1.1.0",
"description": "ddp javascript client",
"main": "src/ddp.js",
"main": "dist/ddp.js",
"scripts": {
"build": "./node_modules/.bin/webpack",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha",
"test": "./node_modules/.bin/_mocha"
"build": "gulp build",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"dev": "gulp",
"lint": "eslint src/",
"test": "istanbul cover _mocha --report lcovonly -- -R spec --compilers js:babel/register"
},

@@ -27,8 +29,18 @@ "repository": {

"devDependencies": {
"babel": "^5.6.14",
"babel-core": "^5.6.17",
"babel-loader": "^5.3.1",
"chai": "^3.0.0",
"coveralls": "^2.11.2",
"istanbul": "^0.3.5",
"mocha": "^2.1.0",
"should": "^4.4.2",
"sinon": "^1.12.2",
"webpack": "^1.4.15"
"eslint": "^0.24.1",
"gulp": "^3.9.0",
"gulp-eslint": "^0.15.0",
"gulp-spawn-mocha": "^2.2.1",
"gulp-util": "^3.0.6",
"istanbul": "^0.3.17",
"mocha": "^2.2.5",
"node-libs-browser": "^0.5.2",
"sinon": "^1.15.4",
"sinon-chai": "^2.8.0",
"webpack": "^1.10.1"
},

@@ -35,0 +47,0 @@ "dependencies": {

@@ -7,3 +7,3 @@ [![Build Status](https://travis-ci.org/mondora/ddp.js.svg?branch=master)](https://travis-ci.org/mondora/ddp.js)

#WARNING
Breaking changes from 0.6.x to 1.0.0, [read the
Breaking changes from ~0.6.0 to >=1.0.0, [read the
CHANGELOG](https://github.com/mondora/ddp.js/blob/master/CHANGELOG.md) for more

@@ -47,25 +47,25 @@ info.

console.log("Connected");
});
var subId = ddp.sub("myCollection");
ddp.on("ready", function (message) {
if (message.id === subId) {
console.log("Subscruption to myCollection ready");
}
});
ddp.on("added", function (message) {
console.log(message.collection);
});
var subId = ddp.sub("mySubscription");
ddp.on("ready", function (message) {
if (message.id === subId) {
console.log("mySubscription ready");
}
});
ddp.on("added", function (message) {
console.log(message.collection);
});
var myLoginParams = {
user: {
email: "user@example.com"
},
password: "hunter2"
};
var methodId = ddp.method("login", [myLoginParams]);
ddp.on("result", function (message) {
if (message.id === methodId && !message.error) {
console.log("Logged in!");
}
});
var myLoginParams = {
user: {
email: "user@example.com"
},
password: "hunter2"
};
var methodId = ddp.method("login", [myLoginParams]);
ddp.on("result", function (message) {
if (message.id === methodId && !message.error) {
console.log("Logged in!");
}
});

@@ -76,3 +76,4 @@ ```

`npm test` to run tests, `npm run coverage` to generate the coverage report.
`npm test` to run tests. Coverage reports are generated in the `coverage/`
directory.

@@ -79,0 +80,0 @@ ##Public API

@@ -1,79 +0,109 @@

"use strict";
import EventEmitter from "wolfy87-eventemitter";
import Queue from "./queue";
import Socket from "./socket";
import {contains, uniqueId} from "./utils";
var EventEmitter = require("wolfy87-eventemitter");
const DDP_VERSION = "1";
const PUBLIC_EVENTS = [
// Subscription messages
"ready", "nosub", "added", "changed", "removed",
// Method messages
"result", "updated",
// Error messages
"error"
];
const RECONNECT_INTERVAL = 10000;
var DDP = function (options) {
// Configuration
this._endpoint = options.endpoint;
this._SocketConstructor = options.SocketConstructor;
// Init
this._init();
};
DDP.prototype = Object.create(EventEmitter.prototype);
DDP.prototype.constructor = DDP;
export default class DDP extends EventEmitter {
DDP.prototype._init = function () {
require("./socket-proxy.js").call(this);
require("./ddp-connection.js").call(this);
require("./public-events.js").call(this);
require("./ping-pong.js").call(this);
require("./socket-connection.js").call(this);
};
emit () {
var args = arguments;
setTimeout(() => {
super.emit.apply(this, args);
}, 0);
}
DDP.prototype.connect = function () {
var c = require("./lib/constants.js");
this._socket.send({
msg: "connect",
version: c.DDP_VERSION,
support: [c.DDP_VERSION]
});
};
constructor (options) {
DDP.prototype.method = function (name, params) {
var id = require("./lib/utils.js").uniqueId();
this._socket.send({
msg: "method",
id: id,
method: name,
params: params
});
return id;
};
super();
DDP.prototype.ping = function () {
var id = require("./lib/utils.js").uniqueId();
this._socket.send({
msg: "ping",
id: id
});
return id;
};
this.status = "disconnected";
DDP.prototype.pong = function (id) {
this._socket.send({
msg: "pong",
id: id
});
return id;
};
this.messageQueue = new Queue((message) => {
if (this.status === "connected") {
this.socket.send(message);
return true;
} else {
return false;
}
});
DDP.prototype.sub = function (name, params) {
var id = require("./lib/utils.js").uniqueId();
this._socket.send({
msg: "sub",
id: id,
name: name,
params: params
});
return id;
};
this.socket = new Socket(options.SocketConstructor, options.endpoint);
DDP.prototype.unsub = function (id) {
this._socket.send({
msg: "unsub",
id: id
});
return id;
};
this.socket.on("open", () => {
// When the socket opens, send the `connect` message
// to establish the DDP connection
this.socket.send({
msg: "connect",
version: DDP_VERSION,
support: [DDP_VERSION]
});
});
module.exports = DDP;
this.socket.on("close", () => {
this.status = "disconnected";
this.messageQueue.empty();
this.emit("disconnected");
// Schedule a reconnection
setTimeout(this.socket.connect.bind(this.socket), RECONNECT_INTERVAL);
});
this.socket.on("message:in", (message) => {
if (message.msg === "connected") {
this.status = "connected";
this.messageQueue.process();
this.emit("connected");
} else if (message.msg === "ping") {
// Reply with a `pong` message to prevent the server from
// closing the connection
this.socket.send({msg: "pong", id: message.id});
} else if (contains(PUBLIC_EVENTS, message.msg)) {
this.emit(message.msg, message);
}
});
this.socket.connect();
}
method (name, params) {
var id = uniqueId();
this.messageQueue.push({
msg: "method",
id: id,
method: name,
params: params
});
return id;
}
sub (name, params) {
var id = uniqueId();
this.messageQueue.push({
msg: "sub",
id: id,
name: name,
params: params
});
return id;
}
unsub (id) {
this.messageQueue.push({
msg: "unsub",
id: id
});
return id;
}
}

@@ -1,186 +0,262 @@

"use strict";
import chai, {expect} from "chai";
import sinon from "sinon";
import sinonChai from "sinon-chai";
import takeTen from "./take-ten";
require("should");
var sinon = require("sinon");
var EventEmitter = require("wolfy87-eventemitter");
chai.use(sinonChai);
var DDP = require("../src/ddp.js");
import DDP from "../src/ddp";
import Socket from "../src/socket";
describe("The DDP module", function () {
it("should export a constructor", function () {
DDP.should.be.of.type("function");
DDP.prototype.constructor.should.equal(DDP);
class SocketConstructorMock {
send () {}
}
const options = {
SocketConstructor: SocketConstructorMock
};
describe("`DDP` class", function () {
describe("`constructor` method", function () {
beforeEach(function () {
sinon.stub(Socket.prototype, "on");
sinon.stub(Socket.prototype, "connect");
});
afterEach(function () {
Socket.prototype.on.restore();
Socket.prototype.connect.restore();
});
it("instantiates a `Socket`", function () {
var ddp = new DDP(options);
expect(ddp.socket).to.be.an.instanceOf(Socket);
});
it("registers handlers for `socket` events", function () {
var ddp = new DDP(options);
expect(ddp.socket.on).to.have.always.been.calledWithMatch(
sinon.match.string,
sinon.match.func
);
});
it("calls `socket.connect`", function () {
var ddp = new DDP(options);
expect(ddp.socket.connect).to.have.callCount(1);
});
});
});
describe("The DDP constructor", function () {
beforeEach(function () {
sinon.stub(DDP.prototype, "_init");
describe("`method` method", function () {
it("sends a DDP `method` message", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.method("name", ["param"]);
expect(ddp.messageQueue.push).to.have.been.calledWith({
msg: "method",
id: id,
method: "name",
params: ["param"]
});
});
it("returns the method's `id`", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.method("name", ["param"]);
expect(id).to.be.a("string");
});
});
afterEach(function () {
DDP.prototype._init.restore();
});
it("should inherit from EventEmitter", function () {
var ddp = new DDP({});
ddp.should.be.instanceOf(EventEmitter);
});
it("should save the endpoint and SocketConstructor passed to it as properties of the instance", function () {
var options = {
endpoint: "endpoint",
SocketConstructor: function () {
// Noop
}
};
var ddp = new DDP(options);
ddp._endpoint.should.equal(options.endpoint);
ddp._SocketConstructor.should.equal(options.SocketConstructor);
});
it("should call the _init method", function () {
var ddp = new DDP({});
ddp._init.called.should.equal(true);
});
});
describe("The connect method", function () {
it("should _socket.send a connect message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var c = require("../src/lib/constants.js");
DDP.prototype.connect.call(ctx);
ctx._socket.send.firstCall.args[0].should.eql({
msg: "connect",
version: c.DDP_VERSION,
support: [c.DDP_VERSION]
describe("`sub` method", function () {
it("sends a DDP `sub` message", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.sub("name", ["param"]);
expect(ddp.messageQueue.push).to.have.been.calledWith({
msg: "sub",
id: id,
name: "name",
params: ["param"]
});
});
it("returns the sub's `id`", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.sub("name", ["param"]);
expect(id).to.be.a("string");
});
});
});
describe("The method method", function () {
it("should _socket.send a method message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
DDP.prototype.method.call(ctx, "methodName", ["list", "of", "params"]);
var arg = ctx._socket.send.firstCall.args[0];
arg.should.eql({
msg: "method",
id: arg.id,
method: "methodName",
params: ["list", "of", "params"]
describe("`unsub` method", function () {
it("sends a DDP `unsub` message", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.unsub("id");
expect(ddp.messageQueue.push).to.have.been.calledWith({
msg: "unsub",
id: id
});
});
it("returns the sub's `id`", function () {
var ddp = new DDP(options);
ddp.messageQueue.push = sinon.spy();
var id = ddp.unsub("id");
expect(id).to.be.a("string");
expect(id).to.equal("id");
});
});
it("should return the id of the method call", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var ret = DDP.prototype.method.call(ctx, "methodName", []);
ret.should.equal(ctx._socket.send.firstCall.args[0].id);
});
});
describe("The ping method", function () {
it("should _socket.send a ping message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
DDP.prototype.ping.call(ctx);
var arg = ctx._socket.send.firstCall.args[0];
arg.should.eql({
msg: "ping",
id: arg.id
describe("`socket` `open` handler", function () {
it("sends the `connect` DDP message", function (done) {
var ddp = new DDP(options);
ddp.socket.send = sinon.spy();
ddp.socket.emit("open");
takeTen(() => {
expect(ddp.socket.send).to.have.been.calledWith({
msg: "connect",
version: "1",
support: ["1"]
});
}, done);
});
});
it("should return the id of the ping call", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var ret = DDP.prototype.ping.call(ctx);
ret.should.equal(ctx._socket.send.firstCall.args[0].id);
});
});
describe("The pong method", function () {
it("should _socket.send a pong message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
DDP.prototype.pong.call(ctx, "0");
ctx._socket.send.firstCall.args[0].should.eql({
msg: "pong",
id: "0"
describe("`socket` `close` handler", function () {
before(function () {
sinon.spy(global, "setTimeout");
});
after(function () {
global.setTimeout.restore();
});
it("emits the `disconnected` event", function (done) {
var ddp = new DDP(options);
ddp.emit = sinon.spy();
ddp.socket.emit("close");
takeTen(() => {
expect(ddp.emit).to.have.been.calledWith("disconnected");
}, done);
});
it("sets the status to `disconnected`", function (done) {
var ddp = new DDP(options);
ddp.status = "connected";
ddp.emit = sinon.spy();
ddp.socket.emit("close");
takeTen(() => {
expect(ddp.status).to.equal("disconnected");
}, done);
});
it("schedules a reconnection", function (done) {
var ddp = new DDP(options);
ddp.socket.emit("close");
var RECONNECT_INTERVAL = 10000;
takeTen(() => {
expect(global.setTimeout).to.have.been.calledWithMatch(
sinon.match.func,
RECONNECT_INTERVAL
);
}, done);
});
});
it("should return the id of the pong call", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var ret = DDP.prototype.pong.call(ctx, "0");
ret.should.equal("0");
});
});
describe("The sub method", function () {
it("should _socket.send a sub message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
DDP.prototype.sub.call(ctx, "subName", ["list", "of", "params"]);
var arg = ctx._socket.send.firstCall.args[0];
arg.should.eql({
msg: "sub",
id: arg.id,
name: "subName",
params: ["list", "of", "params"]
describe("`socket` `message:in` handler", function () {
it("responds to `ping` DDP messages", function (done) {
var ddp = new DDP(options);
ddp.socket.send = sinon.spy();
ddp.socket.emit("message:in", {
id: "id",
msg: "ping"
});
takeTen(() => {
expect(ddp.socket.send).to.have.been.calledWith({
id: "id",
msg: "pong"
});
}, done);
});
it("triggers `messageQueue` processing upon connection", function (done) {
var ddp = new DDP(options);
ddp.emit = sinon.spy();
ddp.messageQueue.process = sinon.spy();
ddp.socket.emit("message:in", {msg: "connected"});
takeTen(() => {
expect(ddp.messageQueue.process).to.have.callCount(1);
}, done);
});
it("sets the status to `connected` upon connection", function (done) {
var ddp = new DDP(options);
ddp.emit = sinon.spy();
ddp.socket.emit("message:in", {msg: "connected"});
takeTen(() => {
expect(ddp.status).to.equal("connected");
}, done);
});
it("emits public DDP messages as events", function (done) {
var ddp = new DDP(options);
ddp.emit = sinon.spy();
var message = {
id: "id",
msg: "result"
};
ddp.socket.emit("message:in", message);
takeTen(() => {
expect(ddp.emit).to.have.been.calledWith("result", message);
}, done);
});
it("ignores unknown (or non public) DDP messages", function (done) {
var ddp = new DDP(options);
ddp.emit = sinon.spy();
var message = {
id: "id",
msg: "not-a-ddp-message"
};
ddp.socket.emit("message:in", message);
takeTen(() => {
expect(ddp.emit).to.have.callCount(0);
}, done);
});
});
it("should return the id of the sub call", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var ret = DDP.prototype.sub.call(ctx, "subName", []);
ret.should.equal(ctx._socket.send.firstCall.args[0].id);
});
});
describe("The unsub method", function () {
it("should _socket.send a unsub message", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
DDP.prototype.unsub.call(ctx, "0");
ctx._socket.send.firstCall.args[0].should.eql({
msg: "unsub",
id: "0"
describe("`messageQueue` consumer", function () {
it("acks if `status` is `connected`", function () {
var ddp = new DDP(options);
ddp.status = "connected";
var ack = ddp.messageQueue.consumer({});
expect(ack).to.equal(true);
});
it("doesn't ack if `status` is `disconnected`", function () {
var ddp = new DDP(options);
ddp.status = "disconnected";
var ack = ddp.messageQueue.consumer({});
expect(ack).to.equal(false);
});
});
it("should return the id of the unsub call", function () {
var ctx = {
_socket: {
send: sinon.spy()
}
};
var ret = DDP.prototype.unsub.call(ctx, "0");
ret.should.equal("0");
});
});

@@ -1,26 +0,33 @@

"use strict";
import {expect} from "chai";
require("should");
import {contains, uniqueId} from "../src/utils";
var u = require("../src/lib/utils.js");
describe("`utils` object", function () {
describe("The utils.contains function", function () {
it("should return true if the first parameter, an array, contains the second parameter", function () {
var array = ["element"];
var element = "element";
u.contains(array, element).should.equal(true);
describe("`contains` function", function () {
it("returns true if the first parameter contains the second parameter", function () {
var array = ["element"];
var element = "element";
expect(contains(array, element)).to.equal(true);
});
it("returns false if the first parameter doesn't contain the second parameter", function () {
var array = ["element"];
var element = "different-element";
expect(contains(array, element)).to.equal(false);
});
});
it("should return false if the first parameter, an array, doesn't contain the second parameter", function () {
var array = ["element"];
var element = "different-element";
u.contains(array, element).should.equal(false);
describe("`uniqueId` function", function () {
it("should return a different string each time it's called", function () {
var ret1 = uniqueId();
var ret2 = uniqueId();
expect(ret1).not.to.equal(ret2);
});
});
});
describe("The utils.uniqueId function", function () {
it("should return a different string each time it's called", function () {
var ret1 = u.uniqueId();
var ret2 = u.uniqueId();
ret1.should.not.equal(ret2);
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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