diff --git a/.eslintrc.json b/.eslintrc.json index d56ea461f..a72371a0c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -51,8 +51,7 @@ "yoda": [2, "never"] }, "env": { - "node": true, - "mocha": true + "browser": true }, "parserOptions": { "ecmaVersion": 5 diff --git a/CHANGELOG.md b/CHANGELOG.md index ee41a4448..1fd8c2f00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ +# [4.0.0](https://github.com/kuzzleio/sdk-javascript/releases/tag/4.0.0) (2017-04-10) + +[Full Changelog](https://github.com/kuzzleio/sdk-javascript/compare/4.0.0...4.0.0) + +### Compatibility + +| Kuzzle | Proxy | +|--------|-------| +| 1.0.0-RC9.6 | 1.0.0-RC9 | + +#### Breaking changes + +- [ [#201](https://github.com/kuzzleio/sdk-javascript/pull/201) ] Rename metadata into volatile ([AnthonySendra](https://github.com/AnthonySendra)) + +#### Bug fixes + +- [ [#194](https://github.com/kuzzleio/sdk-javascript/pull/194) ] Stop calling onClientError when disconnect is called ([jenow](https://github.com/jenow)) +- [ [#193](https://github.com/kuzzleio/sdk-javascript/pull/193) ] Wrap filter in query for deleteDocument ([jenow](https://github.com/jenow)) + +#### Enhancements + +- [ [#199](https://github.com/kuzzleio/sdk-javascript/pull/199) ] Add support for the new retryOnConflict option ([scottinet](https://github.com/scottinet)) +- [ [#191](https://github.com/kuzzleio/sdk-javascript/pull/191) ] Standardize memory storage object ([scottinet](https://github.com/scottinet)) + +#### Exclude + +- [ [#196](https://github.com/kuzzleio/sdk-javascript/pull/196) ] Fix ms.hgetall return value interpretation ([scottinet](https://github.com/scottinet)) +- [ [#198](https://github.com/kuzzleio/sdk-javascript/pull/198) ] Fix ms.zscore return value type ([scottinet](https://github.com/scottinet)) + +#### Others + +- [ [#195](https://github.com/kuzzleio/sdk-javascript/pull/195) ] Moved bufferutil and utf-8-validate to peerDependencies ([jenow](https://github.com/jenow)) +- [ [#190](https://github.com/kuzzleio/sdk-javascript/pull/190) ] Align SearchResult and scroll with other SDKs ([dbengsch](https://github.com/dbengsch)) +- [ [#182](https://github.com/kuzzleio/sdk-javascript/pull/182) ] Collection.createDocument: rename the updateIfExist option ([scottinet](https://github.com/scottinet)) +- [ [#188](https://github.com/kuzzleio/sdk-javascript/pull/188) ] Make all options given to kuzzle constructor writable ([benoitvidis](https://github.com/benoitvidis)) +- [ [#177](https://github.com/kuzzleio/sdk-javascript/pull/177) ] Remove previous and next cache in SearchResult ([dbengsch](https://github.com/dbengsch)) +- [ [#177](https://github.com/kuzzleio/sdk-javascript/pull/177) ] Remove previous and next cache in SearchResult ([dbengsch](https://github.com/dbengsch)) +- [ [#184](https://github.com/kuzzleio/sdk-javascript/pull/184) ] Browsers compatibility fix ([scottinet](https://github.com/scottinet)) +--- + # 3.4.0 Fill changes list: https://github.com/kuzzleio/sdk-javascript/releases/tag/3.4.0 diff --git a/README.md b/README.md index be9856f4d..ef5e3abd4 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ You can access the Kuzzle repository on [Github](https://github.com/kuzzleio/kuz * [Basic usage](#basic-usage-js) * [Building manually](#building-manually) * [Migrating from SDK v1.x](#migrating-from-sdk-v1.x) +* [Note](#note) * [License](#license) ## SDK Documentation @@ -139,6 +140,10 @@ kuzzle * Kuzzle constructor has been changed. Instead of an URL, you have to provide a resolvable server name, or an IP address. If you need to specify a port different than the provided default value, you can do so using the `port` option. +## Note + +* bufferutil and utf-8-validate have been moved to peerDependencies + ## License [Apache 2](LICENSE.md) diff --git a/dist/kuzzle.js b/dist/kuzzle.js index 91bc7b98f..a343af353 100644 --- a/dist/kuzzle.js +++ b/dist/kuzzle.js @@ -1,4 +1,4 @@ -/*! Kuzzle javascript SDK version 3.4.2 */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Kuzzle=t():e.Kuzzle=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){function n(e,t,r){var i=this;if(!(this instanceof n))return new n(e,t,r);if(r||"function"!=typeof t||(r=t,t=null),!e||""===e)throw new Error("host argument missing");return Object.defineProperties(this,{collections:{value:{},writable:!0},connectCB:{value:r},eventListeners:{value:{connected:{lastEmitted:null,listeners:[]},error:{lastEmitted:null,listeners:[]},disconnected:{lastEmitted:null,listeners:[]},reconnected:{lastEmitted:null,listeners:[]},jwtTokenExpired:{lastEmitted:null,listeners:[]},loginAttempt:{lastEmitted:null,listeners:[]},offlineQueuePush:{listeners:[]},offlineQueuePop:{listeners:[]},queryError:{listeners:[]},discarded:{listeners:[]}}},eventTimeout:{value:200},queuing:{value:!1,writable:!0},requestHistory:{value:{},writable:!0},state:{value:"initializing",writable:!0},subscriptions:{value:{pending:{}},writable:!0},autoReconnect:{value:!t||"boolean"!=typeof t.autoReconnect||t.autoReconnect,writable:!0,enumerable:!0},defaultIndex:{value:t&&"string"==typeof t.defaultIndex?t.defaultIndex:void 0,writable:!0,enumerable:!0},reconnectionDelay:{value:t&&"number"==typeof t.reconnectionDelay?t.reconnectionDelay:1e3,writable:!0,enumerable:!0},host:{value:e,writable:!0,enumerable:!0},port:{value:t&&"number"==typeof t.port?t.port:7512,enumerable:!0,writable:!0},sslConnection:{value:!(!t||"boolean"!=typeof t.sslConnection)&&t.sslConnection,writable:!0,enumerable:!0},autoQueue:{value:!1,enumerable:!0,writable:!0},autoReplay:{value:!1,enumerable:!0,writable:!0},autoResubscribe:{value:!0,enumerable:!0,writable:!0},headers:{value:{},enumerable:!0,writable:!0},metadata:{value:{},enumerable:!0,writable:!0},offlineQueue:{value:[],enumerable:!0,writable:!0},queueFilter:{value:null,enumerable:!0,writable:!0},queueMaxSize:{value:500,enumerable:!0,writable:!0},queueTTL:{value:12e4,enumerable:!0,writable:!0},replayInterval:{value:10,enumerable:!0,writable:!0},jwtToken:{value:void 0,enumerable:!0,writable:!0},offlineQueueLoader:{value:null,enumerable:!0,writable:!0}}),t&&(Object.keys(t).forEach(function(e){i.hasOwnProperty(e)&&Object.getOwnPropertyDescriptor(i,e).writable&&(i[e]=t[e])}),"auto"===t.offlineMode&&this.autoReconnect&&(this.autoQueue=this.autoReplay=this.autoResubscribe=!0)),Object.defineProperty(this,"isValid",{value:function(){if("disconnected"===i.state)throw new Error("This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?")}}),Object.defineProperty(this,"addHeaders",{value:function(e,t){return Object.keys(t).forEach(function(r){e[r]||(e[r]=t[r])}),e}}),Object.defineProperty(this,"callbackRequired",{value:function(e,t){if(!t||"function"!=typeof t)throw new Error(e+": a callback argument is required for read queries")}}),Object.defineProperty(this,"security",{value:new h(this),enumerable:!0}),Object.defineProperty(this,"emitEvent",{value:function(e){var t=Date.now(),r=Array.prototype.slice.call(arguments,1),n=this.eventListeners[e];return!(n.lastEmitted&&n.lastEmitted>=t-this.eventTimeout)&&(n.listeners.forEach(function(e){process.nextTick(function(){e.fn.apply(void 0,r)})}),void(void 0!==n.lastEmitted&&(n.lastEmitted=t)))}}),Object.defineProperty(this,"memoryStorage",{value:new p(this),enumerable:!0}),t&&t.connect&&"auto"!==t.connect?this.state="ready":this.connect(),o(this.requestHistory),this.bluebird?this.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["getAllStatistics","getServerInfo","getStatistics","listCollections","listIndexes","login","logout","now","query","checkToken","whoAmI","updateSelf","getMyRights","refreshIndex","getAutoRefresh","setAutoRefresh"];return n&&i.indexOf(e)!==-1}}):void 0}function i(){var e=this,t=Date.now(),r=-1;e.queueTTL>0&&(e.offlineQueue.forEach(function(n,i){n.ts0&&e.offlineQueue.length>e.queueMaxSize&&e.offlineQueue.splice(0,e.offlineQueue.length-e.queueMaxSize).forEach(function(t){e.emitEvent("offlineQueuePop",t.query)})}function o(e){var t=Date.now();Object.keys(e).forEach(function(r){e[r]0?(s.call(t,t.offlineQueue[0].query,t.offlineQueue[0].cb),t.emitEvent("offlineQueuePop",t.offlineQueue.shift()),setTimeout(function(){n()},Math.max(0,t.replayInterval))):t.queuing=!1};if(t.offlineQueueLoader){if("function"!=typeof t.offlineQueueLoader)throw new Error("Invalid value for offlineQueueLoader property. Expected: function. Got: "+typeof t.offlineQueueLoader);if(e=t.offlineQueueLoader(),!Array.isArray(e))throw new Error("Invalid value returned by the offlineQueueLoader function. Expected: array. Got: "+typeof e);t.offlineQueue=e.concat(t.offlineQueue).filter(function(e){if(!e.query||void 0===e.query.requestId||!e.query.action||!e.query.controller)throw new Error("Invalid offline queue request. One or more missing properties: requestId, action, controller.");return!r.hasOwnProperty(e.query.requestId)&&(r[e.query.requestId]=!0)})}n()}function l(){var e=this;Object.keys(e.subscriptions).forEach(function(t){Object.keys(e.subscriptions[t]).forEach(function(r){var n=e.subscriptions[t][r];n.renew(n.callback)})})}function c(){var e=this;Object.keys(e.subscriptions).forEach(function(t){Object.keys(e.subscriptions[t]).forEach(function(r){var n=e.subscriptions[t][r];n.unsubscribe()})})}function a(e,t){t&&t(new Error("Unable to execute request: not connected to a Kuzzle server.\nDiscarded request: "+JSON.stringify(e)))}var f=r(5),d=r(8),h=r(18),p=r(10),y=r(4),b=r(14);n.prototype.connect=function(){var e=this;return e.network&&e.disconnect(),e.network=b(e.host,e.port,e.sslConnection),["initializing","ready","disconnected","error","offline"].indexOf(this.state)===-1?(e.connectCB&&e.connectCB(null,e),e):(e.state="connecting",e.network.connect(e.autoReconnect,e.reconnectionDelay),e.network.onConnect(function(){e.state="connected",l.call(e),u.call(e),e.emitEvent("connected"),e.connectCB&&e.connectCB(null,e)}),e.network.on("discarded",function(t){e.emitEvent("discarded",t)}),e.network.onConnectError(function(t){var r=new Error('Unable to connect to kuzzle proxy server at "'+e.host+'"');r.internal=t,e.state="error",e.emitEvent("error",r),e.connectCB&&e.connectCB(r)}),e.network.onDisconnect(function(){e.state="offline",e.autoReconnect||e.disconnect(),e.autoQueue&&(e.queuing=!0),e.emitEvent("disconnected")}),e.network.onReconnect(function(){var t=function(){e.autoResubscribe&&l.call(e),e.autoReplay&&(i.call(e),u.call(e)),e.emitEvent("reconnected")};e.state="connected",e.jwtToken?e.checkToken(e.jwtToken,function(r,n){!r&&n.valid||(e.jwtToken=void 0,e.emitEvent("jwtTokenExpired")),t()}):t()}),this)},n.prototype.setJwtToken=function(e){if("string"==typeof e)this.jwtToken=e;else{if("object"!=typeof e)return this.emitEvent("loginAttempt",{success:!1,error:"Invalid token argument: "+e}),this;if(!e.result||!e.result.jwt||"string"!=typeof e.result.jwt)return this.emitEvent("loginAttempt",{success:!1,error:"Cannot find a valid JWT token in the following object: "+JSON.stringify(e)}),this;this.jwtToken=e.result.jwt}return l.call(this),this.emitEvent("loginAttempt",{success:!0}),this},n.prototype.unsetJwtToken=function(){return this.jwtToken=void 0,c.call(this),this},n.prototype.getJwtToken=function(){return this.jwtToken},n.prototype.login=function(e){var t,r=this,n={strategy:e},i=null;arguments[1]&&("object"==typeof arguments[1]?t=arguments[1]:"number"==typeof arguments[1]||"string"==typeof arguments[1]?n.expiresIn=arguments[1]:"function"==typeof arguments[1]&&(i=arguments[1])),arguments[2]&&("number"==typeof arguments[2]||"string"==typeof arguments[2]?n.expiresIn=arguments[2]:"function"==typeof arguments[2]&&(i=arguments[2])),arguments[3]&&"function"==typeof arguments[3]&&(i=arguments[3]),"object"==typeof t&&Object.keys(t).forEach(function(e){n[e]=t[e]}),this.query({controller:"auth",action:"login"},{body:n},{queuable:!1},function(e,t){e?(i&&i(e),r.emitEvent("loginAttempt",{success:!1,error:e.message})):(t.result.jwt&&r.setJwtToken(t.result.jwt),i&&i(null,t.result))})},n.prototype.createIndex=function(e,t,r){if(!e){if(!this.defaultIndex)throw new Error("Kuzzle.createIndex: index required");e=this.defaultIndex}return r||"function"!=typeof t||(r=t,t=null),this.query({controller:"index",action:"create"},{index:e},t,"function"!=typeof r?null:r),this},n.prototype.logout=function(e){var t=this,r={action:"logout",controller:"auth",requestId:f.v4(),body:{}};return this.query({controller:"auth",action:"logout"},r,{queuable:!1},"function"!=typeof e?null:function(r){e(r,t)}),t.unsetJwtToken(),t},n.prototype.checkToken=function(e,t){var r={body:{token:e}};this.callbackRequired("Kuzzle.checkToken",t),this.query({controller:"auth",action:"checkToken"},r,{queuable:!1},function(e,r){return e?t(e):void t(null,r.result)})},n.prototype.whoAmI=function(e){var t=this;t.callbackRequired("Kuzzle.whoAmI",e),t.query({controller:"auth",action:"getCurrentUser"},{},{},function(r,n){return r?e(r):void e(null,new y(t.security,n.result._id,n.result._source))})},n.prototype.getMyRights=function(e,t){var r=this;t||"function"!=typeof e||(t=e,e=null),r.callbackRequired("Kuzzle.getMyRights",t),r.query({controller:"auth",action:"getMyRights"},{},e,function(e,r){return e?t(e):void t(null,r.result.hits)})},n.prototype.updateSelf=function(e,t,r){var n=this,i={},o={controller:"auth",action:"updateSelf"};return r||"function"!=typeof t||(r=t,t=null),i.body=e,n.query(o,i,t,r&&function(e,t){r(e,e?void 0:t.result)}),this},n.prototype.addListener=function(e,t){var r,n=Object.keys(this.eventListeners),i=typeof t;if(this.isValid(),n.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+n.toString());if("function"!==i)throw new Error("Invalid listener type: expected a function, got a "+i);return r=f.v4(),this.eventListeners[e].listeners.push({id:r,fn:t}),r},n.prototype.getAllStatistics=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.getAllStatistics",t),this.query({controller:"server",action:"getAllStats"},{},e,function(e,r){return e?t(e):void t(null,r.result.hits)})},n.prototype.getStatistics=function(e,t,r){var n,i;r||(1===arguments.length?(r=arguments[0],t=null,e=null):(r=arguments[1],"object"==typeof arguments[0]?(t=arguments[0],e=null):(e=arguments[0],t=null))),n=function(t,n){return t?r(t):void r(null,e?n.result.hits:[n.result])},this.callbackRequired("Kuzzle.getStatistics",r),i=e?{body:{startTime:e}}:{},this.query({controller:"server",action:e?"getStats":"getLastStats"},i,t,n)},n.prototype.collection=function(e,t){if(this.isValid(),!t){if(!this.defaultIndex)throw new Error("Unable to create a new data collection object: no index specified");t=this.defaultIndex}if("string"!=typeof t||"string"!=typeof e)throw new Error("Invalid index or collection argument: string expected");return this.collections[t]||(this.collections[t]={}),this.collections[t][e]||(this.collections[t][e]=new d(this,e,t)),this.collections[t][e]},n.prototype.flushQueue=function(){return this.offlineQueue=[],this},n.prototype.listCollections=function(){var e,t,r,n,i="all",o=Array.prototype.slice.call(arguments);if(o.forEach(function(n){switch(typeof n){case"string":e=n;break;case"object":t=n;break;case"function":r=n}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.listCollections: index required");e=this.defaultIndex}this.callbackRequired("Kuzzle.listCollections",r),t&&t.type&&(i=t.type),n={body:{type:i}},t&&t.from&&(n.body.from=t.from),t&&t.size&&(n.body.size=t.size),this.query({index:e,controller:"collection",action:"list"},n,t,function(e,t){return e?r(e):void r(null,t.result.collections)})},n.prototype.listIndexes=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.listIndexes",t),this.query({controller:"index",action:"list"},{},e,function(e,r){t(e,e?void 0:r.result.indexes)})},n.prototype.disconnect=function(){var e;this.state="disconnected",this.network.close(),this.network=null;for(e in this.collections)this.collections.hasOwnProperty(e)&&delete this.collections[e]},n.prototype.getServerInfo=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.getServerInfo",t),this.query({controller:"server",action:"info"},{},e,function(e,r){return e?t(e):void t(null,r.result.serverInfo)})},n.prototype.refreshIndex=function(){var e,t,r;if(Array.prototype.slice.call(arguments).forEach(function(n){switch(typeof n){case"string":e=n;break;case"object":t=n;break;case"function":r=n}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.refreshIndex: index required");e=this.defaultIndex}return this.query({index:e,controller:"index",action:"refresh"},{},t,r),this},n.prototype.getAutoRefresh=function(){var e,t,r;if(Array.prototype.slice.call(arguments).forEach(function(n){switch(typeof n){case"string":e=n;break;case"object":t=n;break;case"function":r=n}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.getAutoRefresh: index required");e=this.defaultIndex}this.callbackRequired("Kuzzle.getAutoRefresh",r),this.query({index:e,controller:"index",action:"getAutoRefresh"},{},t,r)},n.prototype.setAutoRefresh=function(){var e,t,r,n;if(Array.prototype.slice.call(arguments).forEach(function(i){switch(typeof i){case"string":e=i;break;case"boolean":t=i;break;case"object":r=i;break;case"function":n=i}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.setAutoRefresh: index required");e=this.defaultIndex}if(void 0===t)throw new Error("Kuzzle.setAutoRefresh: autoRefresh value is required");return this.query({index:e,controller:"index",action:"setAutoRefresh"},{body:{autoRefresh:t}},r,n),this},n.prototype.now=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.now",t),this.query({controller:"server",action:"now"},{},e,function(e,r){t(e,r&&r.result.now)})},n.prototype.query=function(e,t,r,n){var o,u={action:e.action,controller:e.controller,metadata:this.metadata},l=this;if(this.isValid(),n||"function"!=typeof r||(n=r,r=null),r){if(r.queuable===!1&&"offline"===l.state)return l;r.refresh&&(u.refresh=r.refresh),"undefined"!=typeof r.from&&null!==r.from&&(u.from=r.from),r.size&&(u.size=r.size),r.scroll&&(u.scroll=r.scroll),r.scrollId&&(u.scrollId=r.scrollId),r.metadata&&Object.keys(r.metadata).forEach(function(e){u.metadata[e]=r.metadata[e]})}if(!t||"object"!=typeof t||Array.isArray(t))throw new Error("Invalid query parameter: "+t);t.metadata&&Object.keys(t.metadata).forEach(function(e){u.metadata[e]=t.metadata[e]});for(o in t)"metadata"!==o&&t.hasOwnProperty(o)&&(u[o]=t[o]);return u=l.addHeaders(u,this.headers),void 0===l.jwtToken||"auth"===u.controller&&"checkToken"===u.action||(u.jwt=l.jwtToken),e.collection&&(u.collection=e.collection),e.index&&(u.index=e.index),u.requestId||(u.requestId=f.v4()),"connected"===l.state||r&&r.queuable===!1?"connected"===l.state?s.call(this,u,n):a(u,n):l.queuing||r&&r.queuable===!0||["initializing","connecting"].indexOf(l.state)!==-1?(i.call(this,u,n),l.queueFilter&&!l.queueFilter(u)||(l.offlineQueue.push({ts:Date.now(),query:u,cb:n}),l.emitEvent("offlineQueuePush",{query:u,cb:n}))):a(u,n),l},n.prototype.removeAllListeners=function(e){var t=Object.keys(this.eventListeners),r=this;if(e){if(t.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+t.toString());this.eventListeners[e].listeners=[]}else t.forEach(function(e){r.eventListeners[e].listeners=[]});return this},n.prototype.removeListener=function(e,t){var r=Object.keys(this.eventListeners),n=this;if(r.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+r.toString());return this.eventListeners[e].listeners.forEach(function(r,i){r.id===t&&n.eventListeners[e].listeners.splice(i,1)}),this},n.prototype.replayQueue=function(){return"offline"===this.state||this.autoReplay||(i.call(this),u.call(this)),this},n.prototype.setDefaultIndex=function(e){if("string"!=typeof e)throw new Error("Invalid default index: ["+e+"] (an index name is expected)");if(0===e.length)throw new Error("Cannot set an empty index as the default index");return this.defaultIndex=e,this},n.prototype.setHeaders=function(e,t){var r=this;if("object"!=typeof e||Array.isArray(e))throw new Error("Expected a content object, received a "+typeof e);return t?r.headers=e:Object.keys(e).forEach(function(t){r.headers[t]=e[t]}),r},n.prototype.startQueuing=function(){return"offline"!==this.state||this.autoQueue||(this.queuing=!0),this},n.prototype.stopQueuing=function(){return"offline"!==this.state||this.autoQueue||(this.queuing=!1),this},e.exports=n},function(e,t){function r(e,t,r){if(!t)throw new Error("A security document must have an id");if(Object.defineProperties(this,{kuzzle:{value:e.kuzzle},Security:{value:e},id:{value:t,enumerable:!0},content:{value:{},writable:!0,enumerable:!0}}),r&&this.setContent(r,!0),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["delete","update"];return n&&i.indexOf(e)!==-1}})}r.prototype.setContent=function(e){return this.content=e,this},r.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e},r.prototype.delete=function(e,t){var r=this;e&&void 0===t&&"function"==typeof e&&(t=e,e=null),r.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName),{_id:this.id},e,function(e,r){return e?!!t&&t(e):void(t&&t(null,r.result._id))})},r.prototype.update=function(e,t,r){var n={},i=this;if("object"!=typeof e)throw new Error('Parameter "content" must be a object');return t&&void 0===r&&"function"==typeof t&&(r=t,t=null),n._id=i.id,n.body=e,i.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName),n,t,function(e,t){return e?!!r&&r(e):(i.setContent(t.result._source),void(r&&r(null,i)))}),this},e.exports=r},function(e,t){function r(e,t,r){return Object.defineProperties(this,{collection:{value:e.collection,enumerable:!0},dataCollection:{value:e,enumerable:!1},kuzzle:{value:e.kuzzle,enumerable:!1},id:{value:void 0,enumerable:!0,writable:!0},content:{value:{},writable:!0,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0},version:{value:void 0,enumerable:!0,writable:!0}}),!r&&t&&"object"==typeof t&&(r=t,t=null),r&&(r._version&&(this.version=r._version,delete r._version),this.setContent(r,!0)),t&&Object.defineProperty(this,"id",{value:t,enumerable:!0}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["delete","refresh","save"];return n&&i.indexOf(e)!==-1}}):this}r.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e._version=this.version,e=this.kuzzle.addHeaders(e,this.headers)},r.prototype.toString=function(){return JSON.stringify(this.serialize())},r.prototype.delete=function(e,t){var r=this;if(t||"function"!=typeof e||(t=e,e=null),!r.id)throw new Error("Document.delete: cannot delete a document without a document ID");this.kuzzle.query(this.dataCollection.buildQueryArgs("document","delete"),this.serialize(),e,t&&function(e){t(e,e?void 0:r.id)})},r.prototype.refresh=function(e,t){var n=this;if(t||"function"!=typeof e||(t=e,e=null),!n.id)throw new Error("Document.refresh: cannot retrieve a document if no ID has been provided");this.kuzzle.callbackRequired("Document.refresh",t),n.kuzzle.query(n.dataCollection.buildQueryArgs("document","get"),{_id:n.id},e,function(e,i){var o;return e?t(e):(o=new r(n.dataCollection,n.id,i.result._source),o.version=i.result._version,void t(null,o))})},r.prototype.save=function(e,t){var r=this.serialize(),n=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),n.kuzzle.query(this.dataCollection.buildQueryArgs("document","createOrReplace"),r,e,function(e,r){return e?t&&t(e):(n.id=r.result._id,n.version=r.result._version,void(t&&t(null,n)))}),n},r.prototype.publish=function(e){var t=this.serialize();return this.kuzzle.query(this.dataCollection.buildQueryArgs("realtime","publish"),t,e),this},r.prototype.setContent=function(e,t){var r=this;return t?this.content=e:Object.keys(e).forEach(function(t){r.content[t]=e[t]}),this},r.prototype.subscribe=function(e,t){var r;if(e&&!t&&"function"==typeof e&&(t=e,e=null),this.kuzzle.callbackRequired("Document.subscribe",t),!this.id)throw new Error("Document.subscribe: cannot subscribe to a document if no ID has been provided");return r={ids:{values:[this.id]}},this.dataCollection.subscribe(r,e,t)},r.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=r},function(e,t,r){function n(e,t,n){var s=this;this.WebSocket="undefined"!=typeof WebSocket?WebSocket:r(!function(){var e=new Error('Cannot find module "ws"');throw e.code="MODULE_NOT_FOUND",e}()),this.host=e,this.port=t,this.ssl=n,this.client=null,this.wasConnected=!1,this.retrying=!1,this.lasturl=null,this.listeners={error:[],connect:[],disconnect:[],reconnect:[]},this.connect=function(e,t){var r=(this.ssl?"wss://":"ws://")+this.host+":"+this.port,n="undefined"!=typeof window?void 0:{perMessageDeflate:!1};r!==this.lasturl&&(s.wasConnected=!1,this.lasturl=r),this.client=new this.WebSocket(r,n),this.client.onopen=function(){s.wasConnected?i(s.listeners,"reconnect"):i(s.listeners,"connect"),s.wasConnected=!0},this.client.onclose=function(r,n){1e3===r?i(s.listeners,"disconnect"):o.call(s,e,t,n)},this.client.onerror=function(r){o.call(s,e,t,r)},this.client.onmessage=function(e){var t=JSON.parse(e.data||e);t.room&&s.listeners[t.room]?i(s.listeners,t.room,t):s.listeners.discarded&&i(s.listeners,"discarded",t)}},this.onConnect=function(e){this.listeners.connect.push({fn:e,keep:!0})},this.onConnectError=function(e){this.listeners.error.push({fn:e,keep:!0})},this.onDisconnect=function(e){this.listeners.disconnect.push({fn:e,keep:!0})},this.onReconnect=function(e){this.listeners.reconnect.push({fn:e,keep:!0})},this.once=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push({fn:t,keep:!1})},this.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push({fn:t,keep:!0})},this.off=function(e,t){var r=-1;this.listeners[e]&&(this.listeners[e].some(function(e,n){return e.fn===t&&(r=n,!0)}),r!==-1&&(1===this.listeners[e].length&&["error","connect","disconnect","reconnect"].indexOf(e)===-1?delete this.listeners[e]:this.listeners[e].splice(r,1)))},this.send=function(e){this.client&&this.client.readyState===this.client.OPEN&&this.client.send(JSON.stringify(e))},this.close=function(){this.listeners={error:[],connect:[],disconnect:[],reconnect:[]},this.wasConnected=!1,this.client.close(),this.client=null}}function i(e,t,r){var n,i=e[t].length;for(n=0;n1?(e[t].splice(n,1),--n,--i):delete e[t])}function o(e,t,r){var n=this;e&&!n.retrying&&(n.retrying=!0,setTimeout(function(){n.retrying=!1,n.connect(e,t)},t)),i(n.listeners,"error",r)}e.exports=n},function(e,t,r){function n(e,t,r){if(i.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteUser"},updateActionName:{value:"updateUser"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["save","saveRestricted"];return n&&i.indexOf(e)!==-1}})}var i=r(1);n.prototype=Object.create(i.prototype,{constructor:{value:n}}),n.prototype.setProfiles=function(e){if(!Array.isArray(e)||"string"!=typeof e[0])throw new Error('Parameter "profileIds" must be an array of strings');return this.content.profileIds=e,this},n.prototype.addProfile=function(e){if("string"!=typeof e)throw new Error('Parameter "profileId" must be a string');return this.content.profileIds||(this.content.profileIds=[]),this.content.profileIds.indexOf(e)===-1&&this.content.profileIds.push(e),this},n.prototype.save=function(e,t){var r=this.serialize(),n=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),n.kuzzle.query(this.Security.buildQueryArgs("createOrReplaceUser"),r,e,t&&function(e){t(e,e?void 0:n)}),n},n.prototype.saveRestricted=function(e,t){var r=this.serialize(),n=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),n.kuzzle.query(this.Security.buildQueryArgs("createRestrictedUser"),r,e,t&&function(e){t(e,e?void 0:n)}),n},n.prototype.serialize=function(){return{_id:this.id,body:this.content}},n.prototype.getProfiles=function(){return this.content.profileIds},e.exports=n},function(e,t,r){var n=r(19),i=r(20),o=i;o.v1=n,o.v4=i,e.exports=o},function(e,t){function r(e,t){var r=t||0,i=n;return i[e[r++]]+i[e[r++]]+i[e[r++]]+i[e[r++]]+"-"+i[e[r++]]+i[e[r++]]+"-"+i[e[r++]]+i[e[r++]]+"-"+i[e[r++]]+i[e[r++]]+"-"+i[e[r++]]+i[e[r++]]+i[e[r++]]+i[e[r++]]+i[e[r++]]+i[e[r++]]}for(var n=[],i=0;i<256;++i)n[i]=(i+256).toString(16).substr(1);e.exports=r},function(e,t,r){var n,i=window.crypto||window.msCrypto;if(i&&i.getRandomValues){var o=new Uint8Array(16);n=function(){return i.getRandomValues(o),o}}if(!n){var s=new Array(16);n=function(){for(var e,t=0;t<16;t++)0===(3&t)&&(e=4294967296*Math.random()),s[t]=e>>>((3&t)<<3)&255;return s}}e.exports=n},function(e,t,r){function n(e,t,r){if(!r||!t)throw new Error("The Collection object constructor needs an index and a collection arguments");return Object.defineProperties(this,{collection:{value:t,enumerable:!0},index:{value:r,enumerable:!0},kuzzle:{value:e,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0}}),Object.defineProperty(this,"buildQueryArgs",{value:function(e,t){return{controller:e,action:t,collection:this.collection,index:this.index}}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["publishMessage","setHeaders","subscribe"];return n&&i.indexOf(e)===-1}}):this}var i=r(12),o=r(2),s=r(9),u=r(11),l=r(13);n.prototype.count=function(e,t,r){var n;r||"function"!=typeof t||(r=t,t=null),this.kuzzle.callbackRequired("Collection.count",r),n=this.kuzzle.addHeaders({body:e},this.headers),this.kuzzle.query(this.buildQueryArgs("document","count"),n,t,function(e,t){r(e,t&&t.result.count)})},n.prototype.create=function(e,t){var r={};return t||"function"!=typeof e||(t=e,e=null),r=this.kuzzle.addHeaders(r,this.headers),this.kuzzle.query(this.buildQueryArgs("collection","create"),r,e,t),this},n.prototype.createDocument=function(e,t,r,n){var i=this,s={},u="create";return e&&"string"!=typeof e&&(n=r,r=t,t=e,e=null),n||"function"!=typeof r||(n=r,r=null),t instanceof o?s=t.serialize():s.body=t,r&&(u=r.updateIfExist?"createOrReplace":"create"),e&&(s._id=e),s=i.kuzzle.addHeaders(s,i.headers),i.kuzzle.query(this.buildQueryArgs("document",u),s,r,n&&function(e,t){var r;return e?n(e):(r=new o(i,t.result._id,t.result._source),r.version=t.result._version,void n(null,r))}),this},n.prototype.deleteDocument=function(e,t,r){var n,i={};return"string"==typeof e?(i._id=e,n="delete"):(i.body=e,n="deleteByQuery"),r||"function"!=typeof t||(r=t,t=null),i=this.kuzzle.addHeaders(i,this.headers),this.kuzzle.query(this.buildQueryArgs("document",n),i,t,r&&function(e,t){e?r(e):r(null,"delete"===n?[t.result._id]:t.result.ids)}),this},n.prototype.fetchDocument=function(e,t,r){var n={_id:e},i=this;r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Collection.fetch",r),n=i.kuzzle.addHeaders(n,this.headers),i.kuzzle.query(this.buildQueryArgs("document","get"),n,t,function(e,t){var n;return e?r(e):(n=new o(i,t.result._id,t.result._source),n.version=t.result._version,void r(null,n))})},n.prototype.fetchAllDocuments=function(e,t){var r=!1,n=[],o={};t||"function"!=typeof e||(t=e,e={}),e||(e={}),e.from||(e.from=0),e.size||(e.size=1e3),this.kuzzle.callbackRequired("Collection.fetchAllDocuments",t),this.search(o,e,function e(o,s){return o?t(o):void(s instanceof i?(s.total>1e4&&!r&&(r=!0,console.warn("Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead")),s.documents.forEach(function(e){n.push(e)}),s.next(e)):t(null,n))})},n.prototype.getMapping=function(e,t){var r;t||"function"!=typeof e||(t=e,e=null),this.kuzzle.callbackRequired("Collection.getMapping",t),r=new s(this),r.refresh(e,t)},n.prototype.publishMessage=function(e,t,r){var n={};return e instanceof o?n=e.serialize():n.body=e,n=this.kuzzle.addHeaders(n,this.headers),this.kuzzle.query(this.buildQueryArgs("realtime","publish"),n,t,r),this},n.prototype.replaceDocument=function(e,t,r,n){var i=this,s={_id:e,body:t};return n||"function"!=typeof r||(n=r,r=null),s=i.kuzzle.addHeaders(s,this.headers),i.kuzzle.query(this.buildQueryArgs("document","createOrReplace"),s,r,n&&function(e,t){var r;return e?n(e):(r=new o(i,t.result._id,t.result._source),r.version=t.result._version,void n(null,r))}),this},n.prototype.search=function(e,t,r){var n,s=this;r||"function"!=typeof t||(r=t,t={}),s.kuzzle.callbackRequired("Collection.search",r),n=s.kuzzle.addHeaders({body:e},this.headers),s.kuzzle.query(this.buildQueryArgs("document","search"),n,t,function(n,u){var l=[];return n?r(n):(u.result.hits.forEach(function(e){var t=new o(s,e._id,e._source);t.version=e._version,l.push(t)}),u.result._scroll_id&&(t.scrollId=u.result._scroll_id),void r(null,new i(s,u.result.total,l,u.result.aggregations?u.result.aggregations:[],{options:t,filters:e})))})},n.prototype.scroll=function(e,t,r,n){var s={},u=this;if(!e)throw new Error("Collection.scroll: scrollId is required");return n||(n=r,r=null),n||"function"!=typeof t||(n=t,t={}),this.kuzzle.callbackRequired("Collection.scroll",n),s.scrollId=e,t&&t.scroll&&(s.scroll=t.scroll),this.kuzzle.query({controller:"document",action:"scroll"},s,t,function(e,s){var l=[];return e?n(e):(s.result.hits.forEach(function(e){var t=new o(u,e._id,e._source);t.version=e._version,l.push(t)}),s.result._scroll_id&&(t.scrollId=s.result._scroll_id),void n(null,new i(u,s.result.total,l,s.result.aggregations?s.result.aggregations:[],{options:t,filters:r})))}),this},n.prototype.subscribe=function(e,t,r){var n,i;return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.callbackRequired("Collection.subscribe",r),i=new l,n=new u(this,t),n.renew(e,r,i.done.bind(i)),i},n.prototype.truncate=function(e,t){var r={};return t||"function"!=typeof e||(t=e,e=null),r=this.kuzzle.addHeaders(r,this.headers),this.kuzzle.query(this.buildQueryArgs("collection","truncate"),r,e,t),this},n.prototype.updateDocument=function(e,t,r,n){var i={_id:e,body:t},s=this;return n||"function"!=typeof r||(n=r,r=null),i=s.kuzzle.addHeaders(i,this.headers),s.kuzzle.query(this.buildQueryArgs("document","update"),i,r,n&&function(e,t){return e?n(e):void new o(s,t.result._id).refresh(n)}),s},n.prototype.document=function(e,t){return new o(this,e,t)},n.prototype.room=function(e){return new u(this,e)},n.prototype.collectionMapping=function(e){return new s(this,e)},n.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=n},function(e,t){function r(e,t){return Object.defineProperties(this,{collection:{value:e,enumerable:!0},kuzzle:{value:e.kuzzle,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)), -enumerable:!0,writable:!0},mapping:{value:t||{},enumerable:!0,writable:!0}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["set","setHeaders"];return n&&i.indexOf(e)===-1}}):this}r.prototype.apply=function(e,t){var r=this,n=this.kuzzle.addHeaders({body:{properties:this.mapping}},this.headers);return t||"function"!=typeof e||(t=e,e=null),r.kuzzle.query(this.collection.buildQueryArgs("collection","updateMapping"),n,e,function(n){return n?t&&t(n):void r.refresh(e,t)}),this},r.prototype.refresh=function(e,t){var r=this,n=this.kuzzle.addHeaders({},this.headers);return t||"function"!=typeof e||(t=e,e=null),this.kuzzle.query(this.collection.buildQueryArgs("collection","getMapping"),n,e,function(e,n){return e?!!t&&t(e):n.result[r.collection.index]?n.result[r.collection.index].mappings[r.collection.collection]?(r.mapping=n.result[r.collection.index].mappings[r.collection.collection].properties,void 0===r.mapping&&(r.mapping={}),void(t&&t(null,r))):t&&t(new Error("No mapping found for collection "+r.collection.collection)):t&&t(new Error("No mapping found for index "+r.collection.index))}),this},r.prototype.set=function(e,t){return this.mapping[e]=t,this},r.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=r},function(e,t){function r(e){return Object.defineProperties(this,{kuzzle:{value:e,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0}}),this.setHeaders=e.setHeaders.bind(this),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["setHeaders"];return n&&i.indexOf(e)===-1}}):this}!function(){var e=["id","value"],t=["id","keys"],n={append:e,bgrewriteaof:[],bgsave:[],bitcount:["id","start","end"],bitop:["operation","destkey",t],bitpos:["id","bit",{__opts__:["start","end"]}],blpop:[t,"timeout"],brpoplpush:["source","destination"],dbsize:[],decrby:e,del:[t],discard:[],exec:[],exists:[t],expire:["id","seconds"],expireat:["id","timestamp"],flushdb:[],getbit:["id","offset"],getrange:["id","start","end"],hdel:["id",["field","fields"]],hexists:["id","field"],hincrby:["id","field","value"],hmset:["id","values"],hset:["id","field","value"],info:["section"],keys:["pattern"],lastsave:[],lindex:["id","idx"],linsert:["id","position","pivot","value"],lpush:["id",["value","values"]],lrange:["id","start","stop"],lrem:["id","count","value"],lset:["id","idx","value"],ltrim:["id","start","stop"],mset:["values"],multi:[],object:["subcommand","args"],pexpire:["id","milliseconds"],pexpireat:["id","timestamp"],pfadd:["id",["element","elements"]],pfmerge:["destkey",["sourcekey","sourcekeys"]],ping:[],psetex:["id","milliseconds","value"],publish:["channel","message"],randomkey:[],rename:["id","newkey"],renamenx:["id","newkey"],restore:["id","ttl","content"],rpoplpush:["source","destination"],sadd:["id",["member","members"]],save:[],set:["id","value",{__opts__:["ex","px","nx","xx"]}],sdiffstore:["destination",t],setbit:["id","offset","value"],setex:["id","seconds","value"],setrange:["id","offset","value"],sinterstore:["destination",t],sismember:["id","member"],smove:["id","destination","member"],sort:["id",{__opts__:["by","offset","count","get","direction","alpha","store"]}],spop:["id","count"],srem:["id",["member","members"]],sunionstore:["destination",t],unwatch:[],wait:["numslaves","timeout"],zadd:["id",{__opts__:["nx","xx","ch","incr","score","member","members"]}],zcount:["id","min","max"],zincrby:["id","value","member"],zinterstore:["destination",t,{__opts__:["weight","weights","aggregate"]}],zlexcount:["id","min","max"],zrange:["id","start","stop",{__opts__:["withscores"]}],zrangebylex:["id","min","max",{__opts__:["offset","count"]}],zrangebyscore:["id","min","max",{__opts__:["withscores","offset","count"]}],zrem:["id","member"],zremrangebylex:["id","min","max"],zremrangebyscore:["id","min","max"],zrevrangebylex:["id","max","min",{__opts__:["offset","count"]}],zrevrangebyscore:["id","max","min",{__opts__:["withscores","offset","count"]}],zrevrank:["id","member"]};n.decr=n.get=n.dump=n.hgetall=n.hkeys=n.hlen=n.hstrlen=n.hvals=n.incr=n.llen=n.lpop=n.persist=n.pttl=n.rpop=n.scard=n.smembers=n.strlen=n.ttl=n.type=n.zcard=["id"],n.getset=n.lpushx=e,n.del=n.exists=n.mget=n.pfcount=n.sdiff=n.sinter=n.sunion=n.watch=[t],n.incrby=n.incrbyfloat=n.decrby,n.brpop=n.blpop,n.hget=n.hexists,n.hmget=n.hdel,n.hsetnx=n.hset,n.msetnx=n.mset,n.rpush=n.lpush,n.hincrbyfloat=n.hincrby,n.srandmember=n.spop,n.zrevrange=n.zrange,n.zscore=n.zrevrank,Object.keys(n).forEach(function(e){r.prototype[e]=function(){var t,r=Array.prototype.slice.call(arguments),i=null,o={controller:"ms",action:e},s={};return"function"==typeof r[r.length-1]&&(t=r.pop()),r.length&&"object"==typeof r[r.length-1]&&1===Object.keys(r[r.length-1]).length&&void 0!==r[r.length-1].queuable&&(i=r.pop()),n[e].forEach(function(e,t){void 0!==r[t]&&(Array.isArray(e)&&(e=Array.isArray(r[t])?e[1]:e[0]),"id"===e?s._id=r[t]:(s.body||(s.body={}),"object"==typeof e&&void 0!==e.__opts__?e.__opts__.forEach(function(e){void 0!==r[t][e]&&(s.body[e]=r[t][e])}):s.body[e]=r[t]))}),this.kuzzle.query(o,s,i,t),this}})}(),e.exports=r},function(e,t,r){function n(e,t){return Object.defineProperties(this,{callback:{value:null,writable:!0},channel:{value:null,writable:!0},id:{value:u.v4()},lastRenewal:{value:null,writable:!0},notifier:{value:null,writable:!0},onDoneCB:{value:null,writable:!0},queue:{value:[],writable:!0},renewalDelay:{value:500},scope:{value:t&&t.scope?t.scope:"all"},state:{value:t&&t.state?t.state:"done"},subscribing:{value:!1,writable:!0},users:{value:t&&t.users?t.users:"none"},collection:{value:e,enumerable:!0},kuzzle:{value:e.kuzzle,enumerable:!0},filters:{value:null,enumerable:!0,writable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0},metadata:{value:t&&t.metadata?t.metadata:{},enumerable:!0,writable:!0},roomId:{value:null,enumerable:!0,writable:!0},subscribeToSelf:{value:!t||"boolean"!=typeof t.subscribeToSelf||t.subscribeToSelf,enumerable:!0,writable:!0}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["count"];return n&&i.indexOf(e)!==-1}}):this}function i(e){return e.error?this.callback(e.error):"jwtTokenExpired"===e.action?(this.kuzzle.jwtToken=void 0,this.kuzzle.emitEvent("jwtTokenExpired")):("document"===e.controller||"realtime"===e.controller&&"publish"===e.action?(e.type="document",e.document=new l(this.collection,e.result._id,e.result._source),delete e.result):"realtime"===e.controller&&(e.type="user",e.user={count:e.result.count},delete e.result),void(this.kuzzle.requestHistory[e.requestId]?(this.subscribeToSelf&&this.callback(null,e),delete this.kuzzle.requestHistory[e.requestId]):this.callback(null,e)))}function o(){for(var e;this.queue.length>0;)e=this.queue.shift(),this[e.action].apply(this,e.args)}function s(){return"connected"===this.kuzzle.state&&!this.subscribing}var u=r(5),l=r(2);n.prototype.count=function(e){var t;if(this.kuzzle.callbackRequired("Room.count",e),t=this.kuzzle.addHeaders({body:{roomId:this.roomId}},this.headers),!s.call(this))return void this.queue.push({action:"count",args:[e]});if(!this.roomId)throw new Error("Room.count: cannot count subscriptions on an inactive room");this.kuzzle.query(this.collection.buildQueryArgs("realtime","count"),t,function(t,r){e(t,r&&r.result.count)})},n.prototype.renew=function(e,t,r){var n=Date.now(),s={scope:this.scope,state:this.state,users:this.users},u=this;return"function"==typeof e&&(r=t,t=e,e=null),r||(r=u.onDoneCB),u.kuzzle.callbackRequired("Room.renew",t),u.lastRenewal&&n-u.lastRenewal<=u.renewalDelay?r&&r(new Error("Subscription already renewed less than "+u.renewalDelay+"ms ago")):(e&&(u.filters=e),"connected"!==u.kuzzle.state?(u.callback=t,u.onDoneCB=r,void(u.kuzzle.subscriptions.pending[u.id]=u)):u.subscribing?void u.queue.push({action:"renew",args:[e,t,r]}):(u.unsubscribe(),u.roomId=null,u.subscribing=!0,u.callback=t,u.onDoneCB=r,u.kuzzle.subscriptions.pending[u.id]=u,s.body=u.filters,s=u.kuzzle.addHeaders(s,this.headers),void u.kuzzle.query(u.collection.buildQueryArgs("realtime","subscribe"),s,{metadata:u.metadata},function(e,t){return delete u.kuzzle.subscriptions.pending[u.id],u.subscribing=!1,e?(u.queue=[],r&&r(new Error("Error during Kuzzle subscription: "+e.message))):(u.lastRenewal=n,u.roomId=t.result.roomId,u.channel=t.result.channel,u.kuzzle.subscriptions[u.roomId]||(u.kuzzle.subscriptions[u.roomId]={}),u.kuzzle.subscriptions[u.roomId][u.id]=u,u.notifier=i.bind(u),u.kuzzle.network.on(u.channel,u.notifier),o.call(u),void(r&&r(null,u)))})))},n.prototype.unsubscribe=function(){var e,t=this,r=t.roomId;return s.call(this)?(r&&(t.kuzzle.network.off(t.channel,this.notifier),1===Object.keys(t.kuzzle.subscriptions[r]).length?(delete t.kuzzle.subscriptions[r],0===Object.keys(t.kuzzle.subscriptions.pending).length?t.kuzzle.query(t.collection.buildQueryArgs("realtime","unsubscribe"),{body:{roomId:r}}):e=setInterval(function(){0===Object.keys(t.kuzzle.subscriptions.pending).length&&(t.kuzzle.subscriptions[r]||t.kuzzle.query(t.collection.buildQueryArgs("realtime","unsubscribe"),{body:{roomId:r}}),clearInterval(e))},100)):delete t.kuzzle.subscriptions[r][t.id],t.roomId=null),t):(t.queue.push({action:"unsubscribe",args:[]}),t)},n.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=n},function(e,t){function r(e,t,n,i,o,s){return Object.defineProperties(this,{dataCollection:{value:e},total:{value:t,enumerable:!0},documents:{value:n,enumerable:!0},aggregations:{value:i||{},enumerable:!0},searchArgs:{value:o||{},enumerable:!0},fetchedDocument:{value:n.length,enumerable:!0,writable:!0},_previous:{value:s||null,writable:!0},_next:{value:null,writable:!0}}),this._previous instanceof r&&(this._previous._next=this,this.fetchedDocument+=this._previous.fetchedDocument),this.dataCollection.kuzzle.bluebird?this.dataCollection.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["previous","next"];return n&&i.indexOf(e)!==-1}}):this}function n(e,t,r,n){return e?void n(e):(r.fetchedDocument+=t.fetchedDocument,r._previous=t,t._next=r,void n(null,r))}r.prototype.previous=function(e){return e(null,this._previous),this},r.prototype.next=function(e){var t,i=Object.assign({},this.searchArgs.options),o=this;if(!this._next){if(i.scrollId)return this.fetchedDocument>=this.total?void e(null,null):("undefined"!=typeof i.from&&delete i.from,i.size&&delete i.size,void this.dataCollection.scroll(i.scrollId,i,this.searchArgs.filters||{},function(t,r){n(t,o,r,e)}));if(void 0!==i.from&&void 0!==i.size)return t=Object.assign({},this.searchArgs.filters),i.from+=i.size,i.from>=this.total?void e(null,null):void this.dataCollection.search(t,i,function(t,r){n(t,o,r,e)})}return this._next instanceof r?void e(null,this._next):void e(new Error("Unable to retrieve next results from search: missing scrollId or from/size params"))},e.exports=r},function(e,t){function r(){this.cbs=[],this.error=null,this.room=null}r.prototype.onDone=function(e){return this.error||this.room?e(this.error,this.room):this.cbs.push(e),this},r.prototype.done=function(e,t){this.error=e,this.room=t,this.cbs.forEach(function(r){r(e,t)})},e.exports=r},function(e,t,r){function n(e,t,n){if("undefined"!=typeof window){if("undefined"!=typeof WebSocket)return new(r(3))(e,t,n);if(window.io)return new(r(15))(e,t,n);throw new Error("Aborting: no websocket support detected and no socket.io library loaded either.")}return new(r(3))(e,t,n)}e.exports=n},function(e,t){function r(e,t,r){this.host=e,this.port=t,this.ssl=r,this.socket=null,this.connect=function(e,t){this.socket=window.io((this.ssl?"https://":"http://")+this.host+":"+this.port,{reconnection:e,reconnectionDelay:t,forceNew:!0})},this.onConnect=function(e){this.socket.on("connect",e)},this.onConnectError=function(e){this.socket.on("connect_error",e)},this.onDisconnect=function(e){this.socket.on("disconnect",e)},this.onReconnect=function(e){this.socket.on("reconnect",e)},this.once=function(e,t){this.socket.once(e,t)},this.on=function(e,t){this.socket.on(e,t)},this.off=function(e,t){this.socket.off(e,t)},this.send=function(e){this.socket.emit("kuzzle",e)},this.close=function(){this.socket.close(),this.socket=null}}e.exports=r},function(e,t,r){function n(e,t,r){if(i.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteProfile"},updateActionName:{value:"updateProfile"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["hydrate","save"];return n&&i.indexOf(e)!==-1}})}var i=r(1);n.prototype=Object.create(i.prototype,{constructor:{value:n}}),n.prototype.save=function(e,t){var r,n=this;if(!this.content.policies)throw new Error('Argument "policies" is mandatory in a profile. This argument contains an array of objects.');return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),r=this.serialize(),n.kuzzle.query(n.Security.buildQueryArgs("createOrReplaceProfile"),r,e,t&&function(e){t(e,e?void 0:n)}),n},n.prototype.addPolicy=function(e){if("object"!=typeof e||"string"!=typeof e.roleId)throw new Error('Parameter "policies" must be an object containing at least a "roleId" member which must be a string.');return this.content.policies||(this.content.policies=[]),this.content.policies.push(e),this},n.prototype.setPolicies=function(e){if(!Array.isArray(e))throw new Error('Parameter "policies" must be an array of objects containing at least a "roleId" member which must be a string');return e.map(function(e){if("object"!=typeof e||"string"!=typeof e.roleId)throw new Error('Parameter "policies" must be an array of objects containing at least a "roleId" member which must be a string')}),this.content.policies=e,this},n.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e},n.prototype.getPolicies=function(){return this.content.policies},e.exports=n},function(e,t,r){function n(e,t,r){if(i.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteRole"},updateActionName:{value:"updateRole"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["save"];return n&&i.indexOf(e)!==-1}})}var i=r(1);n.prototype=Object.create(i.prototype,{constructor:{value:n}}),n.prototype.save=function(e,t){var r=this.serialize(),n=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),n.kuzzle.query(this.Security.buildQueryArgs("createOrReplaceRole"),r,e,t&&function(e){t(e,e?void 0:n)}),this},e.exports=n},function(e,t,r){function n(e){return Object.defineProperty(this,"kuzzle",{value:e}),Object.defineProperty(this,"buildQueryArgs",{value:function(e){return{controller:"security",action:e}}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,n){var i=["role","profile","user","isActionAllowed"];return n&&i.indexOf(e)===-1}}):this}var i=r(17),o=r(16),s=r(4);n.prototype.fetchRole=function(e,t,r){var n,o=this;if(!e)throw new Error("Id parameter is mandatory for fetchRole function");r||"function"!=typeof t||(r=t,t=null),n={_id:e},o.kuzzle.callbackRequired("Security.fetchRole",r),o.kuzzle.query(this.buildQueryArgs("getRole"),n,t,function(e,t){r(e,e?void 0:new i(o,t.result._id,t.result._source))})},n.prototype.searchRoles=function(e,t,r){var n=this;r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Security.searchRoles",r),n.kuzzle.query(this.buildQueryArgs("searchRoles"),{body:e},t,function(e,t){var o;return e?r(e):(o=t.result.hits.map(function(e){return new i(n,e._id,e._source)}),void r(null,{total:t.result.total,roles:o}))})},n.prototype.createRole=function(e,t,r,n){var o=this,s={},u="createRole";if(!e||"string"!=typeof e)throw new Error("Security.createRole: cannot create a role without a role ID");n||"function"!=typeof r||(n=r,r=null),s._id=e,s.body=t,r&&(u=r.replaceIfExist?"createOrReplaceRole":"createRole"),o.kuzzle.query(this.buildQueryArgs(u),s,r,n&&function(e,t){n(e,e?void 0:new i(o,t.result._id,t.result._source))})},n.prototype.updateRole=function(e,t,r,n){var o=this,s={_id:e,body:t},u="updateRole";if(!e||"string"!=typeof e)throw new Error("Security.updateRole: cannot update a role without a role ID");return n||"function"!=typeof r||(n=r,r=null),o.kuzzle.query(this.buildQueryArgs(u),s,r,n&&function(r){n(r,r?void 0:new i(o,e,t))}),this},n.prototype.deleteRole=function(e,t,r){var n={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteRole"),n,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},n.prototype.role=function(e,t){return new i(this,e,t)},n.prototype.fetchProfile=function(e,t,r){var n,i=this;if(r||"function"!=typeof t||(r=t,t=null),!e||"string"!=typeof e)throw new Error("Id parameter is mandatory for fetchProfile function");n={_id:e},i.kuzzle.callbackRequired("Security.fetchProfile",r),i.kuzzle.query(this.buildQueryArgs("getProfile"),n,t,function(e,t){r(e,e?void 0:new o(i,t.result._id,t.result._source))})},n.prototype.searchProfiles=function(e,t,r){var n=this;r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Security.searchProfiles",r),n.kuzzle.query(this.buildQueryArgs("searchProfiles"),{body:e},t,function(e,t){var i;return e?r(e):(i=t.result.hits.map(function(e){return new o(n,e._id,e._source)}),void r(null,{total:t.result.total,profiles:i}))})},n.prototype.createProfile=function(e,t,r,n){var i=this,s={},u="createProfile";if(!e||"string"!=typeof e)throw new Error("Security.createProfile: cannot create a profile without a profile ID");n||"function"!=typeof r||(n=r,r=null),s._id=e,s.body=t,r&&(u=r.replaceIfExist?"createOrReplaceProfile":"createProfile"),i.kuzzle.query(this.buildQueryArgs(u),s,r,n&&function(e,t){n(e,e?void 0:new o(i,t.result._id,t.result._source))})},n.prototype.updateProfile=function(e,t,r,n){var i=this,s={},u="updateProfile";if(!e||"string"!=typeof e)throw new Error("Security.updateProfile: cannot update a profile without a profile ID");return n||"function"!=typeof r||(n=r,r=null),s._id=e,s.body=t,i.kuzzle.query(this.buildQueryArgs(u),s,r,n&&function(e,t){var r={};return e?n(e):(Object.keys(t.result._source).forEach(function(e){r[e]=t.result._source[e]}),void n(null,new o(i,t.result._id,r)))}),this},n.prototype.deleteProfile=function(e,t,r){var n={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteProfile"),n,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},n.prototype.profile=function(e,t){return new o(this,e,t)},n.prototype.fetchUser=function(e,t,r){var n={_id:e},i=this;if(!e||"string"!=typeof e)throw new Error("Id parameter is mandatory for fetchUser function");r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Security.fetchUser",r),i.kuzzle.query(this.buildQueryArgs("getUser"),n,t,function(e,t){r(e,e?void 0:new s(i,t.result._id,t.result._source))})},n.prototype.searchUsers=function(e,t,r){var n=this;r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Security.searchUsers",r),n.kuzzle.query(this.buildQueryArgs("searchUsers"),{body:e},t,function(e,t){var i;return e?r(e):(i=t.result.hits.map(function(e){return new s(n,e._id,e._source)}),void r(null,{total:t.result.total,users:i}))})},n.prototype.createUser=function(e,t,r,n){var i=this,o={_id:e,body:t},u="createUser";if(!e||"string"!=typeof e)throw new Error("Security.createUser: cannot create a user without a user ID");n||"function"!=typeof r||(n=r,r=null),r&&(u=r.replaceIfExist?"createOrReplaceUser":"createUser"),i.kuzzle.query(this.buildQueryArgs(u),o,null,n&&function(e,t){n(e,e?void 0:new s(i,t.result._id,t.result._source))})},n.prototype.createRestrictedUser=function(e,t,r,n){var i=this,o={_id:e,body:t};if(!e||"string"!=typeof e)throw new Error("Security.createRestrictedUser: cannot create a user without a user ID");if(t.profileIds)throw new Error("Security.createRestrictedUser: cannot provide profileIds");n||"function"!=typeof r||(n=r,r=null),i.kuzzle.query(this.buildQueryArgs("createRestrictedUser"),o,null,n&&function(e,t){n(e,e?void 0:new s(i,t.result._id,t.result._source))})},n.prototype.updateUser=function(e,t,r,n){var i=this,o={},u="updateUser";if(!e||"string"!=typeof e)throw new Error("Security.updateUser: cannot update an user without an user ID");return n||"function"!=typeof r||(n=r,r=null),o._id=e,o.body=t,i.kuzzle.query(this.buildQueryArgs(u),o,r,n&&function(e,t){n(e,e?void 0:new s(i,t.result._id,t.result._source))}),this},n.prototype.deleteUser=function(e,t,r){var n={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteUser"),n,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},n.prototype.user=function(e,t){return new s(this,e,t)},n.prototype.isActionAllowed=function(e,t,r,n,i){var o;if(!e||"object"!=typeof e)throw new Error("rights parameter is mandatory for isActionAllowed function");if(!t||"string"!=typeof t)throw new Error("controller parameter is mandatory for isActionAllowed function");if(!r||"string"!=typeof r)throw new Error("action parameter is mandatory for isActionAllowed function");return o=e.filter(function(e){return e.controller===t||"*"===e.controller}).filter(function(e){return e.action===r||"*"===e.action}).filter(function(e){return e.index===n||"*"===e.index}).filter(function(e){return e.collection===i||"*"===e.collection}),o.some(function(e){return"allowed"===e.value})?"allowed":o.some(function(e){return"conditional"===e.value})?"conditional":"denied"},n.prototype.getUserRights=function(e,t,r){var n={_id:e},i=this;if(!e||"string"!=typeof e)throw new Error("userId parameter is mandatory for getUserRights function");r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Kuzzle.getUserRights",r),this.kuzzle.query(this.buildQueryArgs("getUserRights"),n,t,r&&function(e,t){r(e,e?void 0:t.result.hits)})},e.exports=n},function(e,t,r){function n(e,t,r){var n=t&&r||0,i=t||[];e=e||{};var s=void 0!==e.clockseq?e.clockseq:l,f=void 0!==e.msecs?e.msecs:(new Date).getTime(),d=void 0!==e.nsecs?e.nsecs:a+1,h=f-c+(d-a)/1e4;if(h<0&&void 0===e.clockseq&&(s=s+1&16383),(h<0||f>c)&&void 0===e.nsecs&&(d=0),d>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");c=f,a=d,l=s,f+=122192928e5;var p=(1e4*(268435455&f)+d)%4294967296;i[n++]=p>>>24&255,i[n++]=p>>>16&255,i[n++]=p>>>8&255,i[n++]=255&p;var y=f/4294967296*1e4&268435455;i[n++]=y>>>8&255,i[n++]=255&y,i[n++]=y>>>24&15|16,i[n++]=y>>>16&255,i[n++]=s>>>8|128,i[n++]=255&s;for(var b=e.node||u,v=0;v<6;++v)i[n+v]=b[v];return t?t:o(i)}var i=r(7),o=r(6),s=i(),u=[1|s[0],s[1],s[2],s[3],s[4],s[5]],l=16383&(s[6]<<8|s[7]),c=0,a=0;e.exports=n},function(e,t,r){function n(e,t,r){var n=t&&r||0;"string"==typeof e&&(t="binary"==e?new Array(16):null,e=null),e=e||{};var s=e.random||(e.rng||i)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t)for(var u=0;u<16;++u)t[n+u]=s[u];return t||o(s)}var i=r(7),o=r(6);e.exports=n}])}); +/*! Kuzzle javascript SDK version 4.0.0 */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Kuzzle=t():e.Kuzzle=t()}(this,function(){return function(e){function t(i){if(r[i])return r[i].exports;var n=r[i]={exports:{},id:i,loaded:!1};return e[i].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){function i(e,t,r){var n=this;if(!(this instanceof i))return new i(e,t,r);if(r||"function"!=typeof t||(r=t,t=null),!e||""===e)throw new Error("host argument missing");return Object.defineProperties(this,{collections:{value:{},writable:!0},connectCB:{value:r},eventListeners:{value:{connected:{lastEmitted:null,listeners:[]},error:{lastEmitted:null,listeners:[]},disconnected:{lastEmitted:null,listeners:[]},reconnected:{lastEmitted:null,listeners:[]},jwtTokenExpired:{lastEmitted:null,listeners:[]},loginAttempt:{lastEmitted:null,listeners:[]},offlineQueuePush:{listeners:[]},offlineQueuePop:{listeners:[]},queryError:{listeners:[]},discarded:{listeners:[]}}},eventTimeout:{value:200},queuing:{value:!1,writable:!0},requestHistory:{value:{},writable:!0},state:{value:"initializing",writable:!0},subscriptions:{value:{pending:{}},writable:!0},autoReconnect:{value:!t||"boolean"!=typeof t.autoReconnect||t.autoReconnect,writable:!0,enumerable:!0},defaultIndex:{value:t&&"string"==typeof t.defaultIndex?t.defaultIndex:void 0,writable:!0,enumerable:!0},reconnectionDelay:{value:t&&"number"==typeof t.reconnectionDelay?t.reconnectionDelay:1e3,writable:!0,enumerable:!0},host:{value:e,writable:!0,enumerable:!0},port:{value:t&&"number"==typeof t.port?t.port:7512,enumerable:!0,writable:!0},sslConnection:{value:!(!t||"boolean"!=typeof t.sslConnection)&&t.sslConnection,writable:!0,enumerable:!0},autoQueue:{value:!1,enumerable:!0,writable:!0},autoReplay:{value:!1,enumerable:!0,writable:!0},autoResubscribe:{value:!0,enumerable:!0,writable:!0},headers:{value:{},enumerable:!0,writable:!0},volatile:{value:{},enumerable:!0,writable:!0},offlineQueue:{value:[],enumerable:!0,writable:!0},queueFilter:{value:null,enumerable:!0,writable:!0},queueMaxSize:{value:500,enumerable:!0,writable:!0},queueTTL:{value:12e4,enumerable:!0,writable:!0},replayInterval:{value:10,enumerable:!0,writable:!0},jwtToken:{value:void 0,enumerable:!0,writable:!0},offlineQueueLoader:{value:null,enumerable:!0,writable:!0}}),t&&(Object.keys(t).forEach(function(e){n.hasOwnProperty(e)&&Object.getOwnPropertyDescriptor(n,e).writable&&(n[e]=t[e])}),"auto"===t.offlineMode&&this.autoReconnect&&(this.autoQueue=this.autoReplay=this.autoResubscribe=!0)),Object.defineProperty(this,"isValid",{value:function(){if("disconnected"===n.state)throw new Error("This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?")}}),Object.defineProperty(this,"addHeaders",{value:function(e,t){return Object.keys(t).forEach(function(r){e[r]||(e[r]=t[r])}),e}}),Object.defineProperty(this,"callbackRequired",{value:function(e,t){if(!t||"function"!=typeof t)throw new Error(e+": a callback argument is required for read queries")}}),Object.defineProperty(this,"security",{value:new h(this),enumerable:!0}),Object.defineProperty(this,"emitEvent",{value:function(e){var t=Date.now(),r=Array.prototype.slice.call(arguments,1),i=this.eventListeners[e];return!(i.lastEmitted&&i.lastEmitted>=t-this.eventTimeout)&&(i.listeners.forEach(function(e){setTimeout(function(){e.fn.apply(void 0,r)},0)}),void(void 0!==i.lastEmitted&&(i.lastEmitted=t)))}}),Object.defineProperty(this,"memoryStorage",{value:new p(this),enumerable:!0}),t&&t.connect&&"auto"!==t.connect?this.state="ready":this.connect(),o(this.requestHistory),this.bluebird?this.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["getAllStatistics","getServerInfo","getStatistics","listCollections","listIndexes","login","logout","now","query","checkToken","whoAmI","updateSelf","getMyRights","refreshIndex","getAutoRefresh","setAutoRefresh"];return i&&n.indexOf(e)!==-1}}):void 0}function n(){var e=this,t=Date.now(),r=-1;e.queueTTL>0&&(e.offlineQueue.forEach(function(i,n){i.ts0&&e.offlineQueue.length>e.queueMaxSize&&e.offlineQueue.splice(0,e.offlineQueue.length-e.queueMaxSize).forEach(function(t){e.emitEvent("offlineQueuePop",t.query)})}function o(e){var t=Date.now();Object.keys(e).forEach(function(r){e[r]0?(s.call(t,t.offlineQueue[0].query,t.offlineQueue[0].cb),t.emitEvent("offlineQueuePop",t.offlineQueue.shift()),setTimeout(function(){i()},Math.max(0,t.replayInterval))):t.queuing=!1};if(t.offlineQueueLoader){if("function"!=typeof t.offlineQueueLoader)throw new Error("Invalid value for offlineQueueLoader property. Expected: function. Got: "+typeof t.offlineQueueLoader);if(e=t.offlineQueueLoader(),!Array.isArray(e))throw new Error("Invalid value returned by the offlineQueueLoader function. Expected: array. Got: "+typeof e);t.offlineQueue=e.concat(t.offlineQueue).filter(function(e){if(!e.query||void 0===e.query.requestId||!e.query.action||!e.query.controller)throw new Error("Invalid offline queue request. One or more missing properties: requestId, action, controller.");return!r.hasOwnProperty(e.query.requestId)&&(r[e.query.requestId]=!0)})}i()}function l(){var e=this;Object.keys(e.subscriptions).forEach(function(t){Object.keys(e.subscriptions[t]).forEach(function(r){var i=e.subscriptions[t][r];i.renew(i.callback)})})}function c(){var e=this;Object.keys(e.subscriptions).forEach(function(t){Object.keys(e.subscriptions[t]).forEach(function(r){var i=e.subscriptions[t][r];i.unsubscribe()})})}function a(e,t){t&&t(new Error("Unable to execute request: not connected to a Kuzzle server.\nDiscarded request: "+JSON.stringify(e)))}var d=r(5),f=r(8),h=r(18),p=r(10),y=r(4),b=r(14);i.prototype.connect=function(){var e=this;return e.network&&e.disconnect(),e.network=b(e.host,e.port,e.sslConnection),["initializing","ready","disconnected","error","offline"].indexOf(this.state)===-1?(e.connectCB&&e.connectCB(null,e),e):(e.state="connecting",e.network.connect(e.autoReconnect,e.reconnectionDelay),e.network.onConnect(function(){e.state="connected",l.call(e),u.call(e),e.emitEvent("connected"),e.connectCB&&e.connectCB(null,e)}),e.network.on("discarded",function(t){e.emitEvent("discarded",t)}),e.network.onConnectError(function(t){var r=new Error('Unable to connect to kuzzle proxy server at "'+e.host+'"');r.internal=t,e.state="error",e.emitEvent("error",r),e.connectCB&&e.connectCB(r)}),e.network.onDisconnect(function(){e.state="offline",e.autoReconnect||e.disconnect(),e.autoQueue&&(e.queuing=!0),e.emitEvent("disconnected")}),e.network.onReconnect(function(){var t=function(){e.autoResubscribe&&l.call(e),e.autoReplay&&(n.call(e),u.call(e)),e.emitEvent("reconnected")};e.state="connected",e.jwtToken?e.checkToken(e.jwtToken,function(r,i){!r&&i.valid||(e.jwtToken=void 0,e.emitEvent("jwtTokenExpired")),t()}):t()}),this)},i.prototype.setJwtToken=function(e){if("string"==typeof e)this.jwtToken=e;else{if("object"!=typeof e)return this.emitEvent("loginAttempt",{success:!1,error:"Invalid token argument: "+e}),this;if(!e.result||!e.result.jwt||"string"!=typeof e.result.jwt)return this.emitEvent("loginAttempt",{success:!1,error:"Cannot find a valid JWT token in the following object: "+JSON.stringify(e)}),this;this.jwtToken=e.result.jwt}return l.call(this),this.emitEvent("loginAttempt",{success:!0}),this},i.prototype.unsetJwtToken=function(){return this.jwtToken=void 0,c.call(this),this},i.prototype.getJwtToken=function(){return this.jwtToken},i.prototype.login=function(e){var t,r=this,i={strategy:e},n=null;arguments[1]&&("object"==typeof arguments[1]?t=arguments[1]:"number"==typeof arguments[1]||"string"==typeof arguments[1]?i.expiresIn=arguments[1]:"function"==typeof arguments[1]&&(n=arguments[1])),arguments[2]&&("number"==typeof arguments[2]||"string"==typeof arguments[2]?i.expiresIn=arguments[2]:"function"==typeof arguments[2]&&(n=arguments[2])),arguments[3]&&"function"==typeof arguments[3]&&(n=arguments[3]),"object"==typeof t&&Object.keys(t).forEach(function(e){i[e]=t[e]}),this.query({controller:"auth",action:"login"},{body:i},{queuable:!1},function(e,t){e?(n&&n(e),r.emitEvent("loginAttempt",{success:!1,error:e.message})):(t.result.jwt&&r.setJwtToken(t.result.jwt),n&&n(null,t.result))})},i.prototype.createIndex=function(e,t,r){if(!e){if(!this.defaultIndex)throw new Error("Kuzzle.createIndex: index required");e=this.defaultIndex}return r||"function"!=typeof t||(r=t,t=null),this.query({controller:"index",action:"create"},{index:e},t,"function"!=typeof r?null:r),this},i.prototype.logout=function(e){var t=this,r={action:"logout",controller:"auth",requestId:d.v4(),body:{}};return this.query({controller:"auth",action:"logout"},r,{queuable:!1},"function"!=typeof e?null:function(r){e(r,t)}),t.unsetJwtToken(),t},i.prototype.checkToken=function(e,t){var r={body:{token:e}};this.callbackRequired("Kuzzle.checkToken",t),this.query({controller:"auth",action:"checkToken"},r,{queuable:!1},function(e,r){return e?t(e):void t(null,r.result)})},i.prototype.whoAmI=function(e){var t=this;t.callbackRequired("Kuzzle.whoAmI",e),t.query({controller:"auth",action:"getCurrentUser"},{},{},function(r,i){return r?e(r):void e(null,new y(t.security,i.result._id,i.result._source))})},i.prototype.getMyRights=function(e,t){var r=this;t||"function"!=typeof e||(t=e,e=null),r.callbackRequired("Kuzzle.getMyRights",t),r.query({controller:"auth",action:"getMyRights"},{},e,function(e,r){return e?t(e):void t(null,r.result.hits)})},i.prototype.updateSelf=function(e,t,r){var i=this,n={},o={controller:"auth",action:"updateSelf"};return r||"function"!=typeof t||(r=t,t=null),n.body=e,i.query(o,n,t,r&&function(e,t){r(e,e?void 0:t.result)}),this},i.prototype.addListener=function(e,t){var r,i=Object.keys(this.eventListeners),n=typeof t;if(this.isValid(),i.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+i.toString());if("function"!==n)throw new Error("Invalid listener type: expected a function, got a "+n);return r=d.v4(),this.eventListeners[e].listeners.push({id:r,fn:t}),r},i.prototype.getAllStatistics=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.getAllStatistics",t),this.query({controller:"server",action:"getAllStats"},{},e,function(e,r){return e?t(e):void t(null,r.result.hits)})},i.prototype.getStatistics=function(e,t,r){var i,n;r||(1===arguments.length?(r=arguments[0],t=null,e=null):(r=arguments[1],"object"==typeof arguments[0]?(t=arguments[0],e=null):(e=arguments[0],t=null))),i=function(t,i){return t?r(t):void r(null,e?i.result.hits:[i.result])},this.callbackRequired("Kuzzle.getStatistics",r),n=e?{body:{startTime:e}}:{},this.query({controller:"server",action:e?"getStats":"getLastStats"},n,t,i)},i.prototype.collection=function(e,t){if(this.isValid(),!t){if(!this.defaultIndex)throw new Error("Unable to create a new data collection object: no index specified");t=this.defaultIndex}if("string"!=typeof t||"string"!=typeof e)throw new Error("Invalid index or collection argument: string expected");return this.collections[t]||(this.collections[t]={}),this.collections[t][e]||(this.collections[t][e]=new f(this,e,t)),this.collections[t][e]},i.prototype.flushQueue=function(){return this.offlineQueue=[],this},i.prototype.listCollections=function(){var e,t,r,i,n="all",o=Array.prototype.slice.call(arguments);if(o.forEach(function(i){switch(typeof i){case"string":e=i;break;case"object":t=i;break;case"function":r=i}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.listCollections: index required");e=this.defaultIndex}this.callbackRequired("Kuzzle.listCollections",r),t&&t.type&&(n=t.type),i={body:{type:n}},t&&t.from&&(i.body.from=t.from),t&&t.size&&(i.body.size=t.size),this.query({index:e,controller:"collection",action:"list"},i,t,function(e,t){return e?r(e):void r(null,t.result.collections)})},i.prototype.listIndexes=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.listIndexes",t),this.query({controller:"index",action:"list"},{},e,function(e,r){t(e,e?void 0:r.result.indexes)})},i.prototype.disconnect=function(){var e;this.state="disconnected",this.network.close(),this.network=null;for(e in this.collections)this.collections.hasOwnProperty(e)&&delete this.collections[e]},i.prototype.getServerInfo=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.getServerInfo",t),this.query({controller:"server",action:"info"},{},e,function(e,r){return e?t(e):void t(null,r.result.serverInfo)})},i.prototype.refreshIndex=function(){var e,t,r;if(Array.prototype.slice.call(arguments).forEach(function(i){switch(typeof i){case"string":e=i;break;case"object":t=i;break;case"function":r=i}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.refreshIndex: index required");e=this.defaultIndex}return this.query({index:e,controller:"index",action:"refresh"},{},t,r),this},i.prototype.getAutoRefresh=function(){var e,t,r;if(Array.prototype.slice.call(arguments).forEach(function(i){switch(typeof i){case"string":e=i;break;case"object":t=i;break;case"function":r=i}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.getAutoRefresh: index required");e=this.defaultIndex}this.callbackRequired("Kuzzle.getAutoRefresh",r),this.query({index:e,controller:"index",action:"getAutoRefresh"},{},t,r)},i.prototype.setAutoRefresh=function(){var e,t,r,i;if(Array.prototype.slice.call(arguments).forEach(function(n){switch(typeof n){case"string":e=n;break;case"boolean":t=n;break;case"object":r=n;break;case"function":i=n}}),!e){if(!this.defaultIndex)throw new Error("Kuzzle.setAutoRefresh: index required");e=this.defaultIndex}if(void 0===t)throw new Error("Kuzzle.setAutoRefresh: autoRefresh value is required");return this.query({index:e,controller:"index",action:"setAutoRefresh"},{body:{autoRefresh:t}},r,i),this},i.prototype.now=function(e,t){t||"function"!=typeof e||(t=e,e=null),this.callbackRequired("Kuzzle.now",t),this.query({controller:"server",action:"now"},{},e,function(e,r){t(e,r&&r.result.now)})},i.prototype.query=function(e,t,r,i){var o,u={action:e.action,controller:e.controller,volatile:this.volatile},l=this;if(this.isValid(),i||"function"!=typeof r||(i=r,r=null),r){if(r.queuable===!1&&"offline"===l.state)return l;r.refresh&&(u.refresh=r.refresh),"undefined"!=typeof r.from&&null!==r.from&&(u.from=r.from),r.size&&(u.size=r.size),r.scroll&&(u.scroll=r.scroll),r.scrollId&&(u.scrollId=r.scrollId),r.volatile&&Object.keys(r.volatile).forEach(function(e){u.volatile[e]=r.volatile[e]})}if(!t||"object"!=typeof t||Array.isArray(t))throw new Error("Invalid query parameter: "+t);t.volatile&&Object.keys(t.volatile).forEach(function(e){u.volatile[e]=t.volatile[e]});for(o in t)"volatile"!==o&&t.hasOwnProperty(o)&&(u[o]=t[o]);return u=l.addHeaders(u,this.headers),void 0===l.jwtToken||"auth"===u.controller&&"checkToken"===u.action||(u.jwt=l.jwtToken),e.collection&&(u.collection=e.collection),e.index&&(u.index=e.index),u.requestId||(u.requestId=d.v4()),"connected"===l.state||r&&r.queuable===!1?"connected"===l.state?s.call(this,u,i):a(u,i):l.queuing||r&&r.queuable===!0||["initializing","connecting"].indexOf(l.state)!==-1?(n.call(this,u,i),l.queueFilter&&!l.queueFilter(u)||(l.offlineQueue.push({ts:Date.now(),query:u,cb:i}),l.emitEvent("offlineQueuePush",{query:u,cb:i}))):a(u,i),l},i.prototype.removeAllListeners=function(e){var t=Object.keys(this.eventListeners),r=this;if(e){if(t.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+t.toString());this.eventListeners[e].listeners=[]}else t.forEach(function(e){r.eventListeners[e].listeners=[]});return this},i.prototype.removeListener=function(e,t){var r=Object.keys(this.eventListeners),i=this;if(r.indexOf(e)===-1)throw new Error("["+e+"] is not a known event. Known events: "+r.toString());return this.eventListeners[e].listeners.forEach(function(r,n){r.id===t&&i.eventListeners[e].listeners.splice(n,1)}),this},i.prototype.replayQueue=function(){return"offline"===this.state||this.autoReplay||(n.call(this),u.call(this)),this},i.prototype.setDefaultIndex=function(e){if("string"!=typeof e)throw new Error("Invalid default index: ["+e+"] (an index name is expected)");if(0===e.length)throw new Error("Cannot set an empty index as the default index");return this.defaultIndex=e,this},i.prototype.setHeaders=function(e,t){var r=this;if("object"!=typeof e||Array.isArray(e))throw new Error("Expected a content object, received a "+typeof e);return t?r.headers=e:Object.keys(e).forEach(function(t){r.headers[t]=e[t]}),r},i.prototype.startQueuing=function(){return"offline"!==this.state||this.autoQueue||(this.queuing=!0),this},i.prototype.stopQueuing=function(){return"offline"!==this.state||this.autoQueue||(this.queuing=!1),this},e.exports=i},function(e,t){function r(e,t,r){if(!t)throw new Error("A security document must have an id");if(Object.defineProperties(this,{kuzzle:{value:e.kuzzle},Security:{value:e},id:{value:t,enumerable:!0},content:{value:{},writable:!0,enumerable:!0}}),r&&this.setContent(r,!0),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["delete","update"];return i&&n.indexOf(e)!==-1}})}r.prototype.setContent=function(e){return this.content=e,this},r.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e},r.prototype.delete=function(e,t){var r=this;e&&void 0===t&&"function"==typeof e&&(t=e,e=null),r.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName),{_id:this.id},e,function(e,r){return e?!!t&&t(e):void(t&&t(null,r.result._id))})},r.prototype.update=function(e,t,r){var i={},n=this;if("object"!=typeof e)throw new Error('Parameter "content" must be a object');return t&&void 0===r&&"function"==typeof t&&(r=t,t=null),i._id=n.id,i.body=e,n.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName),i,t,function(e,t){return e?!!r&&r(e):(n.setContent(t.result._source),void(r&&r(null,n)))}),this},e.exports=r},function(e,t){function r(e,t,r){return Object.defineProperties(this,{collection:{value:e.collection,enumerable:!0},dataCollection:{value:e,enumerable:!1},kuzzle:{value:e.kuzzle,enumerable:!1},id:{value:void 0,enumerable:!0,writable:!0},content:{value:{},writable:!0,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0},version:{value:void 0,enumerable:!0,writable:!0}}),!r&&t&&"object"==typeof t&&(r=t,t=null),r&&(r._version&&(this.version=r._version,delete r._version),this.setContent(r,!0)),t&&Object.defineProperty(this,"id",{value:t,enumerable:!0}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["delete","refresh","save"];return i&&n.indexOf(e)!==-1}}):this}r.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e._version=this.version,e=this.kuzzle.addHeaders(e,this.headers)},r.prototype.toString=function(){return JSON.stringify(this.serialize())},r.prototype.delete=function(e,t){var r=this;if(t||"function"!=typeof e||(t=e,e=null),!r.id)throw new Error("Document.delete: cannot delete a document without a document ID");this.kuzzle.query(this.dataCollection.buildQueryArgs("document","delete"),this.serialize(),e,t&&function(e){t(e,e?void 0:r.id)})},r.prototype.refresh=function(e,t){var i=this;if(t||"function"!=typeof e||(t=e,e=null),!i.id)throw new Error("Document.refresh: cannot retrieve a document if no ID has been provided");this.kuzzle.callbackRequired("Document.refresh",t),i.kuzzle.query(i.dataCollection.buildQueryArgs("document","get"),{_id:i.id},e,function(e,n){var o;return e?t(e):(o=new r(i.dataCollection,i.id,n.result._source),o.version=n.result._version,void t(null,o))})},r.prototype.save=function(e,t){var r=this.serialize(),i=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),i.kuzzle.query(this.dataCollection.buildQueryArgs("document","createOrReplace"),r,e,function(e,r){return e?t&&t(e):(i.id=r.result._id,i.version=r.result._version,void(t&&t(null,i)))}),i},r.prototype.publish=function(e){var t=this.serialize();return this.kuzzle.query(this.dataCollection.buildQueryArgs("realtime","publish"),t,e),this},r.prototype.setContent=function(e,t){var r=this;return t?this.content=e:Object.keys(e).forEach(function(t){r.content[t]=e[t]}),this},r.prototype.subscribe=function(e,t){var r;if(e&&!t&&"function"==typeof e&&(t=e,e=null),this.kuzzle.callbackRequired("Document.subscribe",t),!this.id)throw new Error("Document.subscribe: cannot subscribe to a document if no ID has been provided");return r={ids:{values:[this.id]}},this.dataCollection.subscribe(r,e,t)},r.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=r},function(e,t,r){function i(e,t,i){var s=this;this.WebSocket="undefined"!=typeof WebSocket?WebSocket:r(!function(){var e=new Error('Cannot find module "ws"');throw e.code="MODULE_NOT_FOUND",e}()),this.host=e,this.port=t,this.ssl=i,this.client=null,this.wasConnected=!1,this.retrying=!1,this.lasturl=null,this.stopRetryingToConnect=!1,this.listeners={error:[],connect:[],disconnect:[],reconnect:[]},this.connect=function(e,t){var r=(this.ssl?"wss://":"ws://")+this.host+":"+this.port,i="undefined"!=typeof window?void 0:{perMessageDeflate:!1};r!==this.lasturl&&(s.wasConnected=!1,this.lasturl=r),this.client=new this.WebSocket(r,i),this.client.onopen=function(){s.wasConnected?n(s.listeners,"reconnect"):n(s.listeners,"connect"),s.wasConnected=!0,s.stopRetryingToConnect=!1},this.client.onclose=function(r,i){1e3===r?n(s.listeners,"disconnect"):o.call(s,e,t,i)},this.client.onerror=function(r){o.call(s,e,t,r)},this.client.onmessage=function(e){var t=JSON.parse(e.data||e);t.room&&s.listeners[t.room]?n(s.listeners,t.room,t):s.listeners.discarded&&n(s.listeners,"discarded",t)}},this.onConnect=function(e){this.listeners.connect.push({fn:e,keep:!0})},this.onConnectError=function(e){this.listeners.error.push({fn:e,keep:!0})},this.onDisconnect=function(e){this.listeners.disconnect.push({fn:e,keep:!0})},this.onReconnect=function(e){this.listeners.reconnect.push({fn:e,keep:!0})},this.once=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push({fn:t,keep:!1})},this.on=function(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push({fn:t,keep:!0})},this.off=function(e,t){var r=-1;this.listeners[e]&&(this.listeners[e].some(function(e,i){return e.fn===t&&(r=i,!0)}),r!==-1&&(1===this.listeners[e].length&&["error","connect","disconnect","reconnect"].indexOf(e)===-1?delete this.listeners[e]:this.listeners[e].splice(r,1)))},this.send=function(e){this.client&&this.client.readyState===this.client.OPEN&&this.client.send(JSON.stringify(e))},this.close=function(){this.listeners={error:[],connect:[],disconnect:[],reconnect:[]},this.wasConnected=!1,this.client.close(),this.client=null,s.stopRetryingToConnect=!0}}function n(e,t,r){var i,n=e[t].length;for(i=0;i1?(e[t].splice(i,1),--i,--n):delete e[t])}function o(e,t,r){var i=this;!e||i.retrying||i.stopRetryingToConnect||(i.retrying=!0,setTimeout(function(){i.retrying=!1,i.connect(e,t)},t)),n(i.listeners,"error",r)}e.exports=i},function(e,t,r){function i(e,t,r){if(n.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteUser"},updateActionName:{value:"updateUser"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["save","saveRestricted"];return i&&n.indexOf(e)!==-1}})}var n=r(1);i.prototype=Object.create(n.prototype,{constructor:{value:i}}),i.prototype.setProfiles=function(e){if(!Array.isArray(e)||"string"!=typeof e[0])throw new Error('Parameter "profileIds" must be an array of strings');return this.content.profileIds=e,this},i.prototype.addProfile=function(e){if("string"!=typeof e)throw new Error('Parameter "profileId" must be a string');return this.content.profileIds||(this.content.profileIds=[]),this.content.profileIds.indexOf(e)===-1&&this.content.profileIds.push(e),this},i.prototype.save=function(e,t){var r=this.serialize(),i=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),i.kuzzle.query(this.Security.buildQueryArgs("createOrReplaceUser"),r,e,t&&function(e){t(e,e?void 0:i)}),i},i.prototype.saveRestricted=function(e,t){var r=this.serialize(),i=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),i.kuzzle.query(this.Security.buildQueryArgs("createRestrictedUser"),r,e,t&&function(e){t(e,e?void 0:i)}),i},i.prototype.serialize=function(){return{_id:this.id,body:this.content}},i.prototype.getProfiles=function(){return this.content.profileIds},e.exports=i},function(e,t,r){var i=r(19),n=r(20),o=n;o.v1=i,o.v4=n,e.exports=o},function(e,t){function r(e,t){var r=t||0,n=i;return n[e[r++]]+n[e[r++]]+n[e[r++]]+n[e[r++]]+"-"+n[e[r++]]+n[e[r++]]+"-"+n[e[r++]]+n[e[r++]]+"-"+n[e[r++]]+n[e[r++]]+"-"+n[e[r++]]+n[e[r++]]+n[e[r++]]+n[e[r++]]+n[e[r++]]+n[e[r++]]}for(var i=[],n=0;n<256;++n)i[n]=(n+256).toString(16).substr(1);e.exports=r},function(e,t,r){var i,n=window.crypto||window.msCrypto;if(n&&n.getRandomValues){var o=new Uint8Array(16);i=function(){return n.getRandomValues(o),o}}if(!i){var s=new Array(16);i=function(){for(var e,t=0;t<16;t++)0===(3&t)&&(e=4294967296*Math.random()),s[t]=e>>>((3&t)<<3)&255;return s}}e.exports=i},function(e,t,r){function i(e,t,r){if(!r||!t)throw new Error("The Collection object constructor needs an index and a collection arguments");return Object.defineProperties(this,{collection:{value:t,enumerable:!0},index:{value:r,enumerable:!0},kuzzle:{value:e,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0}}),Object.defineProperty(this,"buildQueryArgs",{value:function(e,t){return{controller:e,action:t,collection:this.collection,index:this.index}}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["publishMessage","setHeaders","subscribe"];return i&&n.indexOf(e)===-1}}):this}var n=r(12),o=r(2),s=r(9),u=r(11),l=r(13);i.prototype.count=function(e,t,r){var i;r||"function"!=typeof t||(r=t,t=null),this.kuzzle.callbackRequired("Collection.count",r),i=this.kuzzle.addHeaders({body:e},this.headers),this.kuzzle.query(this.buildQueryArgs("document","count"),i,t,function(e,t){r(e,t&&t.result.count)})},i.prototype.create=function(e,t){var r={};return t||"function"!=typeof e||(t=e,e=null),r=this.kuzzle.addHeaders(r,this.headers),this.kuzzle.query(this.buildQueryArgs("collection","create"),r,e,t),this},i.prototype.createDocument=function(e,t,r,i){var n=this,s={},u="create";if(e&&"string"!=typeof e&&(i=r,r=t,t=e,e=null),i||"function"!=typeof r||(i=r,r=null),t instanceof o?s=t.serialize():s.body=t,r&&r.ifExist)if("replace"===r.ifExist)u="createOrReplace";else if("error"!==r.ifExist)throw new Error('Invalid value for the "ifExist" option: '+r.ifExist);return e&&(s._id=e),s=n.kuzzle.addHeaders(s,n.headers),n.kuzzle.query(this.buildQueryArgs("document",u),s,r,i&&function(e,t){var r;return e?i(e):(r=new o(n,t.result._id,t.result._source),r.version=t.result._version,void i(null,r))}),this},i.prototype.deleteDocument=function(e,t,r){var i,n={};return"string"==typeof e?(n._id=e,i="delete"):(n.body={query:e},i="deleteByQuery"),r||"function"!=typeof t||(r=t,t=null),n=this.kuzzle.addHeaders(n,this.headers),this.kuzzle.query(this.buildQueryArgs("document",i),n,t,r&&function(e,t){e?r(e):r(null,"delete"===i?[t.result._id]:t.result.ids)}),this},i.prototype.fetchDocument=function(e,t,r){var i={_id:e},n=this;r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Collection.fetch",r),i=n.kuzzle.addHeaders(i,this.headers),n.kuzzle.query(this.buildQueryArgs("document","get"),i,t,function(e,t){var i;return e?r(e):(i=new o(n,t.result._id,t.result._source),i.version=t.result._version,void r(null,i))})},i.prototype.fetchAllDocuments=function(e,t){var r=!1,i=[],o={};t||"function"!=typeof e||(t=e,e={}),e||(e={}),e.from||(e.from=0),e.size||(e.size=1e3),this.kuzzle.callbackRequired("Collection.fetchAllDocuments",t),this.search(o,e,function e(o,s){return o?t(o):void(s instanceof n?(s.total>1e4&&!r&&(r=!0,console.warn("Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead")),s.documents.forEach(function(e){i.push(e)}),s.fetchNext(e)):t(null,i))})},i.prototype.getMapping=function(e,t){var r;t||"function"!=typeof e||(t=e,e=null),this.kuzzle.callbackRequired("Collection.getMapping",t),r=new s(this),r.refresh(e,t)},i.prototype.publishMessage=function(e,t,r){var i={};return e instanceof o?i=e.serialize():i.body=e,i=this.kuzzle.addHeaders(i,this.headers),this.kuzzle.query(this.buildQueryArgs("realtime","publish"),i,t,r),this},i.prototype.replaceDocument=function(e,t,r,i){var n=this,s={_id:e,body:t};return i||"function"!=typeof r||(i=r,r=null),s=n.kuzzle.addHeaders(s,this.headers),n.kuzzle.query(this.buildQueryArgs("document","createOrReplace"),s,r,i&&function(e,t){var r;return e?i(e):(r=new o(n,t.result._id,t.result._source),r.version=t.result._version,void i(null,r))}),this},i.prototype.search=function(e,t,r){var i,s=this;r||"function"!=typeof t||(r=t,t={}),s.kuzzle.callbackRequired("Collection.search",r),i=s.kuzzle.addHeaders({body:e},this.headers),s.kuzzle.query(this.buildQueryArgs("document","search"),i,t,function(i,u){var l=[];return i?r(i):(u.result.hits.forEach(function(e){var t=new o(s,e._id,e._source);t.version=e._version,l.push(t)}),u.result._scroll_id&&(t.scrollId=u.result._scroll_id),void r(null,new n(s,u.result.total,l,u.result.aggregations?u.result.aggregations:{},t,e,t.previous||null)))})},i.prototype.scroll=function(e,t,r,i){var s={},u=this;if(!e)throw new Error("Collection.scroll: scrollId is required");return i||(i=r,r=null),i||"function"!=typeof t||(i=t,t={}),this.kuzzle.callbackRequired("Collection.scroll",i),s.scrollId=e,t&&t.scroll&&(s.scroll=t.scroll),this.kuzzle.query({controller:"document",action:"scroll"},s,t,function(e,s){var l=[];return e?i(e):(s.result.hits.forEach(function(e){var t=new o(u,e._id,e._source);t.version=e._version,l.push(t)}),s.result._scroll_id&&(t.scrollId=s.result._scroll_id),void i(null,new n(u,s.result.total,l,{},t,r,t.previous||null)))}),this},i.prototype.subscribe=function(e,t,r){var i,n;return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.callbackRequired("Collection.subscribe",r),n=new l,i=new u(this,t),i.renew(e,r,n.done.bind(n)),n},i.prototype.truncate=function(e,t){var r={};return t||"function"!=typeof e||(t=e,e=null),r=this.kuzzle.addHeaders(r,this.headers),this.kuzzle.query(this.buildQueryArgs("collection","truncate"),r,e,t),this},i.prototype.updateDocument=function(e,t,r,i){var n={_id:e,body:t},s=this;return i||"function"!=typeof r||(i=r,r=null),r&&r.retryOnConflict&&(n.retryOnConflict=r.retryOnConflict),n=s.kuzzle.addHeaders(n,this.headers),s.kuzzle.query(this.buildQueryArgs("document","update"),n,r,i&&function(e,t){return e?i(e):void new o(s,t.result._id).refresh(i)}),s},i.prototype.document=function(e,t){return new o(this,e,t)},i.prototype.room=function(e){return new u(this,e)},i.prototype.collectionMapping=function(e){return new s(this,e)},i.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t), +this},e.exports=i},function(e,t){function r(e,t){return Object.defineProperties(this,{collection:{value:e,enumerable:!0},kuzzle:{value:e.kuzzle,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0},mapping:{value:t||{},enumerable:!0,writable:!0}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["set","setHeaders"];return i&&n.indexOf(e)===-1}}):this}r.prototype.apply=function(e,t){var r=this,i=this.kuzzle.addHeaders({body:{properties:this.mapping}},this.headers);return t||"function"!=typeof e||(t=e,e=null),r.kuzzle.query(this.collection.buildQueryArgs("collection","updateMapping"),i,e,function(i){return i?t&&t(i):void r.refresh(e,t)}),this},r.prototype.refresh=function(e,t){var r=this,i=this.kuzzle.addHeaders({},this.headers);return t||"function"!=typeof e||(t=e,e=null),this.kuzzle.query(this.collection.buildQueryArgs("collection","getMapping"),i,e,function(e,i){return e?!!t&&t(e):i.result[r.collection.index]?i.result[r.collection.index].mappings[r.collection.collection]?(r.mapping=i.result[r.collection.index].mappings[r.collection.collection].properties,void 0===r.mapping&&(r.mapping={}),void(t&&t(null,r))):t&&t(new Error("No mapping found for collection "+r.collection.collection)):t&&t(new Error("No mapping found for index "+r.collection.index))}),this},r.prototype.set=function(e,t){return this.mapping[e]=t,this},r.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=r},function(e,t){function r(e){return Object.defineProperties(this,{kuzzle:{value:e,enumerable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0}}),this.setHeaders=e.setHeaders.bind(this),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["setHeaders"];return i&&n.indexOf(e)===-1}}):this}function i(e,t,r,i){t||"_id"===r?e[r]=i:e.body[r]=i}function n(e,t){var r=[];Object.keys(t).filter(function(e){return t[e]&&["withcoord","withdist","count","sort"].indexOf(e)!==-1}).forEach(function(e){"withcoord"===e||"withdist"===e?(r.push(e),delete t[e]):"count"!==e&&"sort"!==e||("count"===e&&r.push("count"),r.push(t[e])),delete t[e]}),r.length>0&&(e.options=r)}function o(e,t){e.options=["withscores"],t.limit&&(e.limit=t.limit,delete t.limit)}function s(e){return e.map(function(e){return e.map(function(e){return parseFloat(e)})})}function u(e){return Array.isArray(e[0])?e.map(function(e){var t,r={name:e[0]};for(t=1;t1)throw new Error("MemoryStorage."+e+": Too many parameters provided");if(1===r.length&&"object"!=typeof r[0]||Array.isArray(r[0]))throw new Error("MemoryStorage."+e+": Invalid optional parameter (expected an object)");if(r.length&&(n=Object.assign({},r[0]),Array.isArray(k[e].opts)&&k[e].opts.forEach(function(t){null!==n[t]&&void 0!==n[t]&&(i(s,k[e].getter,t,n[t]),delete n[t])})),"function"==typeof k[e].opts&&k[e].opts(s,n||{}),this.kuzzle.query(o,s,n,t&&function(r,i){return r?t(r):k[e].mapResults?t(null,k[e].mapResults(i.result)):void t(null,i.result)}),!k[e].getter)return this}})}(),e.exports=r},function(e,t,r){function i(e,t){return Object.defineProperties(this,{callback:{value:null,writable:!0},channel:{value:null,writable:!0},id:{value:u.v4()},lastRenewal:{value:null,writable:!0},notifier:{value:null,writable:!0},onDoneCB:{value:null,writable:!0},queue:{value:[],writable:!0},renewalDelay:{value:500},scope:{value:t&&t.scope?t.scope:"all"},state:{value:t&&t.state?t.state:"done"},subscribing:{value:!1,writable:!0},users:{value:t&&t.users?t.users:"none"},collection:{value:e,enumerable:!0},kuzzle:{value:e.kuzzle,enumerable:!0},filters:{value:null,enumerable:!0,writable:!0},headers:{value:JSON.parse(JSON.stringify(e.headers)),enumerable:!0,writable:!0},volatile:{value:t&&t.volatile?t.volatile:{},enumerable:!0,writable:!0},roomId:{value:null,enumerable:!0,writable:!0},subscribeToSelf:{value:!t||"boolean"!=typeof t.subscribeToSelf||t.subscribeToSelf,enumerable:!0,writable:!0}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["count"];return i&&n.indexOf(e)!==-1}}):this}function n(e){return e.error?this.callback(e.error):"jwtTokenExpired"===e.action?(this.kuzzle.jwtToken=void 0,this.kuzzle.emitEvent("jwtTokenExpired")):("document"===e.controller||"realtime"===e.controller&&"publish"===e.action?(e.type="document",e.document=new l(this.collection,e.result._id,e.result._source),delete e.result):"realtime"===e.controller&&(e.type="user",e.user={count:e.result.count},delete e.result),void(this.kuzzle.requestHistory[e.requestId]?(this.subscribeToSelf&&this.callback(null,e),delete this.kuzzle.requestHistory[e.requestId]):this.callback(null,e)))}function o(){for(var e;this.queue.length>0;)e=this.queue.shift(),this[e.action].apply(this,e.args)}function s(){return"connected"===this.kuzzle.state&&!this.subscribing}var u=r(5),l=r(2);i.prototype.count=function(e){var t;if(this.kuzzle.callbackRequired("Room.count",e),t=this.kuzzle.addHeaders({body:{roomId:this.roomId}},this.headers),!s.call(this))return void this.queue.push({action:"count",args:[e]});if(!this.roomId)throw new Error("Room.count: cannot count subscriptions on an inactive room");this.kuzzle.query(this.collection.buildQueryArgs("realtime","count"),t,function(t,r){e(t,r&&r.result.count)})},i.prototype.renew=function(e,t,r){var i=Date.now(),s={scope:this.scope,state:this.state,users:this.users},u=this;return"function"==typeof e&&(r=t,t=e,e=null),r||(r=u.onDoneCB),u.kuzzle.callbackRequired("Room.renew",t),u.lastRenewal&&i-u.lastRenewal<=u.renewalDelay?r&&r(new Error("Subscription already renewed less than "+u.renewalDelay+"ms ago")):(e&&(u.filters=e),"connected"!==u.kuzzle.state?(u.callback=t,u.onDoneCB=r,void(u.kuzzle.subscriptions.pending[u.id]=u)):u.subscribing?void u.queue.push({action:"renew",args:[e,t,r]}):(u.unsubscribe(),u.roomId=null,u.subscribing=!0,u.callback=t,u.onDoneCB=r,u.kuzzle.subscriptions.pending[u.id]=u,s.body=u.filters,s=u.kuzzle.addHeaders(s,this.headers),void u.kuzzle.query(u.collection.buildQueryArgs("realtime","subscribe"),s,{volatile:u.volatile},function(e,t){return delete u.kuzzle.subscriptions.pending[u.id],u.subscribing=!1,e?(u.queue=[],r&&r(new Error("Error during Kuzzle subscription: "+e.message))):(u.lastRenewal=i,u.roomId=t.result.roomId,u.channel=t.result.channel,u.kuzzle.subscriptions[u.roomId]||(u.kuzzle.subscriptions[u.roomId]={}),u.kuzzle.subscriptions[u.roomId][u.id]=u,u.notifier=n.bind(u),u.kuzzle.network.on(u.channel,u.notifier),o.call(u),void(r&&r(null,u)))})))},i.prototype.unsubscribe=function(){var e,t=this,r=t.roomId;return s.call(this)?(r&&(t.kuzzle.network.off(t.channel,this.notifier),1===Object.keys(t.kuzzle.subscriptions[r]).length?(delete t.kuzzle.subscriptions[r],0===Object.keys(t.kuzzle.subscriptions.pending).length?t.kuzzle.query(t.collection.buildQueryArgs("realtime","unsubscribe"),{body:{roomId:r}}):e=setInterval(function(){0===Object.keys(t.kuzzle.subscriptions.pending).length&&(t.kuzzle.subscriptions[r]||t.kuzzle.query(t.collection.buildQueryArgs("realtime","unsubscribe"),{body:{roomId:r}}),clearInterval(e))},100)):delete t.kuzzle.subscriptions[r][t.id],t.roomId=null),t):(t.queue.push({action:"unsubscribe",args:[]}),t)},i.prototype.setHeaders=function(e,t){return this.kuzzle.setHeaders.call(this,e,t),this},e.exports=i},function(e,t){function r(e,t,i,n,o,s,u){return Object.defineProperties(this,{collection:{value:e,enumerable:!0},total:{value:t,enumerable:!0},documents:{value:i,enumerable:!0},aggregations:{value:n||{},enumerable:!0},options:{value:o||{},enumerable:!0},filters:{value:s||{},enumerable:!0},fetchedDocument:{value:u instanceof r?i.length+u.fetchedDocument:i.length,enumerable:!0,writable:!0}}),this.collection.kuzzle.bluebird?this.collection.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["fetchNext"];return i&&n.indexOf(e)!==-1}}):this}r.prototype.fetchNext=function(e){var t,r=Object.assign({},this.options);return r.previous=this,r.scrollId?this.fetchedDocument>=this.getTotal()?void e(null,null):("undefined"!=typeof r.from&&delete r.from,r.size&&delete r.size,void this.collection.scroll(r.scrollId,r,this.filters||{},e)):void 0!==r.from&&void 0!==r.size?(t=Object.assign({},this.filters),r.from+=r.size,r.from>=this.getTotal()?void e(null,null):void this.collection.search(t,r,e)):void e(new Error("Unable to retrieve next results from search: missing scrollId or from/size params"))},r.prototype.getDocuments=function(){return this.documents},r.prototype.getTotal=function(){return this.total},r.prototype.getAggregations=function(){return this.aggregations},r.prototype.getOptions=function(){return this.options},r.prototype.getFilters=function(){return this.filters},r.prototype.getCollection=function(){return this.collection},r.prototype.getFetchedDocument=function(){return this.fetchedDocument},e.exports=r},function(e,t){function r(){this.cbs=[],this.error=null,this.room=null}r.prototype.onDone=function(e){return this.error||this.room?e(this.error,this.room):this.cbs.push(e),this},r.prototype.done=function(e,t){this.error=e,this.room=t,this.cbs.forEach(function(r){r(e,t)})},e.exports=r},function(e,t,r){function i(e,t,i){if("undefined"!=typeof window){if("undefined"!=typeof WebSocket)return new(r(3))(e,t,i);if(window.io)return new(r(15))(e,t,i);throw new Error("Aborting: no websocket support detected and no socket.io library loaded either.")}return new(r(3))(e,t,i)}e.exports=i},function(e,t){function r(e,t,r){this.host=e,this.port=t,this.ssl=r,this.socket=null,this.connect=function(e,t){this.socket=window.io((this.ssl?"https://":"http://")+this.host+":"+this.port,{reconnection:e,reconnectionDelay:t,forceNew:!0})},this.onConnect=function(e){this.socket.on("connect",e)},this.onConnectError=function(e){this.socket.on("connect_error",e)},this.onDisconnect=function(e){this.socket.on("disconnect",e)},this.onReconnect=function(e){this.socket.on("reconnect",e)},this.once=function(e,t){this.socket.once(e,t)},this.on=function(e,t){this.socket.on(e,t)},this.off=function(e,t){this.socket.off(e,t)},this.send=function(e){this.socket.emit("kuzzle",e)},this.close=function(){this.socket.close(),this.socket=null}}e.exports=r},function(e,t,r){function i(e,t,r){if(n.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteProfile"},updateActionName:{value:"updateProfile"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["hydrate","save"];return i&&n.indexOf(e)!==-1}})}var n=r(1);i.prototype=Object.create(n.prototype,{constructor:{value:i}}),i.prototype.save=function(e,t){var r,i=this;if(!this.content.policies)throw new Error('Argument "policies" is mandatory in a profile. This argument contains an array of objects.');return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),r=this.serialize(),i.kuzzle.query(i.Security.buildQueryArgs("createOrReplaceProfile"),r,e,t&&function(e){t(e,e?void 0:i)}),i},i.prototype.addPolicy=function(e){if("object"!=typeof e||"string"!=typeof e.roleId)throw new Error('Parameter "policies" must be an object containing at least a "roleId" member which must be a string.');return this.content.policies||(this.content.policies=[]),this.content.policies.push(e),this},i.prototype.setPolicies=function(e){if(!Array.isArray(e))throw new Error('Parameter "policies" must be an array of objects containing at least a "roleId" member which must be a string');return e.map(function(e){if("object"!=typeof e||"string"!=typeof e.roleId)throw new Error('Parameter "policies" must be an array of objects containing at least a "roleId" member which must be a string')}),this.content.policies=e,this},i.prototype.serialize=function(){var e={};return this.id&&(e._id=this.id),e.body=this.content,e},i.prototype.getPolicies=function(){return this.content.policies},e.exports=i},function(e,t,r){function i(e,t,r){if(n.call(this,e,t,r),Object.defineProperties(this,{deleteActionName:{value:"deleteRole"},updateActionName:{value:"updateRole"}}),e.kuzzle.bluebird)return e.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["save"];return i&&n.indexOf(e)!==-1}})}var n=r(1);i.prototype=Object.create(n.prototype,{constructor:{value:i}}),i.prototype.save=function(e,t){var r=this.serialize(),i=this;return e&&void 0===t&&"function"==typeof e&&(t=e,e=null),i.kuzzle.query(this.Security.buildQueryArgs("createOrReplaceRole"),r,e,t&&function(e){t(e,e?void 0:i)}),this},e.exports=i},function(e,t,r){function i(e){return Object.defineProperty(this,"kuzzle",{value:e}),Object.defineProperty(this,"buildQueryArgs",{value:function(e){return{controller:"security",action:e}}}),this.kuzzle.bluebird?this.kuzzle.bluebird.promisifyAll(this,{suffix:"Promise",filter:function(e,t,r,i){var n=["role","profile","user","isActionAllowed"];return i&&n.indexOf(e)===-1}}):this}var n=r(17),o=r(16),s=r(4);i.prototype.fetchRole=function(e,t,r){var i,o=this;if(!e)throw new Error("Id parameter is mandatory for fetchRole function");r||"function"!=typeof t||(r=t,t=null),i={_id:e},o.kuzzle.callbackRequired("Security.fetchRole",r),o.kuzzle.query(this.buildQueryArgs("getRole"),i,t,function(e,t){r(e,e?void 0:new n(o,t.result._id,t.result._source))})},i.prototype.searchRoles=function(e,t,r){var i=this;r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Security.searchRoles",r),i.kuzzle.query(this.buildQueryArgs("searchRoles"),{body:e},t,function(e,t){var o;return e?r(e):(o=t.result.hits.map(function(e){return new n(i,e._id,e._source)}),void r(null,{total:t.result.total,roles:o}))})},i.prototype.createRole=function(e,t,r,i){var o=this,s={},u="createRole";if(!e||"string"!=typeof e)throw new Error("Security.createRole: cannot create a role without a role ID");i||"function"!=typeof r||(i=r,r=null),s._id=e,s.body=t,r&&(u=r.replaceIfExist?"createOrReplaceRole":"createRole"),o.kuzzle.query(this.buildQueryArgs(u),s,r,i&&function(e,t){i(e,e?void 0:new n(o,t.result._id,t.result._source))})},i.prototype.updateRole=function(e,t,r,i){var o=this,s={_id:e,body:t},u="updateRole";if(!e||"string"!=typeof e)throw new Error("Security.updateRole: cannot update a role without a role ID");return i||"function"!=typeof r||(i=r,r=null),o.kuzzle.query(this.buildQueryArgs(u),s,r,i&&function(r){i(r,r?void 0:new n(o,e,t))}),this},i.prototype.deleteRole=function(e,t,r){var i={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteRole"),i,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},i.prototype.role=function(e,t){return new n(this,e,t)},i.prototype.fetchProfile=function(e,t,r){var i,n=this;if(r||"function"!=typeof t||(r=t,t=null),!e||"string"!=typeof e)throw new Error("Id parameter is mandatory for fetchProfile function");i={_id:e},n.kuzzle.callbackRequired("Security.fetchProfile",r),n.kuzzle.query(this.buildQueryArgs("getProfile"),i,t,function(e,t){r(e,e?void 0:new o(n,t.result._id,t.result._source))})},i.prototype.searchProfiles=function(e,t,r){var i=this;r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Security.searchProfiles",r),i.kuzzle.query(this.buildQueryArgs("searchProfiles"),{body:e},t,function(e,t){var n;return e?r(e):(n=t.result.hits.map(function(e){return new o(i,e._id,e._source)}),void r(null,{total:t.result.total,profiles:n}))})},i.prototype.createProfile=function(e,t,r,i){var n=this,s={},u="createProfile";if(!e||"string"!=typeof e)throw new Error("Security.createProfile: cannot create a profile without a profile ID");i||"function"!=typeof r||(i=r,r=null),s._id=e,s.body=t,r&&(u=r.replaceIfExist?"createOrReplaceProfile":"createProfile"),n.kuzzle.query(this.buildQueryArgs(u),s,r,i&&function(e,t){i(e,e?void 0:new o(n,t.result._id,t.result._source))})},i.prototype.updateProfile=function(e,t,r,i){var n=this,s={},u="updateProfile";if(!e||"string"!=typeof e)throw new Error("Security.updateProfile: cannot update a profile without a profile ID");return i||"function"!=typeof r||(i=r,r=null),s._id=e,s.body=t,n.kuzzle.query(this.buildQueryArgs(u),s,r,i&&function(e,t){var r={};return e?i(e):(Object.keys(t.result._source).forEach(function(e){r[e]=t.result._source[e]}),void i(null,new o(n,t.result._id,r)))}),this},i.prototype.deleteProfile=function(e,t,r){var i={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteProfile"),i,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},i.prototype.profile=function(e,t){return new o(this,e,t)},i.prototype.fetchUser=function(e,t,r){var i={_id:e},n=this;if(!e||"string"!=typeof e)throw new Error("Id parameter is mandatory for fetchUser function");r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Security.fetchUser",r),n.kuzzle.query(this.buildQueryArgs("getUser"),i,t,function(e,t){r(e,e?void 0:new s(n,t.result._id,t.result._source))})},i.prototype.searchUsers=function(e,t,r){var i=this;r||"function"!=typeof t||(r=t,t=null),i.kuzzle.callbackRequired("Security.searchUsers",r),i.kuzzle.query(this.buildQueryArgs("searchUsers"),{body:e},t,function(e,t){var n;return e?r(e):(n=t.result.hits.map(function(e){return new s(i,e._id,e._source)}),void r(null,{total:t.result.total,users:n}))})},i.prototype.createUser=function(e,t,r,i){var n=this,o={_id:e,body:t},u="createUser";if(!e||"string"!=typeof e)throw new Error("Security.createUser: cannot create a user without a user ID");i||"function"!=typeof r||(i=r,r=null),r&&(u=r.replaceIfExist?"createOrReplaceUser":"createUser"),n.kuzzle.query(this.buildQueryArgs(u),o,null,i&&function(e,t){i(e,e?void 0:new s(n,t.result._id,t.result._source))})},i.prototype.createRestrictedUser=function(e,t,r,i){var n=this,o={_id:e,body:t};if(!e||"string"!=typeof e)throw new Error("Security.createRestrictedUser: cannot create a user without a user ID");if(t.profileIds)throw new Error("Security.createRestrictedUser: cannot provide profileIds");i||"function"!=typeof r||(i=r,r=null),n.kuzzle.query(this.buildQueryArgs("createRestrictedUser"),o,null,i&&function(e,t){i(e,e?void 0:new s(n,t.result._id,t.result._source))})},i.prototype.updateUser=function(e,t,r,i){var n=this,o={},u="updateUser";if(!e||"string"!=typeof e)throw new Error("Security.updateUser: cannot update an user without an user ID");return i||"function"!=typeof r||(i=r,r=null),o._id=e,o.body=t,n.kuzzle.query(this.buildQueryArgs(u),o,r,i&&function(e,t){i(e,e?void 0:new s(n,t.result._id,t.result._source))}),this},i.prototype.deleteUser=function(e,t,r){var i={_id:e};return r||"function"!=typeof t||(r=t,t=null),this.kuzzle.query(this.buildQueryArgs("deleteUser"),i,t,r&&function(e,t){r(e,e?void 0:t.result._id)}),this},i.prototype.user=function(e,t){return new s(this,e,t)},i.prototype.isActionAllowed=function(e,t,r,i,n){var o;if(!e||"object"!=typeof e)throw new Error("rights parameter is mandatory for isActionAllowed function");if(!t||"string"!=typeof t)throw new Error("controller parameter is mandatory for isActionAllowed function");if(!r||"string"!=typeof r)throw new Error("action parameter is mandatory for isActionAllowed function");return o=e.filter(function(e){return e.controller===t||"*"===e.controller}).filter(function(e){return e.action===r||"*"===e.action}).filter(function(e){return e.index===i||"*"===e.index}).filter(function(e){return e.collection===n||"*"===e.collection}),o.some(function(e){return"allowed"===e.value})?"allowed":o.some(function(e){return"conditional"===e.value})?"conditional":"denied"},i.prototype.getUserRights=function(e,t,r){var i={_id:e},n=this;if(!e||"string"!=typeof e)throw new Error("userId parameter is mandatory for getUserRights function");r||"function"!=typeof t||(r=t,t=null),n.kuzzle.callbackRequired("Kuzzle.getUserRights",r),this.kuzzle.query(this.buildQueryArgs("getUserRights"),i,t,r&&function(e,t){r(e,e?void 0:t.result.hits)})},e.exports=i},function(e,t,r){function i(e,t,r){var i=t&&r||0,n=t||[];e=e||{};var s=void 0!==e.clockseq?e.clockseq:l,d=void 0!==e.msecs?e.msecs:(new Date).getTime(),f=void 0!==e.nsecs?e.nsecs:a+1,h=d-c+(f-a)/1e4;if(h<0&&void 0===e.clockseq&&(s=s+1&16383),(h<0||d>c)&&void 0===e.nsecs&&(f=0),f>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");c=d,a=f,l=s,d+=122192928e5;var p=(1e4*(268435455&d)+f)%4294967296;n[i++]=p>>>24&255,n[i++]=p>>>16&255,n[i++]=p>>>8&255,n[i++]=255&p;var y=d/4294967296*1e4&268435455;n[i++]=y>>>8&255,n[i++]=255&y,n[i++]=y>>>24&15|16,n[i++]=y>>>16&255,n[i++]=s>>>8|128,n[i++]=255&s;for(var b=e.node||u,v=0;v<6;++v)n[i+v]=b[v];return t?t:o(n)}var n=r(7),o=r(6),s=n(),u=[1|s[0],s[1],s[2],s[3],s[4],s[5]],l=16383&(s[6]<<8|s[7]),c=0,a=0;e.exports=i},function(e,t,r){function i(e,t,r){var i=t&&r||0;"string"==typeof e&&(t="binary"==e?new Array(16):null,e=null),e=e||{};var s=e.random||(e.rng||n)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t)for(var u=0;u<16;++u)t[i+u]=s[u];return t||o(s)}var n=r(7),o=r(6);e.exports=i}])}); //# sourceMappingURL=kuzzle.js.map \ No newline at end of file diff --git a/dist/kuzzle.js.map b/dist/kuzzle.js.map index df50d75b3..2a0e10560 100644 --- a/dist/kuzzle.js.map +++ b/dist/kuzzle.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///kuzzle.js","webpack:///webpack/bootstrap ef1329784c2080614ad8","webpack:///./src/Kuzzle.js","webpack:///./src/security/SecurityDocument.js","webpack:///./src/Document.js","webpack:///./src/networkWrapper/wrappers/websocket.js","webpack:///./src/security/User.js","webpack:///../~/uuid/index.js","webpack:///../~/uuid/lib/bytesToUuid.js","webpack:///../~/uuid/lib/rng-browser.js","webpack:///./src/Collection.js","webpack:///./src/CollectionMapping.js","webpack:///./src/MemoryStorage.js","webpack:///./src/Room.js","webpack:///./src/SearchResult.js","webpack:///./src/SubscribeResult.js","webpack:///./src/networkWrapper/index.js","webpack:///./src/networkWrapper/wrappers/socketio.js","webpack:///./src/security/Profile.js","webpack:///./src/security/Role.js","webpack:///./src/security/Security.js","webpack:///../~/uuid/v1.js","webpack:///../~/uuid/v4.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","Kuzzle","host","options","cb","self","Error","Object","defineProperties","collections","value","writable","connectCB","eventListeners","connected","lastEmitted","listeners","error","disconnected","reconnected","jwtTokenExpired","loginAttempt","offlineQueuePush","offlineQueuePop","queryError","discarded","eventTimeout","queuing","requestHistory","state","subscriptions","pending","autoReconnect","enumerable","defaultIndex","undefined","reconnectionDelay","port","sslConnection","autoQueue","autoReplay","autoResubscribe","headers","metadata","offlineQueue","queueFilter","queueMaxSize","queueTTL","replayInterval","jwtToken","offlineQueueLoader","keys","forEach","opt","hasOwnProperty","getOwnPropertyDescriptor","offlineMode","defineProperty","query","header","errorMessagePrefix","callback","Security","event","now","Date","args","Array","prototype","slice","arguments","eventProperties","listener","process","nextTick","fn","apply","MemoryStorage","connect","cleanHistory","bluebird","promisifyAll","suffix","filter","name","func","target","passes","whitelist","indexOf","cleanQueue","lastDocumentIndex","index","ts","splice","droppedRequest","emitEvent","length","key","setTimeout","emitRequest","request","network","once","requestId","response","action","message","assign","status","send","dequeue","additionalQueue","uniqueQueue","dequeuingProcess","shift","Math","max","isArray","concat","controller","renewAllSubscriptions","roomId","subscriptionId","subscription","renew","removeAllSubscriptions","unsubscribe","discardRequest","object","JSON","stringify","uuid","Collection","User","networkWrapper","disconnect","onConnect","on","data","onConnectError","connectionError","internal","onDisconnect","onReconnect","reconnect","checkToken","err","res","valid","setJwtToken","token","success","result","jwt","unsetJwtToken","getJwtToken","login","strategy","credentials","expiresIn","body","queuable","createIndex","logout","v4","callbackRequired","whoAmI","security","_id","_source","getMyRights","hits","updateSelf","content","queryArgs","addListener","listenerId","knownEvents","listenerType","isValid","toString","push","getAllStatistics","getStatistics","timestamp","queryCB","startTime","collection","flushQueue","listCollections","collectionType","arg","type","from","size","listIndexes","indexes","close","getServerInfo","serverInfo","refreshIndex","getAutoRefresh","setAutoRefresh","autoRefresh","attr","refresh","scroll","scrollId","meta","addHeaders","removeAllListeners","eventName","removeListener","replayQueue","setDefaultIndex","setHeaders","replace","startQueuing","stopQueuing","KuzzleSecurityDocument","kuzzle","setContent","serialize","delete","buildQueryArgs","deleteActionName","update","updateActionName","Document","kuzzleDataCollection","documentId","dataCollection","parse","version","_version","newDocument","save","publish","subscribe","filters","ids","values","WSNode","ssl","WebSocket","e","code","client","wasConnected","retrying","lasturl","url","window","perMessageDeflate","onopen","poke","onclose","onClientError","onerror","onmessage","payload","room","keep","off","some","i","readyState","OPEN","create","constructor","setProfiles","profileIds","addProfile","profileId","saveRestricted","getProfiles","v1","bytesToUuid","buf","offset","bth","byteToHex","substr","rng","crypto","msCrypto","getRandomValues","rnds8","Uint8Array","rnds","r","random","blacklist","KuzzleSearchResult","CollectionMapping","Room","KuzzleSubscribeResult","count","createDocument","document","updateIfExist","doc","deleteDocument","fetchDocument","fetchAllDocuments","warnEmitted","documents","search","getNextDocuments","searchResult","total","console","warn","next","getMapping","kuzzleMapping","publishMessage","replaceDocument","_scroll_id","aggregations","subscribeResult","done","bind","truncate","updateDocument","collectionMapping","mapping","properties","mappings","set","field","keyVal","idOrKeys","commands","append","bgrewriteaof","bgsave","bitcount","bitop","bitpos","__opts__","blpop","brpoplpush","dbsize","decrby","del","discard","exec","exists","expire","expireat","flushdb","getbit","getrange","hdel","hexists","hincrby","hmset","hset","info","lastsave","lindex","linsert","lpush","lrange","lrem","lset","ltrim","mset","multi","pexpire","pexpireat","pfadd","pfmerge","ping","psetex","randomkey","rename","renamenx","restore","rpoplpush","sadd","sdiffstore","setbit","setex","setrange","sinterstore","sismember","smove","sort","spop","srem","sunionstore","unwatch","wait","zadd","zcount","zincrby","zinterstore","zlexcount","zrange","zrangebylex","zrangebyscore","zrem","zremrangebylex","zremrangebyscore","zrevrangebylex","zrevrangebyscore","zrevrank","decr","get","dump","hgetall","hkeys","hlen","hstrlen","hvals","incr","llen","lpop","persist","pttl","rpop","scard","smembers","strlen","ttl","zcard","getset","lpushx","mget","pfcount","sdiff","sinter","sunion","watch","incrby","incrbyfloat","brpop","hget","hmget","hsetnx","msetnx","rpush","hincrbyfloat","srandmember","zrevrange","zscore","command","pop","v","channel","lastRenewal","notifier","onDoneCB","queue","renewalDelay","scope","subscribing","users","subscribeToSelf","notificationCallback","user","element","isReady","notificationCB","subscribeQuery","interval","setInterval","clearInterval","searchArgs","previous","fetchedDocument","_previous","_next","handleNextSearchResults","currentSearchResults","newSearchResults","cbs","onDone","io","SocketIO","socket","reconnection","forceNew","emit","Profile","SecurityDocument","policies","addPolicy","policy","roleId","setPolicies","map","getPolicies","Role","fetchRole","searchRoles","roles","createRole","replaceIfExist","updateRole","deleteRole","role","fetchProfile","searchProfiles","profiles","createProfile","updateProfile","updatedContent","property","deleteProfile","profile","fetchUser","searchUsers","createUser","createRestrictedUser","updateUser","deleteUser","isActionAllowed","rights","filteredRights","right","item","getUserRights","userId","b","clockseq","_clockseq","msecs","getTime","nsecs","_lastNSecs","dt","_lastMSecs","tl","tmh","node","_nodeId","n","_seedBytes","ii"],"mappings":"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","file":"kuzzle.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Kuzzle\"] = factory();\n\telse\n\t\troot[\"Kuzzle\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","/*! Kuzzle javascript SDK version 3.4.2 */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Kuzzle\"] = factory();\n\telse\n\t\troot[\"Kuzzle\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t uuid = __webpack_require__(5),\n\t Collection = __webpack_require__(8),\n\t Security = __webpack_require__(18),\n\t MemoryStorage = __webpack_require__(10),\n\t User = __webpack_require__(4),\n\t networkWrapper = __webpack_require__(14);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * Kuzzle object constructor.\n\t *\n\t * @constructor\n\t * @param host - Server name or IP Address to the Kuzzle instance\n\t * @param [options] - Connection options\n\t * @param {responseCallback} [cb] - Handles connection response\n\t * @constructor\n\t */\n\tfunction Kuzzle (host, options, cb) {\n\t var self = this;\n\t\n\t if (!(this instanceof Kuzzle)) {\n\t return new Kuzzle(host, options, cb);\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!host || host === '') {\n\t throw new Error('host argument missing');\n\t }\n\t\n\t Object.defineProperties(this, {\n\t // 'private' properties\n\t collections: {\n\t value: {},\n\t writable: true\n\t },\n\t connectCB: {\n\t value: cb\n\t },\n\t eventListeners: {\n\t value: {\n\t connected: {lastEmitted: null, listeners: []},\n\t error: {lastEmitted: null, listeners: []},\n\t disconnected: {lastEmitted: null, listeners: []},\n\t reconnected: {lastEmitted: null, listeners: []},\n\t jwtTokenExpired: {lastEmitted: null, listeners: []},\n\t loginAttempt: {lastEmitted: null, listeners: []},\n\t offlineQueuePush: {listeners: []},\n\t offlineQueuePop: {listeners: []},\n\t queryError: {listeners: []},\n\t discarded: {listeners: []}\n\t }\n\t },\n\t eventTimeout: {\n\t value: 200\n\t },\n\t queuing: {\n\t value: false,\n\t writable: true\n\t },\n\t requestHistory: {\n\t value: {},\n\t writable: true\n\t },\n\t state: {\n\t value: 'initializing',\n\t writable: true\n\t },\n\t subscriptions: {\n\t /*\n\t Contains the centralized subscription list in the following format:\n\t pending: \n\t 'roomId': {\n\t kuzzleRoomID_1: kuzzleRoomInstance_1,\n\t kuzzleRoomID_2: kuzzleRoomInstance_2,\n\t kuzzleRoomID_...: kuzzleRoomInstance_...\n\t }\n\t\n\t This was made to allow multiple subscriptions on the same set of filters, something that Kuzzle does not permit.\n\t This structure also allows renewing subscriptions after a connection loss\n\t */\n\t value: {\n\t pending: {}\n\t },\n\t writable: true\n\t },\n\t // configuration properties\n\t autoReconnect: {\n\t value: (options && typeof options.autoReconnect === 'boolean') ? options.autoReconnect : true,\n\t writable: true,\n\t enumerable: true\n\t },\n\t defaultIndex: {\n\t value: (options && typeof options.defaultIndex === 'string') ? options.defaultIndex : undefined,\n\t writable: true,\n\t enumerable: true\n\t },\n\t reconnectionDelay: {\n\t value: (options && typeof options.reconnectionDelay === 'number') ? options.reconnectionDelay : 1000,\n\t writable: true,\n\t enumerable: true\n\t },\n\t host: {\n\t value: host,\n\t writable: true,\n\t enumerable: true\n\t },\n\t port: {\n\t value: (options && typeof options.port === 'number') ? options.port : 7512,\n\t enumerable: true,\n\t writable: true\n\t },\n\t sslConnection: {\n\t value: (options && typeof options.sslConnection === 'boolean') ? options.sslConnection : false,\n\t writable: true,\n\t enumerable: true\n\t },\n\t autoQueue: {\n\t value: false,\n\t enumerable: true,\n\t writable: true\n\t },\n\t autoReplay: {\n\t value: false,\n\t enumerable: true,\n\t writable: true\n\t },\n\t autoResubscribe: {\n\t value: true,\n\t enumerable: true,\n\t writable: true\n\t },\n\t headers: {\n\t value: {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t metadata: {\n\t value: {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t /*\n\t Offline queue use the following format:\n\t [\n\t {\n\t ts: ,\n\t query: 'query',\n\t cb: callbackFunction\n\t }\n\t ]\n\t */\n\t offlineQueue: {\n\t value: [],\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueFilter: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueMaxSize: {\n\t value: 500,\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueTTL: {\n\t value: 120000,\n\t enumerable: true,\n\t writable: true\n\t },\n\t replayInterval: {\n\t value: 10,\n\t enumerable: true,\n\t writable: true\n\t },\n\t jwtToken: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t },\n\t offlineQueueLoader: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (options) {\n\t Object.keys(options).forEach(function (opt) {\n\t if (self.hasOwnProperty(opt) && Object.getOwnPropertyDescriptor(self, opt).writable) {\n\t self[opt] = options[opt];\n\t }\n\t });\n\t\n\t if (options.offlineMode === 'auto' && this.autoReconnect) {\n\t this.autoQueue = this.autoReplay = this.autoResubscribe = true;\n\t }\n\t }\n\t\n\t // Helper function ensuring that this Kuzzle object is still valid before performing a query\n\t Object.defineProperty(this, 'isValid', {\n\t value: function () {\n\t if (self.state === 'disconnected') {\n\t throw new Error('This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?');\n\t }\n\t }\n\t });\n\t\n\t // Helper function copying headers to the query data\n\t Object.defineProperty(this, 'addHeaders', {\n\t value: function (query, headers) {\n\t Object.keys(headers).forEach(function (header) {\n\t if (!query[header]) {\n\t query[header] = headers[header];\n\t }\n\t });\n\t\n\t return query;\n\t }\n\t });\n\t\n\t /**\n\t * Some methods (mainly read queries) require a callback function. This function exists to avoid repetition of code,\n\t * and is called by these methods\n\t */\n\t Object.defineProperty(this, 'callbackRequired', {\n\t value: function (errorMessagePrefix, callback) {\n\t if (!callback || typeof callback !== 'function') {\n\t throw new Error(errorMessagePrefix + ': a callback argument is required for read queries');\n\t }\n\t }\n\t });\n\t\n\t /**\n\t * Create an attribute security that embed all methods to manage Role, Profile and User\n\t */\n\t Object.defineProperty(this, 'security', {\n\t value: new Security(this),\n\t enumerable: true\n\t });\n\t\n\t /**\n\t * Emit an event to all registered listeners\n\t * An event cannot be emitted multiple times before a timeout has been reached.\n\t */\n\t Object.defineProperty(this, 'emitEvent', {\n\t value: function emitEvent(event) {\n\t var\n\t now = Date.now(),\n\t args = Array.prototype.slice.call(arguments, 1),\n\t eventProperties = this.eventListeners[event];\n\t\n\t if (eventProperties.lastEmitted && eventProperties.lastEmitted >= now - this.eventTimeout) {\n\t return false;\n\t }\n\t\n\t eventProperties.listeners.forEach(function (listener) {\n\t process.nextTick(function () {\n\t listener.fn.apply(undefined, args);\n\t });\n\t });\n\t\n\t // Events without the 'lastEmitted' property can be emitted without minimum time between emissions\n\t if (eventProperties.lastEmitted !== undefined) {\n\t eventProperties.lastEmitted = now;\n\t }\n\t }\n\t });\n\t\n\t Object.defineProperty(this, 'memoryStorage', {\n\t value: new MemoryStorage(this),\n\t enumerable: true\n\t });\n\t\n\t\n\t if (!options || !options.connect || options.connect === 'auto') {\n\t this.connect();\n\t } else {\n\t this.state = 'ready';\n\t }\n\t\n\t cleanHistory(this.requestHistory);\n\t\n\t if (this.bluebird) {\n\t return this.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['getAllStatistics', 'getServerInfo', 'getStatistics',\n\t 'listCollections', 'listIndexes', 'login', 'logout', 'now', 'query',\n\t 'checkToken', 'whoAmI', 'updateSelf', 'getMyRights',\n\t 'refreshIndex', 'getAutoRefresh', 'setAutoRefresh'\n\t ];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\t/**\n\t * Connects to a Kuzzle instance using the provided host name.\n\t * @returns {Object} this\n\t */\n\tKuzzle.prototype.connect = function () {\n\t var self = this;\n\t\n\t if (self.network) {\n\t self.disconnect();\n\t }\n\t\n\t self.network = networkWrapper(self.host, self.port, self.sslConnection);\n\t\n\t if (['initializing', 'ready', 'disconnected', 'error', 'offline'].indexOf(this.state) === -1) {\n\t if (self.connectCB) {\n\t self.connectCB(null, self);\n\t }\n\t return self;\n\t }\n\t\n\t self.state = 'connecting';\n\t self.network.connect(self.autoReconnect, self.reconnectionDelay);\n\t\n\t self.network.onConnect(function () {\n\t self.state = 'connected';\n\t renewAllSubscriptions.call(self);\n\t dequeue.call(self);\n\t self.emitEvent('connected');\n\t\n\t if (self.connectCB) {\n\t self.connectCB(null, self);\n\t }\n\t });\n\t\n\t self.network.on('discarded', function (data) {\n\t self.emitEvent('discarded', data);\n\t });\n\t\n\t self.network.onConnectError(function (error) {\n\t var connectionError = new Error('Unable to connect to kuzzle proxy server at \"' + self.host + '\"');\n\t\n\t connectionError.internal = error;\n\t self.state = 'error';\n\t self.emitEvent('error', connectionError);\n\t\n\t if (self.connectCB) {\n\t self.connectCB(connectionError);\n\t }\n\t });\n\t\n\t self.network.onDisconnect(function () {\n\t self.state = 'offline';\n\t\n\t if (!self.autoReconnect) {\n\t self.disconnect();\n\t }\n\t\n\t if (self.autoQueue) {\n\t self.queuing = true;\n\t }\n\t\n\t self.emitEvent('disconnected');\n\t });\n\t\n\t self.network.onReconnect(function () {\n\t var reconnect = function () {\n\t // renew subscriptions\n\t if (self.autoResubscribe) {\n\t renewAllSubscriptions.call(self);\n\t }\n\t\n\t // replay queued requests\n\t if (self.autoReplay) {\n\t cleanQueue.call(self);\n\t dequeue.call(self);\n\t }\n\t\n\t // alert listeners\n\t self.emitEvent('reconnected');\n\t };\n\t\n\t self.state = 'connected';\n\t\n\t if (self.jwtToken) {\n\t self.checkToken(self.jwtToken, function (err, res) {\n\t // shouldn't obtain an error but let's invalidate the token anyway\n\t if (err || !res.valid) {\n\t self.jwtToken = undefined;\n\t self.emitEvent('jwtTokenExpired');\n\t }\n\t\n\t reconnect();\n\t });\n\t } else {\n\t reconnect();\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Set the jwtToken used to query kuzzle\n\t * @param token\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.setJwtToken = function(token) {\n\t if (typeof token === 'string') {\n\t this.jwtToken = token;\n\t } else if (typeof token === 'object') {\n\t if (token.result && token.result.jwt && typeof token.result.jwt === 'string') {\n\t this.jwtToken = token.result.jwt;\n\t } else {\n\t this.emitEvent('loginAttempt', {\n\t success: false,\n\t error: 'Cannot find a valid JWT token in the following object: ' + JSON.stringify(token)\n\t });\n\t\n\t return this;\n\t }\n\t } else {\n\t this.emitEvent('loginAttempt', {success: false, error: 'Invalid token argument: ' + token});\n\t return this;\n\t }\n\t\n\t renewAllSubscriptions.call(this);\n\t this.emitEvent('loginAttempt', {success: true});\n\t return this;\n\t};\n\t\n\t/**\n\t * Unset the jwtToken used to query kuzzle\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.unsetJwtToken = function() {\n\t this.jwtToken = undefined;\n\t\n\t removeAllSubscriptions.call(this);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Get the jwtToken used by kuzzle\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.getJwtToken = function() {\n\t return this.jwtToken;\n\t};\n\t\n\t/**\n\t * Send login request to kuzzle with credentials\n\t * If login success, store the jwtToken into kuzzle object\n\t *\n\t * @param strategy\n\t * @param credentials\n\t * @param expiresIn\n\t * @param cb\n\t */\n\tKuzzle.prototype.login = function (strategy) {\n\t var\n\t self = this,\n\t request = {\n\t strategy: strategy\n\t },\n\t credentials,\n\t cb = null;\n\t\n\t // Handle arguments (credentials, expiresIn, cb)\n\t if (arguments[1]) {\n\t if (typeof arguments[1] === 'object') {\n\t credentials = arguments[1];\n\t } else if (typeof arguments[1] === 'number' || typeof arguments[1] === 'string') {\n\t request.expiresIn = arguments[1];\n\t } else if (typeof arguments[1] === 'function') {\n\t cb = arguments[1];\n\t }\n\t }\n\t if (arguments[2]) {\n\t if (typeof arguments[2] === 'number' || typeof arguments[2] === 'string') {\n\t request.expiresIn = arguments[2];\n\t } else if (typeof arguments[2] === 'function') {\n\t cb = arguments[2];\n\t }\n\t }\n\t if (arguments[3] && typeof arguments[3] === 'function') {\n\t cb = arguments[3];\n\t }\n\t\n\t if (typeof credentials === 'object') {\n\t Object.keys(credentials).forEach(function (key) {\n\t request[key] = credentials[key];\n\t });\n\t }\n\t\n\t this.query({controller: 'auth', action: 'login'}, {body: request}, {queuable: false}, function(error, response) {\n\t if (!error) {\n\t if (response.result.jwt) {\n\t self.setJwtToken(response.result.jwt);\n\t }\n\t\n\t cb && cb(null, response.result);\n\t }\n\t else {\n\t cb && cb(error);\n\t self.emitEvent('loginAttempt', {success: false, error: error.message});\n\t }\n\t });\n\t};\n\t\n\t/**\n\t * Create a kuzzle index\n\t *\n\t * @param {string} index\n\t * @param {object} [options]\n\t * @param {responseCallback} cb\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.createIndex = function (index, options, cb) {\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.createIndex: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.query({controller: 'index', action: 'create'}, {index: index}, options, typeof cb !== 'function' ? null : cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Send logout request to kuzzle with jwtToken.\n\t *\n\t * @param cb\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.logout = function (cb) {\n\t var\n\t self = this,\n\t request = {\n\t action: 'logout',\n\t controller: 'auth',\n\t requestId: uuid.v4(),\n\t body: {}\n\t };\n\t\n\t this.query({controller: 'auth', action: 'logout'}, request, {queuable: false}, typeof cb !== 'function' ? null : function(error) {\n\t cb(error, self);\n\t });\n\t\n\t self.unsetJwtToken();\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Checks whether a given jwt token still represents a valid session in Kuzzle.\n\t *\n\t * @param {string} token The jwt token to check\n\t * @param {function} callback The callback to be called when the response is\n\t * available. The signature is `function(error, response)`.\n\t */\n\tKuzzle.prototype.checkToken = function (token, callback) {\n\t var\n\t request = {\n\t body: {\n\t token: token\n\t }\n\t };\n\t\n\t this.callbackRequired('Kuzzle.checkToken', callback);\n\t\n\t this.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}, function (err, response) {\n\t if (err) {\n\t return callback(err);\n\t }\n\t\n\t callback(null, response.result);\n\t });\n\t};\n\t\n\t/**\n\t * Fetches the current user.\n\t *\n\t * @param {function} callback The callback to be called when the response is\n\t * available. The signature is `function(error, response)`.\n\t */\n\tKuzzle.prototype.whoAmI = function (callback) {\n\t var self = this;\n\t\n\t self.callbackRequired('Kuzzle.whoAmI', callback);\n\t\n\t self.query({controller: 'auth', action: 'getCurrentUser'}, {}, {}, function (err, response) {\n\t if (err) {\n\t return callback(err);\n\t }\n\t\n\t callback(null, new User(self.security, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Gets the rights array of the currently logged user.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {function} cb The callback containing the normalized array of rights.\n\t */\n\tKuzzle.prototype.getMyRights = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.callbackRequired('Kuzzle.getMyRights', cb);\n\t\n\t self.query({controller: 'auth', action:'getMyRights'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.hits);\n\t });\n\t};\n\t\n\t/**\n\t * Update current user in Kuzzle.\n\t *\n\t * @param {object} content - a plain javascript object representing the user's modification\n\t * @param {object} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.updateSelf = function (content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t queryArgs = {controller: 'auth', action: 'updateSelf'};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data.body = content;\n\t\n\t self.query(queryArgs, data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Clean up the queue, ensuring the queryTTL and queryMaxSize properties are respected\n\t */\n\tfunction cleanQueue () {\n\t var\n\t self = this,\n\t now = Date.now(),\n\t lastDocumentIndex = -1;\n\t\n\t if (self.queueTTL > 0) {\n\t self.offlineQueue.forEach(function (query, index) {\n\t if (query.ts < now - self.queueTTL) {\n\t lastDocumentIndex = index;\n\t }\n\t });\n\t\n\t if (lastDocumentIndex !== -1) {\n\t self.offlineQueue\n\t .splice(0, lastDocumentIndex + 1)\n\t .forEach(function (droppedRequest) {\n\t self.emitEvent('offlineQueuePop', droppedRequest.query);\n\t });\n\t }\n\t }\n\t\n\t if (self.queueMaxSize > 0 && self.offlineQueue.length > self.queueMaxSize) {\n\t self.offlineQueue\n\t .splice(0, self.offlineQueue.length - self.queueMaxSize)\n\t .forEach(function (droppedRequest) {\n\t self.emitEvent('offlineQueuePop', droppedRequest.query);\n\t });\n\t }\n\t}\n\t\n\t\n\t/**\n\t * Clean history from requests made more than 10s ago\n\t */\n\tfunction cleanHistory (requestHistory) {\n\t var\n\t now = Date.now();\n\t\n\t Object.keys(requestHistory).forEach(function (key) {\n\t if (requestHistory[key] < now - 10000) {\n\t delete requestHistory[key];\n\t }\n\t });\n\t\n\t setTimeout(function () {\n\t cleanHistory(requestHistory);\n\t }, 1000);\n\t}\n\t\n\t/**\n\t * Emit a request to Kuzzle\n\t *\n\t * @param {object} request\n\t * @param {responseCallback} [cb]\n\t */\n\tfunction emitRequest (request, cb) {\n\t var\n\t self = this;\n\t\n\t if (self.jwtToken !== undefined || cb) {\n\t self.network.once(request.requestId, function (response) {\n\t var error = null;\n\t\n\t if (request.action !== 'logout' && response.error && response.error.message === 'Token expired') {\n\t self.jwtToken = undefined;\n\t self.emitEvent('jwtTokenExpired', request, cb);\n\t }\n\t\n\t if (response.error) {\n\t error = new Error(response.error.message);\n\t Object.assign(error, response.error);\n\t error.status = response.status;\n\t self.emitEvent('queryError', error, request, cb);\n\t }\n\t\n\t if (cb) {\n\t cb(error, response);\n\t }\n\t });\n\t }\n\t\n\t this.network.send(request);\n\t\n\t // Track requests made to allow Room.subscribeToSelf to work\n\t self.requestHistory[request.requestId] = Date.now();\n\t}\n\t\n\t/**\n\t * Play all queued requests, in order.\n\t */\n\tfunction dequeue () {\n\t var\n\t self = this,\n\t additionalQueue,\n\t uniqueQueue = {},\n\t dequeuingProcess = function () {\n\t if (self.offlineQueue.length > 0) {\n\t emitRequest.call(self, self.offlineQueue[0].query, self.offlineQueue[0].cb);\n\t self.emitEvent('offlineQueuePop', self.offlineQueue.shift());\n\t\n\t setTimeout(function () {\n\t dequeuingProcess();\n\t }, Math.max(0, self.replayInterval));\n\t } else {\n\t self.queuing = false;\n\t }\n\t };\n\t\n\t if (self.offlineQueueLoader) {\n\t if (typeof self.offlineQueueLoader !== 'function') {\n\t throw new Error('Invalid value for offlineQueueLoader property. Expected: function. Got: ' + typeof self.offlineQueueLoader);\n\t }\n\t\n\t additionalQueue = self.offlineQueueLoader();\n\t if (Array.isArray(additionalQueue)) {\n\t self.offlineQueue = additionalQueue\n\t .concat(self.offlineQueue)\n\t .filter(function (request) {\n\t // throws if the query object does not contain required attributes\n\t if (!request.query || request.query.requestId === undefined || !request.query.action || !request.query.controller) {\n\t throw new Error('Invalid offline queue request. One or more missing properties: requestId, action, controller.');\n\t }\n\t\n\t return uniqueQueue.hasOwnProperty(request.query.requestId) ? false : (uniqueQueue[request.query.requestId] = true);\n\t });\n\t } else {\n\t throw new Error('Invalid value returned by the offlineQueueLoader function. Expected: array. Got: ' + typeof additionalQueue);\n\t }\n\t }\n\t\n\t dequeuingProcess();\n\t}\n\t\n\t/**\n\t * Renew all registered subscriptions. Triggered either by a successful connection/reconnection or by a\n\t * successful login attempt\n\t */\n\tfunction renewAllSubscriptions() {\n\t var self = this;\n\t\n\t Object.keys(self.subscriptions).forEach(function (roomId) {\n\t Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n\t var subscription = self.subscriptions[roomId][subscriptionId];\n\t subscription.renew(subscription.callback);\n\t });\n\t });\n\t}\n\t\n\t/**\n\t * Remove all registered subscriptions. Triggered either by a logout query or by un-setting the token\n\t */\n\tfunction removeAllSubscriptions() {\n\t var self = this;\n\t\n\t Object.keys(self.subscriptions).forEach(function (roomId) {\n\t Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n\t var subscription = self.subscriptions[roomId][subscriptionId];\n\t subscription.unsubscribe();\n\t });\n\t });\n\t}\n\t\n\t/**\n\t * Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their\n\t * insertion.\n\t *\n\t * The ID returned by this function is required to remove this listener at a later time.\n\t *\n\t * @param {string} event - name of the global event to subscribe to (see the 'eventListeners' object property)\n\t * @param {function} listener - callback to invoke each time an event is fired\n\t * @returns {string} Unique listener ID\n\t */\n\tKuzzle.prototype.addListener = function(event, listener) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t listenerType = typeof listener,\n\t listenerId;\n\t\n\t this.isValid();\n\t\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t if (listenerType !== 'function') {\n\t throw new Error('Invalid listener type: expected a function, got a ' + listenerType);\n\t }\n\t\n\t listenerId = uuid.v4();\n\t this.eventListeners[event].listeners.push({id: listenerId, fn: listener});\n\t return listenerId;\n\t};\n\t\n\t\n\t/**\n\t * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n\t * This method returns all available statistics from Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getAllStatistics = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getAllStatistics', cb);\n\t\n\t this.query({controller:'server', action: 'getAllStats'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.hits);\n\t });\n\t};\n\t\n\t/**\n\t * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n\t * This method allows getting either the last statistics frame, or a set of frames starting from a provided timestamp.\n\t *\n\t * @param {number} timestamp - Epoch time. Starting time from which the frames are to be retrieved\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getStatistics = function (timestamp, options, cb) {\n\t var\n\t queryCB,\n\t body;\n\t\n\t if (!cb) {\n\t if (arguments.length === 1) {\n\t cb = arguments[0];\n\t options = null;\n\t timestamp = null;\n\t } else {\n\t cb = arguments[1];\n\t if (typeof arguments[0] === 'object') {\n\t options = arguments[0];\n\t timestamp = null;\n\t } else {\n\t timestamp = arguments[0];\n\t options = null;\n\t }\n\t }\n\t }\n\t\n\t queryCB = function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, timestamp ? res.result.hits : [res.result]);\n\t };\n\t\n\t this.callbackRequired('Kuzzle.getStatistics', cb);\n\t\n\t body = timestamp ? {body: {startTime: timestamp}} : {};\n\t this.query({controller: 'server', action: timestamp ? 'getStats' : 'getLastStats'}, body, options, queryCB);\n\t};\n\t\n\t/**\n\t * Create a new instance of a Collection object.\n\t * If no index is specified, takes the default index.\n\t *\n\t * @param {string} collection - The name of the data collection you want to manipulate\n\t * @param {string} [index] - The name of the data index containing the data collection\n\t * @returns {Collection} A Collection instance\n\t */\n\tKuzzle.prototype.collection = function(collection, index) {\n\t this.isValid();\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Unable to create a new data collection object: no index specified');\n\t }\n\t\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (typeof index !== 'string' || typeof collection !== 'string') {\n\t throw new Error('Invalid index or collection argument: string expected');\n\t }\n\t\n\t if (!this.collections[index]) {\n\t this.collections[index] = {};\n\t }\n\t\n\t if (!this.collections[index][collection]) {\n\t this.collections[index][collection] = new Collection(this, collection, index);\n\t }\n\t\n\t return this.collections[index][collection];\n\t};\n\t\n\t/**\n\t * Empties the offline queue without replaying it.\n\t *\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.flushQueue = function () {\n\t this.offlineQueue = [];\n\t return this;\n\t};\n\t\n\t/**\n\t * Returns the list of known persisted data collections.\n\t *\n\t * @param {string} [index] - Index containing collections to be listed\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.listCollections = function () {\n\t var\n\t collectionType = 'all',\n\t index,\n\t options,\n\t cb,\n\t args = Array.prototype.slice.call(arguments),\n\t query;\n\t\n\t args.forEach(function(arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.listCollections: index required');\n\t }\n\t\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.listCollections', cb);\n\t\n\t if (options && options.type) {\n\t collectionType = options.type;\n\t }\n\t\n\t query = {body: {type: collectionType}};\n\t\n\t if (options && options.from) {\n\t query.body.from = options.from;\n\t }\n\t\n\t if (options && options.size) {\n\t query.body.size = options.size;\n\t }\n\t\n\t this.query({index: index, controller: 'collection', action: 'list'}, query, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.collections);\n\t });\n\t};\n\t\n\t/**\n\t * Returns the list of existing indexes in Kuzzle\n\t *\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.listIndexes = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.listIndexes', cb);\n\t\n\t this.query({controller: 'index', action: 'list'}, {}, options, function (err, res) {\n\t cb(err, err ? undefined : res.result.indexes);\n\t });\n\t};\n\t\n\t/**\n\t * Disconnects from Kuzzle and invalidate this instance.\n\t */\n\tKuzzle.prototype.disconnect = function () {\n\t var collection;\n\t\n\t this.state = 'disconnected';\n\t this.network.close();\n\t this.network = null;\n\t\n\t for (collection in this.collections) {\n\t if (this.collections.hasOwnProperty(collection)) {\n\t delete this.collections[collection];\n\t }\n\t }\n\t};\n\t\n\t/**\n\t * Returns the server informations\n\t *\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getServerInfo = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getServerInfo', cb);\n\t\n\t this.query({controller: 'server', action: 'info'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.serverInfo);\n\t });\n\t};\n\t\n\t/**\n\t * Forces an index refresh\n\t *\n\t * @param {string} index - The index to refresh. Defaults to Kuzzle.defaultIndex\n\t * @param {object} options - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.refreshIndex = function () {\n\t var\n\t index,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function(arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.refreshIndex: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.query({ index: index, controller: 'index', action: 'refresh'}, {}, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Returns de current autoRefresh status for the given index\n\t *\n\t * @param {string} index - The index to get the status from. Defaults to Kuzzle.defaultIndex\n\t * @param {object} options - Optinal arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getAutoRefresh = function () {\n\t var\n\t index,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function (arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.getAutoRefresh: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getAutoRefresh', cb);\n\t this.query({ index: index, controller: 'index', action: 'getAutoRefresh'}, {}, options, cb);\n\t};\n\t\n\t/**\n\t * (Un)Sets the autoRefresh flag on the given index\n\t *\n\t * @param {string} index - the index to modify. Defaults to Kuzzle.defaultIndex\n\t * @param {boolean} autoRefresh - The autoRefresh value to set\n\t * @param {object} options - Optional arguments\n\t * @param {responseCallback} cb - Handles the query result\n\t * @returns {object} this\n\t */\n\tKuzzle.prototype.setAutoRefresh = function () {\n\t var\n\t index,\n\t autoRefresh,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function (arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'boolean':\n\t autoRefresh = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.setAutoRefresh: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (autoRefresh === undefined) {\n\t throw new Error('Kuzzle.setAutoRefresh: autoRefresh value is required');\n\t }\n\t\n\t this.query({ index: index, controller: 'index', action: 'setAutoRefresh'}, { body: { autoRefresh: autoRefresh }}, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Return the current Kuzzle's UTC Epoch time, in milliseconds\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.now = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.now', cb);\n\t\n\t this.query({controller: 'server', action: 'now'}, {}, options, function (err, res) {\n\t cb(err, res && res.result.now);\n\t });\n\t};\n\t\n\t/**\n\t * This is a low-level method, exposed to allow advanced SDK users to bypass high-level methods.\n\t * Base method used to send read queries to Kuzzle\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} queryArgs - Query configuration\n\t * @param {object} query - The query data\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tKuzzle.prototype.query = function (queryArgs, query, options, cb) {\n\t var\n\t attr,\n\t object = {\n\t action: queryArgs.action,\n\t controller: queryArgs.controller,\n\t metadata: this.metadata\n\t },\n\t self = this;\n\t\n\t this.isValid();\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (options) {\n\t if (options.queuable === false && self.state === 'offline') {\n\t return self;\n\t }\n\t\n\t if (options.refresh) {\n\t object.refresh = options.refresh;\n\t }\n\t\n\t if (typeof options.from !== 'undefined' && options.from !== null) {\n\t object.from = options.from;\n\t }\n\t\n\t if (options.size) {\n\t object.size = options.size;\n\t }\n\t\n\t if (options.scroll) {\n\t object.scroll = options.scroll;\n\t }\n\t\n\t if (options.scrollId) {\n\t object.scrollId = options.scrollId;\n\t }\n\t\n\t if (options.metadata) {\n\t Object.keys(options.metadata).forEach(function (meta) {\n\t object.metadata[meta] = options.metadata[meta];\n\t });\n\t }\n\t }\n\t\n\t if (!query || typeof query !== 'object' || Array.isArray(query)) {\n\t throw new Error('Invalid query parameter: ' + query);\n\t }\n\t\n\t if (query.metadata) {\n\t Object.keys(query.metadata).forEach(function (meta) {\n\t object.metadata[meta] = query.metadata[meta];\n\t });\n\t }\n\t\n\t for (attr in query) {\n\t if (attr !== 'metadata' && query.hasOwnProperty(attr)) {\n\t object[attr] = query[attr];\n\t }\n\t }\n\t\n\t object = self.addHeaders(object, this.headers);\n\t\n\t /*\n\t * Do not add the token for the checkToken route, to avoid getting a token error when\n\t * a developer simply wish to verify his token\n\t */\n\t if (self.jwtToken !== undefined && !(object.controller === 'auth' && object.action === 'checkToken')) {\n\t object.jwt = self.jwtToken;\n\t }\n\t\n\t if (queryArgs.collection) {\n\t object.collection = queryArgs.collection;\n\t }\n\t\n\t if (queryArgs.index) {\n\t object.index = queryArgs.index;\n\t }\n\t\n\t if (!object.requestId) {\n\t object.requestId = uuid.v4();\n\t }\n\t\n\t if (self.state === 'connected' || (options && options.queuable === false)) {\n\t if (self.state === 'connected') {\n\t emitRequest.call(this, object, cb);\n\t } else {\n\t discardRequest(object, cb);\n\t }\n\t } else if (self.queuing || (options && options.queuable === true) || ['initializing', 'connecting'].indexOf(self.state) !== -1) {\n\t cleanQueue.call(this, object, cb);\n\t if (!self.queueFilter || self.queueFilter(object)) {\n\t self.offlineQueue.push({ts: Date.now(), query: object, cb: cb});\n\t self.emitEvent('offlineQueuePush', {query: object, cb: cb});\n\t }\n\t }\n\t else {\n\t discardRequest(object, cb);\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Removes all listeners, either from a specific event or from all events\n\t *\n\t * @param {string} event - One of the event described in the Event Handling section of this documentation\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.removeAllListeners = function (event) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t self = this;\n\t\n\t if (event) {\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t this.eventListeners[event].listeners = [];\n\t } else {\n\t knownEvents.forEach(function (eventName) {\n\t self.eventListeners[eventName].listeners = [];\n\t });\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Removes a listener from an event.\n\t *\n\t * @param {string} event - One of the event described in the Event Handling section of this documentation\n\t * @param {string} listenerId - The ID returned by addListener\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.removeListener = function (event, listenerId) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t self = this;\n\t\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t this.eventListeners[event].listeners.forEach(function (listener, index) {\n\t if (listener.id === listenerId) {\n\t self.eventListeners[event].listeners.splice(index, 1);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replays the requests queued during offline mode.\n\t * Works only if the SDK is not in a disconnected state, and if the autoReplay option is set to false.\n\t */\n\tKuzzle.prototype.replayQueue = function () {\n\t if (this.state !== 'offline' && !this.autoReplay) {\n\t cleanQueue.call(this);\n\t dequeue.call(this);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Sets the default Kuzzle index\n\t *\n\t * @param index\n\t * @returns this\n\t */\n\tKuzzle.prototype.setDefaultIndex = function (index) {\n\t if (typeof index !== 'string') {\n\t throw new Error('Invalid default index: [' + index + '] (an index name is expected)');\n\t }\n\t\n\t if (index.length === 0) {\n\t throw new Error('Cannot set an empty index as the default index');\n\t }\n\t\n\t this.defaultIndex = index;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tKuzzle.prototype.setHeaders = function (content, replace) {\n\t var self = this;\n\t\n\t if (typeof content !== 'object' || Array.isArray(content)) {\n\t throw new Error('Expected a content object, received a ' + typeof content);\n\t }\n\t\n\t if (replace) {\n\t self.headers = content;\n\t } else {\n\t Object.keys(content).forEach(function (key) {\n\t self.headers[key] = content[key];\n\t });\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Starts the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n\t */\n\tKuzzle.prototype.startQueuing = function () {\n\t if (this.state === 'offline' && !this.autoQueue) {\n\t this.queuing = true;\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Stops the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n\t */\n\tKuzzle.prototype.stopQueuing = function () {\n\t if (this.state === 'offline' && !this.autoQueue) {\n\t this.queuing = false;\n\t }\n\t\n\t return this;\n\t};\n\t\n\tfunction discardRequest(object, cb) {\n\t if (cb) {\n\t cb(new Error('Unable to execute request: not connected to a Kuzzle server.\\nDiscarded request: ' + JSON.stringify(object)));\n\t }\n\t}\n\t\n\tmodule.exports = Kuzzle;\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tfunction KuzzleSecurityDocument(Security, id, content) {\n\t\n\t if (!id) {\n\t throw new Error('A security document must have an id');\n\t }\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t kuzzle: {\n\t value: Security.kuzzle\n\t },\n\t Security: {\n\t value: Security\n\t },\n\t // read-only properties\n\t // writable properties\n\t id: {\n\t value: id,\n\t enumerable: true\n\t },\n\t content: {\n\t value: {},\n\t writable: true,\n\t enumerable: true\n\t }\n\t });\n\t\n\t if (content) {\n\t this.setContent(content, true);\n\t }\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['delete', 'update'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\t/**\n\t * Replaces the current content with new data.\n\t * Changes made by this function won’t be applied until the save method is called.\n\t *\n\t * @param {Object} data - New securityDocument content\n\t * @return {KuzzleSecurityDocument} this\n\t */\n\tKuzzleSecurityDocument.prototype.setContent = function (data) {\n\t this.content = data;\n\t return this;\n\t};\n\t\n\t/**\n\t * Serialize this object into a pojo\n\t *\n\t * @return {object} pojo representing this securityDocument\n\t */\n\tKuzzleSecurityDocument.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Delete the current KuzzleSecurityDocument into Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tKuzzleSecurityDocument.prototype.delete = function (options, cb) {\n\t var\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName), {_id: this.id}, options, function (error, res) {\n\t if (error) {\n\t return cb ? cb(error) : false;\n\t }\n\t\n\t if (cb) {\n\t cb(null, res.result._id);\n\t }\n\t });\n\t};\n\t\n\t/**\n\t * Update the current KuzzleSecurityDocument into Kuzzle.\n\t *\n\t * @param {object} content - Content to add to KuzzleSecurityDocument\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {KuzzleSecurityDocument} this\n\t */\n\tKuzzleSecurityDocument.prototype.update = function (content, options, cb) {\n\t var\n\t data = {},\n\t self = this;\n\t\n\t if (typeof content !== 'object') {\n\t throw new Error('Parameter \"content\" must be a object');\n\t }\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = self.id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName), data, options, function (error, response) {\n\t if (error) {\n\t return cb ? cb(error) : false;\n\t }\n\t\n\t self.setContent(response.result._source);\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\tmodule.exports = KuzzleSecurityDocument;\n\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * Kuzzle handles documents either as realtime messages or as stored documents.\n\t * Document is the object representation of one of these documents.\n\t *\n\t * Notes:\n\t * - this constructor may be called either with a documentId, a content, neither or both.\n\t * - providing a documentID to the constructor will automatically call refresh, unless a content is also provided\n\t *\n\t *\n\t * @param {object} kuzzleDataCollection - an instanciated Collection object\n\t * @param {string} [documentId] - ID of an existing document\n\t * @param {object} [content] - Initializes this document with the provided content\n\t * @constructor\n\t */\n\tfunction Document(kuzzleDataCollection, documentId, content) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t collection: {\n\t value: kuzzleDataCollection.collection,\n\t enumerable: true\n\t },\n\t dataCollection: {\n\t value: kuzzleDataCollection,\n\t enumerable: false\n\t },\n\t kuzzle: {\n\t value: kuzzleDataCollection.kuzzle,\n\t enumerable: false\n\t },\n\t // writable properties\n\t id: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t },\n\t content: {\n\t value: {},\n\t writable: true,\n\t enumerable: true\n\t },\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t version: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t // handling provided arguments\n\t if (!content && documentId && typeof documentId === 'object') {\n\t content = documentId;\n\t documentId = null;\n\t }\n\t\n\t if (content) {\n\t if (content._version) {\n\t this.version = content._version;\n\t delete content._version;\n\t }\n\t this.setContent(content, true);\n\t }\n\t\n\t if (documentId) {\n\t Object.defineProperty(this, 'id', {\n\t value: documentId,\n\t enumerable: true\n\t });\n\t }\n\t\n\t // promisifying\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['delete', 'refresh', 'save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this document\n\t */\n\tDocument.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t data._version = this.version;\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Overrides the toString() method in order to return a serialized version of the document\n\t *\n\t * @return {string} serialized version of this object\n\t */\n\tDocument.prototype.toString = function () {\n\t return JSON.stringify(this.serialize());\n\t};\n\t\n\t/**\n\t * Deletes this document in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.delete = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!self.id) {\n\t throw new Error('Document.delete: cannot delete a document without a document ID');\n\t }\n\t\n\t this.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'delete'), this.serialize(), options, cb && function (err) {\n\t cb(err, err ? undefined : self.id);\n\t });\n\t};\n\t\n\t/**\n\t * Replaces the current content with the last version of this document stored in Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.refresh = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!self.id) {\n\t throw new Error('Document.refresh: cannot retrieve a document if no ID has been provided');\n\t }\n\t\n\t this.kuzzle.callbackRequired('Document.refresh', cb);\n\t\n\t self.kuzzle.query(self.dataCollection.buildQueryArgs('document', 'get'), {_id: self.id}, options, function (error, res) {\n\t var newDocument;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t newDocument = new Document(self.dataCollection, self.id, res.result._source);\n\t newDocument.version = res.result._version;\n\t\n\t cb(null, newDocument);\n\t });\n\t};\n\t\n\t/**\n\t * Saves this document into Kuzzle.\n\t *\n\t * If this is a new document, this function will create it in Kuzzle and the id property will be made available.\n\t * Otherwise, this method will replace the latest version of this document in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'createOrReplace'), data, options, function (error, res) {\n\t if (error) {\n\t return cb && cb(error);\n\t }\n\t\n\t self.id = res.result._id;\n\t self.version = res.result._version;\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Sends the content of this document as a realtime message.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @returns {*} this\n\t */\n\tDocument.prototype.publish = function (options) {\n\t var data = this.serialize();\n\t\n\t this.kuzzle.query(this.dataCollection.buildQueryArgs('realtime', 'publish'), data, options);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replaces the current content with new data.\n\t * Changes made by this function won’t be applied until the save method is called.\n\t *\n\t * @param {object} data - New content\n\t * @param {boolean} replace - if true: replace this document content with the provided data\n\t */\n\tDocument.prototype.setContent = function (data, replace) {\n\t var self = this;\n\t\n\t if (replace) {\n\t this.content = data;\n\t }\n\t else {\n\t Object.keys(data).forEach(function (key) {\n\t self.content[key] = data[key];\n\t });\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Listens to events concerning this document. Has no effect if the document does not have an ID\n\t * (i.e. if the document has not yet been created as a persisted document).\n\t *\n\t * @param {object} [options] - subscription options\n\t * @param {responseCallback} cb - callback that will be called each time a change has been detected on this document\n\t */\n\tDocument.prototype.subscribe = function (options, cb) {\n\t var filters;\n\t\n\t if (options && !cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Document.subscribe', cb);\n\t\n\t if (!this.id) {\n\t throw new Error('Document.subscribe: cannot subscribe to a document if no ID has been provided');\n\t }\n\t\n\t filters = { ids: { values: [this.id] } };\n\t\n\t return this.dataCollection.subscribe(filters, options, cb);\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tDocument.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\t\n\tmodule.exports = Document;\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tfunction WSNode(host, port, ssl) {\n\t var self = this;\n\t this.WebSocket = typeof WebSocket !== 'undefined' ? WebSocket : __webpack_require__(!(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"ws\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));\n\t this.host = host;\n\t this.port = port;\n\t this.ssl = ssl;\n\t this.client = null;\n\t this.wasConnected = false;\n\t this.retrying = false;\n\t this.lasturl = null;\n\t\n\t /*\n\t Listeners are stored using the following format:\n\t roomId: {\n\t fn: callback_function,\n\t once: boolean\n\t }\n\t */\n\t this.listeners = {\n\t error: [],\n\t connect: [],\n\t disconnect: [],\n\t reconnect: []\n\t };\n\t\n\t /**\n\t * Creates a new socket from the provided arguments\n\t *\n\t * @constructor\n\t * @param {boolean} autoReconnect\n\t * @param {int} reconnectionDelay\n\t * @returns {Object} Socket\n\t */\n\t this.connect = function (autoReconnect, reconnectionDelay) {\n\t var\n\t url = (this.ssl ? 'wss://' : 'ws://') + this.host + ':' + this.port,\n\t options = typeof window !== 'undefined' ? undefined : {perMessageDeflate: false};\n\t\n\t if (url !== this.lasturl) {\n\t self.wasConnected = false;\n\t this.lasturl = url;\n\t }\n\t\n\t this.client = new this.WebSocket(url, options);\n\t\n\t this.client.onopen = function () {\n\t if (self.wasConnected) {\n\t poke(self.listeners, 'reconnect');\n\t }\n\t else {\n\t poke(self.listeners, 'connect');\n\t }\n\t self.wasConnected = true;\n\t };\n\t\n\t this.client.onclose = function (code, message) {\n\t if (code === 1000) {\n\t poke(self.listeners, 'disconnect');\n\t }\n\t else {\n\t onClientError.call(self, autoReconnect, reconnectionDelay, message);\n\t }\n\t };\n\t\n\t this.client.onerror = function (error) {\n\t onClientError.call(self, autoReconnect, reconnectionDelay, error);\n\t };\n\t\n\t this.client.onmessage = function (payload) {\n\t var data = JSON.parse(payload.data || payload);\n\t\n\t if (data.room && self.listeners[data.room]) {\n\t poke(self.listeners, data.room, data);\n\t }\n\t else if (self.listeners.discarded) {\n\t poke(self.listeners, 'discarded', data);\n\t }\n\t };\n\t };\n\t\n\t /**\n\t * Fires the provided callback whence a connection is established\n\t *\n\t * @param {function} callback\n\t */\n\t this.onConnect = function (callback) {\n\t this.listeners.connect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection error is received\n\t * @param {function} callback\n\t */\n\t this.onConnectError = function (callback) {\n\t this.listeners.error.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a disconnection occurred\n\t * @param {function} callback\n\t */\n\t this.onDisconnect = function (callback) {\n\t this.listeners.disconnect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection has been reestablished\n\t * @param {function} callback\n\t */\n\t this.onReconnect = function (callback) {\n\t this.listeners.reconnect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Registers a callback on a room. Once 1 message is received, fires the\n\t * callback and unregister it afterward.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.once = function (roomId, callback) {\n\t if (!this.listeners[roomId]) {\n\t this.listeners[roomId] = [];\n\t }\n\t\n\t this.listeners[roomId].push({\n\t fn: callback,\n\t keep: false\n\t });\n\t };\n\t\n\t /**\n\t * Registers a callback on a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.on = function (roomId, callback) {\n\t if (!this.listeners[roomId]) {\n\t this.listeners[roomId] = [];\n\t }\n\t\n\t this.listeners[roomId].push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Unregisters a callback from a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.off = function (roomId, callback) {\n\t var index = -1;\n\t\n\t if (this.listeners[roomId]) {\n\t // Array.findIndex is not supported by internet explorer\n\t this.listeners[roomId].some(function (listener, i) {\n\t if (listener.fn === callback) {\n\t index = i;\n\t return true;\n\t }\n\t\n\t return false;\n\t });\n\t\n\t if (index !== -1) {\n\t if (this.listeners[roomId].length === 1 && ['error', 'connect', 'disconnect', 'reconnect'].indexOf(roomId) === -1) {\n\t delete this.listeners[roomId];\n\t }\n\t else {\n\t this.listeners[roomId].splice(index, 1);\n\t }\n\t }\n\t }\n\t };\n\t\n\t\n\t /**\n\t * Sends a payload to the connected server\n\t *\n\t * @param {Object} payload\n\t */\n\t this.send = function (payload) {\n\t if (this.client && this.client.readyState === this.client.OPEN) {\n\t this.client.send(JSON.stringify(payload));\n\t }\n\t };\n\t\n\t /**\n\t * Closes the connection\n\t */\n\t this.close = function () {\n\t this.listeners = {\n\t error: [],\n\t connect: [],\n\t disconnect: [],\n\t reconnect: []\n\t };\n\t\n\t this.wasConnected = false;\n\t this.client.close();\n\t this.client = null;\n\t };\n\t}\n\t\n\t/**\n\t * Executes all registered listeners in the provided\n\t * \"listeners\" structure.\n\t *\n\t * Listeners are of the following format:\n\t * [\n\t * { fn: callback, once: boolean },\n\t * ...\n\t * ]\n\t *\n\t * @private\n\t * @param {Object} listeners\n\t * @param {string} roomId\n\t * @param {Object} [payload]\n\t */\n\tfunction poke (listeners, roomId, payload) {\n\t var\n\t i,\n\t length = listeners[roomId].length;\n\t\n\t for (i = 0; i < length; ++i) {\n\t listeners[roomId][i].fn(payload);\n\t\n\t if (!listeners[roomId][i].keep) {\n\t if (listeners[roomId].length > 1) {\n\t listeners[roomId].splice(i, 1);\n\t --i;\n\t --length;\n\t }\n\t else {\n\t delete listeners[roomId];\n\t }\n\t }\n\t }\n\t}\n\t\n\t/**\n\t * Called when the connection closes with an error state\n\t *\n\t * @param {boolean} autoReconnect\n\t * @param {number} reconnectionDelay\n\t * @param {string|Object} message\n\t */\n\tfunction onClientError(autoReconnect, reconnectionDelay, message) {\n\t var self = this;\n\t\n\t if (autoReconnect && !self.retrying) {\n\t self.retrying = true;\n\t setTimeout(function () {\n\t self.retrying = false;\n\t self.connect(autoReconnect, reconnectionDelay);\n\t }, reconnectionDelay);\n\t }\n\t\n\t poke(self.listeners, 'error', message);\n\t}\n\t\n\tmodule.exports = WSNode;\n\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t KuzzleSecurityDocument = __webpack_require__(1);\n\t\n\t/**\n\t * @param {Security} Security\n\t * @param {string} id\n\t * @param {Object} content\n\t * @constructor\n\t */\n\tfunction User(Security, id, content) {\n\t\n\t KuzzleSecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteUser'\n\t },\n\t updateActionName: {\n\t value: 'updateUser'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['save', 'saveRestricted'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\tUser.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n\t constructor: {\n\t value: User\n\t }\n\t});\n\t\n\t/**\n\t * Set profiles in content\n\t * @param {array} profileIds - an array of profiles ids string\n\t *\n\t * @returns {User} this\n\t */\n\tUser.prototype.setProfiles = function (profileIds) {\n\t if (!Array.isArray(profileIds) || typeof profileIds[0] !== 'string') {\n\t throw new Error('Parameter \"profileIds\" must be an array of strings');\n\t }\n\t\n\t this.content.profileIds = profileIds;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Add a profile\n\t * @param {string} profileId - a profile ids string\n\t *\n\t * @returns {User} this\n\t */\n\tUser.prototype.addProfile = function (profileId) {\n\t if (typeof profileId !== 'string') {\n\t throw new Error('Parameter \"profileId\" must be a string');\n\t }\n\t\n\t if (!this.content.profileIds) {\n\t this.content.profileIds = [];\n\t }\n\t\n\t if (this.content.profileIds.indexOf(profileId) === -1) {\n\t this.content.profileIds.push(profileId);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Saves this user into Kuzzle.\n\t *\n\t * If this is a new user, this function will create it in Kuzzle.\n\t * Otherwise, this method will replace the latest version of this user in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {User} this\n\t */\n\tUser.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Saves this user as restricted into Kuzzle.\n\t *\n\t * This function will create a new user. It is not usable to update an existing user.\n\t * The \"profileIds\" property must not be provided, or the request will be rejected by Kuzzle.\n\t * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n\t *\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {User} this\n\t */\n\tUser.prototype.saveRestricted = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createRestrictedUser'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this User\n\t */\n\tUser.prototype.serialize = function () {\n\t return {_id: this.id, body: this.content};\n\t};\n\t\n\t/**\n\t * Return the associated profiles IDs\n\t *\n\t * @return {array} the associated profiles IDs\n\t */\n\tUser.prototype.getProfiles = function () {\n\t return this.content.profileIds;\n\t};\n\t\n\tmodule.exports = User;\n\n\n/***/ },\n/* 5 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar v1 = __webpack_require__(19);\n\tvar v4 = __webpack_require__(20);\n\t\n\tvar uuid = v4;\n\tuuid.v1 = v1;\n\tuuid.v4 = v4;\n\t\n\tmodule.exports = uuid;\n\n\n/***/ },\n/* 6 */\n/***/ function(module, exports) {\n\n\t/**\n\t * Convert array of 16 byte values to UUID string format of the form:\n\t * XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n\t */\n\tvar byteToHex = [];\n\tfor (var i = 0; i < 256; ++i) {\n\t byteToHex[i] = (i + 0x100).toString(16).substr(1);\n\t}\n\t\n\tfunction bytesToUuid(buf, offset) {\n\t var i = offset || 0;\n\t var bth = byteToHex;\n\t return bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]];\n\t}\n\t\n\tmodule.exports = bytesToUuid;\n\n\n/***/ },\n/* 7 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t// Unique ID creation requires a high quality random # generator. In the\n\t// browser this is a little complicated due to unknown quality of Math.random()\n\t// and inconsistent support for the `crypto` API. We do the best we can via\n\t// feature-detection\n\tvar rng;\n\t\n\tvar crypto = (window).crypto || (window).msCrypto; // for IE 11\n\tif (crypto && crypto.getRandomValues) {\n\t // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n\t var rnds8 = new Uint8Array(16);\n\t rng = function whatwgRNG() {\n\t crypto.getRandomValues(rnds8);\n\t return rnds8;\n\t };\n\t}\n\t\n\tif (!rng) {\n\t // Math.random()-based (RNG)\n\t //\n\t // If all else fails, use Math.random(). It's fast, but is of unspecified\n\t // quality.\n\t var rnds = new Array(16);\n\t rng = function() {\n\t for (var i = 0, r; i < 16; i++) {\n\t if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n\t rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n\t }\n\t\n\t return rnds;\n\t };\n\t}\n\t\n\tmodule.exports = rng;\n\n\n/***/ },\n/* 8 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t KuzzleSearchResult = __webpack_require__(12),\n\t Document = __webpack_require__(2),\n\t CollectionMapping = __webpack_require__(9),\n\t Room = __webpack_require__(11),\n\t KuzzleSubscribeResult = __webpack_require__(13);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * A data collection is a set of data managed by Kuzzle. It acts like a data table for persistent documents,\n\t * or like a room for pub/sub messages.\n\t *\n\t * @property {string} collection\n\t * @property {string} index\n\t * @property {Kuzzle} kuzzle\n\t * @property {Array.} collection\n\t * @param {object} kuzzle - Kuzzle instance to inherit from\n\t * @param {string} collection - name of the data collection to handle\n\t * @param {string} index - Index containing the data collection\n\t * @constructor\n\t */\n\tfunction Collection(kuzzle, collection, index) {\n\t if (!index || !collection) {\n\t throw new Error('The Collection object constructor needs an index and a collection arguments');\n\t }\n\t\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t index: {\n\t value: index,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzle.headers)),\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t Object.defineProperty(this, 'buildQueryArgs', {\n\t value: function (controller, action) {\n\t return {\n\t controller: controller,\n\t action: action,\n\t collection: this.collection,\n\t index: this.index\n\t };\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['publishMessage', 'setHeaders', 'subscribe'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Returns the number of documents matching the provided set of filters.\n\t *\n\t * There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function\n\t *\n\t * @param {object} filters - Filters in Elasticsearch Query DSL format\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.count = function (filters, options, cb) {\n\t var\n\t query;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.count', cb);\n\t\n\t query = this.kuzzle.addHeaders({body: filters}, this.headers);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('document', 'count'), query, options, function (error, result) {\n\t cb(error, result && result.result.count);\n\t });\n\t};\n\t\n\t/**\n\t * Create a new empty data collection, with no associated mapping.\n\t * Kuzzle automatically creates data collections when storing documents, but there are cases where we\n\t * want to create and prepare data collections before storing documents in it.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.create = function (options, cb) {\n\t var data = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('collection', 'create'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Create a new document in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t * - updateIfExist (boolean, default: false):\n\t * If the same document already exists: throw an error if sets to false.\n\t * Update the existing document otherwise\n\t *\n\t * @param {string} [id] - (optional) document identifier\n\t * @param {object} document - either an instance of a Document object, or a document\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Object} this\n\t */\n\tCollection.prototype.createDocument = function (id, document, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'create';\n\t\n\t if (id && typeof id !== 'string') {\n\t cb = options;\n\t options = document;\n\t document = id;\n\t id = null;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (document instanceof Document) {\n\t data = document.serialize();\n\t } else {\n\t data.body = document;\n\t }\n\t\n\t if (options) {\n\t action = options.updateIfExist ? 'createOrReplace' : 'create';\n\t }\n\t\n\t if (id) {\n\t data._id = id;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, self.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n\t var doc;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t doc = new Document(self, res.result._id, res.result._source);\n\t doc.version = res.result._version;\n\t cb(null, doc);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete persistent documents.\n\t *\n\t * There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string|object} arg - Either a document ID (will delete only this particular document), or a set of filters\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Collection} this\n\t */\n\tCollection.prototype.deleteDocument = function (arg, options, cb) {\n\t var\n\t action,\n\t data = {};\n\t\n\t if (typeof arg === 'string') {\n\t data._id = arg;\n\t action = 'delete';\n\t } else {\n\t data.body = arg;\n\t action = 'deleteByQuery';\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n\t if (err) {\n\t cb(err);\n\t }\n\t else {\n\t cb(null, (action === 'delete' ? [res.result._id] : res.result.ids));\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Retrieve a single stored document using its unique document ID.\n\t *\n\t * @param {string} documentId - Unique document identifier\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.fetchDocument = function (documentId, options, cb) {\n\t var\n\t data = {_id: documentId},\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Collection.fetch', cb);\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'get'), data, options, function (err, res) {\n\t var document;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t document = new Document(self, res.result._id, res.result._source);\n\t document.version = res.result._version;\n\t cb(null, document);\n\t });\n\t};\n\t\n\t/**\n\t * Retrieves all documents stored in this data collection\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.fetchAllDocuments = function (options, cb) {\n\t var\n\t warnEmitted = false,\n\t documents = [],\n\t filters = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t // copying pagination options to the search filter\n\t if (!options) {\n\t options = {};\n\t }\n\t\n\t if (!options.from) {\n\t options.from = 0;\n\t }\n\t\n\t if (!options.size) {\n\t options.size = 1000;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.fetchAllDocuments', cb);\n\t\n\t this.search(filters, options, function getNextDocuments (error, searchResult) {\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t if (searchResult instanceof KuzzleSearchResult) {\n\t if (searchResult.total > 10000 && !warnEmitted) {\n\t warnEmitted = true;\n\t console.warn('Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead'); // eslint-disable-line no-console\n\t }\n\t\n\t searchResult.documents.forEach(function(document) {\n\t documents.push(document);\n\t });\n\t searchResult.next(getNextDocuments);\n\t }\n\t else {\n\t cb(null, documents);\n\t }\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Instantiates a CollectionMapping object containing the current mapping of this collection.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Returns an instantiated CollectionMapping object\n\t */\n\tCollection.prototype.getMapping = function (options, cb) {\n\t var kuzzleMapping;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.getMapping', cb);\n\t\n\t kuzzleMapping = new CollectionMapping(this);\n\t kuzzleMapping.refresh(options, cb);\n\t};\n\t\n\t/**\n\t * Publish a realtime message\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} document - either a Document instance or a JSON object\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Returns a raw Kuzzle response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.publishMessage = function (document, options, cb) {\n\t var data = {};\n\t\n\t if (document instanceof Document) {\n\t data = document.serialize();\n\t } else {\n\t data.body = document;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('realtime', 'publish'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replace an existing document with a new one.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string} documentId - Unique document identifier of the document to replace\n\t * @param {object} content - JSON object representing the new document version\n\t * @param {object} [options] - additional arguments\n\t * @param {responseCallback} [cb] - Returns an instantiated Document object\n\t * @return {object} this\n\t */\n\tCollection.prototype.replaceDocument = function (documentId, content, options, cb) {\n\t var\n\t self = this,\n\t data = {\n\t _id: documentId,\n\t body: content\n\t };\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'createOrReplace'), data, options, cb && function (err, res) {\n\t var document;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t document = new Document(self, res.result._id, res.result._source);\n\t document.version = res.result._version;\n\t cb(null, document);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Executes an advanced search on the data collection.\n\t *\n\t * /!\\ There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function.\n\t *\n\t * @param {object} filters - Filters in Elasticsearch Query DSL format\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\t\n\tCollection.prototype.search = function (filters, options, cb) {\n\t var\n\t query,\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t self.kuzzle.callbackRequired('Collection.search', cb);\n\t\n\t query = self.kuzzle.addHeaders({body: filters}, this.headers);\n\t\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) {\n\t var documents = [];\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t result.result.hits.forEach(function (doc) {\n\t var newDocument = new Document(self, doc._id, doc._source);\n\t\n\t newDocument.version = doc._version;\n\t\n\t documents.push(newDocument);\n\t });\n\t\n\t if (result.result._scroll_id) {\n\t options.scrollId = result.result._scroll_id;\n\t }\n\t\n\t cb(null, new KuzzleSearchResult(\n\t self,\n\t result.result.total,\n\t documents,\n\t result.result.aggregations ? result.result.aggregations : [],\n\t {options: options, filters: filters}\n\t ));\n\t });\n\t};\n\t\n\t/**\n\t * A \"scroll\" option can be passed to search queries, creating persistent\n\t * paginated results.\n\t * This method can be used to manually get the next page of a search result,\n\t * instead of using KuzzleSearchResult.next()\n\t *\n\t * @param {string} scrollId\n\t * @param {object} [options]\n\t * @param {object} [filters]\n\t * @param {responseCallback} cb\n\t */\n\tCollection.prototype.scroll = function (scrollId, options, filters, cb) {\n\t var\n\t request = {},\n\t self = this;\n\t\n\t if (!scrollId) {\n\t throw new Error('Collection.scroll: scrollId is required');\n\t }\n\t\n\t if (!cb) {\n\t cb = filters;\n\t filters = null;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.scroll', cb);\n\t\n\t request.scrollId = scrollId;\n\t\n\t if (options && options.scroll) {\n\t request.scroll = options.scroll;\n\t }\n\t\n\t this.kuzzle.query({controller: 'document', action: 'scroll'}, request, options, function (error, result) {\n\t var documents = [];\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t result.result.hits.forEach(function (doc) {\n\t var newDocument = new Document(self, doc._id, doc._source);\n\t\n\t newDocument.version = doc._version;\n\t\n\t documents.push(newDocument);\n\t });\n\t\n\t if (result.result._scroll_id) {\n\t options.scrollId = result.result._scroll_id;\n\t }\n\t\n\t cb(null, new KuzzleSearchResult(\n\t self,\n\t result.result.total,\n\t documents,\n\t result.result.aggregations ? result.result.aggregations : [],\n\t {options: options, filters: filters}\n\t ));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Subscribes to this data collection with a set of filters.\n\t * To subscribe to the entire data collection, simply provide an empty filter.\n\t *\n\t * @param {object} filters - Filters in Kuzzle DSL format\n\t * @param {object} [options] - subscriptions options\n\t * @param {responseCallback} cb - called for each new notification\n\t * @returns {*} KuzzleSubscribeResult object\n\t */\n\tCollection.prototype.subscribe = function (filters, options, cb) {\n\t var\n\t room,\n\t subscribeResult;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.subscribe', cb);\n\t\n\t subscribeResult = new KuzzleSubscribeResult();\n\t room = new Room(this, options);\n\t\n\t room.renew(filters, cb, subscribeResult.done.bind(subscribeResult));\n\t\n\t return subscribeResult;\n\t};\n\t\n\t/**\n\t * Truncate the data collection, removing all stored documents but keeping all associated mappings.\n\t * This method is a lot faster than removing all documents using a query.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.truncate = function (options, cb) {\n\t var data = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('collection', 'truncate'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t\n\t/**\n\t * Update parts of a document\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - metadata (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string} documentId - Unique document identifier of the document to update\n\t * @param {object} content - JSON object containing changes to perform on the document\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Returns an instantiated Document object\n\t * @return {object} this\n\t */\n\tCollection.prototype.updateDocument = function (documentId, content, options, cb) {\n\t var\n\t data = {\n\t _id: documentId,\n\t body: content\n\t },\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'update'), data, options, cb && function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t (new Document(self, res.result._id)).refresh(cb);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t\n\t/**\n\t * Instantiate a new Document object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - document id\n\t * @param {object} content - document content\n\t * @constructor\n\t */\n\tCollection.prototype.document = function (id, content) {\n\t return new Document(this, id, content);\n\t};\n\t\n\t/**\n\t * Instantiate a new Room object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {object} [options] - subscription configuration\n\t * @constructor\n\t */\n\tCollection.prototype.room = function (options) {\n\t return new Room(this, options);\n\t};\n\t\n\t/**\n\t * Instantiate a new CollectionMapping object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {object} [mapping] - mapping to instantiate the CollectionMapping object with\n\t * @constructor\n\t */\n\tCollection.prototype.collectionMapping = function (mapping) {\n\t return new CollectionMapping(this, mapping);\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tCollection.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\tmodule.exports = Collection;\n\n\n/***/ },\n/* 9 */\n/***/ function(module, exports) {\n\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t\n\t/**\n\t * When creating a new data collection in the persistent data storage layer, Kuzzle uses a default mapping.\n\t * It means that, by default, you won’t be able to exploit the full capabilities of our persistent data storage layer\n\t * (currently handled by ElasticSearch), and your searches may suffer from below-average performances, depending on\n\t * the amount of data you stored in a collection and the complexity of your database.\n\t *\n\t * The CollectionMapping object allow to get the current mapping of a data collection and to modify it if needed.\n\t *\n\t * @param {object} collection - Instance of the inherited Collection object\n\t * @param {object} [mapping] - mappings\n\t * @constructor\n\t */\n\tfunction CollectionMapping(collection, mapping) {\n\t Object.defineProperties(this, {\n\t //read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: collection.kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(collection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t mapping: {\n\t value: mapping || {},\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['set', 'setHeaders'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Applies the new mapping to the data collection.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tCollectionMapping.prototype.apply = function (options, cb) {\n\t var\n\t self = this,\n\t data = this.kuzzle.addHeaders({body: {properties: this.mapping}}, this.headers);\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.collection.buildQueryArgs('collection', 'updateMapping'), data, options, function (err) {\n\t if (err) {\n\t return cb && cb(err);\n\t }\n\t\n\t self.refresh(options, cb);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replaces the current content with the mapping stored in Kuzzle\n\t *\n\t * Calling this function will discard any uncommited changes. You can commit changes by calling the “apply” function\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tCollectionMapping.prototype.refresh = function (options, cb) {\n\t var\n\t self = this,\n\t data = this.kuzzle.addHeaders({}, this.headers);\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.collection.buildQueryArgs('collection', 'getMapping'), data, options, function (err, res) {\n\t if (err) {\n\t return cb ? cb(err) : false;\n\t }\n\t\n\t if (res.result[self.collection.index]) {\n\t if (res.result[self.collection.index].mappings[self.collection.collection]) {\n\t self.mapping = res.result[self.collection.index].mappings[self.collection.collection].properties;\n\t\n\t // Mappings can be empty. The mapping property should never be \"undefined\"\n\t if (self.mapping === undefined) {\n\t self.mapping = {};\n\t }\n\t } else {\n\t return cb && cb(new Error('No mapping found for collection ' + self.collection.collection));\n\t }\n\t } else {\n\t return cb && cb(new Error('No mapping found for index ' + self.collection.index));\n\t }\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t\n\t/**\n\t * Adds or updates a field mapping.\n\t *\n\t * Changes made by this function won’t be applied until you call the apply method\n\t *\n\t * @param {string} field - Name of the field from which the mapping is to be added or updated\n\t * @param {object} mapping - corresponding field mapping\n\t * @returns {CollectionMapping}\n\t */\n\tCollectionMapping.prototype.set = function (field, mapping) {\n\t this.mapping[field] = mapping;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tCollectionMapping.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\tmodule.exports = CollectionMapping;\n\n\n/***/ },\n/* 10 */\n/***/ function(module, exports) {\n\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t\n\t/**\n\t * Kuzzle's memory storage is a separate data store from the database layer.\n\t * It is internaly based on Redis. You can access most of Redis functions (all\n\t * lowercased), excepting:\n\t * * all cluster based functions\n\t * * all script based functions\n\t * * all cursors functions\n\t *\n\t * For instance:\n\t * kuzzle.memoryStorage\n\t * .set('myKey', 'myValue')\n\t * .get('myKey', function (err, response) {\n\t * console.log(response.result);\n\t *\n\t * // { _id: 'foo', body: { value: 'myValue' }}\n\t * });\n\t *\n\t *\n\t * @param {object} kuzzle - Kuzzle instance to inherit from\n\t * @constructor\n\t */\n\tfunction MemoryStorage(kuzzle) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t kuzzle: {\n\t value: kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzle.headers)),\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t this.setHeaders = kuzzle.setHeaders.bind(this);\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['setHeaders'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t\n\t/**\n\t * constructs the memoryStorage functions.\n\t */\n\t(function() {\n\t\n\t var\n\t keyVal = ['id', 'value'],\n\t idOrKeys = ['id', 'keys'],\n\t commands = {\n\t append: keyVal,\n\t bgrewriteaof: [],\n\t bgsave: [],\n\t bitcount: ['id', 'start', 'end'],\n\t bitop: ['operation', 'destkey', idOrKeys],\n\t bitpos: ['id', 'bit', { __opts__: ['start', 'end']}],\n\t blpop: [idOrKeys, 'timeout'],\n\t brpoplpush: ['source', 'destination'],\n\t dbsize: [],\n\t decrby: keyVal,\n\t del: [idOrKeys],\n\t discard: [],\n\t exec: [],\n\t exists: [idOrKeys],\n\t expire: ['id', 'seconds'],\n\t expireat: ['id', 'timestamp'],\n\t flushdb: [],\n\t // @todo: implement geolocation methods once available in Redis stable release\n\t getbit: ['id', 'offset'],\n\t getrange: ['id', 'start', 'end'],\n\t hdel: ['id', ['field', 'fields']],\n\t hexists: ['id', 'field'],\n\t hincrby: ['id', 'field', 'value'],\n\t hmset: ['id', 'values'],\n\t hset: ['id', 'field', 'value'],\n\t info: ['section'],\n\t keys: [ 'pattern' ],\n\t lastsave: [],\n\t lindex: ['id', 'idx'],\n\t linsert: ['id', 'position', 'pivot', 'value'],\n\t lpush: ['id', ['value', 'values']],\n\t lrange: ['id', 'start', 'stop'],\n\t lrem: ['id', 'count', 'value'],\n\t lset: ['id', 'idx', 'value'],\n\t ltrim: ['id', 'start', 'stop'],\n\t mset: ['values'],\n\t multi: [],\n\t object: ['subcommand', 'args'],\n\t pexpire: ['id', 'milliseconds'],\n\t pexpireat: ['id', 'timestamp'],\n\t pfadd: ['id', ['element', 'elements']],\n\t pfmerge: ['destkey', ['sourcekey', 'sourcekeys']],\n\t ping: [],\n\t psetex: ['id', 'milliseconds', 'value'],\n\t publish: ['channel', 'message'],\n\t randomkey: [],\n\t rename: ['id', 'newkey'],\n\t renamenx: ['id', 'newkey'],\n\t restore: ['id', 'ttl', 'content'],\n\t rpoplpush: ['source', 'destination'],\n\t sadd: ['id', ['member', 'members']],\n\t save: [],\n\t set: ['id', 'value', {__opts__:['ex', 'px', 'nx', 'xx']}],\n\t sdiffstore: ['destination', idOrKeys],\n\t setbit: ['id', 'offset', 'value'],\n\t setex: ['id', 'seconds', 'value'],\n\t setrange: ['id', 'offset', 'value'],\n\t sinterstore: ['destination', idOrKeys],\n\t sismember: ['id', 'member'],\n\t smove: ['id', 'destination', 'member'],\n\t sort: ['id', {__opts__:['by', 'offset', 'count', 'get', 'direction', 'alpha', 'store']}],\n\t spop: ['id', 'count'],\n\t srem: ['id', ['member', 'members']],\n\t sunionstore: ['destination', idOrKeys],\n\t unwatch: [],\n\t wait: ['numslaves', 'timeout'],\n\t zadd: ['id', {__opts__: ['nx', 'xx', 'ch', 'incr', 'score', 'member', 'members']}],\n\t zcount: ['id', 'min', 'max'],\n\t zincrby: ['id', 'value', 'member'],\n\t zinterstore: ['destination', idOrKeys, {__opts__: ['weight', 'weights', 'aggregate']}],\n\t zlexcount: ['id', 'min', 'max'],\n\t zrange: ['id', 'start', 'stop', {__opts__: ['withscores']}],\n\t zrangebylex: ['id', 'min', 'max', {__opts__: ['offset', 'count']}],\n\t zrangebyscore: ['id', 'min', 'max', {__opts__: ['withscores', 'offset', 'count']}],\n\t zrem: ['id', 'member'],\n\t zremrangebylex: ['id', 'min', 'max'],\n\t zremrangebyscore: ['id', 'min', 'max'],\n\t zrevrangebylex: ['id', 'max', 'min', {__opts__: ['offset', 'count']}],\n\t zrevrangebyscore: ['id', 'max', 'min', {__opts__: ['withscores', 'offset', 'count']}],\n\t zrevrank: ['id', 'member']\n\t };\n\t\n\t // unique argument key\n\t commands.decr = commands.get = commands.dump = commands.hgetall = commands.hkeys = commands.hlen = commands.hstrlen = commands.hvals = commands.incr = commands.llen = commands.lpop = commands.persist = commands.pttl = commands.rpop = commands.scard = commands.smembers = commands.strlen = commands.ttl = commands.type = commands.zcard = ['id'];\n\t\n\t // key value\n\t commands.getset = commands.lpushx = keyVal;\n\t\n\t // key key...\n\t commands.del = commands.exists = commands.mget = commands.pfcount = commands.sdiff = commands.sinter = commands.sunion = commands.watch = [idOrKeys];\n\t\n\t commands.incrby = commands.incrbyfloat = commands.decrby;\n\t commands.brpop = commands.blpop;\n\t commands.hget = commands.hexists;\n\t commands.hmget = commands.hdel;\n\t commands.hsetnx = commands.hset;\n\t commands.msetnx = commands.mset;\n\t commands.rpush = commands.lpush;\n\t commands.hincrbyfloat = commands.hincrby;\n\t commands.srandmember = commands.spop;\n\t commands.zrevrange = commands.zrange;\n\t commands.zscore = commands.zrevrank;\n\t\n\t Object.keys(commands).forEach(function (command) {\n\t MemoryStorage.prototype[command] = function () {\n\t var\n\t args = Array.prototype.slice.call(arguments),\n\t options = null,\n\t cb,\n\t query = {\n\t controller: 'ms',\n\t action: command\n\t },\n\t data = {};\n\t\n\t if (typeof args[args.length - 1] === 'function') {\n\t cb = args.pop();\n\t }\n\t\n\t if (args.length && typeof args[args.length - 1] === 'object' && Object.keys(args[args.length - 1]).length === 1 && args[args.length - 1].queuable !== undefined) {\n\t options = args.pop();\n\t }\n\t\n\t commands[command].forEach(function (v, i) {\n\t if (args[i] === undefined) {\n\t return;\n\t }\n\t\n\t if (Array.isArray(v)) {\n\t v = Array.isArray(args[i]) ? v[1] : v[0];\n\t }\n\t\n\t if (v === 'id') {\n\t data._id = args[i];\n\t }\n\t else {\n\t if (!data.body) {\n\t data.body = {};\n\t }\n\t\n\t if (typeof v === 'object' && v.__opts__ !== undefined) {\n\t v.__opts__.forEach(function (arg) {\n\t if (args[i][arg] !== undefined) {\n\t data.body[arg] = args[i][arg];\n\t }\n\t });\n\t }\n\t else {\n\t data.body[v] = args[i];\n\t }\n\t }\n\t });\n\t\n\t this.kuzzle.query(query, data, options, cb);\n\t\n\t return this;\n\t\n\t };\n\t });\n\t\n\t})();\n\t\n\tmodule.exports = MemoryStorage;\n\n\n/***/ },\n/* 11 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t uuid = __webpack_require__(5),\n\t Document = __webpack_require__(2);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * This object is the result of a subscription request, allowing to manipulate the subscription itself.\n\t *\n\t * In Kuzzle, you don’t exactly subscribe to a room or a topic but, instead, you subscribe to documents.\n\t *\n\t * What it means is that, to subscribe, you provide to Kuzzle a set of matching filters.\n\t * Once you have subscribed, if a pub/sub message is published matching your filters, or if a matching stored\n\t * document change (because it is created, updated or deleted), then you’ll receive a notification about it.\n\t *\n\t * @param {object} kuzzleDataCollection - an instantiated and valid kuzzle object\n\t * @param {object} [options] - subscription optional configuration\n\t * @constructor\n\t */\n\tfunction Room(kuzzleDataCollection, options) {\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t callback: {\n\t value: null,\n\t writable: true\n\t },\n\t channel: {\n\t value: null,\n\t writable: true\n\t },\n\t id: {\n\t value: uuid.v4()\n\t },\n\t lastRenewal: {\n\t value: null,\n\t writable: true\n\t },\n\t notifier: {\n\t value: null,\n\t writable: true\n\t },\n\t onDoneCB: {\n\t value: null,\n\t writable: true\n\t },\n\t queue: {\n\t value: [],\n\t writable: true\n\t },\n\t // Delay before allowing a subscription renewal\n\t renewalDelay: {\n\t value: 500\n\t },\n\t scope: {\n\t value: options && options.scope ? options.scope : 'all'\n\t },\n\t state: {\n\t value: options && options.state ? options.state : 'done'\n\t },\n\t subscribing: {\n\t value: false,\n\t writable: true\n\t },\n\t users: {\n\t value: options && options.users ? options.users : 'none'\n\t },\n\t // read-only properties\n\t collection: {\n\t value: kuzzleDataCollection,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: kuzzleDataCollection.kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t filters: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t metadata: {\n\t value: (options && options.metadata) ? options.metadata : {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t roomId: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t subscribeToSelf: {\n\t value: options && typeof options.subscribeToSelf === 'boolean' ? options.subscribeToSelf : true,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['count'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Returns the number of other subscriptions on that room.\n\t *\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tRoom.prototype.count = function (cb) {\n\t var data;\n\t\n\t this.kuzzle.callbackRequired('Room.count', cb);\n\t\n\t data = this.kuzzle.addHeaders({body: {roomId: this.roomId}}, this.headers);\n\t\n\t if (!isReady.call(this)) {\n\t this.queue.push({action: 'count', args: [cb]});\n\t return;\n\t }\n\t\n\t if (!this.roomId) {\n\t throw new Error('Room.count: cannot count subscriptions on an inactive room');\n\t }\n\t\n\t this.kuzzle.query(this.collection.buildQueryArgs('realtime', 'count'), data, function (err, res) {\n\t cb(err, res && res.result.count);\n\t });\n\t};\n\t\n\t/**\n\t * Renew the subscription using new filters\n\t *\n\t * @param {object} [filters] - Filters in Kuzzle DSL format\n\t * @param {responseCallback} notificationCB - called for each new notification\n\t * @param {responseCallback} [cb] - handles the query response\n\t */\n\tRoom.prototype.renew = function (filters, notificationCB, cb) {\n\t var\n\t now = Date.now(),\n\t subscribeQuery = {\n\t scope: this.scope,\n\t state: this.state,\n\t users: this.users\n\t },\n\t self = this;\n\t\n\t if (typeof filters === 'function') {\n\t cb = notificationCB;\n\t notificationCB = filters;\n\t filters = null;\n\t }\n\t\n\t if (!cb) {\n\t cb = self.onDoneCB;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Room.renew', notificationCB);\n\t\n\t /*\n\t Skip subscription renewal if another one was performed a moment before\n\t */\n\t if (self.lastRenewal && (now - self.lastRenewal) <= self.renewalDelay) {\n\t return cb && cb(new Error('Subscription already renewed less than ' + self.renewalDelay + 'ms ago'));\n\t }\n\t\n\t if (filters) {\n\t self.filters = filters;\n\t }\n\t\n\t /*\n\t if not yet connected, register itself to the subscriptions list and wait for the\n\t main Kuzzle object to renew once online\n\t */\n\t if (self.kuzzle.state !== 'connected') {\n\t self.callback = notificationCB;\n\t self.onDoneCB = cb;\n\t self.kuzzle.subscriptions.pending[self.id] = self;\n\t return;\n\t }\n\t\n\t if (self.subscribing) {\n\t self.queue.push({action: 'renew', args: [filters, notificationCB, cb]});\n\t return;\n\t }\n\t\n\t self.unsubscribe();\n\t self.roomId = null;\n\t self.subscribing = true;\n\t self.callback = notificationCB;\n\t self.onDoneCB = cb;\n\t self.kuzzle.subscriptions.pending[self.id] = self;\n\t\n\t subscribeQuery.body = self.filters;\n\t subscribeQuery = self.kuzzle.addHeaders(subscribeQuery, this.headers);\n\t\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {metadata: self.metadata}, function (error, response) {\n\t delete self.kuzzle.subscriptions.pending[self.id];\n\t self.subscribing = false;\n\t\n\t if (error) {\n\t self.queue = [];\n\t return cb && cb(new Error('Error during Kuzzle subscription: ' + error.message));\n\t }\n\t\n\t self.lastRenewal = now;\n\t self.roomId = response.result.roomId;\n\t self.channel = response.result.channel;\n\t\n\t if (!self.kuzzle.subscriptions[self.roomId]) {\n\t self.kuzzle.subscriptions[self.roomId] = {};\n\t }\n\t\n\t self.kuzzle.subscriptions[self.roomId][self.id] = self;\n\t\n\t self.notifier = notificationCallback.bind(self);\n\t self.kuzzle.network.on(self.channel, self.notifier);\n\t\n\t dequeue.call(self);\n\t cb && cb(null, self);\n\t });\n\t};\n\t\n\t/**\n\t * Unsubscribes from Kuzzle.\n\t *\n\t * Stop listening immediately. If there is no listener left on that room, sends an unsubscribe request to Kuzzle, once\n\t * pending subscriptions reaches 0, and only if there is still no listener on that room.\n\t * We wait for pending subscriptions to finish to avoid unsubscribing while another subscription on that room is\n\t *\n\t * @return {*} this\n\t */\n\tRoom.prototype.unsubscribe = function () {\n\t var\n\t self = this,\n\t room = self.roomId,\n\t interval;\n\t\n\t if (!isReady.call(this)) {\n\t self.queue.push({action: 'unsubscribe', args: []});\n\t return self;\n\t }\n\t\n\t if (room) {\n\t self.kuzzle.network.off(self.channel, this.notifier);\n\t\n\t if (Object.keys(self.kuzzle.subscriptions[room]).length === 1) {\n\t delete self.kuzzle.subscriptions[room];\n\t\n\t if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n\t } else {\n\t interval = setInterval(function () {\n\t if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n\t if (!self.kuzzle.subscriptions[room]) {\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n\t }\n\t clearInterval(interval);\n\t }\n\t }, 100);\n\t }\n\t } else {\n\t delete self.kuzzle.subscriptions[room][self.id];\n\t }\n\t\n\t self.roomId = null;\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tRoom.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\t/**\n\t * Callback called by the network handler when a message is sent to the subscribed room ID\n\t * Calls the registered callback if the notification passes the subscription filters\n\t *\n\t * @param {object} data - data\n\t * @returns {*}\n\t */\n\tfunction notificationCallback (data) {\n\t if (data.error) {\n\t return this.callback(data.error);\n\t }\n\t\n\t if (data.action === 'jwtTokenExpired') {\n\t this.kuzzle.jwtToken = undefined;\n\t return this.kuzzle.emitEvent('jwtTokenExpired');\n\t }\n\t\n\t if (data.controller === 'document' || (data.controller === 'realtime' && data.action === 'publish')) {\n\t data.type = 'document';\n\t data.document = new Document(this.collection, data.result._id, data.result._source);\n\t delete data.result;\n\t }\n\t else if (data.controller === 'realtime') {\n\t data.type = 'user';\n\t data.user = {count: data.result.count};\n\t delete data.result;\n\t }\n\t\n\t if (this.kuzzle.requestHistory[data.requestId]) {\n\t if (this.subscribeToSelf) {\n\t this.callback(null, data);\n\t }\n\t delete this.kuzzle.requestHistory[data.requestId];\n\t } else {\n\t this.callback(null, data);\n\t }\n\t}\n\t\n\t\n\t/**\n\t * Dequeue actions performed while subscription was being renewed\n\t */\n\tfunction dequeue () {\n\t var element;\n\t\n\t while (this.queue.length > 0) {\n\t element = this.queue.shift();\n\t\n\t this[element.action].apply(this, element.args);\n\t }\n\t}\n\t\n\tfunction isReady() {\n\t return this.kuzzle.state === 'connected' && !this.subscribing;\n\t}\n\t\n\tmodule.exports = Room;\n\n\n/***/ },\n/* 12 */\n/***/ function(module, exports) {\n\n\t/**\n\t *\n\t * @param {Collection} dataCollection\n\t * @param {int} total\n\t * @param {Document[]} documents\n\t * @param {object} [aggregations]\n\t * @param {object} [searchArgs]\n\t * @param {KuzzleSearchResult} [previous]\n\t * @constructor\n\t */\n\tfunction KuzzleSearchResult (dataCollection, total, documents, aggregations, searchArgs, previous) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t dataCollection: {\n\t value: dataCollection,\n\t },\n\t total: {\n\t value: total,\n\t enumerable: true\n\t },\n\t documents: {\n\t value: documents,\n\t enumerable: true\n\t },\n\t aggregations: {\n\t value: aggregations || {},\n\t enumerable: true\n\t },\n\t searchArgs: {\n\t value: searchArgs || {},\n\t enumerable: true\n\t },\n\t // writable properties\n\t fetchedDocument: {\n\t value: documents.length,\n\t enumerable: true,\n\t writable: true\n\t },\n\t _previous: {\n\t value: previous || null,\n\t writable: true\n\t },\n\t _next: {\n\t value: null,\n\t writable: true\n\t }\n\t });\n\t\n\t if (this._previous instanceof KuzzleSearchResult) {\n\t this._previous._next = this;\n\t this.fetchedDocument += this._previous.fetchedDocument;\n\t }\n\t\n\t // promisifying\n\t if (this.dataCollection.kuzzle.bluebird) {\n\t return this.dataCollection.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['previous', 'next'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t\n\t/**\n\t * @param cb\n\t * @returns {*}\n\t */\n\tKuzzleSearchResult.prototype.previous = function (cb) {\n\t cb(null, this._previous);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * @param {function} cb\n\t */\n\tKuzzleSearchResult.prototype.next = function (cb) {\n\t var\n\t filters,\n\t options = Object.assign({}, this.searchArgs.options),\n\t self = this;\n\t\n\t if (!this._next) {\n\t // retrieve next results with scroll if original search use it\n\t if (options.scrollId) {\n\t if (this.fetchedDocument >= this.total) {\n\t cb(null, null);\n\t return;\n\t }\n\t\n\t // from and size parameters are not valid for a scroll action\n\t if (typeof options.from !== 'undefined') {\n\t delete options.from;\n\t }\n\t\n\t if (options.size) {\n\t delete options.size;\n\t }\n\t\n\t this.dataCollection.scroll(\n\t options.scrollId,\n\t options,\n\t this.searchArgs.filters || {},\n\t function(error, newSearchResults) {\n\t handleNextSearchResults(error, self, newSearchResults, cb);\n\t }\n\t );\n\t\n\t return;\n\t }\n\t // retrieve next results with from/size if original search use it\n\t else if (options.from !== undefined && options.size !== undefined) {\n\t filters = Object.assign({}, this.searchArgs.filters);\n\t\n\t // check if we need to do next request to fetch all matching documents\n\t options.from += options.size;\n\t\n\t if (options.from >= this.total) {\n\t cb(null, null);\n\t\n\t return;\n\t }\n\t\n\t this.dataCollection.search(\n\t filters,\n\t options,\n\t function(error, newSearchResults) {\n\t handleNextSearchResults(error, self, newSearchResults, cb);\n\t }\n\t );\n\t\n\t return;\n\t }\n\t }\n\t\n\t if (this._next instanceof KuzzleSearchResult) {\n\t cb(null, this._next);\n\t\n\t return;\n\t }\n\t\n\t cb(new Error('Unable to retrieve next results from search: missing scrollId or from/size params'));\n\t};\n\t\n\t/**\n\t * @param {Error} error\n\t * @param {KuzzleSearchResult} currentSearchResults\n\t * @param {KuzzleSearchResult} newSearchResults\n\t * @param {Function} cb\n\t */\n\tfunction handleNextSearchResults (error, currentSearchResults, newSearchResults, cb) {\n\t if (error) {\n\t cb(error);\n\t return;\n\t }\n\t\n\t newSearchResults.fetchedDocument += currentSearchResults.fetchedDocument;\n\t\n\t newSearchResults._previous = currentSearchResults;\n\t currentSearchResults._next = newSearchResults;\n\t\n\t\n\t cb(null, newSearchResults);\n\t}\n\t\n\tmodule.exports = KuzzleSearchResult;\n\n\n/***/ },\n/* 13 */\n/***/ function(module, exports) {\n\n\t/**\n\t * Sugar-code handling the result of a Room.renew call\n\t * @constructor\n\t */\n\tfunction KuzzleSubscribeResult() {\n\t this.cbs = [];\n\t this.error = null;\n\t this.room = null;\n\t}\n\t\n\t/**\n\t * Registers a callback to be called with a subscription result\n\t * @param {Function} cb\n\t */\n\tKuzzleSubscribeResult.prototype.onDone = function (cb) {\n\t if (this.error || this.room) {\n\t cb(this.error, this.room);\n\t }\n\t else {\n\t this.cbs.push(cb);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Calls all registered callbacks\n\t *\n\t * @param {Object} error object\n\t * @param {Room} room\n\t */\n\tKuzzleSubscribeResult.prototype.done = function (error, room) {\n\t this.error = error;\n\t this.room = room;\n\t\n\t this.cbs.forEach(function (cb) {\n\t cb(error, room);\n\t });\n\t};\n\t\n\tmodule.exports = KuzzleSubscribeResult;\n\n\n/***/ },\n/* 14 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/**\n\t *\n\t * @param host\n\t * @param port\n\t * @param sslConnection\n\t * @returns {Object} tnstantiated WebSocket/Socket.IO object\n\t */\n\t\n\tfunction network(host, port, sslConnection) {\n\t // Web browser / NodeJS websocket handling\n\t if (typeof window !== 'undefined') {\n\t // use native websockets if the browser supports it\n\t if (typeof WebSocket !== 'undefined') {\n\t return new (__webpack_require__(3))(host, port, sslConnection);\n\t }\n\t // otherwise fallback to socket.io, if available\n\t else if (window.io) {\n\t return new (__webpack_require__(15))(host, port, sslConnection);\n\t }\n\t\n\t throw new Error('Aborting: no websocket support detected and no socket.io library loaded either.');\n\t }\n\t\n\t return new (__webpack_require__(3))(host, port, sslConnection);\n\t}\n\t\n\tmodule.exports = network;\n\n\n/***/ },\n/* 15 */\n/***/ function(module, exports) {\n\n\tfunction SocketIO(host, port, ssl) {\n\t this.host = host;\n\t this.port = port;\n\t this.ssl = ssl;\n\t this.socket = null;\n\t\n\t /**\n\t * Creates a new socket from the provided arguments\n\t *\n\t * @constructor\n\t * @param {boolean} autoReconnect\n\t * @param {int} reconnectionDelay\n\t */\n\t this.connect = function (autoReconnect, reconnectionDelay) {\n\t this.socket = window.io((this.ssl ? 'https://' : 'http://') + this.host + ':' + this.port, {\n\t reconnection: autoReconnect,\n\t reconnectionDelay: reconnectionDelay,\n\t forceNew: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whence a connection is established\n\t *\n\t * @param {function} callback\n\t */\n\t this.onConnect = function (callback) {\n\t this.socket.on('connect', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection error is received\n\t * @param {function} callback\n\t */\n\t this.onConnectError = function (callback) {\n\t this.socket.on('connect_error', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a disconnection occurred\n\t * @param {function} callback\n\t */\n\t this.onDisconnect = function (callback) {\n\t this.socket.on('disconnect', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection has been reestablished\n\t * @param {function} callback\n\t */\n\t this.onReconnect = function (callback) {\n\t this.socket.on('reconnect', callback);\n\t };\n\t\n\t /**\n\t * Registers a callback on a room. Once 1 message is received, fires the\n\t * callback and unregister it afterward.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.once = function (roomId, callback) {\n\t this.socket.once(roomId, callback);\n\t };\n\t\n\t /**\n\t * Registers a callback on a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.on = function (roomId, callback) {\n\t this.socket.on(roomId, callback);\n\t };\n\t\n\t /**\n\t * Unregisters a callback from a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.off = function (roomId, callback) {\n\t this.socket.off(roomId, callback);\n\t };\n\t\n\t\n\t /**\n\t * Sends a payload to the connected server\n\t *\n\t * @param {Object} payload\n\t */\n\t this.send = function (payload) {\n\t this.socket.emit('kuzzle', payload);\n\t };\n\t\n\t /**\n\t * Closes the connection\n\t */\n\t this.close = function () {\n\t this.socket.close();\n\t this.socket = null;\n\t };\n\t}\n\t\n\tmodule.exports = SocketIO;\n\n\n/***/ },\n/* 16 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t SecurityDocument = __webpack_require__(1);\n\t\n\tfunction Profile(Security, id, content) {\n\t\n\t SecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteProfile'\n\t },\n\t updateActionName: {\n\t value: 'updateProfile'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['hydrate', 'save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t}\n\t\n\tProfile.prototype = Object.create(SecurityDocument.prototype, {\n\t constructor: {\n\t value: Profile\n\t }\n\t});\n\t\n\t/**\n\t * Persist to the persistent layer the current profile\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.save = function (options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!this.content.policies) {\n\t throw new Error('Argument \"policies\" is mandatory in a profile. This argument contains an array of objects.');\n\t }\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.serialize();\n\t\n\t self.kuzzle.query(self.Security.buildQueryArgs('createOrReplaceProfile'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t\n\t/**\n\t * Add a policy in the policies list\n\t * @param {Object} policy - must be an object containing at least a \"roleId\" member which must be a string.\n\t *\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.addPolicy = function (policy) {\n\t\n\t if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n\t throw new Error('Parameter \"policies\" must be an object containing at least a \"roleId\" member which must be a string.');\n\t }\n\t\n\t if (!this.content.policies) {\n\t this.content.policies = [];\n\t }\n\t\n\t this.content.policies.push(policy);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Set policies list\n\t * @param {Array} policies - must be an array of objects containing at least a \"roleId\" member which must be a string\n\t *\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.setPolicies = function (policies) {\n\t\n\t if (!Array.isArray(policies)) {\n\t throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n\t }\n\t\n\t policies.map(function (policy) {\n\t if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n\t throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n\t }\n\t });\n\t\n\t this.content.policies = policies;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this securityDocument\n\t */\n\tProfile.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Returns the list of policies associated to this profile.\n\t * Each policy element is an array of objects containing at least a \"roleId\" member which must be a string\n\t *\n\t * @return {object} an array of policies\n\t */\n\tProfile.prototype.getPolicies = function () {\n\t return this.content.policies;\n\t};\n\t\n\tmodule.exports = Profile;\n\n\n/***/ },\n/* 17 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar KuzzleSecurityDocument = __webpack_require__(1);\n\t\n\tfunction Role(Security, id, content) {\n\t\n\t KuzzleSecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteRole'\n\t },\n\t updateActionName: {\n\t value: 'updateRole'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t}\n\t\n\tRole.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n\t constructor: {\n\t value: Role\n\t }\n\t});\n\t\n\t/**\n\t * Saves this role into Kuzzle.\n\t *\n\t * If this is a new role, this function will create it in Kuzzle.\n\t * Otherwise, this method will replace the latest version of this role in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Role} this object\n\t */\n\tRole.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceRole'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return this;\n\t};\n\t\n\tmodule.exports = Role;\n\n\n/***/ },\n/* 18 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t Role = __webpack_require__(17),\n\t Profile = __webpack_require__(16),\n\t User = __webpack_require__(4);\n\t\n\t/**\n\t * Kuzzle security constructor\n\t *\n\t * @param kuzzle\n\t * @returns {Security}\n\t * @constructor\n\t */\n\tfunction Security(kuzzle) {\n\t\n\t Object.defineProperty(this, 'kuzzle', {\n\t value: kuzzle\n\t });\n\t\n\t Object.defineProperty(this, 'buildQueryArgs', {\n\t value: function (action) {\n\t return {\n\t controller: 'security',\n\t action: action\n\t };\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['role', 'profile', 'user', 'isActionAllowed'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t\n\t/**\n\t * Retrieve a single Role using its unique role ID.\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchRole = function (id, options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!id) {\n\t throw new Error('Id parameter is mandatory for fetchRole function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = {_id: id};\n\t\n\t self.kuzzle.callbackRequired('Security.fetchRole', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getRole'), data, options, function (err, response) {\n\t cb(err, err ? undefined : new Role(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on roles according to a filter\n\t *\n\t * /!\\ There is a small delay between role creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a role that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - this object can contains an array `indexes` with a list of index id, a integer `from` and a integer `size`\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t *\n\t */\n\tSecurity.prototype.searchRoles = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchRoles', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchRoles'), {body: filters}, options, function (error, result) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = result.result.hits.map(function (doc) {\n\t return new Role(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: result.result.total, roles: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new role in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same role already exists: throw an error if sets to false.\n\t * Replace the existing role otherwise\n\t *\n\t * @param {string} id - role identifier\n\t * @param {object} content - a plain javascript object representing the role\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createRole = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'createRole';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createRole: cannot create a role without a role ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceRole' : 'createRole';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new Role(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update a role in Kuzzle.\n\t *\n\t * @param {string} id - role identifier\n\t * @param {object} content - a plain javascript object representing the role's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateRole = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content},\n\t action = 'updateRole';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateRole: cannot update a role without a role ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err) {\n\t cb(err, err ? undefined : new Role(self, id, content));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete role.\n\t *\n\t * There is a small delay between role deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a role that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Role id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteRole = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteRole'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new Role object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - role id\n\t * @param {object} content - role content\n\t * @constructor\n\t */\n\tSecurity.prototype.role = function(id, content) {\n\t return new Role(this, id, content);\n\t};\n\t\n\t\n\t/**\n\t * Get a specific profile from kuzzle\n\t *\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} cb - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchProfile = function (id, options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Id parameter is mandatory for fetchProfile function');\n\t }\n\t\n\t\n\t data = {_id: id};\n\t\n\t self.kuzzle.callbackRequired('Security.fetchProfile', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getProfile'), data, options, function (error, response) {\n\t cb(error, error ? undefined : new Profile(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on profiles according to a filter\n\t *\n\t *\n\t * /!\\ There is a small delay between profile creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a profile that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - this object can contains an array `roles` with a list of roles id, a integer `from` and a integer `size`\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.searchProfiles = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchProfiles', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchProfiles'), {body: filters}, options, function (error, response) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = response.result.hits.map(function (doc) {\n\t return new Profile(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: response.result.total, profiles: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new profile in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same profile already exists: throw an error if sets to false.\n\t * Replace the existing profile otherwise\n\t *\n\t * @param {string} id - profile identifier\n\t * @param {object} content - attribute `roles` in `content` must only contains an array of role id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createProfile = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'createProfile';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createProfile: cannot create a profile without a profile ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceProfile' : 'createProfile';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new Profile(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update a profile in Kuzzle.\n\t *\n\t * @param {string} id - profile identifier\n\t * @param {object} content - a plain javascript object representing the profile's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateProfile = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'updateProfile';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateProfile: cannot update a profile without a profile ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t var updatedContent = {};\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t Object.keys(res.result._source).forEach(function (property) {\n\t updatedContent[property] = res.result._source[property];\n\t });\n\t\n\t cb(null, new Profile(self, res.result._id, updatedContent));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete profile.\n\t *\n\t * There is a small delay between profile deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a profile that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Profile id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteProfile = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteProfile'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new Profile object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - profile id\n\t * @param {object} content - profile content\n\t * @constructor\n\t */\n\tSecurity.prototype.profile = function(id, content) {\n\t return new Profile(this, id, content);\n\t};\n\t\n\t/**\n\t * Get a specific user from kuzzle using its unique ID\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} cb - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchUser = function (id, options, cb) {\n\t var\n\t data = {_id: id},\n\t self = this;\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Id parameter is mandatory for fetchUser function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.fetchUser', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getUser'), data, options, function (err, response) {\n\t cb(err, err ? undefined : new User(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on user according to a filter\n\t *\n\t * /!\\ There is a small delay between user creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a user that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - same filters as documents filters\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.searchUsers = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchUsers', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchUsers'), {body: filters}, options, function (error, response) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = response.result.hits.map(function (doc) {\n\t return new User(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: response.result.total, users: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new user in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same user already exists: throw an error if sets to false.\n\t * Replace the existing user otherwise\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content},\n\t action = 'createUser';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createUser: cannot create a user without a user ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceUser' : 'createUser';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, null, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Create a new restricted user in Kuzzle.\n\t *\n\t * This function will create a new user. It is not usable to update an existing user.\n\t * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - attribute `profile` in `content` must only contains the profile id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createRestrictedUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content};\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createRestrictedUser: cannot create a user without a user ID');\n\t }\n\t\n\t if (content.profileIds) {\n\t throw new Error('Security.createRestrictedUser: cannot provide profileIds');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs('createRestrictedUser'), data, null, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update an user in Kuzzle.\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - a plain javascript object representing the user's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'updateUser';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateUser: cannot update an user without an user ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete user.\n\t *\n\t * There is a small delay between user deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a user that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Profile id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteUser = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteUser'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new User object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - user id\n\t * @param {object} content - user content\n\t * @constructor\n\t */\n\tSecurity.prototype.user = function(id, content) {\n\t return new User(this, id, content);\n\t};\n\t\n\t/**\n\t * Tells whether an action is allowed, denied or conditional based on the rights\n\t * rights provided as the first argument. An action is defined as a couple of\n\t * action and controller (mandatory), plus an index and a collection(optional).\n\t *\n\t * @param {object} rights - The rights rights associated to a user\n\t * (see getMyrights and getUserrights).\n\t * @param {string} controller - The controller to check the action onto.\n\t * @param {string} action - The action to perform.\n\t * @param {string} index - (optional) The name of index to perform the action onto.\n\t * @param {string} collection - (optional) The name of the collection to perform the action onto.\n\t *\n\t * @returns {string} ['allowed', 'denied', 'conditional'] where conditional cases\n\t * correspond to rights containing closures.\n\t * See also http://kuzzle.io/guide/#roles-definition\n\t */\n\tSecurity.prototype.isActionAllowed = function(rights, controller, action, index, collection) {\n\t var filteredRights;\n\t\n\t if (!rights || typeof rights !== 'object') {\n\t throw new Error('rights parameter is mandatory for isActionAllowed function');\n\t }\n\t if (!controller || typeof controller !== 'string') {\n\t throw new Error('controller parameter is mandatory for isActionAllowed function');\n\t }\n\t if (!action || typeof action !== 'string') {\n\t throw new Error('action parameter is mandatory for isActionAllowed function');\n\t }\n\t\n\t // We filter in all the rights that match the request (including wildcards).\n\t filteredRights = rights\n\t .filter(function (right) {\n\t return right.controller === controller || right.controller === '*';\n\t })\n\t .filter(function (right) {\n\t return right.action === action || right.action === '*';\n\t })\n\t .filter(function (right) {\n\t return right.index === index || right.index === '*';\n\t })\n\t .filter(function (right) {\n\t return right.collection === collection || right.collection === '*';\n\t });\n\t\n\t // Then, if at least one right allows the action, we return 'allowed'\n\t if (filteredRights.some(function (item) { return item.value === 'allowed'; })) {\n\t return 'allowed';\n\t }\n\t // If no right allows the action, we check for conditionals.\n\t if (filteredRights.some(function (item) { return item.value === 'conditional'; })) {\n\t return 'conditional';\n\t }\n\t // Otherwise we return 'denied'.\n\t return 'denied';\n\t};\n\t\n\t\n\t/**\n\t * Gets the rights array of a given user.\n\t *\n\t * @param {string} userId The id of the user.\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {function} cb The callback containing the normalized array of rights.\n\t */\n\tSecurity.prototype.getUserRights = function (userId, options, cb) {\n\t var\n\t data = {_id: userId},\n\t self = this;\n\t\n\t if (!userId || typeof userId !== 'string') {\n\t throw new Error('userId parameter is mandatory for getUserRights function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Kuzzle.getUserRights', cb);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('getUserRights'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result.hits);\n\t });\n\t};\n\t\n\tmodule.exports = Security;\n\n\n/***/ },\n/* 19 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t// Unique ID creation requires a high quality random # generator. We feature\n\t// detect to determine the best RNG source, normalizing to a function that\n\t// returns 128-bits of randomness, since that's what's usually required\n\tvar rng = __webpack_require__(7);\n\tvar bytesToUuid = __webpack_require__(6);\n\t\n\t// **`v1()` - Generate time-based UUID**\n\t//\n\t// Inspired by https://github.com/LiosK/UUID.js\n\t// and http://docs.python.org/library/uuid.html\n\t\n\t// random #'s we need to init node and clockseq\n\tvar _seedBytes = rng();\n\t\n\t// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n\tvar _nodeId = [\n\t _seedBytes[0] | 0x01,\n\t _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]\n\t];\n\t\n\t// Per 4.2.2, randomize (14 bit) clockseq\n\tvar _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;\n\t\n\t// Previous uuid creation time\n\tvar _lastMSecs = 0, _lastNSecs = 0;\n\t\n\t// See https://github.com/broofa/node-uuid for API details\n\tfunction v1(options, buf, offset) {\n\t var i = buf && offset || 0;\n\t var b = buf || [];\n\t\n\t options = options || {};\n\t\n\t var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\t\n\t // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n\t // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n\t // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n\t // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n\t var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\t\n\t // Per 4.2.1.2, use count of uuid's generated during the current clock\n\t // cycle to simulate higher resolution clock\n\t var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\t\n\t // Time since last uuid creation (in msecs)\n\t var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\t\n\t // Per 4.2.1.2, Bump clockseq on clock regression\n\t if (dt < 0 && options.clockseq === undefined) {\n\t clockseq = clockseq + 1 & 0x3fff;\n\t }\n\t\n\t // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n\t // time interval\n\t if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n\t nsecs = 0;\n\t }\n\t\n\t // Per 4.2.1.2 Throw error if too many uuids are requested\n\t if (nsecs >= 10000) {\n\t throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n\t }\n\t\n\t _lastMSecs = msecs;\n\t _lastNSecs = nsecs;\n\t _clockseq = clockseq;\n\t\n\t // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n\t msecs += 12219292800000;\n\t\n\t // `time_low`\n\t var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n\t b[i++] = tl >>> 24 & 0xff;\n\t b[i++] = tl >>> 16 & 0xff;\n\t b[i++] = tl >>> 8 & 0xff;\n\t b[i++] = tl & 0xff;\n\t\n\t // `time_mid`\n\t var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n\t b[i++] = tmh >>> 8 & 0xff;\n\t b[i++] = tmh & 0xff;\n\t\n\t // `time_high_and_version`\n\t b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n\t b[i++] = tmh >>> 16 & 0xff;\n\t\n\t // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n\t b[i++] = clockseq >>> 8 | 0x80;\n\t\n\t // `clock_seq_low`\n\t b[i++] = clockseq & 0xff;\n\t\n\t // `node`\n\t var node = options.node || _nodeId;\n\t for (var n = 0; n < 6; ++n) {\n\t b[i + n] = node[n];\n\t }\n\t\n\t return buf ? buf : bytesToUuid(b);\n\t}\n\t\n\tmodule.exports = v1;\n\n\n/***/ },\n/* 20 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar rng = __webpack_require__(7);\n\tvar bytesToUuid = __webpack_require__(6);\n\t\n\tfunction v4(options, buf, offset) {\n\t var i = buf && offset || 0;\n\t\n\t if (typeof(options) == 'string') {\n\t buf = options == 'binary' ? new Array(16) : null;\n\t options = null;\n\t }\n\t options = options || {};\n\t\n\t var rnds = options.random || (options.rng || rng)();\n\t\n\t // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\t rnds[6] = (rnds[6] & 0x0f) | 0x40;\n\t rnds[8] = (rnds[8] & 0x3f) | 0x80;\n\t\n\t // Copy bytes to buffer, if provided\n\t if (buf) {\n\t for (var ii = 0; ii < 16; ++ii) {\n\t buf[i + ii] = rnds[ii];\n\t }\n\t }\n\t\n\t return buf || bytesToUuid(rnds);\n\t}\n\t\n\tmodule.exports = v4;\n\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// kuzzle.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap ef1329784c2080614ad8","var\n uuid = require('uuid'),\n Collection = require('./Collection.js'),\n Security = require('./security/Security'),\n MemoryStorage = require('./MemoryStorage'),\n User = require('./security/User'),\n networkWrapper = require('./networkWrapper');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * Kuzzle object constructor.\n *\n * @constructor\n * @param host - Server name or IP Address to the Kuzzle instance\n * @param [options] - Connection options\n * @param {responseCallback} [cb] - Handles connection response\n * @constructor\n */\nfunction Kuzzle (host, options, cb) {\n var self = this;\n\n if (!(this instanceof Kuzzle)) {\n return new Kuzzle(host, options, cb);\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!host || host === '') {\n throw new Error('host argument missing');\n }\n\n Object.defineProperties(this, {\n // 'private' properties\n collections: {\n value: {},\n writable: true\n },\n connectCB: {\n value: cb\n },\n eventListeners: {\n value: {\n connected: {lastEmitted: null, listeners: []},\n error: {lastEmitted: null, listeners: []},\n disconnected: {lastEmitted: null, listeners: []},\n reconnected: {lastEmitted: null, listeners: []},\n jwtTokenExpired: {lastEmitted: null, listeners: []},\n loginAttempt: {lastEmitted: null, listeners: []},\n offlineQueuePush: {listeners: []},\n offlineQueuePop: {listeners: []},\n queryError: {listeners: []},\n discarded: {listeners: []}\n }\n },\n eventTimeout: {\n value: 200\n },\n queuing: {\n value: false,\n writable: true\n },\n requestHistory: {\n value: {},\n writable: true\n },\n state: {\n value: 'initializing',\n writable: true\n },\n subscriptions: {\n /*\n Contains the centralized subscription list in the following format:\n pending: \n 'roomId': {\n kuzzleRoomID_1: kuzzleRoomInstance_1,\n kuzzleRoomID_2: kuzzleRoomInstance_2,\n kuzzleRoomID_...: kuzzleRoomInstance_...\n }\n\n This was made to allow multiple subscriptions on the same set of filters, something that Kuzzle does not permit.\n This structure also allows renewing subscriptions after a connection loss\n */\n value: {\n pending: {}\n },\n writable: true\n },\n // configuration properties\n autoReconnect: {\n value: (options && typeof options.autoReconnect === 'boolean') ? options.autoReconnect : true,\n writable: true,\n enumerable: true\n },\n defaultIndex: {\n value: (options && typeof options.defaultIndex === 'string') ? options.defaultIndex : undefined,\n writable: true,\n enumerable: true\n },\n reconnectionDelay: {\n value: (options && typeof options.reconnectionDelay === 'number') ? options.reconnectionDelay : 1000,\n writable: true,\n enumerable: true\n },\n host: {\n value: host,\n writable: true,\n enumerable: true\n },\n port: {\n value: (options && typeof options.port === 'number') ? options.port : 7512,\n enumerable: true,\n writable: true\n },\n sslConnection: {\n value: (options && typeof options.sslConnection === 'boolean') ? options.sslConnection : false,\n writable: true,\n enumerable: true\n },\n autoQueue: {\n value: false,\n enumerable: true,\n writable: true\n },\n autoReplay: {\n value: false,\n enumerable: true,\n writable: true\n },\n autoResubscribe: {\n value: true,\n enumerable: true,\n writable: true\n },\n headers: {\n value: {},\n enumerable: true,\n writable: true\n },\n metadata: {\n value: {},\n enumerable: true,\n writable: true\n },\n /*\n Offline queue use the following format:\n [\n {\n ts: ,\n query: 'query',\n cb: callbackFunction\n }\n ]\n */\n offlineQueue: {\n value: [],\n enumerable: true,\n writable: true\n },\n queueFilter: {\n value: null,\n enumerable: true,\n writable: true\n },\n queueMaxSize: {\n value: 500,\n enumerable: true,\n writable: true\n },\n queueTTL: {\n value: 120000,\n enumerable: true,\n writable: true\n },\n replayInterval: {\n value: 10,\n enumerable: true,\n writable: true\n },\n jwtToken: {\n value: undefined,\n enumerable: true,\n writable: true\n },\n offlineQueueLoader: {\n value: null,\n enumerable: true,\n writable: true\n }\n });\n\n if (options) {\n Object.keys(options).forEach(function (opt) {\n if (self.hasOwnProperty(opt) && Object.getOwnPropertyDescriptor(self, opt).writable) {\n self[opt] = options[opt];\n }\n });\n\n if (options.offlineMode === 'auto' && this.autoReconnect) {\n this.autoQueue = this.autoReplay = this.autoResubscribe = true;\n }\n }\n\n // Helper function ensuring that this Kuzzle object is still valid before performing a query\n Object.defineProperty(this, 'isValid', {\n value: function () {\n if (self.state === 'disconnected') {\n throw new Error('This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?');\n }\n }\n });\n\n // Helper function copying headers to the query data\n Object.defineProperty(this, 'addHeaders', {\n value: function (query, headers) {\n Object.keys(headers).forEach(function (header) {\n if (!query[header]) {\n query[header] = headers[header];\n }\n });\n\n return query;\n }\n });\n\n /**\n * Some methods (mainly read queries) require a callback function. This function exists to avoid repetition of code,\n * and is called by these methods\n */\n Object.defineProperty(this, 'callbackRequired', {\n value: function (errorMessagePrefix, callback) {\n if (!callback || typeof callback !== 'function') {\n throw new Error(errorMessagePrefix + ': a callback argument is required for read queries');\n }\n }\n });\n\n /**\n * Create an attribute security that embed all methods to manage Role, Profile and User\n */\n Object.defineProperty(this, 'security', {\n value: new Security(this),\n enumerable: true\n });\n\n /**\n * Emit an event to all registered listeners\n * An event cannot be emitted multiple times before a timeout has been reached.\n */\n Object.defineProperty(this, 'emitEvent', {\n value: function emitEvent(event) {\n var\n now = Date.now(),\n args = Array.prototype.slice.call(arguments, 1),\n eventProperties = this.eventListeners[event];\n\n if (eventProperties.lastEmitted && eventProperties.lastEmitted >= now - this.eventTimeout) {\n return false;\n }\n\n eventProperties.listeners.forEach(function (listener) {\n process.nextTick(function () {\n listener.fn.apply(undefined, args);\n });\n });\n\n // Events without the 'lastEmitted' property can be emitted without minimum time between emissions\n if (eventProperties.lastEmitted !== undefined) {\n eventProperties.lastEmitted = now;\n }\n }\n });\n\n Object.defineProperty(this, 'memoryStorage', {\n value: new MemoryStorage(this),\n enumerable: true\n });\n\n\n if (!options || !options.connect || options.connect === 'auto') {\n this.connect();\n } else {\n this.state = 'ready';\n }\n\n cleanHistory(this.requestHistory);\n\n if (this.bluebird) {\n return this.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['getAllStatistics', 'getServerInfo', 'getStatistics',\n 'listCollections', 'listIndexes', 'login', 'logout', 'now', 'query',\n 'checkToken', 'whoAmI', 'updateSelf', 'getMyRights',\n 'refreshIndex', 'getAutoRefresh', 'setAutoRefresh'\n ];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\n/**\n * Connects to a Kuzzle instance using the provided host name.\n * @returns {Object} this\n */\nKuzzle.prototype.connect = function () {\n var self = this;\n\n if (self.network) {\n self.disconnect();\n }\n\n self.network = networkWrapper(self.host, self.port, self.sslConnection);\n\n if (['initializing', 'ready', 'disconnected', 'error', 'offline'].indexOf(this.state) === -1) {\n if (self.connectCB) {\n self.connectCB(null, self);\n }\n return self;\n }\n\n self.state = 'connecting';\n self.network.connect(self.autoReconnect, self.reconnectionDelay);\n\n self.network.onConnect(function () {\n self.state = 'connected';\n renewAllSubscriptions.call(self);\n dequeue.call(self);\n self.emitEvent('connected');\n\n if (self.connectCB) {\n self.connectCB(null, self);\n }\n });\n\n self.network.on('discarded', function (data) {\n self.emitEvent('discarded', data);\n });\n\n self.network.onConnectError(function (error) {\n var connectionError = new Error('Unable to connect to kuzzle proxy server at \"' + self.host + '\"');\n\n connectionError.internal = error;\n self.state = 'error';\n self.emitEvent('error', connectionError);\n\n if (self.connectCB) {\n self.connectCB(connectionError);\n }\n });\n\n self.network.onDisconnect(function () {\n self.state = 'offline';\n\n if (!self.autoReconnect) {\n self.disconnect();\n }\n\n if (self.autoQueue) {\n self.queuing = true;\n }\n\n self.emitEvent('disconnected');\n });\n\n self.network.onReconnect(function () {\n var reconnect = function () {\n // renew subscriptions\n if (self.autoResubscribe) {\n renewAllSubscriptions.call(self);\n }\n\n // replay queued requests\n if (self.autoReplay) {\n cleanQueue.call(self);\n dequeue.call(self);\n }\n\n // alert listeners\n self.emitEvent('reconnected');\n };\n\n self.state = 'connected';\n\n if (self.jwtToken) {\n self.checkToken(self.jwtToken, function (err, res) {\n // shouldn't obtain an error but let's invalidate the token anyway\n if (err || !res.valid) {\n self.jwtToken = undefined;\n self.emitEvent('jwtTokenExpired');\n }\n\n reconnect();\n });\n } else {\n reconnect();\n }\n });\n\n return this;\n};\n\n/**\n * Set the jwtToken used to query kuzzle\n * @param token\n * @returns {Kuzzle}\n */\nKuzzle.prototype.setJwtToken = function(token) {\n if (typeof token === 'string') {\n this.jwtToken = token;\n } else if (typeof token === 'object') {\n if (token.result && token.result.jwt && typeof token.result.jwt === 'string') {\n this.jwtToken = token.result.jwt;\n } else {\n this.emitEvent('loginAttempt', {\n success: false,\n error: 'Cannot find a valid JWT token in the following object: ' + JSON.stringify(token)\n });\n\n return this;\n }\n } else {\n this.emitEvent('loginAttempt', {success: false, error: 'Invalid token argument: ' + token});\n return this;\n }\n\n renewAllSubscriptions.call(this);\n this.emitEvent('loginAttempt', {success: true});\n return this;\n};\n\n/**\n * Unset the jwtToken used to query kuzzle\n * @returns {Kuzzle}\n */\nKuzzle.prototype.unsetJwtToken = function() {\n this.jwtToken = undefined;\n\n removeAllSubscriptions.call(this);\n\n return this;\n};\n\n/**\n * Get the jwtToken used by kuzzle\n * @returns {Kuzzle}\n */\nKuzzle.prototype.getJwtToken = function() {\n return this.jwtToken;\n};\n\n/**\n * Send login request to kuzzle with credentials\n * If login success, store the jwtToken into kuzzle object\n *\n * @param strategy\n * @param credentials\n * @param expiresIn\n * @param cb\n */\nKuzzle.prototype.login = function (strategy) {\n var\n self = this,\n request = {\n strategy: strategy\n },\n credentials,\n cb = null;\n\n // Handle arguments (credentials, expiresIn, cb)\n if (arguments[1]) {\n if (typeof arguments[1] === 'object') {\n credentials = arguments[1];\n } else if (typeof arguments[1] === 'number' || typeof arguments[1] === 'string') {\n request.expiresIn = arguments[1];\n } else if (typeof arguments[1] === 'function') {\n cb = arguments[1];\n }\n }\n if (arguments[2]) {\n if (typeof arguments[2] === 'number' || typeof arguments[2] === 'string') {\n request.expiresIn = arguments[2];\n } else if (typeof arguments[2] === 'function') {\n cb = arguments[2];\n }\n }\n if (arguments[3] && typeof arguments[3] === 'function') {\n cb = arguments[3];\n }\n\n if (typeof credentials === 'object') {\n Object.keys(credentials).forEach(function (key) {\n request[key] = credentials[key];\n });\n }\n\n this.query({controller: 'auth', action: 'login'}, {body: request}, {queuable: false}, function(error, response) {\n if (!error) {\n if (response.result.jwt) {\n self.setJwtToken(response.result.jwt);\n }\n\n cb && cb(null, response.result);\n }\n else {\n cb && cb(error);\n self.emitEvent('loginAttempt', {success: false, error: error.message});\n }\n });\n};\n\n/**\n * Create a kuzzle index\n *\n * @param {string} index\n * @param {object} [options]\n * @param {responseCallback} cb\n * @returns {Kuzzle}\n */\nKuzzle.prototype.createIndex = function (index, options, cb) {\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.createIndex: index required');\n }\n index = this.defaultIndex;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.query({controller: 'index', action: 'create'}, {index: index}, options, typeof cb !== 'function' ? null : cb);\n\n return this;\n};\n\n/**\n * Send logout request to kuzzle with jwtToken.\n *\n * @param cb\n * @returns {Kuzzle}\n */\nKuzzle.prototype.logout = function (cb) {\n var\n self = this,\n request = {\n action: 'logout',\n controller: 'auth',\n requestId: uuid.v4(),\n body: {}\n };\n\n this.query({controller: 'auth', action: 'logout'}, request, {queuable: false}, typeof cb !== 'function' ? null : function(error) {\n cb(error, self);\n });\n\n self.unsetJwtToken();\n\n return self;\n};\n\n/**\n * Checks whether a given jwt token still represents a valid session in Kuzzle.\n *\n * @param {string} token The jwt token to check\n * @param {function} callback The callback to be called when the response is\n * available. The signature is `function(error, response)`.\n */\nKuzzle.prototype.checkToken = function (token, callback) {\n var\n request = {\n body: {\n token: token\n }\n };\n\n this.callbackRequired('Kuzzle.checkToken', callback);\n\n this.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}, function (err, response) {\n if (err) {\n return callback(err);\n }\n\n callback(null, response.result);\n });\n};\n\n/**\n * Fetches the current user.\n *\n * @param {function} callback The callback to be called when the response is\n * available. The signature is `function(error, response)`.\n */\nKuzzle.prototype.whoAmI = function (callback) {\n var self = this;\n\n self.callbackRequired('Kuzzle.whoAmI', callback);\n\n self.query({controller: 'auth', action: 'getCurrentUser'}, {}, {}, function (err, response) {\n if (err) {\n return callback(err);\n }\n\n callback(null, new User(self.security, response.result._id, response.result._source));\n });\n};\n\n/**\n * Gets the rights array of the currently logged user.\n *\n * @param {object} [options] - Optional parameters\n * @param {function} cb The callback containing the normalized array of rights.\n */\nKuzzle.prototype.getMyRights = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.callbackRequired('Kuzzle.getMyRights', cb);\n\n self.query({controller: 'auth', action:'getMyRights'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.hits);\n });\n};\n\n/**\n * Update current user in Kuzzle.\n *\n * @param {object} content - a plain javascript object representing the user's modification\n * @param {object} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.updateSelf = function (content, options, cb) {\n var\n self = this,\n data = {},\n queryArgs = {controller: 'auth', action: 'updateSelf'};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data.body = content;\n\n self.query(queryArgs, data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result);\n });\n\n return this;\n};\n\n/**\n * Clean up the queue, ensuring the queryTTL and queryMaxSize properties are respected\n */\nfunction cleanQueue () {\n var\n self = this,\n now = Date.now(),\n lastDocumentIndex = -1;\n\n if (self.queueTTL > 0) {\n self.offlineQueue.forEach(function (query, index) {\n if (query.ts < now - self.queueTTL) {\n lastDocumentIndex = index;\n }\n });\n\n if (lastDocumentIndex !== -1) {\n self.offlineQueue\n .splice(0, lastDocumentIndex + 1)\n .forEach(function (droppedRequest) {\n self.emitEvent('offlineQueuePop', droppedRequest.query);\n });\n }\n }\n\n if (self.queueMaxSize > 0 && self.offlineQueue.length > self.queueMaxSize) {\n self.offlineQueue\n .splice(0, self.offlineQueue.length - self.queueMaxSize)\n .forEach(function (droppedRequest) {\n self.emitEvent('offlineQueuePop', droppedRequest.query);\n });\n }\n}\n\n\n/**\n * Clean history from requests made more than 10s ago\n */\nfunction cleanHistory (requestHistory) {\n var\n now = Date.now();\n\n Object.keys(requestHistory).forEach(function (key) {\n if (requestHistory[key] < now - 10000) {\n delete requestHistory[key];\n }\n });\n\n setTimeout(function () {\n cleanHistory(requestHistory);\n }, 1000);\n}\n\n/**\n * Emit a request to Kuzzle\n *\n * @param {object} request\n * @param {responseCallback} [cb]\n */\nfunction emitRequest (request, cb) {\n var\n self = this;\n\n if (self.jwtToken !== undefined || cb) {\n self.network.once(request.requestId, function (response) {\n var error = null;\n\n if (request.action !== 'logout' && response.error && response.error.message === 'Token expired') {\n self.jwtToken = undefined;\n self.emitEvent('jwtTokenExpired', request, cb);\n }\n\n if (response.error) {\n error = new Error(response.error.message);\n Object.assign(error, response.error);\n error.status = response.status;\n self.emitEvent('queryError', error, request, cb);\n }\n\n if (cb) {\n cb(error, response);\n }\n });\n }\n\n this.network.send(request);\n\n // Track requests made to allow Room.subscribeToSelf to work\n self.requestHistory[request.requestId] = Date.now();\n}\n\n/**\n * Play all queued requests, in order.\n */\nfunction dequeue () {\n var\n self = this,\n additionalQueue,\n uniqueQueue = {},\n dequeuingProcess = function () {\n if (self.offlineQueue.length > 0) {\n emitRequest.call(self, self.offlineQueue[0].query, self.offlineQueue[0].cb);\n self.emitEvent('offlineQueuePop', self.offlineQueue.shift());\n\n setTimeout(function () {\n dequeuingProcess();\n }, Math.max(0, self.replayInterval));\n } else {\n self.queuing = false;\n }\n };\n\n if (self.offlineQueueLoader) {\n if (typeof self.offlineQueueLoader !== 'function') {\n throw new Error('Invalid value for offlineQueueLoader property. Expected: function. Got: ' + typeof self.offlineQueueLoader);\n }\n\n additionalQueue = self.offlineQueueLoader();\n if (Array.isArray(additionalQueue)) {\n self.offlineQueue = additionalQueue\n .concat(self.offlineQueue)\n .filter(function (request) {\n // throws if the query object does not contain required attributes\n if (!request.query || request.query.requestId === undefined || !request.query.action || !request.query.controller) {\n throw new Error('Invalid offline queue request. One or more missing properties: requestId, action, controller.');\n }\n\n return uniqueQueue.hasOwnProperty(request.query.requestId) ? false : (uniqueQueue[request.query.requestId] = true);\n });\n } else {\n throw new Error('Invalid value returned by the offlineQueueLoader function. Expected: array. Got: ' + typeof additionalQueue);\n }\n }\n\n dequeuingProcess();\n}\n\n/**\n * Renew all registered subscriptions. Triggered either by a successful connection/reconnection or by a\n * successful login attempt\n */\nfunction renewAllSubscriptions() {\n var self = this;\n\n Object.keys(self.subscriptions).forEach(function (roomId) {\n Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n var subscription = self.subscriptions[roomId][subscriptionId];\n subscription.renew(subscription.callback);\n });\n });\n}\n\n/**\n * Remove all registered subscriptions. Triggered either by a logout query or by un-setting the token\n */\nfunction removeAllSubscriptions() {\n var self = this;\n\n Object.keys(self.subscriptions).forEach(function (roomId) {\n Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n var subscription = self.subscriptions[roomId][subscriptionId];\n subscription.unsubscribe();\n });\n });\n}\n\n/**\n * Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their\n * insertion.\n *\n * The ID returned by this function is required to remove this listener at a later time.\n *\n * @param {string} event - name of the global event to subscribe to (see the 'eventListeners' object property)\n * @param {function} listener - callback to invoke each time an event is fired\n * @returns {string} Unique listener ID\n */\nKuzzle.prototype.addListener = function(event, listener) {\n var\n knownEvents = Object.keys(this.eventListeners),\n listenerType = typeof listener,\n listenerId;\n\n this.isValid();\n\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n if (listenerType !== 'function') {\n throw new Error('Invalid listener type: expected a function, got a ' + listenerType);\n }\n\n listenerId = uuid.v4();\n this.eventListeners[event].listeners.push({id: listenerId, fn: listener});\n return listenerId;\n};\n\n\n/**\n * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n * This method returns all available statistics from Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getAllStatistics = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.getAllStatistics', cb);\n\n this.query({controller:'server', action: 'getAllStats'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.hits);\n });\n};\n\n/**\n * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n * This method allows getting either the last statistics frame, or a set of frames starting from a provided timestamp.\n *\n * @param {number} timestamp - Epoch time. Starting time from which the frames are to be retrieved\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getStatistics = function (timestamp, options, cb) {\n var\n queryCB,\n body;\n\n if (!cb) {\n if (arguments.length === 1) {\n cb = arguments[0];\n options = null;\n timestamp = null;\n } else {\n cb = arguments[1];\n if (typeof arguments[0] === 'object') {\n options = arguments[0];\n timestamp = null;\n } else {\n timestamp = arguments[0];\n options = null;\n }\n }\n }\n\n queryCB = function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, timestamp ? res.result.hits : [res.result]);\n };\n\n this.callbackRequired('Kuzzle.getStatistics', cb);\n\n body = timestamp ? {body: {startTime: timestamp}} : {};\n this.query({controller: 'server', action: timestamp ? 'getStats' : 'getLastStats'}, body, options, queryCB);\n};\n\n/**\n * Create a new instance of a Collection object.\n * If no index is specified, takes the default index.\n *\n * @param {string} collection - The name of the data collection you want to manipulate\n * @param {string} [index] - The name of the data index containing the data collection\n * @returns {Collection} A Collection instance\n */\nKuzzle.prototype.collection = function(collection, index) {\n this.isValid();\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Unable to create a new data collection object: no index specified');\n }\n\n index = this.defaultIndex;\n }\n\n if (typeof index !== 'string' || typeof collection !== 'string') {\n throw new Error('Invalid index or collection argument: string expected');\n }\n\n if (!this.collections[index]) {\n this.collections[index] = {};\n }\n\n if (!this.collections[index][collection]) {\n this.collections[index][collection] = new Collection(this, collection, index);\n }\n\n return this.collections[index][collection];\n};\n\n/**\n * Empties the offline queue without replaying it.\n *\n * @returns {Kuzzle}\n */\nKuzzle.prototype.flushQueue = function () {\n this.offlineQueue = [];\n return this;\n};\n\n/**\n * Returns the list of known persisted data collections.\n *\n * @param {string} [index] - Index containing collections to be listed\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.listCollections = function () {\n var\n collectionType = 'all',\n index,\n options,\n cb,\n args = Array.prototype.slice.call(arguments),\n query;\n\n args.forEach(function(arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.listCollections: index required');\n }\n\n index = this.defaultIndex;\n }\n\n this.callbackRequired('Kuzzle.listCollections', cb);\n\n if (options && options.type) {\n collectionType = options.type;\n }\n\n query = {body: {type: collectionType}};\n\n if (options && options.from) {\n query.body.from = options.from;\n }\n\n if (options && options.size) {\n query.body.size = options.size;\n }\n\n this.query({index: index, controller: 'collection', action: 'list'}, query, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.collections);\n });\n};\n\n/**\n * Returns the list of existing indexes in Kuzzle\n *\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.listIndexes = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.listIndexes', cb);\n\n this.query({controller: 'index', action: 'list'}, {}, options, function (err, res) {\n cb(err, err ? undefined : res.result.indexes);\n });\n};\n\n/**\n * Disconnects from Kuzzle and invalidate this instance.\n */\nKuzzle.prototype.disconnect = function () {\n var collection;\n\n this.state = 'disconnected';\n this.network.close();\n this.network = null;\n\n for (collection in this.collections) {\n if (this.collections.hasOwnProperty(collection)) {\n delete this.collections[collection];\n }\n }\n};\n\n/**\n * Returns the server informations\n *\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getServerInfo = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.getServerInfo', cb);\n\n this.query({controller: 'server', action: 'info'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.serverInfo);\n });\n};\n\n/**\n * Forces an index refresh\n *\n * @param {string} index - The index to refresh. Defaults to Kuzzle.defaultIndex\n * @param {object} options - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n * @returns {Kuzzle}\n */\nKuzzle.prototype.refreshIndex = function () {\n var\n index,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function(arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.refreshIndex: index required');\n }\n index = this.defaultIndex;\n }\n\n this.query({ index: index, controller: 'index', action: 'refresh'}, {}, options, cb);\n\n return this;\n};\n\n/**\n * Returns de current autoRefresh status for the given index\n *\n * @param {string} index - The index to get the status from. Defaults to Kuzzle.defaultIndex\n * @param {object} options - Optinal arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getAutoRefresh = function () {\n var\n index,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function (arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.getAutoRefresh: index required');\n }\n index = this.defaultIndex;\n }\n\n this.callbackRequired('Kuzzle.getAutoRefresh', cb);\n this.query({ index: index, controller: 'index', action: 'getAutoRefresh'}, {}, options, cb);\n};\n\n/**\n * (Un)Sets the autoRefresh flag on the given index\n *\n * @param {string} index - the index to modify. Defaults to Kuzzle.defaultIndex\n * @param {boolean} autoRefresh - The autoRefresh value to set\n * @param {object} options - Optional arguments\n * @param {responseCallback} cb - Handles the query result\n * @returns {object} this\n */\nKuzzle.prototype.setAutoRefresh = function () {\n var\n index,\n autoRefresh,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function (arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'boolean':\n autoRefresh = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.setAutoRefresh: index required');\n }\n index = this.defaultIndex;\n }\n\n if (autoRefresh === undefined) {\n throw new Error('Kuzzle.setAutoRefresh: autoRefresh value is required');\n }\n\n this.query({ index: index, controller: 'index', action: 'setAutoRefresh'}, { body: { autoRefresh: autoRefresh }}, options, cb);\n\n return this;\n};\n\n/**\n * Return the current Kuzzle's UTC Epoch time, in milliseconds\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.now = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.now', cb);\n\n this.query({controller: 'server', action: 'now'}, {}, options, function (err, res) {\n cb(err, res && res.result.now);\n });\n};\n\n/**\n * This is a low-level method, exposed to allow advanced SDK users to bypass high-level methods.\n * Base method used to send read queries to Kuzzle\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} queryArgs - Query configuration\n * @param {object} query - The query data\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n */\nKuzzle.prototype.query = function (queryArgs, query, options, cb) {\n var\n attr,\n object = {\n action: queryArgs.action,\n controller: queryArgs.controller,\n metadata: this.metadata\n },\n self = this;\n\n this.isValid();\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (options) {\n if (options.queuable === false && self.state === 'offline') {\n return self;\n }\n\n if (options.refresh) {\n object.refresh = options.refresh;\n }\n\n if (typeof options.from !== 'undefined' && options.from !== null) {\n object.from = options.from;\n }\n\n if (options.size) {\n object.size = options.size;\n }\n\n if (options.scroll) {\n object.scroll = options.scroll;\n }\n\n if (options.scrollId) {\n object.scrollId = options.scrollId;\n }\n\n if (options.metadata) {\n Object.keys(options.metadata).forEach(function (meta) {\n object.metadata[meta] = options.metadata[meta];\n });\n }\n }\n\n if (!query || typeof query !== 'object' || Array.isArray(query)) {\n throw new Error('Invalid query parameter: ' + query);\n }\n\n if (query.metadata) {\n Object.keys(query.metadata).forEach(function (meta) {\n object.metadata[meta] = query.metadata[meta];\n });\n }\n\n for (attr in query) {\n if (attr !== 'metadata' && query.hasOwnProperty(attr)) {\n object[attr] = query[attr];\n }\n }\n\n object = self.addHeaders(object, this.headers);\n\n /*\n * Do not add the token for the checkToken route, to avoid getting a token error when\n * a developer simply wish to verify his token\n */\n if (self.jwtToken !== undefined && !(object.controller === 'auth' && object.action === 'checkToken')) {\n object.jwt = self.jwtToken;\n }\n\n if (queryArgs.collection) {\n object.collection = queryArgs.collection;\n }\n\n if (queryArgs.index) {\n object.index = queryArgs.index;\n }\n\n if (!object.requestId) {\n object.requestId = uuid.v4();\n }\n\n if (self.state === 'connected' || (options && options.queuable === false)) {\n if (self.state === 'connected') {\n emitRequest.call(this, object, cb);\n } else {\n discardRequest(object, cb);\n }\n } else if (self.queuing || (options && options.queuable === true) || ['initializing', 'connecting'].indexOf(self.state) !== -1) {\n cleanQueue.call(this, object, cb);\n if (!self.queueFilter || self.queueFilter(object)) {\n self.offlineQueue.push({ts: Date.now(), query: object, cb: cb});\n self.emitEvent('offlineQueuePush', {query: object, cb: cb});\n }\n }\n else {\n discardRequest(object, cb);\n }\n\n return self;\n};\n\n/**\n * Removes all listeners, either from a specific event or from all events\n *\n * @param {string} event - One of the event described in the Event Handling section of this documentation\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.removeAllListeners = function (event) {\n var\n knownEvents = Object.keys(this.eventListeners),\n self = this;\n\n if (event) {\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n this.eventListeners[event].listeners = [];\n } else {\n knownEvents.forEach(function (eventName) {\n self.eventListeners[eventName].listeners = [];\n });\n }\n\n return this;\n};\n\n/**\n * Removes a listener from an event.\n *\n * @param {string} event - One of the event described in the Event Handling section of this documentation\n * @param {string} listenerId - The ID returned by addListener\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.removeListener = function (event, listenerId) {\n var\n knownEvents = Object.keys(this.eventListeners),\n self = this;\n\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n this.eventListeners[event].listeners.forEach(function (listener, index) {\n if (listener.id === listenerId) {\n self.eventListeners[event].listeners.splice(index, 1);\n }\n });\n\n return this;\n};\n\n/**\n * Replays the requests queued during offline mode.\n * Works only if the SDK is not in a disconnected state, and if the autoReplay option is set to false.\n */\nKuzzle.prototype.replayQueue = function () {\n if (this.state !== 'offline' && !this.autoReplay) {\n cleanQueue.call(this);\n dequeue.call(this);\n }\n\n return this;\n};\n\n/**\n * Sets the default Kuzzle index\n *\n * @param index\n * @returns this\n */\nKuzzle.prototype.setDefaultIndex = function (index) {\n if (typeof index !== 'string') {\n throw new Error('Invalid default index: [' + index + '] (an index name is expected)');\n }\n\n if (index.length === 0) {\n throw new Error('Cannot set an empty index as the default index');\n }\n\n this.defaultIndex = index;\n\n return this;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nKuzzle.prototype.setHeaders = function (content, replace) {\n var self = this;\n\n if (typeof content !== 'object' || Array.isArray(content)) {\n throw new Error('Expected a content object, received a ' + typeof content);\n }\n\n if (replace) {\n self.headers = content;\n } else {\n Object.keys(content).forEach(function (key) {\n self.headers[key] = content[key];\n });\n }\n\n return self;\n};\n\n/**\n * Starts the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n */\nKuzzle.prototype.startQueuing = function () {\n if (this.state === 'offline' && !this.autoQueue) {\n this.queuing = true;\n }\n return this;\n};\n\n/**\n * Stops the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n */\nKuzzle.prototype.stopQueuing = function () {\n if (this.state === 'offline' && !this.autoQueue) {\n this.queuing = false;\n }\n\n return this;\n};\n\nfunction discardRequest(object, cb) {\n if (cb) {\n cb(new Error('Unable to execute request: not connected to a Kuzzle server.\\nDiscarded request: ' + JSON.stringify(object)));\n }\n}\n\nmodule.exports = Kuzzle;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Kuzzle.js\n// module id = 0\n// module chunks = 0","function KuzzleSecurityDocument(Security, id, content) {\n\n if (!id) {\n throw new Error('A security document must have an id');\n }\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n kuzzle: {\n value: Security.kuzzle\n },\n Security: {\n value: Security\n },\n // read-only properties\n // writable properties\n id: {\n value: id,\n enumerable: true\n },\n content: {\n value: {},\n writable: true,\n enumerable: true\n }\n });\n\n if (content) {\n this.setContent(content, true);\n }\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['delete', 'update'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\n/**\n * Replaces the current content with new data.\n * Changes made by this function won’t be applied until the save method is called.\n *\n * @param {Object} data - New securityDocument content\n * @return {KuzzleSecurityDocument} this\n */\nKuzzleSecurityDocument.prototype.setContent = function (data) {\n this.content = data;\n return this;\n};\n\n/**\n * Serialize this object into a pojo\n *\n * @return {object} pojo representing this securityDocument\n */\nKuzzleSecurityDocument.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n\n return data;\n};\n\n/**\n * Delete the current KuzzleSecurityDocument into Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n */\nKuzzleSecurityDocument.prototype.delete = function (options, cb) {\n var\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName), {_id: this.id}, options, function (error, res) {\n if (error) {\n return cb ? cb(error) : false;\n }\n\n if (cb) {\n cb(null, res.result._id);\n }\n });\n};\n\n/**\n * Update the current KuzzleSecurityDocument into Kuzzle.\n *\n * @param {object} content - Content to add to KuzzleSecurityDocument\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {KuzzleSecurityDocument} this\n */\nKuzzleSecurityDocument.prototype.update = function (content, options, cb) {\n var\n data = {},\n self = this;\n\n if (typeof content !== 'object') {\n throw new Error('Parameter \"content\" must be a object');\n }\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = self.id;\n data.body = content;\n\n self.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName), data, options, function (error, response) {\n if (error) {\n return cb ? cb(error) : false;\n }\n\n self.setContent(response.result._source);\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return this;\n};\n\nmodule.exports = KuzzleSecurityDocument;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/SecurityDocument.js\n// module id = 1\n// module chunks = 0","/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * Kuzzle handles documents either as realtime messages or as stored documents.\n * Document is the object representation of one of these documents.\n *\n * Notes:\n * - this constructor may be called either with a documentId, a content, neither or both.\n * - providing a documentID to the constructor will automatically call refresh, unless a content is also provided\n *\n *\n * @param {object} kuzzleDataCollection - an instanciated Collection object\n * @param {string} [documentId] - ID of an existing document\n * @param {object} [content] - Initializes this document with the provided content\n * @constructor\n */\nfunction Document(kuzzleDataCollection, documentId, content) {\n Object.defineProperties(this, {\n // read-only properties\n collection: {\n value: kuzzleDataCollection.collection,\n enumerable: true\n },\n dataCollection: {\n value: kuzzleDataCollection,\n enumerable: false\n },\n kuzzle: {\n value: kuzzleDataCollection.kuzzle,\n enumerable: false\n },\n // writable properties\n id: {\n value: undefined,\n enumerable: true,\n writable: true\n },\n content: {\n value: {},\n writable: true,\n enumerable: true\n },\n headers: {\n value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)),\n enumerable: true,\n writable: true\n },\n version: {\n value: undefined,\n enumerable: true,\n writable: true\n }\n });\n\n // handling provided arguments\n if (!content && documentId && typeof documentId === 'object') {\n content = documentId;\n documentId = null;\n }\n\n if (content) {\n if (content._version) {\n this.version = content._version;\n delete content._version;\n }\n this.setContent(content, true);\n }\n\n if (documentId) {\n Object.defineProperty(this, 'id', {\n value: documentId,\n enumerable: true\n });\n }\n\n // promisifying\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['delete', 'refresh', 'save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this document\n */\nDocument.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n data._version = this.version;\n data = this.kuzzle.addHeaders(data, this.headers);\n\n return data;\n};\n\n/**\n * Overrides the toString() method in order to return a serialized version of the document\n *\n * @return {string} serialized version of this object\n */\nDocument.prototype.toString = function () {\n return JSON.stringify(this.serialize());\n};\n\n/**\n * Deletes this document in Kuzzle.\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.delete = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!self.id) {\n throw new Error('Document.delete: cannot delete a document without a document ID');\n }\n\n this.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'delete'), this.serialize(), options, cb && function (err) {\n cb(err, err ? undefined : self.id);\n });\n};\n\n/**\n * Replaces the current content with the last version of this document stored in Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.refresh = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!self.id) {\n throw new Error('Document.refresh: cannot retrieve a document if no ID has been provided');\n }\n\n this.kuzzle.callbackRequired('Document.refresh', cb);\n\n self.kuzzle.query(self.dataCollection.buildQueryArgs('document', 'get'), {_id: self.id}, options, function (error, res) {\n var newDocument;\n\n if (error) {\n return cb(error);\n }\n\n newDocument = new Document(self.dataCollection, self.id, res.result._source);\n newDocument.version = res.result._version;\n\n cb(null, newDocument);\n });\n};\n\n/**\n * Saves this document into Kuzzle.\n *\n * If this is a new document, this function will create it in Kuzzle and the id property will be made available.\n * Otherwise, this method will replace the latest version of this document in Kuzzle by the current content\n * of this object.\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'createOrReplace'), data, options, function (error, res) {\n if (error) {\n return cb && cb(error);\n }\n\n self.id = res.result._id;\n self.version = res.result._version;\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return self;\n};\n\n/**\n * Sends the content of this document as a realtime message.\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @returns {*} this\n */\nDocument.prototype.publish = function (options) {\n var data = this.serialize();\n\n this.kuzzle.query(this.dataCollection.buildQueryArgs('realtime', 'publish'), data, options);\n\n return this;\n};\n\n/**\n * Replaces the current content with new data.\n * Changes made by this function won’t be applied until the save method is called.\n *\n * @param {object} data - New content\n * @param {boolean} replace - if true: replace this document content with the provided data\n */\nDocument.prototype.setContent = function (data, replace) {\n var self = this;\n\n if (replace) {\n this.content = data;\n }\n else {\n Object.keys(data).forEach(function (key) {\n self.content[key] = data[key];\n });\n }\n\n return this;\n};\n\n/**\n * Listens to events concerning this document. Has no effect if the document does not have an ID\n * (i.e. if the document has not yet been created as a persisted document).\n *\n * @param {object} [options] - subscription options\n * @param {responseCallback} cb - callback that will be called each time a change has been detected on this document\n */\nDocument.prototype.subscribe = function (options, cb) {\n var filters;\n\n if (options && !cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Document.subscribe', cb);\n\n if (!this.id) {\n throw new Error('Document.subscribe: cannot subscribe to a document if no ID has been provided');\n }\n\n filters = { ids: { values: [this.id] } };\n\n return this.dataCollection.subscribe(filters, options, cb);\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nDocument.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\n\nmodule.exports = Document;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Document.js\n// module id = 2\n// module chunks = 0","function WSNode(host, port, ssl) {\n var self = this;\n this.WebSocket = typeof WebSocket !== 'undefined' ? WebSocket : require('ws');\n this.host = host;\n this.port = port;\n this.ssl = ssl;\n this.client = null;\n this.wasConnected = false;\n this.retrying = false;\n this.lasturl = null;\n\n /*\n Listeners are stored using the following format:\n roomId: {\n fn: callback_function,\n once: boolean\n }\n */\n this.listeners = {\n error: [],\n connect: [],\n disconnect: [],\n reconnect: []\n };\n\n /**\n * Creates a new socket from the provided arguments\n *\n * @constructor\n * @param {boolean} autoReconnect\n * @param {int} reconnectionDelay\n * @returns {Object} Socket\n */\n this.connect = function (autoReconnect, reconnectionDelay) {\n var\n url = (this.ssl ? 'wss://' : 'ws://') + this.host + ':' + this.port,\n options = typeof window !== 'undefined' ? undefined : {perMessageDeflate: false};\n\n if (url !== this.lasturl) {\n self.wasConnected = false;\n this.lasturl = url;\n }\n\n this.client = new this.WebSocket(url, options);\n\n this.client.onopen = function () {\n if (self.wasConnected) {\n poke(self.listeners, 'reconnect');\n }\n else {\n poke(self.listeners, 'connect');\n }\n self.wasConnected = true;\n };\n\n this.client.onclose = function (code, message) {\n if (code === 1000) {\n poke(self.listeners, 'disconnect');\n }\n else {\n onClientError.call(self, autoReconnect, reconnectionDelay, message);\n }\n };\n\n this.client.onerror = function (error) {\n onClientError.call(self, autoReconnect, reconnectionDelay, error);\n };\n\n this.client.onmessage = function (payload) {\n var data = JSON.parse(payload.data || payload);\n\n if (data.room && self.listeners[data.room]) {\n poke(self.listeners, data.room, data);\n }\n else if (self.listeners.discarded) {\n poke(self.listeners, 'discarded', data);\n }\n };\n };\n\n /**\n * Fires the provided callback whence a connection is established\n *\n * @param {function} callback\n */\n this.onConnect = function (callback) {\n this.listeners.connect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a connection error is received\n * @param {function} callback\n */\n this.onConnectError = function (callback) {\n this.listeners.error.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a disconnection occurred\n * @param {function} callback\n */\n this.onDisconnect = function (callback) {\n this.listeners.disconnect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a connection has been reestablished\n * @param {function} callback\n */\n this.onReconnect = function (callback) {\n this.listeners.reconnect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Registers a callback on a room. Once 1 message is received, fires the\n * callback and unregister it afterward.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.once = function (roomId, callback) {\n if (!this.listeners[roomId]) {\n this.listeners[roomId] = [];\n }\n\n this.listeners[roomId].push({\n fn: callback,\n keep: false\n });\n };\n\n /**\n * Registers a callback on a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.on = function (roomId, callback) {\n if (!this.listeners[roomId]) {\n this.listeners[roomId] = [];\n }\n\n this.listeners[roomId].push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Unregisters a callback from a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.off = function (roomId, callback) {\n var index = -1;\n\n if (this.listeners[roomId]) {\n // Array.findIndex is not supported by internet explorer\n this.listeners[roomId].some(function (listener, i) {\n if (listener.fn === callback) {\n index = i;\n return true;\n }\n\n return false;\n });\n\n if (index !== -1) {\n if (this.listeners[roomId].length === 1 && ['error', 'connect', 'disconnect', 'reconnect'].indexOf(roomId) === -1) {\n delete this.listeners[roomId];\n }\n else {\n this.listeners[roomId].splice(index, 1);\n }\n }\n }\n };\n\n\n /**\n * Sends a payload to the connected server\n *\n * @param {Object} payload\n */\n this.send = function (payload) {\n if (this.client && this.client.readyState === this.client.OPEN) {\n this.client.send(JSON.stringify(payload));\n }\n };\n\n /**\n * Closes the connection\n */\n this.close = function () {\n this.listeners = {\n error: [],\n connect: [],\n disconnect: [],\n reconnect: []\n };\n\n this.wasConnected = false;\n this.client.close();\n this.client = null;\n };\n}\n\n/**\n * Executes all registered listeners in the provided\n * \"listeners\" structure.\n *\n * Listeners are of the following format:\n * [\n * { fn: callback, once: boolean },\n * ...\n * ]\n *\n * @private\n * @param {Object} listeners\n * @param {string} roomId\n * @param {Object} [payload]\n */\nfunction poke (listeners, roomId, payload) {\n var\n i,\n length = listeners[roomId].length;\n\n for (i = 0; i < length; ++i) {\n listeners[roomId][i].fn(payload);\n\n if (!listeners[roomId][i].keep) {\n if (listeners[roomId].length > 1) {\n listeners[roomId].splice(i, 1);\n --i;\n --length;\n }\n else {\n delete listeners[roomId];\n }\n }\n }\n}\n\n/**\n * Called when the connection closes with an error state\n *\n * @param {boolean} autoReconnect\n * @param {number} reconnectionDelay\n * @param {string|Object} message\n */\nfunction onClientError(autoReconnect, reconnectionDelay, message) {\n var self = this;\n\n if (autoReconnect && !self.retrying) {\n self.retrying = true;\n setTimeout(function () {\n self.retrying = false;\n self.connect(autoReconnect, reconnectionDelay);\n }, reconnectionDelay);\n }\n\n poke(self.listeners, 'error', message);\n}\n\nmodule.exports = WSNode;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/wrappers/websocket.js\n// module id = 3\n// module chunks = 0","var\n KuzzleSecurityDocument = require('./SecurityDocument');\n\n/**\n * @param {Security} Security\n * @param {string} id\n * @param {Object} content\n * @constructor\n */\nfunction User(Security, id, content) {\n\n KuzzleSecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteUser'\n },\n updateActionName: {\n value: 'updateUser'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['save', 'saveRestricted'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\nUser.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n constructor: {\n value: User\n }\n});\n\n/**\n * Set profiles in content\n * @param {array} profileIds - an array of profiles ids string\n *\n * @returns {User} this\n */\nUser.prototype.setProfiles = function (profileIds) {\n if (!Array.isArray(profileIds) || typeof profileIds[0] !== 'string') {\n throw new Error('Parameter \"profileIds\" must be an array of strings');\n }\n\n this.content.profileIds = profileIds;\n\n return this;\n};\n\n/**\n * Add a profile\n * @param {string} profileId - a profile ids string\n *\n * @returns {User} this\n */\nUser.prototype.addProfile = function (profileId) {\n if (typeof profileId !== 'string') {\n throw new Error('Parameter \"profileId\" must be a string');\n }\n\n if (!this.content.profileIds) {\n this.content.profileIds = [];\n }\n\n if (this.content.profileIds.indexOf(profileId) === -1) {\n this.content.profileIds.push(profileId);\n }\n\n return this;\n};\n\n/**\n * Saves this user into Kuzzle.\n *\n * If this is a new user, this function will create it in Kuzzle.\n * Otherwise, this method will replace the latest version of this user in Kuzzle by the current content\n * of this object.\n *\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {User} this\n */\nUser.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n/**\n * Saves this user as restricted into Kuzzle.\n *\n * This function will create a new user. It is not usable to update an existing user.\n * The \"profileIds\" property must not be provided, or the request will be rejected by Kuzzle.\n * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n *\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {User} this\n */\nUser.prototype.saveRestricted = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createRestrictedUser'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this User\n */\nUser.prototype.serialize = function () {\n return {_id: this.id, body: this.content};\n};\n\n/**\n * Return the associated profiles IDs\n *\n * @return {array} the associated profiles IDs\n */\nUser.prototype.getProfiles = function () {\n return this.content.profileIds;\n};\n\nmodule.exports = User;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/User.js\n// module id = 4\n// module chunks = 0","var v1 = require('./v1');\nvar v4 = require('./v4');\n\nvar uuid = v4;\nuuid.v1 = v1;\nuuid.v4 = v4;\n\nmodule.exports = uuid;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/uuid/index.js\n// module id = 5\n// module chunks = 0","/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).substr(1);\n}\n\nfunction bytesToUuid(buf, offset) {\n var i = offset || 0;\n var bth = byteToHex;\n return bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]];\n}\n\nmodule.exports = bytesToUuid;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/uuid/lib/bytesToUuid.js\n// module id = 6\n// module chunks = 0","// Unique ID creation requires a high quality random # generator. In the\n// browser this is a little complicated due to unknown quality of Math.random()\n// and inconsistent support for the `crypto` API. We do the best we can via\n// feature-detection\nvar rng;\n\nvar crypto = global.crypto || global.msCrypto; // for IE 11\nif (crypto && crypto.getRandomValues) {\n // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n var rnds8 = new Uint8Array(16);\n rng = function whatwgRNG() {\n crypto.getRandomValues(rnds8);\n return rnds8;\n };\n}\n\nif (!rng) {\n // Math.random()-based (RNG)\n //\n // If all else fails, use Math.random(). It's fast, but is of unspecified\n // quality.\n var rnds = new Array(16);\n rng = function() {\n for (var i = 0, r; i < 16; i++) {\n if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n }\n\n return rnds;\n };\n}\n\nmodule.exports = rng;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/uuid/lib/rng-browser.js\n// module id = 7\n// module chunks = 0","var\n KuzzleSearchResult = require('./SearchResult'),\n Document = require('./Document'),\n CollectionMapping = require('./CollectionMapping'),\n Room = require('./Room'),\n KuzzleSubscribeResult = require('./SubscribeResult');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * A data collection is a set of data managed by Kuzzle. It acts like a data table for persistent documents,\n * or like a room for pub/sub messages.\n *\n * @property {string} collection\n * @property {string} index\n * @property {Kuzzle} kuzzle\n * @property {Array.} collection\n * @param {object} kuzzle - Kuzzle instance to inherit from\n * @param {string} collection - name of the data collection to handle\n * @param {string} index - Index containing the data collection\n * @constructor\n */\nfunction Collection(kuzzle, collection, index) {\n if (!index || !collection) {\n throw new Error('The Collection object constructor needs an index and a collection arguments');\n }\n\n Object.defineProperties(this, {\n // read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n index: {\n value: index,\n enumerable: true\n },\n kuzzle: {\n value: kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(kuzzle.headers)),\n enumerable: true,\n writable: true\n }\n });\n\n Object.defineProperty(this, 'buildQueryArgs', {\n value: function (controller, action) {\n return {\n controller: controller,\n action: action,\n collection: this.collection,\n index: this.index\n };\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['publishMessage', 'setHeaders', 'subscribe'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Returns the number of documents matching the provided set of filters.\n *\n * There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function\n *\n * @param {object} filters - Filters in Elasticsearch Query DSL format\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.count = function (filters, options, cb) {\n var\n query;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.count', cb);\n\n query = this.kuzzle.addHeaders({body: filters}, this.headers);\n\n this.kuzzle.query(this.buildQueryArgs('document', 'count'), query, options, function (error, result) {\n cb(error, result && result.result.count);\n });\n};\n\n/**\n * Create a new empty data collection, with no associated mapping.\n * Kuzzle automatically creates data collections when storing documents, but there are cases where we\n * want to create and prepare data collections before storing documents in it.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n * @returns {*} this\n */\nCollection.prototype.create = function (options, cb) {\n var data = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('collection', 'create'), data, options, cb);\n\n return this;\n};\n\n/**\n * Create a new document in Kuzzle.\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n * - updateIfExist (boolean, default: false):\n * If the same document already exists: throw an error if sets to false.\n * Update the existing document otherwise\n *\n * @param {string} [id] - (optional) document identifier\n * @param {object} document - either an instance of a Document object, or a document\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Object} this\n */\nCollection.prototype.createDocument = function (id, document, options, cb) {\n var\n self = this,\n data = {},\n action = 'create';\n\n if (id && typeof id !== 'string') {\n cb = options;\n options = document;\n document = id;\n id = null;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (document instanceof Document) {\n data = document.serialize();\n } else {\n data.body = document;\n }\n\n if (options) {\n action = options.updateIfExist ? 'createOrReplace' : 'create';\n }\n\n if (id) {\n data._id = id;\n }\n\n data = self.kuzzle.addHeaders(data, self.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n var doc;\n\n if (err) {\n return cb(err);\n }\n\n doc = new Document(self, res.result._id, res.result._source);\n doc.version = res.result._version;\n cb(null, doc);\n });\n\n return this;\n};\n\n/**\n * Delete persistent documents.\n *\n * There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string|object} arg - Either a document ID (will delete only this particular document), or a set of filters\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Collection} this\n */\nCollection.prototype.deleteDocument = function (arg, options, cb) {\n var\n action,\n data = {};\n\n if (typeof arg === 'string') {\n data._id = arg;\n action = 'delete';\n } else {\n data.body = arg;\n action = 'deleteByQuery';\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n\n this.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n if (err) {\n cb(err);\n }\n else {\n cb(null, (action === 'delete' ? [res.result._id] : res.result.ids));\n }\n });\n\n return this;\n};\n\n/**\n * Retrieve a single stored document using its unique document ID.\n *\n * @param {string} documentId - Unique document identifier\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.fetchDocument = function (documentId, options, cb) {\n var\n data = {_id: documentId},\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Collection.fetch', cb);\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'get'), data, options, function (err, res) {\n var document;\n\n if (err) {\n return cb(err);\n }\n\n document = new Document(self, res.result._id, res.result._source);\n document.version = res.result._version;\n cb(null, document);\n });\n};\n\n/**\n * Retrieves all documents stored in this data collection\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.fetchAllDocuments = function (options, cb) {\n var\n warnEmitted = false,\n documents = [],\n filters = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n // copying pagination options to the search filter\n if (!options) {\n options = {};\n }\n\n if (!options.from) {\n options.from = 0;\n }\n\n if (!options.size) {\n options.size = 1000;\n }\n\n this.kuzzle.callbackRequired('Collection.fetchAllDocuments', cb);\n\n this.search(filters, options, function getNextDocuments (error, searchResult) {\n if (error) {\n return cb(error);\n }\n\n if (searchResult instanceof KuzzleSearchResult) {\n if (searchResult.total > 10000 && !warnEmitted) {\n warnEmitted = true;\n console.warn('Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead'); // eslint-disable-line no-console\n }\n\n searchResult.documents.forEach(function(document) {\n documents.push(document);\n });\n searchResult.next(getNextDocuments);\n }\n else {\n cb(null, documents);\n }\n });\n};\n\n\n/**\n * Instantiates a CollectionMapping object containing the current mapping of this collection.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Returns an instantiated CollectionMapping object\n */\nCollection.prototype.getMapping = function (options, cb) {\n var kuzzleMapping;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.getMapping', cb);\n\n kuzzleMapping = new CollectionMapping(this);\n kuzzleMapping.refresh(options, cb);\n};\n\n/**\n * Publish a realtime message\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} document - either a Document instance or a JSON object\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Returns a raw Kuzzle response\n * @returns {*} this\n */\nCollection.prototype.publishMessage = function (document, options, cb) {\n var data = {};\n\n if (document instanceof Document) {\n data = document.serialize();\n } else {\n data.body = document;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('realtime', 'publish'), data, options, cb);\n\n return this;\n};\n\n/**\n * Replace an existing document with a new one.\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string} documentId - Unique document identifier of the document to replace\n * @param {object} content - JSON object representing the new document version\n * @param {object} [options] - additional arguments\n * @param {responseCallback} [cb] - Returns an instantiated Document object\n * @return {object} this\n */\nCollection.prototype.replaceDocument = function (documentId, content, options, cb) {\n var\n self = this,\n data = {\n _id: documentId,\n body: content\n };\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'createOrReplace'), data, options, cb && function (err, res) {\n var document;\n\n if (err) {\n return cb(err);\n }\n\n document = new Document(self, res.result._id, res.result._source);\n document.version = res.result._version;\n cb(null, document);\n });\n\n return this;\n};\n\n/**\n * Executes an advanced search on the data collection.\n *\n * /!\\ There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function.\n *\n * @param {object} filters - Filters in Elasticsearch Query DSL format\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\n\nCollection.prototype.search = function (filters, options, cb) {\n var\n query,\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n self.kuzzle.callbackRequired('Collection.search', cb);\n\n query = self.kuzzle.addHeaders({body: filters}, this.headers);\n\n\n self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) {\n var documents = [];\n\n if (error) {\n return cb(error);\n }\n\n result.result.hits.forEach(function (doc) {\n var newDocument = new Document(self, doc._id, doc._source);\n\n newDocument.version = doc._version;\n\n documents.push(newDocument);\n });\n\n if (result.result._scroll_id) {\n options.scrollId = result.result._scroll_id;\n }\n\n cb(null, new KuzzleSearchResult(\n self,\n result.result.total,\n documents,\n result.result.aggregations ? result.result.aggregations : [],\n {options: options, filters: filters}\n ));\n });\n};\n\n/**\n * A \"scroll\" option can be passed to search queries, creating persistent\n * paginated results.\n * This method can be used to manually get the next page of a search result,\n * instead of using KuzzleSearchResult.next()\n *\n * @param {string} scrollId\n * @param {object} [options]\n * @param {object} [filters]\n * @param {responseCallback} cb\n */\nCollection.prototype.scroll = function (scrollId, options, filters, cb) {\n var\n request = {},\n self = this;\n\n if (!scrollId) {\n throw new Error('Collection.scroll: scrollId is required');\n }\n\n if (!cb) {\n cb = filters;\n filters = null;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n this.kuzzle.callbackRequired('Collection.scroll', cb);\n\n request.scrollId = scrollId;\n\n if (options && options.scroll) {\n request.scroll = options.scroll;\n }\n\n this.kuzzle.query({controller: 'document', action: 'scroll'}, request, options, function (error, result) {\n var documents = [];\n\n if (error) {\n return cb(error);\n }\n\n result.result.hits.forEach(function (doc) {\n var newDocument = new Document(self, doc._id, doc._source);\n\n newDocument.version = doc._version;\n\n documents.push(newDocument);\n });\n\n if (result.result._scroll_id) {\n options.scrollId = result.result._scroll_id;\n }\n\n cb(null, new KuzzleSearchResult(\n self,\n result.result.total,\n documents,\n result.result.aggregations ? result.result.aggregations : [],\n {options: options, filters: filters}\n ));\n });\n\n return this;\n};\n\n/**\n * Subscribes to this data collection with a set of filters.\n * To subscribe to the entire data collection, simply provide an empty filter.\n *\n * @param {object} filters - Filters in Kuzzle DSL format\n * @param {object} [options] - subscriptions options\n * @param {responseCallback} cb - called for each new notification\n * @returns {*} KuzzleSubscribeResult object\n */\nCollection.prototype.subscribe = function (filters, options, cb) {\n var\n room,\n subscribeResult;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.subscribe', cb);\n\n subscribeResult = new KuzzleSubscribeResult();\n room = new Room(this, options);\n\n room.renew(filters, cb, subscribeResult.done.bind(subscribeResult));\n\n return subscribeResult;\n};\n\n/**\n * Truncate the data collection, removing all stored documents but keeping all associated mappings.\n * This method is a lot faster than removing all documents using a query.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n * @returns {*} this\n */\nCollection.prototype.truncate = function (options, cb) {\n var data = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('collection', 'truncate'), data, options, cb);\n\n return this;\n};\n\n\n/**\n * Update parts of a document\n *\n * Takes an optional argument object with the following properties:\n * - metadata (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string} documentId - Unique document identifier of the document to update\n * @param {object} content - JSON object containing changes to perform on the document\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Returns an instantiated Document object\n * @return {object} this\n */\nCollection.prototype.updateDocument = function (documentId, content, options, cb) {\n var\n data = {\n _id: documentId,\n body: content\n },\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'update'), data, options, cb && function (err, res) {\n if (err) {\n return cb(err);\n }\n\n (new Document(self, res.result._id)).refresh(cb);\n });\n\n return self;\n};\n\n\n/**\n * Instantiate a new Document object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - document id\n * @param {object} content - document content\n * @constructor\n */\nCollection.prototype.document = function (id, content) {\n return new Document(this, id, content);\n};\n\n/**\n * Instantiate a new Room object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {object} [options] - subscription configuration\n * @constructor\n */\nCollection.prototype.room = function (options) {\n return new Room(this, options);\n};\n\n/**\n * Instantiate a new CollectionMapping object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {object} [mapping] - mapping to instantiate the CollectionMapping object with\n * @constructor\n */\nCollection.prototype.collectionMapping = function (mapping) {\n return new CollectionMapping(this, mapping);\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nCollection.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\nmodule.exports = Collection;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Collection.js\n// module id = 8\n// module chunks = 0","/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n\n/**\n * When creating a new data collection in the persistent data storage layer, Kuzzle uses a default mapping.\n * It means that, by default, you won’t be able to exploit the full capabilities of our persistent data storage layer\n * (currently handled by ElasticSearch), and your searches may suffer from below-average performances, depending on\n * the amount of data you stored in a collection and the complexity of your database.\n *\n * The CollectionMapping object allow to get the current mapping of a data collection and to modify it if needed.\n *\n * @param {object} collection - Instance of the inherited Collection object\n * @param {object} [mapping] - mappings\n * @constructor\n */\nfunction CollectionMapping(collection, mapping) {\n Object.defineProperties(this, {\n //read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n kuzzle: {\n value: collection.kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(collection.headers)),\n enumerable: true,\n writable: true\n },\n mapping: {\n value: mapping || {},\n enumerable: true,\n writable: true\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['set', 'setHeaders'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Applies the new mapping to the data collection.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n */\nCollectionMapping.prototype.apply = function (options, cb) {\n var\n self = this,\n data = this.kuzzle.addHeaders({body: {properties: this.mapping}}, this.headers);\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.collection.buildQueryArgs('collection', 'updateMapping'), data, options, function (err) {\n if (err) {\n return cb && cb(err);\n }\n\n self.refresh(options, cb);\n });\n\n return this;\n};\n\n/**\n * Replaces the current content with the mapping stored in Kuzzle\n *\n * Calling this function will discard any uncommited changes. You can commit changes by calling the “apply” function\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nCollectionMapping.prototype.refresh = function (options, cb) {\n var\n self = this,\n data = this.kuzzle.addHeaders({}, this.headers);\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.collection.buildQueryArgs('collection', 'getMapping'), data, options, function (err, res) {\n if (err) {\n return cb ? cb(err) : false;\n }\n\n if (res.result[self.collection.index]) {\n if (res.result[self.collection.index].mappings[self.collection.collection]) {\n self.mapping = res.result[self.collection.index].mappings[self.collection.collection].properties;\n\n // Mappings can be empty. The mapping property should never be \"undefined\"\n if (self.mapping === undefined) {\n self.mapping = {};\n }\n } else {\n return cb && cb(new Error('No mapping found for collection ' + self.collection.collection));\n }\n } else {\n return cb && cb(new Error('No mapping found for index ' + self.collection.index));\n }\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return this;\n};\n\n\n/**\n * Adds or updates a field mapping.\n *\n * Changes made by this function won’t be applied until you call the apply method\n *\n * @param {string} field - Name of the field from which the mapping is to be added or updated\n * @param {object} mapping - corresponding field mapping\n * @returns {CollectionMapping}\n */\nCollectionMapping.prototype.set = function (field, mapping) {\n this.mapping[field] = mapping;\n\n return this;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nCollectionMapping.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\nmodule.exports = CollectionMapping;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/CollectionMapping.js\n// module id = 9\n// module chunks = 0","/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n\n/**\n * Kuzzle's memory storage is a separate data store from the database layer.\n * It is internaly based on Redis. You can access most of Redis functions (all\n * lowercased), excepting:\n * * all cluster based functions\n * * all script based functions\n * * all cursors functions\n *\n * For instance:\n * kuzzle.memoryStorage\n * .set('myKey', 'myValue')\n * .get('myKey', function (err, response) {\n * console.log(response.result);\n *\n * // { _id: 'foo', body: { value: 'myValue' }}\n * });\n *\n *\n * @param {object} kuzzle - Kuzzle instance to inherit from\n * @constructor\n */\nfunction MemoryStorage(kuzzle) {\n Object.defineProperties(this, {\n // read-only properties\n kuzzle: {\n value: kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(kuzzle.headers)),\n enumerable: true,\n writable: true\n }\n });\n\n this.setHeaders = kuzzle.setHeaders.bind(this);\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['setHeaders'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n\n/**\n * constructs the memoryStorage functions.\n */\n(function() {\n\n var\n keyVal = ['id', 'value'],\n idOrKeys = ['id', 'keys'],\n commands = {\n append: keyVal,\n bgrewriteaof: [],\n bgsave: [],\n bitcount: ['id', 'start', 'end'],\n bitop: ['operation', 'destkey', idOrKeys],\n bitpos: ['id', 'bit', { __opts__: ['start', 'end']}],\n blpop: [idOrKeys, 'timeout'],\n brpoplpush: ['source', 'destination'],\n dbsize: [],\n decrby: keyVal,\n del: [idOrKeys],\n discard: [],\n exec: [],\n exists: [idOrKeys],\n expire: ['id', 'seconds'],\n expireat: ['id', 'timestamp'],\n flushdb: [],\n // @todo: implement geolocation methods once available in Redis stable release\n getbit: ['id', 'offset'],\n getrange: ['id', 'start', 'end'],\n hdel: ['id', ['field', 'fields']],\n hexists: ['id', 'field'],\n hincrby: ['id', 'field', 'value'],\n hmset: ['id', 'values'],\n hset: ['id', 'field', 'value'],\n info: ['section'],\n keys: [ 'pattern' ],\n lastsave: [],\n lindex: ['id', 'idx'],\n linsert: ['id', 'position', 'pivot', 'value'],\n lpush: ['id', ['value', 'values']],\n lrange: ['id', 'start', 'stop'],\n lrem: ['id', 'count', 'value'],\n lset: ['id', 'idx', 'value'],\n ltrim: ['id', 'start', 'stop'],\n mset: ['values'],\n multi: [],\n object: ['subcommand', 'args'],\n pexpire: ['id', 'milliseconds'],\n pexpireat: ['id', 'timestamp'],\n pfadd: ['id', ['element', 'elements']],\n pfmerge: ['destkey', ['sourcekey', 'sourcekeys']],\n ping: [],\n psetex: ['id', 'milliseconds', 'value'],\n publish: ['channel', 'message'],\n randomkey: [],\n rename: ['id', 'newkey'],\n renamenx: ['id', 'newkey'],\n restore: ['id', 'ttl', 'content'],\n rpoplpush: ['source', 'destination'],\n sadd: ['id', ['member', 'members']],\n save: [],\n set: ['id', 'value', {__opts__:['ex', 'px', 'nx', 'xx']}],\n sdiffstore: ['destination', idOrKeys],\n setbit: ['id', 'offset', 'value'],\n setex: ['id', 'seconds', 'value'],\n setrange: ['id', 'offset', 'value'],\n sinterstore: ['destination', idOrKeys],\n sismember: ['id', 'member'],\n smove: ['id', 'destination', 'member'],\n sort: ['id', {__opts__:['by', 'offset', 'count', 'get', 'direction', 'alpha', 'store']}],\n spop: ['id', 'count'],\n srem: ['id', ['member', 'members']],\n sunionstore: ['destination', idOrKeys],\n unwatch: [],\n wait: ['numslaves', 'timeout'],\n zadd: ['id', {__opts__: ['nx', 'xx', 'ch', 'incr', 'score', 'member', 'members']}],\n zcount: ['id', 'min', 'max'],\n zincrby: ['id', 'value', 'member'],\n zinterstore: ['destination', idOrKeys, {__opts__: ['weight', 'weights', 'aggregate']}],\n zlexcount: ['id', 'min', 'max'],\n zrange: ['id', 'start', 'stop', {__opts__: ['withscores']}],\n zrangebylex: ['id', 'min', 'max', {__opts__: ['offset', 'count']}],\n zrangebyscore: ['id', 'min', 'max', {__opts__: ['withscores', 'offset', 'count']}],\n zrem: ['id', 'member'],\n zremrangebylex: ['id', 'min', 'max'],\n zremrangebyscore: ['id', 'min', 'max'],\n zrevrangebylex: ['id', 'max', 'min', {__opts__: ['offset', 'count']}],\n zrevrangebyscore: ['id', 'max', 'min', {__opts__: ['withscores', 'offset', 'count']}],\n zrevrank: ['id', 'member']\n };\n\n // unique argument key\n commands.decr = commands.get = commands.dump = commands.hgetall = commands.hkeys = commands.hlen = commands.hstrlen = commands.hvals = commands.incr = commands.llen = commands.lpop = commands.persist = commands.pttl = commands.rpop = commands.scard = commands.smembers = commands.strlen = commands.ttl = commands.type = commands.zcard = ['id'];\n\n // key value\n commands.getset = commands.lpushx = keyVal;\n\n // key key...\n commands.del = commands.exists = commands.mget = commands.pfcount = commands.sdiff = commands.sinter = commands.sunion = commands.watch = [idOrKeys];\n\n commands.incrby = commands.incrbyfloat = commands.decrby;\n commands.brpop = commands.blpop;\n commands.hget = commands.hexists;\n commands.hmget = commands.hdel;\n commands.hsetnx = commands.hset;\n commands.msetnx = commands.mset;\n commands.rpush = commands.lpush;\n commands.hincrbyfloat = commands.hincrby;\n commands.srandmember = commands.spop;\n commands.zrevrange = commands.zrange;\n commands.zscore = commands.zrevrank;\n\n Object.keys(commands).forEach(function (command) {\n MemoryStorage.prototype[command] = function () {\n var\n args = Array.prototype.slice.call(arguments),\n options = null,\n cb,\n query = {\n controller: 'ms',\n action: command\n },\n data = {};\n\n if (typeof args[args.length - 1] === 'function') {\n cb = args.pop();\n }\n\n if (args.length && typeof args[args.length - 1] === 'object' && Object.keys(args[args.length - 1]).length === 1 && args[args.length - 1].queuable !== undefined) {\n options = args.pop();\n }\n\n commands[command].forEach(function (v, i) {\n if (args[i] === undefined) {\n return;\n }\n\n if (Array.isArray(v)) {\n v = Array.isArray(args[i]) ? v[1] : v[0];\n }\n\n if (v === 'id') {\n data._id = args[i];\n }\n else {\n if (!data.body) {\n data.body = {};\n }\n\n if (typeof v === 'object' && v.__opts__ !== undefined) {\n v.__opts__.forEach(function (arg) {\n if (args[i][arg] !== undefined) {\n data.body[arg] = args[i][arg];\n }\n });\n }\n else {\n data.body[v] = args[i];\n }\n }\n });\n\n this.kuzzle.query(query, data, options, cb);\n\n return this;\n\n };\n });\n\n})();\n\nmodule.exports = MemoryStorage;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/MemoryStorage.js\n// module id = 10\n// module chunks = 0","var\n uuid = require('uuid'),\n Document = require('./Document');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * This object is the result of a subscription request, allowing to manipulate the subscription itself.\n *\n * In Kuzzle, you don’t exactly subscribe to a room or a topic but, instead, you subscribe to documents.\n *\n * What it means is that, to subscribe, you provide to Kuzzle a set of matching filters.\n * Once you have subscribed, if a pub/sub message is published matching your filters, or if a matching stored\n * document change (because it is created, updated or deleted), then you’ll receive a notification about it.\n *\n * @param {object} kuzzleDataCollection - an instantiated and valid kuzzle object\n * @param {object} [options] - subscription optional configuration\n * @constructor\n */\nfunction Room(kuzzleDataCollection, options) {\n // Define properties\n Object.defineProperties(this, {\n // private properties\n callback: {\n value: null,\n writable: true\n },\n channel: {\n value: null,\n writable: true\n },\n id: {\n value: uuid.v4()\n },\n lastRenewal: {\n value: null,\n writable: true\n },\n notifier: {\n value: null,\n writable: true\n },\n onDoneCB: {\n value: null,\n writable: true\n },\n queue: {\n value: [],\n writable: true\n },\n // Delay before allowing a subscription renewal\n renewalDelay: {\n value: 500\n },\n scope: {\n value: options && options.scope ? options.scope : 'all'\n },\n state: {\n value: options && options.state ? options.state : 'done'\n },\n subscribing: {\n value: false,\n writable: true\n },\n users: {\n value: options && options.users ? options.users : 'none'\n },\n // read-only properties\n collection: {\n value: kuzzleDataCollection,\n enumerable: true\n },\n kuzzle: {\n value: kuzzleDataCollection.kuzzle,\n enumerable: true\n },\n // writable properties\n filters: {\n value: null,\n enumerable: true,\n writable: true\n },\n headers: {\n value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)),\n enumerable: true,\n writable: true\n },\n metadata: {\n value: (options && options.metadata) ? options.metadata : {},\n enumerable: true,\n writable: true\n },\n roomId: {\n value: null,\n enumerable: true,\n writable: true\n },\n subscribeToSelf: {\n value: options && typeof options.subscribeToSelf === 'boolean' ? options.subscribeToSelf : true,\n enumerable: true,\n writable: true\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['count'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Returns the number of other subscriptions on that room.\n *\n * @param {responseCallback} cb - Handles the query response\n */\nRoom.prototype.count = function (cb) {\n var data;\n\n this.kuzzle.callbackRequired('Room.count', cb);\n\n data = this.kuzzle.addHeaders({body: {roomId: this.roomId}}, this.headers);\n\n if (!isReady.call(this)) {\n this.queue.push({action: 'count', args: [cb]});\n return;\n }\n\n if (!this.roomId) {\n throw new Error('Room.count: cannot count subscriptions on an inactive room');\n }\n\n this.kuzzle.query(this.collection.buildQueryArgs('realtime', 'count'), data, function (err, res) {\n cb(err, res && res.result.count);\n });\n};\n\n/**\n * Renew the subscription using new filters\n *\n * @param {object} [filters] - Filters in Kuzzle DSL format\n * @param {responseCallback} notificationCB - called for each new notification\n * @param {responseCallback} [cb] - handles the query response\n */\nRoom.prototype.renew = function (filters, notificationCB, cb) {\n var\n now = Date.now(),\n subscribeQuery = {\n scope: this.scope,\n state: this.state,\n users: this.users\n },\n self = this;\n\n if (typeof filters === 'function') {\n cb = notificationCB;\n notificationCB = filters;\n filters = null;\n }\n\n if (!cb) {\n cb = self.onDoneCB;\n }\n\n self.kuzzle.callbackRequired('Room.renew', notificationCB);\n\n /*\n Skip subscription renewal if another one was performed a moment before\n */\n if (self.lastRenewal && (now - self.lastRenewal) <= self.renewalDelay) {\n return cb && cb(new Error('Subscription already renewed less than ' + self.renewalDelay + 'ms ago'));\n }\n\n if (filters) {\n self.filters = filters;\n }\n\n /*\n if not yet connected, register itself to the subscriptions list and wait for the\n main Kuzzle object to renew once online\n */\n if (self.kuzzle.state !== 'connected') {\n self.callback = notificationCB;\n self.onDoneCB = cb;\n self.kuzzle.subscriptions.pending[self.id] = self;\n return;\n }\n\n if (self.subscribing) {\n self.queue.push({action: 'renew', args: [filters, notificationCB, cb]});\n return;\n }\n\n self.unsubscribe();\n self.roomId = null;\n self.subscribing = true;\n self.callback = notificationCB;\n self.onDoneCB = cb;\n self.kuzzle.subscriptions.pending[self.id] = self;\n\n subscribeQuery.body = self.filters;\n subscribeQuery = self.kuzzle.addHeaders(subscribeQuery, this.headers);\n\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {metadata: self.metadata}, function (error, response) {\n delete self.kuzzle.subscriptions.pending[self.id];\n self.subscribing = false;\n\n if (error) {\n self.queue = [];\n return cb && cb(new Error('Error during Kuzzle subscription: ' + error.message));\n }\n\n self.lastRenewal = now;\n self.roomId = response.result.roomId;\n self.channel = response.result.channel;\n\n if (!self.kuzzle.subscriptions[self.roomId]) {\n self.kuzzle.subscriptions[self.roomId] = {};\n }\n\n self.kuzzle.subscriptions[self.roomId][self.id] = self;\n\n self.notifier = notificationCallback.bind(self);\n self.kuzzle.network.on(self.channel, self.notifier);\n\n dequeue.call(self);\n cb && cb(null, self);\n });\n};\n\n/**\n * Unsubscribes from Kuzzle.\n *\n * Stop listening immediately. If there is no listener left on that room, sends an unsubscribe request to Kuzzle, once\n * pending subscriptions reaches 0, and only if there is still no listener on that room.\n * We wait for pending subscriptions to finish to avoid unsubscribing while another subscription on that room is\n *\n * @return {*} this\n */\nRoom.prototype.unsubscribe = function () {\n var\n self = this,\n room = self.roomId,\n interval;\n\n if (!isReady.call(this)) {\n self.queue.push({action: 'unsubscribe', args: []});\n return self;\n }\n\n if (room) {\n self.kuzzle.network.off(self.channel, this.notifier);\n\n if (Object.keys(self.kuzzle.subscriptions[room]).length === 1) {\n delete self.kuzzle.subscriptions[room];\n\n if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n } else {\n interval = setInterval(function () {\n if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n if (!self.kuzzle.subscriptions[room]) {\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n }\n clearInterval(interval);\n }\n }, 100);\n }\n } else {\n delete self.kuzzle.subscriptions[room][self.id];\n }\n\n self.roomId = null;\n }\n\n return self;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nRoom.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\n/**\n * Callback called by the network handler when a message is sent to the subscribed room ID\n * Calls the registered callback if the notification passes the subscription filters\n *\n * @param {object} data - data\n * @returns {*}\n */\nfunction notificationCallback (data) {\n if (data.error) {\n return this.callback(data.error);\n }\n\n if (data.action === 'jwtTokenExpired') {\n this.kuzzle.jwtToken = undefined;\n return this.kuzzle.emitEvent('jwtTokenExpired');\n }\n\n if (data.controller === 'document' || (data.controller === 'realtime' && data.action === 'publish')) {\n data.type = 'document';\n data.document = new Document(this.collection, data.result._id, data.result._source);\n delete data.result;\n }\n else if (data.controller === 'realtime') {\n data.type = 'user';\n data.user = {count: data.result.count};\n delete data.result;\n }\n\n if (this.kuzzle.requestHistory[data.requestId]) {\n if (this.subscribeToSelf) {\n this.callback(null, data);\n }\n delete this.kuzzle.requestHistory[data.requestId];\n } else {\n this.callback(null, data);\n }\n}\n\n\n/**\n * Dequeue actions performed while subscription was being renewed\n */\nfunction dequeue () {\n var element;\n\n while (this.queue.length > 0) {\n element = this.queue.shift();\n\n this[element.action].apply(this, element.args);\n }\n}\n\nfunction isReady() {\n return this.kuzzle.state === 'connected' && !this.subscribing;\n}\n\nmodule.exports = Room;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Room.js\n// module id = 11\n// module chunks = 0","/**\n *\n * @param {Collection} dataCollection\n * @param {int} total\n * @param {Document[]} documents\n * @param {object} [aggregations]\n * @param {object} [searchArgs]\n * @param {KuzzleSearchResult} [previous]\n * @constructor\n */\nfunction KuzzleSearchResult (dataCollection, total, documents, aggregations, searchArgs, previous) {\n Object.defineProperties(this, {\n // read-only properties\n dataCollection: {\n value: dataCollection,\n },\n total: {\n value: total,\n enumerable: true\n },\n documents: {\n value: documents,\n enumerable: true\n },\n aggregations: {\n value: aggregations || {},\n enumerable: true\n },\n searchArgs: {\n value: searchArgs || {},\n enumerable: true\n },\n // writable properties\n fetchedDocument: {\n value: documents.length,\n enumerable: true,\n writable: true\n },\n _previous: {\n value: previous || null,\n writable: true\n },\n _next: {\n value: null,\n writable: true\n }\n });\n\n if (this._previous instanceof KuzzleSearchResult) {\n this._previous._next = this;\n this.fetchedDocument += this._previous.fetchedDocument;\n }\n\n // promisifying\n if (this.dataCollection.kuzzle.bluebird) {\n return this.dataCollection.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['previous', 'next'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n\n/**\n * @param cb\n * @returns {*}\n */\nKuzzleSearchResult.prototype.previous = function (cb) {\n cb(null, this._previous);\n\n return this;\n};\n\n/**\n * @param {function} cb\n */\nKuzzleSearchResult.prototype.next = function (cb) {\n var\n filters,\n options = Object.assign({}, this.searchArgs.options),\n self = this;\n\n if (!this._next) {\n // retrieve next results with scroll if original search use it\n if (options.scrollId) {\n if (this.fetchedDocument >= this.total) {\n cb(null, null);\n return;\n }\n\n // from and size parameters are not valid for a scroll action\n if (typeof options.from !== 'undefined') {\n delete options.from;\n }\n\n if (options.size) {\n delete options.size;\n }\n\n this.dataCollection.scroll(\n options.scrollId,\n options,\n this.searchArgs.filters || {},\n function(error, newSearchResults) {\n handleNextSearchResults(error, self, newSearchResults, cb);\n }\n );\n\n return;\n }\n // retrieve next results with from/size if original search use it\n else if (options.from !== undefined && options.size !== undefined) {\n filters = Object.assign({}, this.searchArgs.filters);\n\n // check if we need to do next request to fetch all matching documents\n options.from += options.size;\n\n if (options.from >= this.total) {\n cb(null, null);\n\n return;\n }\n\n this.dataCollection.search(\n filters,\n options,\n function(error, newSearchResults) {\n handleNextSearchResults(error, self, newSearchResults, cb);\n }\n );\n\n return;\n }\n }\n\n if (this._next instanceof KuzzleSearchResult) {\n cb(null, this._next);\n\n return;\n }\n\n cb(new Error('Unable to retrieve next results from search: missing scrollId or from/size params'));\n};\n\n/**\n * @param {Error} error\n * @param {KuzzleSearchResult} currentSearchResults\n * @param {KuzzleSearchResult} newSearchResults\n * @param {Function} cb\n */\nfunction handleNextSearchResults (error, currentSearchResults, newSearchResults, cb) {\n if (error) {\n cb(error);\n return;\n }\n\n newSearchResults.fetchedDocument += currentSearchResults.fetchedDocument;\n\n newSearchResults._previous = currentSearchResults;\n currentSearchResults._next = newSearchResults;\n\n\n cb(null, newSearchResults);\n}\n\nmodule.exports = KuzzleSearchResult;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/SearchResult.js\n// module id = 12\n// module chunks = 0","/**\n * Sugar-code handling the result of a Room.renew call\n * @constructor\n */\nfunction KuzzleSubscribeResult() {\n this.cbs = [];\n this.error = null;\n this.room = null;\n}\n\n/**\n * Registers a callback to be called with a subscription result\n * @param {Function} cb\n */\nKuzzleSubscribeResult.prototype.onDone = function (cb) {\n if (this.error || this.room) {\n cb(this.error, this.room);\n }\n else {\n this.cbs.push(cb);\n }\n\n return this;\n};\n\n/**\n * Calls all registered callbacks\n *\n * @param {Object} error object\n * @param {Room} room\n */\nKuzzleSubscribeResult.prototype.done = function (error, room) {\n this.error = error;\n this.room = room;\n\n this.cbs.forEach(function (cb) {\n cb(error, room);\n });\n};\n\nmodule.exports = KuzzleSubscribeResult;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/SubscribeResult.js\n// module id = 13\n// module chunks = 0","/**\n *\n * @param host\n * @param port\n * @param sslConnection\n * @returns {Object} tnstantiated WebSocket/Socket.IO object\n */\n\nfunction network(host, port, sslConnection) {\n // Web browser / NodeJS websocket handling\n if (typeof window !== 'undefined') {\n // use native websockets if the browser supports it\n if (typeof WebSocket !== 'undefined') {\n return new (require('./wrappers/websocket'))(host, port, sslConnection);\n }\n // otherwise fallback to socket.io, if available\n else if (window.io) {\n return new (require('./wrappers/socketio'))(host, port, sslConnection);\n }\n\n throw new Error('Aborting: no websocket support detected and no socket.io library loaded either.');\n }\n\n return new (require('./wrappers/websocket'))(host, port, sslConnection);\n}\n\nmodule.exports = network;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/index.js\n// module id = 14\n// module chunks = 0","function SocketIO(host, port, ssl) {\n this.host = host;\n this.port = port;\n this.ssl = ssl;\n this.socket = null;\n\n /**\n * Creates a new socket from the provided arguments\n *\n * @constructor\n * @param {boolean} autoReconnect\n * @param {int} reconnectionDelay\n */\n this.connect = function (autoReconnect, reconnectionDelay) {\n this.socket = window.io((this.ssl ? 'https://' : 'http://') + this.host + ':' + this.port, {\n reconnection: autoReconnect,\n reconnectionDelay: reconnectionDelay,\n forceNew: true\n });\n };\n\n /**\n * Fires the provided callback whence a connection is established\n *\n * @param {function} callback\n */\n this.onConnect = function (callback) {\n this.socket.on('connect', callback);\n };\n\n /**\n * Fires the provided callback whenever a connection error is received\n * @param {function} callback\n */\n this.onConnectError = function (callback) {\n this.socket.on('connect_error', callback);\n };\n\n /**\n * Fires the provided callback whenever a disconnection occurred\n * @param {function} callback\n */\n this.onDisconnect = function (callback) {\n this.socket.on('disconnect', callback);\n };\n\n /**\n * Fires the provided callback whenever a connection has been reestablished\n * @param {function} callback\n */\n this.onReconnect = function (callback) {\n this.socket.on('reconnect', callback);\n };\n\n /**\n * Registers a callback on a room. Once 1 message is received, fires the\n * callback and unregister it afterward.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.once = function (roomId, callback) {\n this.socket.once(roomId, callback);\n };\n\n /**\n * Registers a callback on a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.on = function (roomId, callback) {\n this.socket.on(roomId, callback);\n };\n\n /**\n * Unregisters a callback from a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.off = function (roomId, callback) {\n this.socket.off(roomId, callback);\n };\n\n\n /**\n * Sends a payload to the connected server\n *\n * @param {Object} payload\n */\n this.send = function (payload) {\n this.socket.emit('kuzzle', payload);\n };\n\n /**\n * Closes the connection\n */\n this.close = function () {\n this.socket.close();\n this.socket = null;\n };\n}\n\nmodule.exports = SocketIO;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/wrappers/socketio.js\n// module id = 15\n// module chunks = 0","var\n SecurityDocument = require('./SecurityDocument');\n\nfunction Profile(Security, id, content) {\n\n SecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteProfile'\n },\n updateActionName: {\n value: 'updateProfile'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['hydrate', 'save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n}\n\nProfile.prototype = Object.create(SecurityDocument.prototype, {\n constructor: {\n value: Profile\n }\n});\n\n/**\n * Persist to the persistent layer the current profile\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Profile} this\n */\nProfile.prototype.save = function (options, cb) {\n var\n data,\n self = this;\n\n if (!this.content.policies) {\n throw new Error('Argument \"policies\" is mandatory in a profile. This argument contains an array of objects.');\n }\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.serialize();\n\n self.kuzzle.query(self.Security.buildQueryArgs('createOrReplaceProfile'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n\n/**\n * Add a policy in the policies list\n * @param {Object} policy - must be an object containing at least a \"roleId\" member which must be a string.\n *\n * @returns {Profile} this\n */\nProfile.prototype.addPolicy = function (policy) {\n\n if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n throw new Error('Parameter \"policies\" must be an object containing at least a \"roleId\" member which must be a string.');\n }\n\n if (!this.content.policies) {\n this.content.policies = [];\n }\n\n this.content.policies.push(policy);\n\n return this;\n};\n\n/**\n * Set policies list\n * @param {Array} policies - must be an array of objects containing at least a \"roleId\" member which must be a string\n *\n * @returns {Profile} this\n */\nProfile.prototype.setPolicies = function (policies) {\n\n if (!Array.isArray(policies)) {\n throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n }\n\n policies.map(function (policy) {\n if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n }\n });\n\n this.content.policies = policies;\n\n return this;\n};\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this securityDocument\n */\nProfile.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n\n return data;\n};\n\n/**\n * Returns the list of policies associated to this profile.\n * Each policy element is an array of objects containing at least a \"roleId\" member which must be a string\n *\n * @return {object} an array of policies\n */\nProfile.prototype.getPolicies = function () {\n return this.content.policies;\n};\n\nmodule.exports = Profile;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Profile.js\n// module id = 16\n// module chunks = 0","var KuzzleSecurityDocument = require('./SecurityDocument');\n\nfunction Role(Security, id, content) {\n\n KuzzleSecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteRole'\n },\n updateActionName: {\n value: 'updateRole'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n}\n\nRole.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n constructor: {\n value: Role\n }\n});\n\n/**\n * Saves this role into Kuzzle.\n *\n * If this is a new role, this function will create it in Kuzzle.\n * Otherwise, this method will replace the latest version of this role in Kuzzle by the current content\n * of this object.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Role} this object\n */\nRole.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceRole'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return this;\n};\n\nmodule.exports = Role;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Role.js\n// module id = 17\n// module chunks = 0","var\n Role = require('./Role'),\n Profile = require('./Profile'),\n User = require('./User');\n\n/**\n * Kuzzle security constructor\n *\n * @param kuzzle\n * @returns {Security}\n * @constructor\n */\nfunction Security(kuzzle) {\n\n Object.defineProperty(this, 'kuzzle', {\n value: kuzzle\n });\n\n Object.defineProperty(this, 'buildQueryArgs', {\n value: function (action) {\n return {\n controller: 'security',\n action: action\n };\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['role', 'profile', 'user', 'isActionAllowed'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n\n/**\n * Retrieve a single Role using its unique role ID.\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.fetchRole = function (id, options, cb) {\n var\n data,\n self = this;\n\n if (!id) {\n throw new Error('Id parameter is mandatory for fetchRole function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = {_id: id};\n\n self.kuzzle.callbackRequired('Security.fetchRole', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getRole'), data, options, function (err, response) {\n cb(err, err ? undefined : new Role(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on roles according to a filter\n *\n * /!\\ There is a small delay between role creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a role that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - this object can contains an array `indexes` with a list of index id, a integer `from` and a integer `size`\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n *\n */\nSecurity.prototype.searchRoles = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchRoles', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchRoles'), {body: filters}, options, function (error, result) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = result.result.hits.map(function (doc) {\n return new Role(self, doc._id, doc._source);\n });\n\n cb(null, { total: result.result.total, roles: documents });\n });\n};\n\n/**\n * Create a new role in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same role already exists: throw an error if sets to false.\n * Replace the existing role otherwise\n *\n * @param {string} id - role identifier\n * @param {object} content - a plain javascript object representing the role\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createRole = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'createRole';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createRole: cannot create a role without a role ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceRole' : 'createRole';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new Role(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update a role in Kuzzle.\n *\n * @param {string} id - role identifier\n * @param {object} content - a plain javascript object representing the role's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateRole = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content},\n action = 'updateRole';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateRole: cannot update a role without a role ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err) {\n cb(err, err ? undefined : new Role(self, id, content));\n });\n\n return this;\n};\n\n/**\n * Delete role.\n *\n * There is a small delay between role deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a role that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Role id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteRole = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteRole'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new Role object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - role id\n * @param {object} content - role content\n * @constructor\n */\nSecurity.prototype.role = function(id, content) {\n return new Role(this, id, content);\n};\n\n\n/**\n * Get a specific profile from kuzzle\n *\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} cb - returns Kuzzle's response\n */\nSecurity.prototype.fetchProfile = function (id, options, cb) {\n var\n data,\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!id || typeof id !== 'string') {\n throw new Error('Id parameter is mandatory for fetchProfile function');\n }\n\n\n data = {_id: id};\n\n self.kuzzle.callbackRequired('Security.fetchProfile', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getProfile'), data, options, function (error, response) {\n cb(error, error ? undefined : new Profile(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on profiles according to a filter\n *\n *\n * /!\\ There is a small delay between profile creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a profile that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - this object can contains an array `roles` with a list of roles id, a integer `from` and a integer `size`\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.searchProfiles = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchProfiles', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchProfiles'), {body: filters}, options, function (error, response) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = response.result.hits.map(function (doc) {\n return new Profile(self, doc._id, doc._source);\n });\n\n cb(null, { total: response.result.total, profiles: documents });\n });\n};\n\n/**\n * Create a new profile in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same profile already exists: throw an error if sets to false.\n * Replace the existing profile otherwise\n *\n * @param {string} id - profile identifier\n * @param {object} content - attribute `roles` in `content` must only contains an array of role id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createProfile = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'createProfile';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createProfile: cannot create a profile without a profile ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceProfile' : 'createProfile';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new Profile(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update a profile in Kuzzle.\n *\n * @param {string} id - profile identifier\n * @param {object} content - a plain javascript object representing the profile's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateProfile = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'updateProfile';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateProfile: cannot update a profile without a profile ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n var updatedContent = {};\n\n if (err) {\n return cb(err);\n }\n\n Object.keys(res.result._source).forEach(function (property) {\n updatedContent[property] = res.result._source[property];\n });\n\n cb(null, new Profile(self, res.result._id, updatedContent));\n });\n\n return this;\n};\n\n/**\n * Delete profile.\n *\n * There is a small delay between profile deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a profile that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Profile id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteProfile = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteProfile'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new Profile object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - profile id\n * @param {object} content - profile content\n * @constructor\n */\nSecurity.prototype.profile = function(id, content) {\n return new Profile(this, id, content);\n};\n\n/**\n * Get a specific user from kuzzle using its unique ID\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} cb - returns Kuzzle's response\n */\nSecurity.prototype.fetchUser = function (id, options, cb) {\n var\n data = {_id: id},\n self = this;\n\n if (!id || typeof id !== 'string') {\n throw new Error('Id parameter is mandatory for fetchUser function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.fetchUser', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getUser'), data, options, function (err, response) {\n cb(err, err ? undefined : new User(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on user according to a filter\n *\n * /!\\ There is a small delay between user creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a user that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - same filters as documents filters\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.searchUsers = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchUsers', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchUsers'), {body: filters}, options, function (error, response) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = response.result.hits.map(function (doc) {\n return new User(self, doc._id, doc._source);\n });\n\n cb(null, { total: response.result.total, users: documents });\n });\n};\n\n/**\n * Create a new user in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same user already exists: throw an error if sets to false.\n * Replace the existing user otherwise\n *\n * @param {string} id - user identifier\n * @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createUser = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content},\n action = 'createUser';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createUser: cannot create a user without a user ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceUser' : 'createUser';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, null, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n};\n\n/**\n * Create a new restricted user in Kuzzle.\n *\n * This function will create a new user. It is not usable to update an existing user.\n * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n *\n * @param {string} id - user identifier\n * @param {object} content - attribute `profile` in `content` must only contains the profile id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createRestrictedUser = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content};\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createRestrictedUser: cannot create a user without a user ID');\n }\n\n if (content.profileIds) {\n throw new Error('Security.createRestrictedUser: cannot provide profileIds');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.buildQueryArgs('createRestrictedUser'), data, null, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update an user in Kuzzle.\n *\n * @param {string} id - user identifier\n * @param {object} content - a plain javascript object representing the user's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateUser = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'updateUser';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateUser: cannot update an user without an user ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n\n return this;\n};\n\n/**\n * Delete user.\n *\n * There is a small delay between user deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a user that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Profile id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteUser = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteUser'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new User object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - user id\n * @param {object} content - user content\n * @constructor\n */\nSecurity.prototype.user = function(id, content) {\n return new User(this, id, content);\n};\n\n/**\n * Tells whether an action is allowed, denied or conditional based on the rights\n * rights provided as the first argument. An action is defined as a couple of\n * action and controller (mandatory), plus an index and a collection(optional).\n *\n * @param {object} rights - The rights rights associated to a user\n * (see getMyrights and getUserrights).\n * @param {string} controller - The controller to check the action onto.\n * @param {string} action - The action to perform.\n * @param {string} index - (optional) The name of index to perform the action onto.\n * @param {string} collection - (optional) The name of the collection to perform the action onto.\n *\n * @returns {string} ['allowed', 'denied', 'conditional'] where conditional cases\n * correspond to rights containing closures.\n * See also http://kuzzle.io/guide/#roles-definition\n */\nSecurity.prototype.isActionAllowed = function(rights, controller, action, index, collection) {\n var filteredRights;\n\n if (!rights || typeof rights !== 'object') {\n throw new Error('rights parameter is mandatory for isActionAllowed function');\n }\n if (!controller || typeof controller !== 'string') {\n throw new Error('controller parameter is mandatory for isActionAllowed function');\n }\n if (!action || typeof action !== 'string') {\n throw new Error('action parameter is mandatory for isActionAllowed function');\n }\n\n // We filter in all the rights that match the request (including wildcards).\n filteredRights = rights\n .filter(function (right) {\n return right.controller === controller || right.controller === '*';\n })\n .filter(function (right) {\n return right.action === action || right.action === '*';\n })\n .filter(function (right) {\n return right.index === index || right.index === '*';\n })\n .filter(function (right) {\n return right.collection === collection || right.collection === '*';\n });\n\n // Then, if at least one right allows the action, we return 'allowed'\n if (filteredRights.some(function (item) { return item.value === 'allowed'; })) {\n return 'allowed';\n }\n // If no right allows the action, we check for conditionals.\n if (filteredRights.some(function (item) { return item.value === 'conditional'; })) {\n return 'conditional';\n }\n // Otherwise we return 'denied'.\n return 'denied';\n};\n\n\n/**\n * Gets the rights array of a given user.\n *\n * @param {string} userId The id of the user.\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {function} cb The callback containing the normalized array of rights.\n */\nSecurity.prototype.getUserRights = function (userId, options, cb) {\n var\n data = {_id: userId},\n self = this;\n\n if (!userId || typeof userId !== 'string') {\n throw new Error('userId parameter is mandatory for getUserRights function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Kuzzle.getUserRights', cb);\n\n this.kuzzle.query(this.buildQueryArgs('getUserRights'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result.hits);\n });\n};\n\nmodule.exports = Security;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Security.js\n// module id = 18\n// module chunks = 0","// Unique ID creation requires a high quality random # generator. We feature\n// detect to determine the best RNG source, normalizing to a function that\n// returns 128-bits of randomness, since that's what's usually required\nvar rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\n\n// random #'s we need to init node and clockseq\nvar _seedBytes = rng();\n\n// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\nvar _nodeId = [\n _seedBytes[0] | 0x01,\n _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]\n];\n\n// Per 4.2.2, randomize (14 bit) clockseq\nvar _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;\n\n// Previous uuid creation time\nvar _lastMSecs = 0, _lastNSecs = 0;\n\n// See https://github.com/broofa/node-uuid for API details\nfunction v1(options, buf, offset) {\n var i = buf && offset || 0;\n var b = buf || [];\n\n options = options || {};\n\n var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\n // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\n // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\n // Time since last uuid creation (in msecs)\n var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\n // Per 4.2.1.2, Bump clockseq on clock regression\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n }\n\n // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n }\n\n // Per 4.2.1.2 Throw error if too many uuids are requested\n if (nsecs >= 10000) {\n throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq;\n\n // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n msecs += 12219292800000;\n\n // `time_low`\n var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff;\n\n // `time_mid`\n var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff;\n\n // `time_high_and_version`\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n b[i++] = tmh >>> 16 & 0xff;\n\n // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n b[i++] = clockseq >>> 8 | 0x80;\n\n // `clock_seq_low`\n b[i++] = clockseq & 0xff;\n\n // `node`\n var node = options.node || _nodeId;\n for (var n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf ? buf : bytesToUuid(b);\n}\n\nmodule.exports = v1;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/uuid/v1.js\n// module id = 19\n// module chunks = 0","var rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\nfunction v4(options, buf, offset) {\n var i = buf && offset || 0;\n\n if (typeof(options) == 'string') {\n buf = options == 'binary' ? new Array(16) : null;\n options = null;\n }\n options = options || {};\n\n var rnds = options.random || (options.rng || rng)();\n\n // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n\n // Copy bytes to buffer, if provided\n if (buf) {\n for (var ii = 0; ii < 16; ++ii) {\n buf[i + ii] = rnds[ii];\n }\n }\n\n return buf || bytesToUuid(rnds);\n}\n\nmodule.exports = v4;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/uuid/v4.js\n// module id = 20\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///kuzzle.js","webpack:///webpack/bootstrap f340330cbc588882f8a5","webpack:///./src/Kuzzle.js","webpack:///./src/security/SecurityDocument.js","webpack:///./src/Document.js","webpack:///./src/networkWrapper/wrappers/websocket.js","webpack:///./src/security/User.js","webpack:///./~/uuid/index.js","webpack:///./~/uuid/lib/bytesToUuid.js","webpack:///./~/uuid/lib/rng-browser.js","webpack:///./src/Collection.js","webpack:///./src/CollectionMapping.js","webpack:///./src/MemoryStorage.js","webpack:///./src/Room.js","webpack:///./src/SearchResult.js","webpack:///./src/SubscribeResult.js","webpack:///./src/networkWrapper/index.js","webpack:///./src/networkWrapper/wrappers/socketio.js","webpack:///./src/security/Profile.js","webpack:///./src/security/Role.js","webpack:///./src/security/Security.js","webpack:///./~/uuid/v1.js","webpack:///./~/uuid/v4.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","Kuzzle","host","options","cb","self","Error","Object","defineProperties","collections","value","writable","connectCB","eventListeners","connected","lastEmitted","listeners","error","disconnected","reconnected","jwtTokenExpired","loginAttempt","offlineQueuePush","offlineQueuePop","queryError","discarded","eventTimeout","queuing","requestHistory","state","subscriptions","pending","autoReconnect","enumerable","defaultIndex","undefined","reconnectionDelay","port","sslConnection","autoQueue","autoReplay","autoResubscribe","headers","volatile","offlineQueue","queueFilter","queueMaxSize","queueTTL","replayInterval","jwtToken","offlineQueueLoader","keys","forEach","opt","hasOwnProperty","getOwnPropertyDescriptor","offlineMode","defineProperty","query","header","errorMessagePrefix","callback","Security","event","now","Date","args","Array","prototype","slice","arguments","eventProperties","listener","setTimeout","fn","apply","MemoryStorage","connect","cleanHistory","bluebird","promisifyAll","suffix","filter","name","func","target","passes","whitelist","indexOf","cleanQueue","lastDocumentIndex","index","ts","splice","droppedRequest","emitEvent","length","key","emitRequest","request","network","once","requestId","response","action","message","assign","status","send","dequeue","additionalQueue","uniqueQueue","dequeuingProcess","shift","Math","max","isArray","concat","controller","renewAllSubscriptions","roomId","subscriptionId","subscription","renew","removeAllSubscriptions","unsubscribe","discardRequest","object","JSON","stringify","uuid","Collection","User","networkWrapper","disconnect","onConnect","on","data","onConnectError","connectionError","internal","onDisconnect","onReconnect","reconnect","checkToken","err","res","valid","setJwtToken","token","success","result","jwt","unsetJwtToken","getJwtToken","login","strategy","credentials","expiresIn","body","queuable","createIndex","logout","v4","callbackRequired","whoAmI","security","_id","_source","getMyRights","hits","updateSelf","content","queryArgs","addListener","listenerId","knownEvents","listenerType","isValid","toString","push","getAllStatistics","getStatistics","timestamp","queryCB","startTime","collection","flushQueue","listCollections","collectionType","arg","type","from","size","listIndexes","indexes","close","getServerInfo","serverInfo","refreshIndex","getAutoRefresh","setAutoRefresh","autoRefresh","attr","refresh","scroll","scrollId","meta","addHeaders","removeAllListeners","eventName","removeListener","replayQueue","setDefaultIndex","setHeaders","replace","startQueuing","stopQueuing","SecurityDocument","kuzzle","setContent","serialize","delete","buildQueryArgs","deleteActionName","update","updateActionName","Document","documentId","dataCollection","parse","version","_version","newDocument","save","publish","subscribe","filters","ids","values","WSNode","ssl","WebSocket","e","code","client","wasConnected","retrying","lasturl","stopRetryingToConnect","url","window","perMessageDeflate","onopen","poke","onclose","onClientError","onerror","onmessage","payload","room","keep","off","some","i","readyState","OPEN","KuzzleSecurityDocument","create","constructor","setProfiles","profileIds","addProfile","profileId","saveRestricted","getProfiles","v1","bytesToUuid","buf","offset","bth","byteToHex","substr","rng","crypto","msCrypto","getRandomValues","rnds8","Uint8Array","rnds","r","random","blacklist","KuzzleSearchResult","CollectionMapping","Room","SubscribeResult","count","createDocument","document","ifExist","doc","deleteDocument","fetchDocument","fetchAllDocuments","warnEmitted","documents","search","fetchNextDocuments","searchResult","total","console","warn","fetchNext","getMapping","kuzzleMapping","publishMessage","replaceDocument","_scroll_id","aggregations","previous","subscribeResult","done","bind","truncate","updateDocument","retryOnConflict","collectionMapping","mapping","properties","mappings","set","field","assignParameter","getter","assignGeoRadiusOptions","parsed","assignZrangeOptions","limit","mapGeoposResults","results","map","coords","latlon","parseFloat","mapGeoRadiusResults","point","coordinates","coord","distance","mapStringToArray","mapArrayStringToArrayInt","parseInt","mapZrangeResults","buffer","mapped","member","score","getId","required","getIdField","getKeys","getMember","getxScan","opts","getZrange","mapResults","getZrangeBy","setId","setIdValue","setIdFieldValue","setEntries","commands","append","bitcount","bitop","bitpos","dbsize","decr","decrby","del","exists","expire","expireat","flushdb","geoadd","geodist","geohash","geopos","georadius","georadiusbymember","get","getbit","getrange","getset","hdel","hexists","hget","hgetall","hincrby","hincrbyfloat","hkeys","hlen","hmget","hmset","hscan","hset","hsetnx","hstrlen","hvals","incr","incrby","incrbyfloat","lindex","linsert","llen","lpop","lpush","lpushx","lrange","lrem","lset","ltrim","mget","mset","msetnx","persist","pexpire","pexpireat","pfadd","pfcount","pfmerge","ping","psetex","pttl","randomkey","rename","renamenx","rpop","rpoplpush","rpush","rpushx","sadd","scan","scard","sdiff","sdiffstore","setex","setnx","sinter","sinterstore","sismember","smembers","smove","sort","spop","srandmember","srem","sscan","strlen","sunion","sunionstore","time","touch","ttl","zadd","zcard","zcount","zincrby","zinterstore","zlexcount","zrange","zrangebylex","zrevrangebylex","zrangebyscore","zrank","zrem","zremrangebylex","zremrangebyrank","zremrangebyscore","zrevrange","zrevrangebyscore","zrevrank","zscan","zscore","zunionstore","command","pop","param","channel","lastRenewal","notifier","onDoneCB","queue","renewalDelay","scope","subscribing","users","subscribeToSelf","notificationCallback","user","element","isReady","notificationCB","subscribeQuery","interval","setInterval","clearInterval","SearchResult","fetchedDocument","getTotal","getDocuments","getAggregations","getOptions","getFilters","getCollection","getFetchedDocument","cbs","onDone","io","SocketIO","socket","reconnection","forceNew","emit","Profile","policies","addPolicy","policy","roleId","setPolicies","getPolicies","Role","fetchRole","searchRoles","roles","createRole","replaceIfExist","updateRole","deleteRole","role","fetchProfile","searchProfiles","profiles","createProfile","updateProfile","updatedContent","property","deleteProfile","profile","fetchUser","searchUsers","createUser","createRestrictedUser","updateUser","deleteUser","isActionAllowed","rights","filteredRights","right","item","getUserRights","userId","b","clockseq","_clockseq","msecs","getTime","nsecs","_lastNSecs","dt","_lastMSecs","tl","tmh","node","_nodeId","n","_seedBytes","ii"],"mappings":"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","file":"kuzzle.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Kuzzle\"] = factory();\n\telse\n\t\troot[\"Kuzzle\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","/*! Kuzzle javascript SDK version 4.0.0 */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Kuzzle\"] = factory();\n\telse\n\t\troot[\"Kuzzle\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t uuid = __webpack_require__(5),\n\t Collection = __webpack_require__(8),\n\t Security = __webpack_require__(18),\n\t MemoryStorage = __webpack_require__(10),\n\t User = __webpack_require__(4),\n\t networkWrapper = __webpack_require__(14);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * Kuzzle object constructor.\n\t *\n\t * @constructor\n\t * @param host - Server name or IP Address to the Kuzzle instance\n\t * @param [options] - Connection options\n\t * @param {responseCallback} [cb] - Handles connection response\n\t * @constructor\n\t */\n\tfunction Kuzzle (host, options, cb) {\n\t var self = this;\n\t\n\t if (!(this instanceof Kuzzle)) {\n\t return new Kuzzle(host, options, cb);\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!host || host === '') {\n\t throw new Error('host argument missing');\n\t }\n\t\n\t Object.defineProperties(this, {\n\t // 'private' properties\n\t collections: {\n\t value: {},\n\t writable: true\n\t },\n\t connectCB: {\n\t value: cb\n\t },\n\t eventListeners: {\n\t value: {\n\t connected: {lastEmitted: null, listeners: []},\n\t error: {lastEmitted: null, listeners: []},\n\t disconnected: {lastEmitted: null, listeners: []},\n\t reconnected: {lastEmitted: null, listeners: []},\n\t jwtTokenExpired: {lastEmitted: null, listeners: []},\n\t loginAttempt: {lastEmitted: null, listeners: []},\n\t offlineQueuePush: {listeners: []},\n\t offlineQueuePop: {listeners: []},\n\t queryError: {listeners: []},\n\t discarded: {listeners: []}\n\t }\n\t },\n\t eventTimeout: {\n\t value: 200\n\t },\n\t queuing: {\n\t value: false,\n\t writable: true\n\t },\n\t requestHistory: {\n\t value: {},\n\t writable: true\n\t },\n\t state: {\n\t value: 'initializing',\n\t writable: true\n\t },\n\t subscriptions: {\n\t /*\n\t Contains the centralized subscription list in the following format:\n\t pending: \n\t 'roomId': {\n\t kuzzleRoomID_1: kuzzleRoomInstance_1,\n\t kuzzleRoomID_2: kuzzleRoomInstance_2,\n\t kuzzleRoomID_...: kuzzleRoomInstance_...\n\t }\n\t\n\t This was made to allow multiple subscriptions on the same set of filters, something that Kuzzle does not permit.\n\t This structure also allows renewing subscriptions after a connection loss\n\t */\n\t value: {\n\t pending: {}\n\t },\n\t writable: true\n\t },\n\t // configuration properties\n\t autoReconnect: {\n\t value: (options && typeof options.autoReconnect === 'boolean') ? options.autoReconnect : true,\n\t writable: true,\n\t enumerable: true\n\t },\n\t defaultIndex: {\n\t value: (options && typeof options.defaultIndex === 'string') ? options.defaultIndex : undefined,\n\t writable: true,\n\t enumerable: true\n\t },\n\t reconnectionDelay: {\n\t value: (options && typeof options.reconnectionDelay === 'number') ? options.reconnectionDelay : 1000,\n\t writable: true,\n\t enumerable: true\n\t },\n\t host: {\n\t value: host,\n\t writable: true,\n\t enumerable: true\n\t },\n\t port: {\n\t value: (options && typeof options.port === 'number') ? options.port : 7512,\n\t enumerable: true,\n\t writable: true\n\t },\n\t sslConnection: {\n\t value: (options && typeof options.sslConnection === 'boolean') ? options.sslConnection : false,\n\t writable: true,\n\t enumerable: true\n\t },\n\t autoQueue: {\n\t value: false,\n\t enumerable: true,\n\t writable: true\n\t },\n\t autoReplay: {\n\t value: false,\n\t enumerable: true,\n\t writable: true\n\t },\n\t autoResubscribe: {\n\t value: true,\n\t enumerable: true,\n\t writable: true\n\t },\n\t headers: {\n\t value: {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t volatile: {\n\t value: {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t /*\n\t Offline queue use the following format:\n\t [\n\t {\n\t ts: ,\n\t query: 'query',\n\t cb: callbackFunction\n\t }\n\t ]\n\t */\n\t offlineQueue: {\n\t value: [],\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueFilter: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueMaxSize: {\n\t value: 500,\n\t enumerable: true,\n\t writable: true\n\t },\n\t queueTTL: {\n\t value: 120000,\n\t enumerable: true,\n\t writable: true\n\t },\n\t replayInterval: {\n\t value: 10,\n\t enumerable: true,\n\t writable: true\n\t },\n\t jwtToken: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t },\n\t offlineQueueLoader: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (options) {\n\t Object.keys(options).forEach(function (opt) {\n\t if (self.hasOwnProperty(opt) && Object.getOwnPropertyDescriptor(self, opt).writable) {\n\t self[opt] = options[opt];\n\t }\n\t });\n\t\n\t if (options.offlineMode === 'auto' && this.autoReconnect) {\n\t this.autoQueue = this.autoReplay = this.autoResubscribe = true;\n\t }\n\t }\n\t\n\t // Helper function ensuring that this Kuzzle object is still valid before performing a query\n\t Object.defineProperty(this, 'isValid', {\n\t value: function () {\n\t if (self.state === 'disconnected') {\n\t throw new Error('This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?');\n\t }\n\t }\n\t });\n\t\n\t // Helper function copying headers to the query data\n\t Object.defineProperty(this, 'addHeaders', {\n\t value: function (query, headers) {\n\t Object.keys(headers).forEach(function (header) {\n\t if (!query[header]) {\n\t query[header] = headers[header];\n\t }\n\t });\n\t\n\t return query;\n\t }\n\t });\n\t\n\t /**\n\t * Some methods (mainly read queries) require a callback function. This function exists to avoid repetition of code,\n\t * and is called by these methods\n\t */\n\t Object.defineProperty(this, 'callbackRequired', {\n\t value: function (errorMessagePrefix, callback) {\n\t if (!callback || typeof callback !== 'function') {\n\t throw new Error(errorMessagePrefix + ': a callback argument is required for read queries');\n\t }\n\t }\n\t });\n\t\n\t /**\n\t * Create an attribute security that embed all methods to manage Role, Profile and User\n\t */\n\t Object.defineProperty(this, 'security', {\n\t value: new Security(this),\n\t enumerable: true\n\t });\n\t\n\t /**\n\t * Emit an event to all registered listeners\n\t * An event cannot be emitted multiple times before a timeout has been reached.\n\t */\n\t Object.defineProperty(this, 'emitEvent', {\n\t value: function emitEvent(event) {\n\t var\n\t now = Date.now(),\n\t args = Array.prototype.slice.call(arguments, 1),\n\t eventProperties = this.eventListeners[event];\n\t\n\t if (eventProperties.lastEmitted && eventProperties.lastEmitted >= now - this.eventTimeout) {\n\t return false;\n\t }\n\t\n\t eventProperties.listeners.forEach(function (listener) {\n\t setTimeout(function () {\n\t listener.fn.apply(undefined, args);\n\t }, 0);\n\t });\n\t\n\t // Events without the 'lastEmitted' property can be emitted without minimum time between emissions\n\t if (eventProperties.lastEmitted !== undefined) {\n\t eventProperties.lastEmitted = now;\n\t }\n\t }\n\t });\n\t\n\t Object.defineProperty(this, 'memoryStorage', {\n\t value: new MemoryStorage(this),\n\t enumerable: true\n\t });\n\t\n\t\n\t if (!options || !options.connect || options.connect === 'auto') {\n\t this.connect();\n\t } else {\n\t this.state = 'ready';\n\t }\n\t\n\t cleanHistory(this.requestHistory);\n\t\n\t if (this.bluebird) {\n\t return this.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['getAllStatistics', 'getServerInfo', 'getStatistics',\n\t 'listCollections', 'listIndexes', 'login', 'logout', 'now', 'query',\n\t 'checkToken', 'whoAmI', 'updateSelf', 'getMyRights',\n\t 'refreshIndex', 'getAutoRefresh', 'setAutoRefresh'\n\t ];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\t/**\n\t * Connects to a Kuzzle instance using the provided host name.\n\t * @returns {Object} this\n\t */\n\tKuzzle.prototype.connect = function () {\n\t var self = this;\n\t\n\t if (self.network) {\n\t self.disconnect();\n\t }\n\t\n\t self.network = networkWrapper(self.host, self.port, self.sslConnection);\n\t\n\t if (['initializing', 'ready', 'disconnected', 'error', 'offline'].indexOf(this.state) === -1) {\n\t if (self.connectCB) {\n\t self.connectCB(null, self);\n\t }\n\t return self;\n\t }\n\t\n\t self.state = 'connecting';\n\t self.network.connect(self.autoReconnect, self.reconnectionDelay);\n\t\n\t self.network.onConnect(function () {\n\t self.state = 'connected';\n\t renewAllSubscriptions.call(self);\n\t dequeue.call(self);\n\t self.emitEvent('connected');\n\t\n\t if (self.connectCB) {\n\t self.connectCB(null, self);\n\t }\n\t });\n\t\n\t self.network.on('discarded', function (data) {\n\t self.emitEvent('discarded', data);\n\t });\n\t\n\t self.network.onConnectError(function (error) {\n\t var connectionError = new Error('Unable to connect to kuzzle proxy server at \"' + self.host + '\"');\n\t\n\t connectionError.internal = error;\n\t self.state = 'error';\n\t self.emitEvent('error', connectionError);\n\t\n\t if (self.connectCB) {\n\t self.connectCB(connectionError);\n\t }\n\t });\n\t\n\t self.network.onDisconnect(function () {\n\t self.state = 'offline';\n\t\n\t if (!self.autoReconnect) {\n\t self.disconnect();\n\t }\n\t\n\t if (self.autoQueue) {\n\t self.queuing = true;\n\t }\n\t\n\t self.emitEvent('disconnected');\n\t });\n\t\n\t self.network.onReconnect(function () {\n\t var reconnect = function () {\n\t // renew subscriptions\n\t if (self.autoResubscribe) {\n\t renewAllSubscriptions.call(self);\n\t }\n\t\n\t // replay queued requests\n\t if (self.autoReplay) {\n\t cleanQueue.call(self);\n\t dequeue.call(self);\n\t }\n\t\n\t // alert listeners\n\t self.emitEvent('reconnected');\n\t };\n\t\n\t self.state = 'connected';\n\t\n\t if (self.jwtToken) {\n\t self.checkToken(self.jwtToken, function (err, res) {\n\t // shouldn't obtain an error but let's invalidate the token anyway\n\t if (err || !res.valid) {\n\t self.jwtToken = undefined;\n\t self.emitEvent('jwtTokenExpired');\n\t }\n\t\n\t reconnect();\n\t });\n\t } else {\n\t reconnect();\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Set the jwtToken used to query kuzzle\n\t * @param token\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.setJwtToken = function(token) {\n\t if (typeof token === 'string') {\n\t this.jwtToken = token;\n\t } else if (typeof token === 'object') {\n\t if (token.result && token.result.jwt && typeof token.result.jwt === 'string') {\n\t this.jwtToken = token.result.jwt;\n\t } else {\n\t this.emitEvent('loginAttempt', {\n\t success: false,\n\t error: 'Cannot find a valid JWT token in the following object: ' + JSON.stringify(token)\n\t });\n\t\n\t return this;\n\t }\n\t } else {\n\t this.emitEvent('loginAttempt', {success: false, error: 'Invalid token argument: ' + token});\n\t return this;\n\t }\n\t\n\t renewAllSubscriptions.call(this);\n\t this.emitEvent('loginAttempt', {success: true});\n\t return this;\n\t};\n\t\n\t/**\n\t * Unset the jwtToken used to query kuzzle\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.unsetJwtToken = function() {\n\t this.jwtToken = undefined;\n\t\n\t removeAllSubscriptions.call(this);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Get the jwtToken used by kuzzle\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.getJwtToken = function() {\n\t return this.jwtToken;\n\t};\n\t\n\t/**\n\t * Send login request to kuzzle with credentials\n\t * If login success, store the jwtToken into kuzzle object\n\t *\n\t * @param strategy\n\t * @param credentials\n\t * @param expiresIn\n\t * @param cb\n\t */\n\tKuzzle.prototype.login = function (strategy) {\n\t var\n\t self = this,\n\t request = {\n\t strategy: strategy\n\t },\n\t credentials,\n\t cb = null;\n\t\n\t // Handle arguments (credentials, expiresIn, cb)\n\t if (arguments[1]) {\n\t if (typeof arguments[1] === 'object') {\n\t credentials = arguments[1];\n\t } else if (typeof arguments[1] === 'number' || typeof arguments[1] === 'string') {\n\t request.expiresIn = arguments[1];\n\t } else if (typeof arguments[1] === 'function') {\n\t cb = arguments[1];\n\t }\n\t }\n\t if (arguments[2]) {\n\t if (typeof arguments[2] === 'number' || typeof arguments[2] === 'string') {\n\t request.expiresIn = arguments[2];\n\t } else if (typeof arguments[2] === 'function') {\n\t cb = arguments[2];\n\t }\n\t }\n\t if (arguments[3] && typeof arguments[3] === 'function') {\n\t cb = arguments[3];\n\t }\n\t\n\t if (typeof credentials === 'object') {\n\t Object.keys(credentials).forEach(function (key) {\n\t request[key] = credentials[key];\n\t });\n\t }\n\t\n\t this.query({controller: 'auth', action: 'login'}, {body: request}, {queuable: false}, function(error, response) {\n\t if (!error) {\n\t if (response.result.jwt) {\n\t self.setJwtToken(response.result.jwt);\n\t }\n\t\n\t cb && cb(null, response.result);\n\t }\n\t else {\n\t cb && cb(error);\n\t self.emitEvent('loginAttempt', {success: false, error: error.message});\n\t }\n\t });\n\t};\n\t\n\t/**\n\t * Create a kuzzle index\n\t *\n\t * @param {string} index\n\t * @param {object} [options]\n\t * @param {responseCallback} cb\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.createIndex = function (index, options, cb) {\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.createIndex: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.query({controller: 'index', action: 'create'}, {index: index}, options, typeof cb !== 'function' ? null : cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Send logout request to kuzzle with jwtToken.\n\t *\n\t * @param cb\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.logout = function (cb) {\n\t var\n\t self = this,\n\t request = {\n\t action: 'logout',\n\t controller: 'auth',\n\t requestId: uuid.v4(),\n\t body: {}\n\t };\n\t\n\t this.query({controller: 'auth', action: 'logout'}, request, {queuable: false}, typeof cb !== 'function' ? null : function(error) {\n\t cb(error, self);\n\t });\n\t\n\t self.unsetJwtToken();\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Checks whether a given jwt token still represents a valid session in Kuzzle.\n\t *\n\t * @param {string} token The jwt token to check\n\t * @param {function} callback The callback to be called when the response is\n\t * available. The signature is `function(error, response)`.\n\t */\n\tKuzzle.prototype.checkToken = function (token, callback) {\n\t var\n\t request = {\n\t body: {\n\t token: token\n\t }\n\t };\n\t\n\t this.callbackRequired('Kuzzle.checkToken', callback);\n\t\n\t this.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}, function (err, response) {\n\t if (err) {\n\t return callback(err);\n\t }\n\t\n\t callback(null, response.result);\n\t });\n\t};\n\t\n\t/**\n\t * Fetches the current user.\n\t *\n\t * @param {function} callback The callback to be called when the response is\n\t * available. The signature is `function(error, response)`.\n\t */\n\tKuzzle.prototype.whoAmI = function (callback) {\n\t var self = this;\n\t\n\t self.callbackRequired('Kuzzle.whoAmI', callback);\n\t\n\t self.query({controller: 'auth', action: 'getCurrentUser'}, {}, {}, function (err, response) {\n\t if (err) {\n\t return callback(err);\n\t }\n\t\n\t callback(null, new User(self.security, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Gets the rights array of the currently logged user.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {function} cb The callback containing the normalized array of rights.\n\t */\n\tKuzzle.prototype.getMyRights = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.callbackRequired('Kuzzle.getMyRights', cb);\n\t\n\t self.query({controller: 'auth', action:'getMyRights'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.hits);\n\t });\n\t};\n\t\n\t/**\n\t * Update current user in Kuzzle.\n\t *\n\t * @param {object} content - a plain javascript object representing the user's modification\n\t * @param {object} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.updateSelf = function (content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t queryArgs = {controller: 'auth', action: 'updateSelf'};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data.body = content;\n\t\n\t self.query(queryArgs, data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Clean up the queue, ensuring the queryTTL and queryMaxSize properties are respected\n\t */\n\tfunction cleanQueue () {\n\t var\n\t self = this,\n\t now = Date.now(),\n\t lastDocumentIndex = -1;\n\t\n\t if (self.queueTTL > 0) {\n\t self.offlineQueue.forEach(function (query, index) {\n\t if (query.ts < now - self.queueTTL) {\n\t lastDocumentIndex = index;\n\t }\n\t });\n\t\n\t if (lastDocumentIndex !== -1) {\n\t self.offlineQueue\n\t .splice(0, lastDocumentIndex + 1)\n\t .forEach(function (droppedRequest) {\n\t self.emitEvent('offlineQueuePop', droppedRequest.query);\n\t });\n\t }\n\t }\n\t\n\t if (self.queueMaxSize > 0 && self.offlineQueue.length > self.queueMaxSize) {\n\t self.offlineQueue\n\t .splice(0, self.offlineQueue.length - self.queueMaxSize)\n\t .forEach(function (droppedRequest) {\n\t self.emitEvent('offlineQueuePop', droppedRequest.query);\n\t });\n\t }\n\t}\n\t\n\t\n\t/**\n\t * Clean history from requests made more than 10s ago\n\t */\n\tfunction cleanHistory (requestHistory) {\n\t var\n\t now = Date.now();\n\t\n\t Object.keys(requestHistory).forEach(function (key) {\n\t if (requestHistory[key] < now - 10000) {\n\t delete requestHistory[key];\n\t }\n\t });\n\t\n\t setTimeout(function () {\n\t cleanHistory(requestHistory);\n\t }, 1000);\n\t}\n\t\n\t/**\n\t * Emit a request to Kuzzle\n\t *\n\t * @param {object} request\n\t * @param {responseCallback} [cb]\n\t */\n\tfunction emitRequest (request, cb) {\n\t var\n\t self = this;\n\t\n\t if (self.jwtToken !== undefined || cb) {\n\t self.network.once(request.requestId, function (response) {\n\t var error = null;\n\t\n\t if (request.action !== 'logout' && response.error && response.error.message === 'Token expired') {\n\t self.jwtToken = undefined;\n\t self.emitEvent('jwtTokenExpired', request, cb);\n\t }\n\t\n\t if (response.error) {\n\t error = new Error(response.error.message);\n\t Object.assign(error, response.error);\n\t error.status = response.status;\n\t self.emitEvent('queryError', error, request, cb);\n\t }\n\t\n\t if (cb) {\n\t cb(error, response);\n\t }\n\t });\n\t }\n\t\n\t this.network.send(request);\n\t\n\t // Track requests made to allow Room.subscribeToSelf to work\n\t self.requestHistory[request.requestId] = Date.now();\n\t}\n\t\n\t/**\n\t * Play all queued requests, in order.\n\t */\n\tfunction dequeue () {\n\t var\n\t self = this,\n\t additionalQueue,\n\t uniqueQueue = {},\n\t dequeuingProcess = function () {\n\t if (self.offlineQueue.length > 0) {\n\t emitRequest.call(self, self.offlineQueue[0].query, self.offlineQueue[0].cb);\n\t self.emitEvent('offlineQueuePop', self.offlineQueue.shift());\n\t\n\t setTimeout(function () {\n\t dequeuingProcess();\n\t }, Math.max(0, self.replayInterval));\n\t } else {\n\t self.queuing = false;\n\t }\n\t };\n\t\n\t if (self.offlineQueueLoader) {\n\t if (typeof self.offlineQueueLoader !== 'function') {\n\t throw new Error('Invalid value for offlineQueueLoader property. Expected: function. Got: ' + typeof self.offlineQueueLoader);\n\t }\n\t\n\t additionalQueue = self.offlineQueueLoader();\n\t if (Array.isArray(additionalQueue)) {\n\t self.offlineQueue = additionalQueue\n\t .concat(self.offlineQueue)\n\t .filter(function (request) {\n\t // throws if the query object does not contain required attributes\n\t if (!request.query || request.query.requestId === undefined || !request.query.action || !request.query.controller) {\n\t throw new Error('Invalid offline queue request. One or more missing properties: requestId, action, controller.');\n\t }\n\t\n\t return uniqueQueue.hasOwnProperty(request.query.requestId) ? false : (uniqueQueue[request.query.requestId] = true);\n\t });\n\t } else {\n\t throw new Error('Invalid value returned by the offlineQueueLoader function. Expected: array. Got: ' + typeof additionalQueue);\n\t }\n\t }\n\t\n\t dequeuingProcess();\n\t}\n\t\n\t/**\n\t * Renew all registered subscriptions. Triggered either by a successful connection/reconnection or by a\n\t * successful login attempt\n\t */\n\tfunction renewAllSubscriptions() {\n\t var self = this;\n\t\n\t Object.keys(self.subscriptions).forEach(function (roomId) {\n\t Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n\t var subscription = self.subscriptions[roomId][subscriptionId];\n\t subscription.renew(subscription.callback);\n\t });\n\t });\n\t}\n\t\n\t/**\n\t * Remove all registered subscriptions. Triggered either by a logout query or by un-setting the token\n\t */\n\tfunction removeAllSubscriptions() {\n\t var self = this;\n\t\n\t Object.keys(self.subscriptions).forEach(function (roomId) {\n\t Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n\t var subscription = self.subscriptions[roomId][subscriptionId];\n\t subscription.unsubscribe();\n\t });\n\t });\n\t}\n\t\n\t/**\n\t * Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their\n\t * insertion.\n\t *\n\t * The ID returned by this function is required to remove this listener at a later time.\n\t *\n\t * @param {string} event - name of the global event to subscribe to (see the 'eventListeners' object property)\n\t * @param {function} listener - callback to invoke each time an event is fired\n\t * @returns {string} Unique listener ID\n\t */\n\tKuzzle.prototype.addListener = function(event, listener) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t listenerType = typeof listener,\n\t listenerId;\n\t\n\t this.isValid();\n\t\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t if (listenerType !== 'function') {\n\t throw new Error('Invalid listener type: expected a function, got a ' + listenerType);\n\t }\n\t\n\t listenerId = uuid.v4();\n\t this.eventListeners[event].listeners.push({id: listenerId, fn: listener});\n\t return listenerId;\n\t};\n\t\n\t\n\t/**\n\t * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n\t * This method returns all available statistics from Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getAllStatistics = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getAllStatistics', cb);\n\t\n\t this.query({controller:'server', action: 'getAllStats'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.hits);\n\t });\n\t};\n\t\n\t/**\n\t * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n\t * This method allows getting either the last statistics frame, or a set of frames starting from a provided timestamp.\n\t *\n\t * @param {number} timestamp - Epoch time. Starting time from which the frames are to be retrieved\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getStatistics = function (timestamp, options, cb) {\n\t var\n\t queryCB,\n\t body;\n\t\n\t if (!cb) {\n\t if (arguments.length === 1) {\n\t cb = arguments[0];\n\t options = null;\n\t timestamp = null;\n\t } else {\n\t cb = arguments[1];\n\t if (typeof arguments[0] === 'object') {\n\t options = arguments[0];\n\t timestamp = null;\n\t } else {\n\t timestamp = arguments[0];\n\t options = null;\n\t }\n\t }\n\t }\n\t\n\t queryCB = function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, timestamp ? res.result.hits : [res.result]);\n\t };\n\t\n\t this.callbackRequired('Kuzzle.getStatistics', cb);\n\t\n\t body = timestamp ? {body: {startTime: timestamp}} : {};\n\t this.query({controller: 'server', action: timestamp ? 'getStats' : 'getLastStats'}, body, options, queryCB);\n\t};\n\t\n\t/**\n\t * Create a new instance of a Collection object.\n\t * If no index is specified, takes the default index.\n\t *\n\t * @param {string} collection - The name of the data collection you want to manipulate\n\t * @param {string} [index] - The name of the data index containing the data collection\n\t * @returns {Collection} A Collection instance\n\t */\n\tKuzzle.prototype.collection = function(collection, index) {\n\t this.isValid();\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Unable to create a new data collection object: no index specified');\n\t }\n\t\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (typeof index !== 'string' || typeof collection !== 'string') {\n\t throw new Error('Invalid index or collection argument: string expected');\n\t }\n\t\n\t if (!this.collections[index]) {\n\t this.collections[index] = {};\n\t }\n\t\n\t if (!this.collections[index][collection]) {\n\t this.collections[index][collection] = new Collection(this, collection, index);\n\t }\n\t\n\t return this.collections[index][collection];\n\t};\n\t\n\t/**\n\t * Empties the offline queue without replaying it.\n\t *\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.flushQueue = function () {\n\t this.offlineQueue = [];\n\t return this;\n\t};\n\t\n\t/**\n\t * Returns the list of known persisted data collections.\n\t *\n\t * @param {string} [index] - Index containing collections to be listed\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.listCollections = function () {\n\t var\n\t collectionType = 'all',\n\t index,\n\t options,\n\t cb,\n\t args = Array.prototype.slice.call(arguments),\n\t query;\n\t\n\t args.forEach(function(arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.listCollections: index required');\n\t }\n\t\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.listCollections', cb);\n\t\n\t if (options && options.type) {\n\t collectionType = options.type;\n\t }\n\t\n\t query = {body: {type: collectionType}};\n\t\n\t if (options && options.from) {\n\t query.body.from = options.from;\n\t }\n\t\n\t if (options && options.size) {\n\t query.body.size = options.size;\n\t }\n\t\n\t this.query({index: index, controller: 'collection', action: 'list'}, query, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.collections);\n\t });\n\t};\n\t\n\t/**\n\t * Returns the list of existing indexes in Kuzzle\n\t *\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.listIndexes = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.listIndexes', cb);\n\t\n\t this.query({controller: 'index', action: 'list'}, {}, options, function (err, res) {\n\t cb(err, err ? undefined : res.result.indexes);\n\t });\n\t};\n\t\n\t/**\n\t * Disconnects from Kuzzle and invalidate this instance.\n\t */\n\tKuzzle.prototype.disconnect = function () {\n\t var collection;\n\t\n\t this.state = 'disconnected';\n\t this.network.close();\n\t this.network = null;\n\t\n\t for (collection in this.collections) {\n\t if (this.collections.hasOwnProperty(collection)) {\n\t delete this.collections[collection];\n\t }\n\t }\n\t};\n\t\n\t/**\n\t * Returns the server informations\n\t *\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getServerInfo = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getServerInfo', cb);\n\t\n\t this.query({controller: 'server', action: 'info'}, {}, options, function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t cb(null, res.result.serverInfo);\n\t });\n\t};\n\t\n\t/**\n\t * Forces an index refresh\n\t *\n\t * @param {string} index - The index to refresh. Defaults to Kuzzle.defaultIndex\n\t * @param {object} options - Optional arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t * @returns {Kuzzle}\n\t */\n\tKuzzle.prototype.refreshIndex = function () {\n\t var\n\t index,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function(arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.refreshIndex: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.query({ index: index, controller: 'index', action: 'refresh'}, {}, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Returns de current autoRefresh status for the given index\n\t *\n\t * @param {string} index - The index to get the status from. Defaults to Kuzzle.defaultIndex\n\t * @param {object} options - Optinal arguments\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.getAutoRefresh = function () {\n\t var\n\t index,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function (arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.getAutoRefresh: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.getAutoRefresh', cb);\n\t this.query({ index: index, controller: 'index', action: 'getAutoRefresh'}, {}, options, cb);\n\t};\n\t\n\t/**\n\t * (Un)Sets the autoRefresh flag on the given index\n\t *\n\t * @param {string} index - the index to modify. Defaults to Kuzzle.defaultIndex\n\t * @param {boolean} autoRefresh - The autoRefresh value to set\n\t * @param {object} options - Optional arguments\n\t * @param {responseCallback} cb - Handles the query result\n\t * @returns {object} this\n\t */\n\tKuzzle.prototype.setAutoRefresh = function () {\n\t var\n\t index,\n\t autoRefresh,\n\t options,\n\t cb;\n\t\n\t Array.prototype.slice.call(arguments).forEach(function (arg) {\n\t switch (typeof arg) {\n\t case 'string':\n\t index = arg;\n\t break;\n\t case 'boolean':\n\t autoRefresh = arg;\n\t break;\n\t case 'object':\n\t options = arg;\n\t break;\n\t case 'function':\n\t cb = arg;\n\t break;\n\t }\n\t });\n\t\n\t if (!index) {\n\t if (!this.defaultIndex) {\n\t throw new Error('Kuzzle.setAutoRefresh: index required');\n\t }\n\t index = this.defaultIndex;\n\t }\n\t\n\t if (autoRefresh === undefined) {\n\t throw new Error('Kuzzle.setAutoRefresh: autoRefresh value is required');\n\t }\n\t\n\t this.query({ index: index, controller: 'index', action: 'setAutoRefresh'}, { body: { autoRefresh: autoRefresh }}, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Return the current Kuzzle's UTC Epoch time, in milliseconds\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tKuzzle.prototype.now = function (options, cb) {\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.callbackRequired('Kuzzle.now', cb);\n\t\n\t this.query({controller: 'server', action: 'now'}, {}, options, function (err, res) {\n\t cb(err, res && res.result.now);\n\t });\n\t};\n\t\n\t/**\n\t * This is a low-level method, exposed to allow advanced SDK users to bypass high-level methods.\n\t * Base method used to send read queries to Kuzzle\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} queryArgs - Query configuration\n\t * @param {object} query - The query data\n\t * @param {object} [options] - Optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tKuzzle.prototype.query = function (queryArgs, query, options, cb) {\n\t var\n\t attr,\n\t object = {\n\t action: queryArgs.action,\n\t controller: queryArgs.controller,\n\t volatile: this.volatile\n\t },\n\t self = this;\n\t\n\t this.isValid();\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (options) {\n\t if (options.queuable === false && self.state === 'offline') {\n\t return self;\n\t }\n\t\n\t if (options.refresh) {\n\t object.refresh = options.refresh;\n\t }\n\t\n\t if (typeof options.from !== 'undefined' && options.from !== null) {\n\t object.from = options.from;\n\t }\n\t\n\t if (options.size) {\n\t object.size = options.size;\n\t }\n\t\n\t if (options.scroll) {\n\t object.scroll = options.scroll;\n\t }\n\t\n\t if (options.scrollId) {\n\t object.scrollId = options.scrollId;\n\t }\n\t\n\t if (options.volatile) {\n\t Object.keys(options.volatile).forEach(function (meta) {\n\t object.volatile[meta] = options.volatile[meta];\n\t });\n\t }\n\t }\n\t\n\t if (!query || typeof query !== 'object' || Array.isArray(query)) {\n\t throw new Error('Invalid query parameter: ' + query);\n\t }\n\t\n\t if (query.volatile) {\n\t Object.keys(query.volatile).forEach(function (meta) {\n\t object.volatile[meta] = query.volatile[meta];\n\t });\n\t }\n\t\n\t for (attr in query) {\n\t if (attr !== 'volatile' && query.hasOwnProperty(attr)) {\n\t object[attr] = query[attr];\n\t }\n\t }\n\t\n\t object = self.addHeaders(object, this.headers);\n\t\n\t /*\n\t * Do not add the token for the checkToken route, to avoid getting a token error when\n\t * a developer simply wish to verify his token\n\t */\n\t if (self.jwtToken !== undefined && !(object.controller === 'auth' && object.action === 'checkToken')) {\n\t object.jwt = self.jwtToken;\n\t }\n\t\n\t if (queryArgs.collection) {\n\t object.collection = queryArgs.collection;\n\t }\n\t\n\t if (queryArgs.index) {\n\t object.index = queryArgs.index;\n\t }\n\t\n\t if (!object.requestId) {\n\t object.requestId = uuid.v4();\n\t }\n\t\n\t if (self.state === 'connected' || (options && options.queuable === false)) {\n\t if (self.state === 'connected') {\n\t emitRequest.call(this, object, cb);\n\t } else {\n\t discardRequest(object, cb);\n\t }\n\t } else if (self.queuing || (options && options.queuable === true) || ['initializing', 'connecting'].indexOf(self.state) !== -1) {\n\t cleanQueue.call(this, object, cb);\n\t if (!self.queueFilter || self.queueFilter(object)) {\n\t self.offlineQueue.push({ts: Date.now(), query: object, cb: cb});\n\t self.emitEvent('offlineQueuePush', {query: object, cb: cb});\n\t }\n\t }\n\t else {\n\t discardRequest(object, cb);\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Removes all listeners, either from a specific event or from all events\n\t *\n\t * @param {string} event - One of the event described in the Event Handling section of this documentation\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.removeAllListeners = function (event) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t self = this;\n\t\n\t if (event) {\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t this.eventListeners[event].listeners = [];\n\t } else {\n\t knownEvents.forEach(function (eventName) {\n\t self.eventListeners[eventName].listeners = [];\n\t });\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Removes a listener from an event.\n\t *\n\t * @param {string} event - One of the event described in the Event Handling section of this documentation\n\t * @param {string} listenerId - The ID returned by addListener\n\t * @returns {Kuzzle} this object\n\t */\n\tKuzzle.prototype.removeListener = function (event, listenerId) {\n\t var\n\t knownEvents = Object.keys(this.eventListeners),\n\t self = this;\n\t\n\t if (knownEvents.indexOf(event) === -1) {\n\t throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n\t }\n\t\n\t this.eventListeners[event].listeners.forEach(function (listener, index) {\n\t if (listener.id === listenerId) {\n\t self.eventListeners[event].listeners.splice(index, 1);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replays the requests queued during offline mode.\n\t * Works only if the SDK is not in a disconnected state, and if the autoReplay option is set to false.\n\t */\n\tKuzzle.prototype.replayQueue = function () {\n\t if (this.state !== 'offline' && !this.autoReplay) {\n\t cleanQueue.call(this);\n\t dequeue.call(this);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Sets the default Kuzzle index\n\t *\n\t * @param index\n\t * @returns this\n\t */\n\tKuzzle.prototype.setDefaultIndex = function (index) {\n\t if (typeof index !== 'string') {\n\t throw new Error('Invalid default index: [' + index + '] (an index name is expected)');\n\t }\n\t\n\t if (index.length === 0) {\n\t throw new Error('Cannot set an empty index as the default index');\n\t }\n\t\n\t this.defaultIndex = index;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tKuzzle.prototype.setHeaders = function (content, replace) {\n\t var self = this;\n\t\n\t if (typeof content !== 'object' || Array.isArray(content)) {\n\t throw new Error('Expected a content object, received a ' + typeof content);\n\t }\n\t\n\t if (replace) {\n\t self.headers = content;\n\t } else {\n\t Object.keys(content).forEach(function (key) {\n\t self.headers[key] = content[key];\n\t });\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Starts the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n\t */\n\tKuzzle.prototype.startQueuing = function () {\n\t if (this.state === 'offline' && !this.autoQueue) {\n\t this.queuing = true;\n\t }\n\t return this;\n\t};\n\t\n\t/**\n\t * Stops the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n\t */\n\tKuzzle.prototype.stopQueuing = function () {\n\t if (this.state === 'offline' && !this.autoQueue) {\n\t this.queuing = false;\n\t }\n\t\n\t return this;\n\t};\n\t\n\tfunction discardRequest(object, cb) {\n\t if (cb) {\n\t cb(new Error('Unable to execute request: not connected to a Kuzzle server.\\nDiscarded request: ' + JSON.stringify(object)));\n\t }\n\t}\n\t\n\tmodule.exports = Kuzzle;\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tfunction SecurityDocument(Security, id, content) {\n\t\n\t if (!id) {\n\t throw new Error('A security document must have an id');\n\t }\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t kuzzle: {\n\t value: Security.kuzzle\n\t },\n\t Security: {\n\t value: Security\n\t },\n\t // read-only properties\n\t // writable properties\n\t id: {\n\t value: id,\n\t enumerable: true\n\t },\n\t content: {\n\t value: {},\n\t writable: true,\n\t enumerable: true\n\t }\n\t });\n\t\n\t if (content) {\n\t this.setContent(content, true);\n\t }\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['delete', 'update'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\t/**\n\t * Replaces the current content with new data.\n\t * Changes made by this function won’t be applied until the save method is called.\n\t *\n\t * @param {Object} data - New securityDocument content\n\t * @return {SecurityDocument} this\n\t */\n\tSecurityDocument.prototype.setContent = function (data) {\n\t this.content = data;\n\t return this;\n\t};\n\t\n\t/**\n\t * Serialize this object into a pojo\n\t *\n\t * @return {object} pojo representing this securityDocument\n\t */\n\tSecurityDocument.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Delete the current KuzzleSecurityDocument into Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tSecurityDocument.prototype.delete = function (options, cb) {\n\t var\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName), {_id: this.id}, options, function (error, res) {\n\t if (error) {\n\t return cb ? cb(error) : false;\n\t }\n\t\n\t if (cb) {\n\t cb(null, res.result._id);\n\t }\n\t });\n\t};\n\t\n\t/**\n\t * Update the current KuzzleSecurityDocument into Kuzzle.\n\t *\n\t * @param {object} content - Content to add to KuzzleSecurityDocument\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {SecurityDocument} this\n\t */\n\tSecurityDocument.prototype.update = function (content, options, cb) {\n\t var\n\t data = {},\n\t self = this;\n\t\n\t if (typeof content !== 'object') {\n\t throw new Error('Parameter \"content\" must be a object');\n\t }\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = self.id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName), data, options, function (error, response) {\n\t if (error) {\n\t return cb ? cb(error) : false;\n\t }\n\t\n\t self.setContent(response.result._source);\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\tmodule.exports = SecurityDocument;\n\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * Kuzzle handles documents either as realtime messages or as stored documents.\n\t * Document is the object representation of one of these documents.\n\t *\n\t * Notes:\n\t * - this constructor may be called either with a documentId, a content, neither or both.\n\t * - providing a documentID to the constructor will automatically call refresh, unless a content is also provided\n\t *\n\t *\n\t * @param {Collection} collection - an instanciated Collection object\n\t * @param {string} [documentId] - ID of an existing document\n\t * @param {object} [content] - Initializes this document with the provided content\n\t * @constructor\n\t */\n\tfunction Document(collection, documentId, content) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t collection: {\n\t value: collection.collection,\n\t enumerable: true\n\t },\n\t dataCollection: {\n\t value: collection,\n\t enumerable: false\n\t },\n\t kuzzle: {\n\t value: collection.kuzzle,\n\t enumerable: false\n\t },\n\t // writable properties\n\t id: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t },\n\t content: {\n\t value: {},\n\t writable: true,\n\t enumerable: true\n\t },\n\t headers: {\n\t value: JSON.parse(JSON.stringify(collection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t version: {\n\t value: undefined,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t // handling provided arguments\n\t if (!content && documentId && typeof documentId === 'object') {\n\t content = documentId;\n\t documentId = null;\n\t }\n\t\n\t if (content) {\n\t if (content._version) {\n\t this.version = content._version;\n\t delete content._version;\n\t }\n\t this.setContent(content, true);\n\t }\n\t\n\t if (documentId) {\n\t Object.defineProperty(this, 'id', {\n\t value: documentId,\n\t enumerable: true\n\t });\n\t }\n\t\n\t // promisifying\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['delete', 'refresh', 'save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this document\n\t */\n\tDocument.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t data._version = this.version;\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Overrides the toString() method in order to return a serialized version of the document\n\t *\n\t * @return {string} serialized version of this object\n\t */\n\tDocument.prototype.toString = function () {\n\t return JSON.stringify(this.serialize());\n\t};\n\t\n\t/**\n\t * Deletes this document in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.delete = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!self.id) {\n\t throw new Error('Document.delete: cannot delete a document without a document ID');\n\t }\n\t\n\t this.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'delete'), this.serialize(), options, cb && function (err) {\n\t cb(err, err ? undefined : self.id);\n\t });\n\t};\n\t\n\t/**\n\t * Replaces the current content with the last version of this document stored in Kuzzle.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.refresh = function (options, cb) {\n\t var self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!self.id) {\n\t throw new Error('Document.refresh: cannot retrieve a document if no ID has been provided');\n\t }\n\t\n\t this.kuzzle.callbackRequired('Document.refresh', cb);\n\t\n\t self.kuzzle.query(self.dataCollection.buildQueryArgs('document', 'get'), {_id: self.id}, options, function (error, res) {\n\t var newDocument;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t newDocument = new Document(self.dataCollection, self.id, res.result._source);\n\t newDocument.version = res.result._version;\n\t\n\t cb(null, newDocument);\n\t });\n\t};\n\t\n\t/**\n\t * Saves this document into Kuzzle.\n\t *\n\t * If this is a new document, this function will create it in Kuzzle and the id property will be made available.\n\t * Otherwise, this method will replace the latest version of this document in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tDocument.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'createOrReplace'), data, options, function (error, res) {\n\t if (error) {\n\t return cb && cb(error);\n\t }\n\t\n\t self.id = res.result._id;\n\t self.version = res.result._version;\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Sends the content of this document as a realtime message.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @returns {*} this\n\t */\n\tDocument.prototype.publish = function (options) {\n\t var data = this.serialize();\n\t\n\t this.kuzzle.query(this.dataCollection.buildQueryArgs('realtime', 'publish'), data, options);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replaces the current content with new data.\n\t * Changes made by this function won’t be applied until the save method is called.\n\t *\n\t * @param {object} data - New content\n\t * @param {boolean} replace - if true: replace this document content with the provided data\n\t */\n\tDocument.prototype.setContent = function (data, replace) {\n\t var self = this;\n\t\n\t if (replace) {\n\t this.content = data;\n\t }\n\t else {\n\t Object.keys(data).forEach(function (key) {\n\t self.content[key] = data[key];\n\t });\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Listens to events concerning this document. Has no effect if the document does not have an ID\n\t * (i.e. if the document has not yet been created as a persisted document).\n\t *\n\t * @param {object} [options] - subscription options\n\t * @param {responseCallback} cb - callback that will be called each time a change has been detected on this document\n\t */\n\tDocument.prototype.subscribe = function (options, cb) {\n\t var filters;\n\t\n\t if (options && !cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Document.subscribe', cb);\n\t\n\t if (!this.id) {\n\t throw new Error('Document.subscribe: cannot subscribe to a document if no ID has been provided');\n\t }\n\t\n\t filters = { ids: { values: [this.id] } };\n\t\n\t return this.dataCollection.subscribe(filters, options, cb);\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tDocument.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\t\n\tmodule.exports = Document;\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tfunction WSNode(host, port, ssl) {\n\t var self = this;\n\t this.WebSocket = typeof WebSocket !== 'undefined' ? WebSocket : __webpack_require__(!(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"ws\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));\n\t this.host = host;\n\t this.port = port;\n\t this.ssl = ssl;\n\t this.client = null;\n\t this.wasConnected = false;\n\t this.retrying = false;\n\t this.lasturl = null;\n\t this.stopRetryingToConnect = false;\n\t\n\t /*\n\t Listeners are stored using the following format:\n\t roomId: {\n\t fn: callback_function,\n\t once: boolean\n\t }\n\t */\n\t this.listeners = {\n\t error: [],\n\t connect: [],\n\t disconnect: [],\n\t reconnect: []\n\t };\n\t\n\t /**\n\t * Creates a new socket from the provided arguments\n\t *\n\t * @constructor\n\t * @param {boolean} autoReconnect\n\t * @param {int} reconnectionDelay\n\t * @returns {Object} Socket\n\t */\n\t this.connect = function (autoReconnect, reconnectionDelay) {\n\t var\n\t url = (this.ssl ? 'wss://' : 'ws://') + this.host + ':' + this.port,\n\t options = typeof window !== 'undefined' ? undefined : {perMessageDeflate: false};\n\t\n\t if (url !== this.lasturl) {\n\t self.wasConnected = false;\n\t this.lasturl = url;\n\t }\n\t\n\t this.client = new this.WebSocket(url, options);\n\t\n\t this.client.onopen = function () {\n\t if (self.wasConnected) {\n\t poke(self.listeners, 'reconnect');\n\t }\n\t else {\n\t poke(self.listeners, 'connect');\n\t }\n\t self.wasConnected = true;\n\t self.stopRetryingToConnect = false;\n\t };\n\t\n\t this.client.onclose = function (code, message) {\n\t if (code === 1000) {\n\t poke(self.listeners, 'disconnect');\n\t }\n\t else {\n\t onClientError.call(self, autoReconnect, reconnectionDelay, message);\n\t }\n\t };\n\t\n\t this.client.onerror = function (error) {\n\t onClientError.call(self, autoReconnect, reconnectionDelay, error);\n\t };\n\t\n\t this.client.onmessage = function (payload) {\n\t var data = JSON.parse(payload.data || payload);\n\t\n\t if (data.room && self.listeners[data.room]) {\n\t poke(self.listeners, data.room, data);\n\t }\n\t else if (self.listeners.discarded) {\n\t poke(self.listeners, 'discarded', data);\n\t }\n\t };\n\t };\n\t\n\t /**\n\t * Fires the provided callback whence a connection is established\n\t *\n\t * @param {function} callback\n\t */\n\t this.onConnect = function (callback) {\n\t this.listeners.connect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection error is received\n\t * @param {function} callback\n\t */\n\t this.onConnectError = function (callback) {\n\t this.listeners.error.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a disconnection occurred\n\t * @param {function} callback\n\t */\n\t this.onDisconnect = function (callback) {\n\t this.listeners.disconnect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection has been reestablished\n\t * @param {function} callback\n\t */\n\t this.onReconnect = function (callback) {\n\t this.listeners.reconnect.push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Registers a callback on a room. Once 1 message is received, fires the\n\t * callback and unregister it afterward.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.once = function (roomId, callback) {\n\t if (!this.listeners[roomId]) {\n\t this.listeners[roomId] = [];\n\t }\n\t\n\t this.listeners[roomId].push({\n\t fn: callback,\n\t keep: false\n\t });\n\t };\n\t\n\t /**\n\t * Registers a callback on a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.on = function (roomId, callback) {\n\t if (!this.listeners[roomId]) {\n\t this.listeners[roomId] = [];\n\t }\n\t\n\t this.listeners[roomId].push({\n\t fn: callback,\n\t keep: true\n\t });\n\t };\n\t\n\t /**\n\t * Unregisters a callback from a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.off = function (roomId, callback) {\n\t var index = -1;\n\t\n\t if (this.listeners[roomId]) {\n\t // Array.findIndex is not supported by internet explorer\n\t this.listeners[roomId].some(function (listener, i) {\n\t if (listener.fn === callback) {\n\t index = i;\n\t return true;\n\t }\n\t\n\t return false;\n\t });\n\t\n\t if (index !== -1) {\n\t if (this.listeners[roomId].length === 1 && ['error', 'connect', 'disconnect', 'reconnect'].indexOf(roomId) === -1) {\n\t delete this.listeners[roomId];\n\t }\n\t else {\n\t this.listeners[roomId].splice(index, 1);\n\t }\n\t }\n\t }\n\t };\n\t\n\t\n\t /**\n\t * Sends a payload to the connected server\n\t *\n\t * @param {Object} payload\n\t */\n\t this.send = function (payload) {\n\t if (this.client && this.client.readyState === this.client.OPEN) {\n\t this.client.send(JSON.stringify(payload));\n\t }\n\t };\n\t\n\t /**\n\t * Closes the connection\n\t */\n\t this.close = function () {\n\t this.listeners = {\n\t error: [],\n\t connect: [],\n\t disconnect: [],\n\t reconnect: []\n\t };\n\t\n\t this.wasConnected = false;\n\t this.client.close();\n\t this.client = null;\n\t self.stopRetryingToConnect = true;\n\t };\n\t}\n\t\n\t/**\n\t * Executes all registered listeners in the provided\n\t * \"listeners\" structure.\n\t *\n\t * Listeners are of the following format:\n\t * [\n\t * { fn: callback, once: boolean },\n\t * ...\n\t * ]\n\t *\n\t * @private\n\t * @param {Object} listeners\n\t * @param {string} roomId\n\t * @param {Object} [payload]\n\t */\n\tfunction poke (listeners, roomId, payload) {\n\t var\n\t i,\n\t length = listeners[roomId].length;\n\t\n\t for (i = 0; i < length; ++i) {\n\t listeners[roomId][i].fn(payload);\n\t\n\t if (!listeners[roomId][i].keep) {\n\t if (listeners[roomId].length > 1) {\n\t listeners[roomId].splice(i, 1);\n\t --i;\n\t --length;\n\t }\n\t else {\n\t delete listeners[roomId];\n\t }\n\t }\n\t }\n\t}\n\t\n\t/**\n\t * Called when the connection closes with an error state\n\t *\n\t * @param {boolean} autoReconnect\n\t * @param {number} reconnectionDelay\n\t * @param {string|Object} message\n\t */\n\tfunction onClientError(autoReconnect, reconnectionDelay, message) {\n\t var self = this;\n\t\n\t if (autoReconnect && !self.retrying && !self.stopRetryingToConnect) {\n\t self.retrying = true;\n\t setTimeout(function () {\n\t self.retrying = false;\n\t self.connect(autoReconnect, reconnectionDelay);\n\t }, reconnectionDelay);\n\t }\n\t\n\t poke(self.listeners, 'error', message);\n\t}\n\t\n\tmodule.exports = WSNode;\n\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t KuzzleSecurityDocument = __webpack_require__(1);\n\t\n\t/**\n\t * @param {Security} Security\n\t * @param {string} id\n\t * @param {Object} content\n\t * @constructor\n\t */\n\tfunction User(Security, id, content) {\n\t\n\t KuzzleSecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteUser'\n\t },\n\t updateActionName: {\n\t value: 'updateUser'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['save', 'saveRestricted'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t}\n\t\n\tUser.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n\t constructor: {\n\t value: User\n\t }\n\t});\n\t\n\t/**\n\t * Set profiles in content\n\t * @param {array} profileIds - an array of profiles ids string\n\t *\n\t * @returns {User} this\n\t */\n\tUser.prototype.setProfiles = function (profileIds) {\n\t if (!Array.isArray(profileIds) || typeof profileIds[0] !== 'string') {\n\t throw new Error('Parameter \"profileIds\" must be an array of strings');\n\t }\n\t\n\t this.content.profileIds = profileIds;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Add a profile\n\t * @param {string} profileId - a profile ids string\n\t *\n\t * @returns {User} this\n\t */\n\tUser.prototype.addProfile = function (profileId) {\n\t if (typeof profileId !== 'string') {\n\t throw new Error('Parameter \"profileId\" must be a string');\n\t }\n\t\n\t if (!this.content.profileIds) {\n\t this.content.profileIds = [];\n\t }\n\t\n\t if (this.content.profileIds.indexOf(profileId) === -1) {\n\t this.content.profileIds.push(profileId);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Saves this user into Kuzzle.\n\t *\n\t * If this is a new user, this function will create it in Kuzzle.\n\t * Otherwise, this method will replace the latest version of this user in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {User} this\n\t */\n\tUser.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Saves this user as restricted into Kuzzle.\n\t *\n\t * This function will create a new user. It is not usable to update an existing user.\n\t * The \"profileIds\" property must not be provided, or the request will be rejected by Kuzzle.\n\t * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n\t *\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {User} this\n\t */\n\tUser.prototype.saveRestricted = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createRestrictedUser'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this User\n\t */\n\tUser.prototype.serialize = function () {\n\t return {_id: this.id, body: this.content};\n\t};\n\t\n\t/**\n\t * Return the associated profiles IDs\n\t *\n\t * @return {array} the associated profiles IDs\n\t */\n\tUser.prototype.getProfiles = function () {\n\t return this.content.profileIds;\n\t};\n\t\n\tmodule.exports = User;\n\n\n/***/ },\n/* 5 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar v1 = __webpack_require__(19);\n\tvar v4 = __webpack_require__(20);\n\t\n\tvar uuid = v4;\n\tuuid.v1 = v1;\n\tuuid.v4 = v4;\n\t\n\tmodule.exports = uuid;\n\n\n/***/ },\n/* 6 */\n/***/ function(module, exports) {\n\n\t/**\n\t * Convert array of 16 byte values to UUID string format of the form:\n\t * XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n\t */\n\tvar byteToHex = [];\n\tfor (var i = 0; i < 256; ++i) {\n\t byteToHex[i] = (i + 0x100).toString(16).substr(1);\n\t}\n\t\n\tfunction bytesToUuid(buf, offset) {\n\t var i = offset || 0;\n\t var bth = byteToHex;\n\t return bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] + '-' +\n\t bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]] +\n\t bth[buf[i++]] + bth[buf[i++]];\n\t}\n\t\n\tmodule.exports = bytesToUuid;\n\n\n/***/ },\n/* 7 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t// Unique ID creation requires a high quality random # generator. In the\n\t// browser this is a little complicated due to unknown quality of Math.random()\n\t// and inconsistent support for the `crypto` API. We do the best we can via\n\t// feature-detection\n\tvar rng;\n\t\n\tvar crypto = (window).crypto || (window).msCrypto; // for IE 11\n\tif (crypto && crypto.getRandomValues) {\n\t // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n\t var rnds8 = new Uint8Array(16);\n\t rng = function whatwgRNG() {\n\t crypto.getRandomValues(rnds8);\n\t return rnds8;\n\t };\n\t}\n\t\n\tif (!rng) {\n\t // Math.random()-based (RNG)\n\t //\n\t // If all else fails, use Math.random(). It's fast, but is of unspecified\n\t // quality.\n\t var rnds = new Array(16);\n\t rng = function() {\n\t for (var i = 0, r; i < 16; i++) {\n\t if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n\t rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n\t }\n\t\n\t return rnds;\n\t };\n\t}\n\t\n\tmodule.exports = rng;\n\n\n/***/ },\n/* 8 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t KuzzleSearchResult = __webpack_require__(12),\n\t Document = __webpack_require__(2),\n\t CollectionMapping = __webpack_require__(9),\n\t Room = __webpack_require__(11),\n\t SubscribeResult = __webpack_require__(13);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * A data collection is a set of data managed by Kuzzle. It acts like a data table for persistent documents,\n\t * or like a room for pub/sub messages.\n\t *\n\t * @property {string} collection\n\t * @property {string} index\n\t * @property {Kuzzle} kuzzle\n\t * @property {Array.} collection\n\t * @param {object} kuzzle - Kuzzle instance to inherit from\n\t * @param {string} collection - name of the data collection to handle\n\t * @param {string} index - Index containing the data collection\n\t * @constructor\n\t */\n\tfunction Collection(kuzzle, collection, index) {\n\t if (!index || !collection) {\n\t throw new Error('The Collection object constructor needs an index and a collection arguments');\n\t }\n\t\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t index: {\n\t value: index,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzle.headers)),\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t Object.defineProperty(this, 'buildQueryArgs', {\n\t value: function (controller, action) {\n\t return {\n\t controller: controller,\n\t action: action,\n\t collection: this.collection,\n\t index: this.index\n\t };\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['publishMessage', 'setHeaders', 'subscribe'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Returns the number of documents matching the provided set of filters.\n\t *\n\t * There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function\n\t *\n\t * @param {object} filters - Filters in Elasticsearch Query DSL format\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.count = function (filters, options, cb) {\n\t var\n\t query;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.count', cb);\n\t\n\t query = this.kuzzle.addHeaders({body: filters}, this.headers);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('document', 'count'), query, options, function (error, result) {\n\t cb(error, result && result.result.count);\n\t });\n\t};\n\t\n\t/**\n\t * Create a new empty data collection, with no associated mapping.\n\t * Kuzzle automatically creates data collections when storing documents, but there are cases where we\n\t * want to create and prepare data collections before storing documents in it.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.create = function (options, cb) {\n\t var data = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('collection', 'create'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Create a new document in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t * - ifExist (string, allowed values: \"error\" (default), \"replace\"):\n\t * If the same document already exists:\n\t * - resolves with an error if set to \"error\".\n\t * - replaces the existing document if set to \"replace\"\n\t *\n\t * @param {string} [id] - (optional) document identifier\n\t * @param {object} document - either an instance of a Document object, or a document\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Object} this\n\t */\n\tCollection.prototype.createDocument = function (id, document, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'create';\n\t\n\t if (id && typeof id !== 'string') {\n\t cb = options;\n\t options = document;\n\t document = id;\n\t id = null;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (document instanceof Document) {\n\t data = document.serialize();\n\t } else {\n\t data.body = document;\n\t }\n\t\n\t if (options && options.ifExist) {\n\t if (options.ifExist === 'replace') {\n\t action = 'createOrReplace';\n\t }\n\t else if (options.ifExist !== 'error') {\n\t throw new Error('Invalid value for the \"ifExist\" option: ' + options.ifExist);\n\t }\n\t }\n\t\n\t if (id) {\n\t data._id = id;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, self.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n\t var doc;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t doc = new Document(self, res.result._id, res.result._source);\n\t doc.version = res.result._version;\n\t cb(null, doc);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete persistent documents.\n\t *\n\t * There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string|object} arg - Either a document ID (will delete only this particular document), or a set of filters\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Collection} this\n\t */\n\tCollection.prototype.deleteDocument = function (arg, options, cb) {\n\t var\n\t action,\n\t data = {};\n\t\n\t if (typeof arg === 'string') {\n\t data._id = arg;\n\t action = 'delete';\n\t } else {\n\t data.body = {query: arg};\n\t action = 'deleteByQuery';\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n\t if (err) {\n\t cb(err);\n\t }\n\t else {\n\t cb(null, (action === 'delete' ? [res.result._id] : res.result.ids));\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Retrieve a single stored document using its unique document ID.\n\t *\n\t * @param {string} documentId - Unique document identifier\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.fetchDocument = function (documentId, options, cb) {\n\t var\n\t data = {_id: documentId},\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Collection.fetch', cb);\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'get'), data, options, function (err, res) {\n\t var document;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t document = new Document(self, res.result._id, res.result._source);\n\t document.version = res.result._version;\n\t cb(null, document);\n\t });\n\t};\n\t\n\t/**\n\t * Retrieves all documents stored in this data collection\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tCollection.prototype.fetchAllDocuments = function (options, cb) {\n\t var\n\t warnEmitted = false,\n\t documents = [],\n\t filters = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t // copying pagination options to the search filter\n\t if (!options) {\n\t options = {};\n\t }\n\t\n\t if (!options.from) {\n\t options.from = 0;\n\t }\n\t\n\t if (!options.size) {\n\t options.size = 1000;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.fetchAllDocuments', cb);\n\t\n\t this.search(filters, options, function fetchNextDocuments (error, searchResult) {\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t if (searchResult instanceof KuzzleSearchResult) {\n\t if (searchResult.total > 10000 && !warnEmitted) {\n\t warnEmitted = true;\n\t console.warn('Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead'); // eslint-disable-line no-console\n\t }\n\t\n\t searchResult.documents.forEach(function(document) {\n\t documents.push(document);\n\t });\n\t searchResult.fetchNext(fetchNextDocuments);\n\t }\n\t else {\n\t cb(null, documents);\n\t }\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Instantiates a CollectionMapping object containing the current mapping of this collection.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Returns an instantiated CollectionMapping object\n\t */\n\tCollection.prototype.getMapping = function (options, cb) {\n\t var kuzzleMapping;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.getMapping', cb);\n\t\n\t kuzzleMapping = new CollectionMapping(this);\n\t kuzzleMapping.refresh(options, cb);\n\t};\n\t\n\t/**\n\t * Publish a realtime message\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {object} document - either a Document instance or a JSON object\n\t * @param {object} [options] - optional arguments\n\t * @param {responseCallback} [cb] - Returns a raw Kuzzle response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.publishMessage = function (document, options, cb) {\n\t var data = {};\n\t\n\t if (document instanceof Document) {\n\t data = document.serialize();\n\t } else {\n\t data.body = document;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('realtime', 'publish'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replace an existing document with a new one.\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string} documentId - Unique document identifier of the document to replace\n\t * @param {object} content - JSON object representing the new document version\n\t * @param {object} [options] - additional arguments\n\t * @param {responseCallback} [cb] - Returns an instantiated Document object\n\t * @return {object} this\n\t */\n\tCollection.prototype.replaceDocument = function (documentId, content, options, cb) {\n\t var\n\t self = this,\n\t data = {\n\t _id: documentId,\n\t body: content\n\t };\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'createOrReplace'), data, options, cb && function (err, res) {\n\t var document;\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t document = new Document(self, res.result._id, res.result._source);\n\t document.version = res.result._version;\n\t cb(null, document);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Executes an advanced search on the data collection.\n\t *\n\t * /!\\ There is a small delay between documents creation and their existence in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a document that was just been created won’t be returned by this function.\n\t *\n\t * @param {object} filters - Filters in Elasticsearch Query DSL format\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\t\n\tCollection.prototype.search = function (filters, options, cb) {\n\t var\n\t query,\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t self.kuzzle.callbackRequired('Collection.search', cb);\n\t\n\t query = self.kuzzle.addHeaders({body: filters}, this.headers);\n\t\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) {\n\t var documents = [];\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t result.result.hits.forEach(function (doc) {\n\t var newDocument = new Document(self, doc._id, doc._source);\n\t\n\t newDocument.version = doc._version;\n\t\n\t documents.push(newDocument);\n\t });\n\t\n\t if (result.result._scroll_id) {\n\t options.scrollId = result.result._scroll_id;\n\t }\n\t\n\t cb(null, new KuzzleSearchResult(\n\t self,\n\t result.result.total,\n\t documents,\n\t result.result.aggregations ? result.result.aggregations : {},\n\t options,\n\t filters,\n\t options.previous || null\n\t ));\n\t });\n\t};\n\t\n\t/**\n\t * A \"scroll\" option can be passed to search queries, creating persistent\n\t * paginated results.\n\t * This method can be used to manually get the next page of a search result,\n\t * instead of using KuzzleSearchResult.next()\n\t *\n\t * @param {string} scrollId\n\t * @param {object} [options]\n\t * @param {object} [filters]\n\t * @param {responseCallback} cb\n\t */\n\tCollection.prototype.scroll = function (scrollId, options, filters, cb) {\n\t var\n\t request = {},\n\t self = this;\n\t\n\t if (!scrollId) {\n\t throw new Error('Collection.scroll: scrollId is required');\n\t }\n\t\n\t if (!cb) {\n\t cb = filters;\n\t filters = null;\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = {};\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.scroll', cb);\n\t\n\t request.scrollId = scrollId;\n\t\n\t if (options && options.scroll) {\n\t request.scroll = options.scroll;\n\t }\n\t\n\t this.kuzzle.query({controller: 'document', action: 'scroll'}, request, options, function (error, result) {\n\t var documents = [];\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t result.result.hits.forEach(function (doc) {\n\t var newDocument = new Document(self, doc._id, doc._source);\n\t\n\t newDocument.version = doc._version;\n\t\n\t documents.push(newDocument);\n\t });\n\t\n\t if (result.result._scroll_id) {\n\t options.scrollId = result.result._scroll_id;\n\t }\n\t\n\t cb(null, new KuzzleSearchResult(\n\t self,\n\t result.result.total,\n\t documents,\n\t {},\n\t options,\n\t filters,\n\t options.previous || null\n\t ));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Subscribes to this data collection with a set of filters.\n\t * To subscribe to the entire data collection, simply provide an empty filter.\n\t *\n\t * @param {object} filters - Filters in Kuzzle DSL format\n\t * @param {object} [options] - subscriptions options\n\t * @param {responseCallback} cb - called for each new notification\n\t * @returns {*} KuzzleSubscribeResult object\n\t */\n\tCollection.prototype.subscribe = function (filters, options, cb) {\n\t var\n\t room,\n\t subscribeResult;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.callbackRequired('Collection.subscribe', cb);\n\t\n\t subscribeResult = new SubscribeResult();\n\t room = new Room(this, options);\n\t\n\t room.renew(filters, cb, subscribeResult.done.bind(subscribeResult));\n\t\n\t return subscribeResult;\n\t};\n\t\n\t/**\n\t * Truncate the data collection, removing all stored documents but keeping all associated mappings.\n\t * This method is a lot faster than removing all documents using a query.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t * @returns {*} this\n\t */\n\tCollection.prototype.truncate = function (options, cb) {\n\t var data = {};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.kuzzle.addHeaders(data, this.headers);\n\t this.kuzzle.query(this.buildQueryArgs('collection', 'truncate'), data, options, cb);\n\t\n\t return this;\n\t};\n\t\n\t\n\t/**\n\t * Update parts of a document\n\t *\n\t * Takes an optional argument object with the following properties:\n\t * - volatile (object, default: null):\n\t * Additional information passed to notifications to other users\n\t *\n\t * @param {string} documentId - Unique document identifier of the document to update\n\t * @param {object} content - JSON object containing changes to perform on the document\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Returns an instantiated Document object\n\t * @return {object} this\n\t */\n\tCollection.prototype.updateDocument = function (documentId, content, options, cb) {\n\t var\n\t data = {\n\t _id: documentId,\n\t body: content\n\t },\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (options && options.retryOnConflict) {\n\t data.retryOnConflict = options.retryOnConflict;\n\t }\n\t\n\t data = self.kuzzle.addHeaders(data, this.headers);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('document', 'update'), data, options, cb && function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t (new Document(self, res.result._id)).refresh(cb);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t\n\t/**\n\t * Instantiate a new Document object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - document id\n\t * @param {object} content - document content\n\t * @constructor\n\t */\n\tCollection.prototype.document = function (id, content) {\n\t return new Document(this, id, content);\n\t};\n\t\n\t/**\n\t * Instantiate a new Room object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {object} [options] - subscription configuration\n\t * @constructor\n\t */\n\tCollection.prototype.room = function (options) {\n\t return new Room(this, options);\n\t};\n\t\n\t/**\n\t * Instantiate a new CollectionMapping object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {object} [mapping] - mapping to instantiate the CollectionMapping object with\n\t * @constructor\n\t */\n\tCollection.prototype.collectionMapping = function (mapping) {\n\t return new CollectionMapping(this, mapping);\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tCollection.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\tmodule.exports = Collection;\n\n\n/***/ },\n/* 9 */\n/***/ function(module, exports) {\n\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t\n\t/**\n\t * When creating a new data collection in the persistent data storage layer, Kuzzle uses a default mapping.\n\t * It means that, by default, you won’t be able to exploit the full capabilities of our persistent data storage layer\n\t * (currently handled by ElasticSearch), and your searches may suffer from below-average performances, depending on\n\t * the amount of data you stored in a collection and the complexity of your database.\n\t *\n\t * The CollectionMapping object allow to get the current mapping of a data collection and to modify it if needed.\n\t *\n\t * @param {object} collection - Instance of the inherited Collection object\n\t * @param {object} [mapping] - mappings\n\t * @constructor\n\t */\n\tfunction CollectionMapping(collection, mapping) {\n\t Object.defineProperties(this, {\n\t //read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: collection.kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(collection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t mapping: {\n\t value: mapping || {},\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['set', 'setHeaders'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Applies the new mapping to the data collection.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t */\n\tCollectionMapping.prototype.apply = function (options, cb) {\n\t var\n\t self = this,\n\t data = this.kuzzle.addHeaders({body: {properties: this.mapping}}, this.headers);\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.collection.buildQueryArgs('collection', 'updateMapping'), data, options, function (err) {\n\t if (err) {\n\t return cb && cb(err);\n\t }\n\t\n\t self.refresh(options, cb);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Replaces the current content with the mapping stored in Kuzzle\n\t *\n\t * Calling this function will discard any uncommited changes. You can commit changes by calling the “apply” function\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {*} this\n\t */\n\tCollectionMapping.prototype.refresh = function (options, cb) {\n\t var\n\t self = this,\n\t data = this.kuzzle.addHeaders({}, this.headers);\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.collection.buildQueryArgs('collection', 'getMapping'), data, options, function (err, res) {\n\t if (err) {\n\t return cb ? cb(err) : false;\n\t }\n\t\n\t if (res.result[self.collection.index]) {\n\t if (res.result[self.collection.index].mappings[self.collection.collection]) {\n\t self.mapping = res.result[self.collection.index].mappings[self.collection.collection].properties;\n\t\n\t // Mappings can be empty. The mapping property should never be \"undefined\"\n\t if (self.mapping === undefined) {\n\t self.mapping = {};\n\t }\n\t } else {\n\t return cb && cb(new Error('No mapping found for collection ' + self.collection.collection));\n\t }\n\t } else {\n\t return cb && cb(new Error('No mapping found for index ' + self.collection.index));\n\t }\n\t\n\t if (cb) {\n\t cb(null, self);\n\t }\n\t });\n\t\n\t return this;\n\t};\n\t\n\t\n\t/**\n\t * Adds or updates a field mapping.\n\t *\n\t * Changes made by this function won’t be applied until you call the apply method\n\t *\n\t * @param {string} field - Name of the field from which the mapping is to be added or updated\n\t * @param {object} mapping - corresponding field mapping\n\t * @returns {CollectionMapping}\n\t */\n\tCollectionMapping.prototype.set = function (field, mapping) {\n\t this.mapping[field] = mapping;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tCollectionMapping.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\tmodule.exports = CollectionMapping;\n\n\n/***/ },\n/* 10 */\n/***/ function(module, exports) {\n\n\t// Parameter mutualization\n\tvar\n\t getId = {getter: true, required: ['_id']},\n\t getIdField = {getter: true, required: ['_id', 'field']},\n\t getKeys = {getter: true, required: ['keys']},\n\t getMember = {getter: true, required: ['_id', 'member']},\n\t getxScan = {getter: true, required: ['_id', 'cursor'], opts: ['match', 'count']},\n\t getZrange = {\n\t getter: true,\n\t required: ['_id', 'start', 'stop'],\n\t opts: assignZrangeOptions,\n\t mapResults: mapZrangeResults\n\t },\n\t getZrangeBy = {\n\t getter: true,\n\t required: ['_id', 'min', 'max'],\n\t opts: assignZrangeOptions,\n\t mapResults: mapZrangeResults\n\t },\n\t setId = {required: ['_id']},\n\t setIdValue = {required: ['_id', 'value']},\n\t setIdFieldValue = {required: ['_id', 'field', 'value']},\n\t setEntries = {required: ['entries']};\n\t\n\t// Redis commands\n\tvar\n\t commands = {\n\t append: setIdValue,\n\t bitcount: {getter: true, required: ['_id'], opts: ['start', 'end']},\n\t bitop: {required: ['_id', 'operation', 'keys']},\n\t bitpos: {getter: true, required: ['_id', 'bit'], opts: ['start', 'end']},\n\t dbsize: {getter: true},\n\t decr: setId,\n\t decrby: setIdValue,\n\t del: {required: ['keys']},\n\t exists: getKeys,\n\t expire: {required: ['_id', 'seconds']},\n\t expireat: {required: ['_id', 'timestamp']},\n\t flushdb: {},\n\t geoadd: {required: ['_id', 'points']},\n\t geodist: {\n\t getter: true,\n\t required: ['_id', 'member1', 'member2'],\n\t opts: ['unit'],\n\t mapResults: parseFloat\n\t },\n\t geohash: {getter: true, required: ['_id', 'members']},\n\t geopos: {getter: true, required: ['_id', 'members'], mapResults: mapGeoposResults},\n\t georadius: {\n\t getter: true,\n\t required: ['_id', 'lon', 'lat', 'distance', 'unit'],\n\t opts: assignGeoRadiusOptions,\n\t mapResults: mapGeoRadiusResults\n\t },\n\t georadiusbymember: {\n\t getter: true,\n\t required: ['_id', 'member', 'distance', 'unit'],\n\t opts: assignGeoRadiusOptions,\n\t mapResults: mapGeoRadiusResults\n\t },\n\t get: getId,\n\t getbit: {getter: true, required: ['_id', 'offset']},\n\t getrange: {getter: true, required: ['_id', 'start', 'end']},\n\t getset: setIdValue,\n\t hdel: {required: ['_id', 'fields']},\n\t hexists: getIdField,\n\t hget: getIdField,\n\t hgetall: {getter: true, required: ['_id']},\n\t hincrby: setIdFieldValue,\n\t hincrbyfloat: {required: ['_id', 'field', 'value'], mapResults: parseFloat},\n\t hkeys: getId,\n\t hlen: getId,\n\t hmget: {getter: true, required: ['_id', 'fields']},\n\t hmset: {required: ['_id', 'entries']},\n\t hscan: getxScan,\n\t hset: setIdFieldValue,\n\t hsetnx: setIdFieldValue,\n\t hstrlen: getIdField,\n\t hvals: getId,\n\t incr: setId,\n\t incrby: setIdValue,\n\t incrbyfloat: {required: ['_id', 'value'], mapResults: parseFloat},\n\t keys: {getter: true, required: ['pattern']},\n\t lindex: {getter: true, required: ['_id', 'index']},\n\t linsert: {required: ['_id', 'position', 'pivot', 'value']},\n\t llen: getId,\n\t lpop: setId,\n\t lpush: {required: ['_id', 'values']},\n\t lpushx: setIdValue,\n\t lrange: {getter: true, required: ['_id', 'start', 'stop']},\n\t lrem: {required: ['_id', 'count', 'value']},\n\t lset: {required: ['_id', 'index', 'value']},\n\t ltrim: {required: ['_id', 'start', 'stop']},\n\t mget: getKeys,\n\t mset: setEntries,\n\t msetnx: setEntries,\n\t object: {getter: true, required: ['_id', 'subcommand']},\n\t persist: setId,\n\t pexpire: {required: ['_id', 'milliseconds']},\n\t pexpireat: {required: ['_id', 'timestamp']},\n\t pfadd: {required: ['_id', 'elements']},\n\t pfcount: getKeys,\n\t pfmerge: {required: ['_id', 'sources']},\n\t ping: {getter: true},\n\t psetex: {required: ['_id', 'value', 'milliseconds']},\n\t pttl: getId,\n\t randomkey: {getter: true},\n\t rename: {required: ['_id', 'newkey']},\n\t renamenx: {required: ['_id', 'newkey']},\n\t rpop: setId,\n\t rpoplpush: {required: ['source', 'destination']},\n\t rpush: {required: ['_id', 'values']},\n\t rpushx: setIdValue,\n\t sadd: {required: ['_id', 'members']},\n\t scan: {getter: true, required: ['cursor'], opts: ['match', 'count']},\n\t scard: getId,\n\t sdiff: {getter: true, required: ['_id', 'keys']},\n\t sdiffstore: {required: ['_id', 'keys', 'destination']},\n\t set: {required: ['_id', 'value'], opts: ['ex', 'px', 'nx', 'xx']},\n\t setex: {required: ['_id', 'value', 'seconds']},\n\t setnx: setIdValue,\n\t sinter: getKeys,\n\t sinterstore: {required: ['destination', 'keys']},\n\t sismember: getMember,\n\t smembers: getId,\n\t smove: {required: ['_id', 'destination', 'member']},\n\t sort: {getter: true, required: ['_id'], opts: ['alpha', 'by', 'direction', 'get', 'limit']},\n\t spop: {required: ['_id'], opts: ['count'], mapResults: mapStringToArray },\n\t srandmember: {getter: true, required: ['_id'], opts: ['count'], mapResults: mapStringToArray},\n\t srem: {required: ['_id', 'members']},\n\t sscan: getxScan,\n\t strlen: getId,\n\t sunion: getKeys,\n\t sunionstore: {required: ['destination', 'keys']},\n\t time: {getter: true, mapResults: mapArrayStringToArrayInt},\n\t touch: {required: ['keys']},\n\t ttl: getId,\n\t type: getId,\n\t zadd: {required: ['_id', 'elements'], opts: ['nx', 'xx', 'ch', 'incr']},\n\t zcard: getId,\n\t zcount: {getter: true, required: ['_id', 'min', 'max']},\n\t zincrby: {required: ['_id', 'member', 'value']},\n\t zinterstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']},\n\t zlexcount: {getter: true, required: ['_id', 'min', 'max']},\n\t zrange: getZrange,\n\t zrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']},\n\t zrevrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']},\n\t zrangebyscore: getZrangeBy,\n\t zrank: getMember,\n\t zrem: {required: ['_id', 'members']},\n\t zremrangebylex: {required: ['_id', 'min', 'max']},\n\t zremrangebyrank: {required: ['_id', 'start', 'stop']},\n\t zremrangebyscore: {required: ['_id', 'min', 'max']},\n\t zrevrange: getZrange,\n\t zrevrangebyscore: getZrangeBy,\n\t zrevrank: getMember,\n\t zscan: getxScan,\n\t zscore: {getter: true, required: ['_id', 'member'], mapResults: parseFloat},\n\t zunionstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']}\n\t };\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t\n\t/**\n\t * Kuzzle's memory storage is a separate data store from the database layer.\n\t * It is internaly based on Redis. You can access most of Redis functions (all\n\t * lowercased), except functions falling in the following categories:\n\t *\n\t * - blocking functions\n\t * - cluster commands\n\t * - configuration commands\n\t * - cursor functions\n\t * - database administration commands\n\t * - debugging functions\n\t * - script based functions\n\t * - transaction functions\n\t *\n\t * @param {object} kuzzle - Kuzzle instance to inherit from\n\t * @constructor\n\t */\n\tfunction MemoryStorage(kuzzle) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t kuzzle: {\n\t value: kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t headers: {\n\t value: JSON.parse(JSON.stringify(kuzzle.headers)),\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t this.setHeaders = kuzzle.setHeaders.bind(this);\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['setHeaders'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t// Dynamically builds this class' prototypes using the \"commands\" global variable\n\t(function () {\n\t Object.keys(commands).forEach(function (command) {\n\t MemoryStorage.prototype[command] = function () {\n\t var\n\t args = Array.prototype.slice.call(arguments),\n\t options = null,\n\t cb,\n\t query = {\n\t controller: 'ms',\n\t action: command\n\t },\n\t data = {};\n\t\n\t if (args.length && typeof args[args.length - 1] === 'function') {\n\t cb = args.pop();\n\t }\n\t\n\t commands[command].getter && this.kuzzle.callbackRequired('MemoryStorage.' + command, cb);\n\t\n\t if (!commands[command].getter) {\n\t data.body = {};\n\t }\n\t\n\t if (commands[command].required) {\n\t commands[command].required.forEach(function (param) {\n\t var value = args.shift();\n\t\n\t if (value === undefined) {\n\t throw new Error('MemoryStorage.' + command + ': Missing parameter \"' + param + '\"');\n\t }\n\t\n\t assignParameter(data, commands[command].getter, param, value);\n\t });\n\t }\n\t\n\t if (args.length > 1) {\n\t throw new Error('MemoryStorage.' + command + ': Too many parameters provided');\n\t }\n\t\n\t if (args.length === 1 && typeof args[0] !== 'object' || Array.isArray(args[0])) {\n\t throw new Error('MemoryStorage.' + command + ': Invalid optional parameter (expected an object)');\n\t }\n\t\n\t if (args.length) {\n\t options = Object.assign({}, args[0]);\n\t\n\t if (Array.isArray(commands[command].opts)) {\n\t commands[command].opts.forEach(function (opt) {\n\t if (options[opt] !== null && options[opt] !== undefined) {\n\t assignParameter(data, commands[command].getter, opt, options[opt]);\n\t delete options[opt];\n\t }\n\t });\n\t }\n\t }\n\t\n\t /*\n\t Options function mapper does not necessarily need\n\t options to be passed by clients.\n\t */\n\t if (typeof commands[command].opts === 'function') {\n\t commands[command].opts(data, options || {});\n\t }\n\t\n\t this.kuzzle.query(query, data, options, cb && function (err, res) {\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t if (commands[command].mapResults) {\n\t return cb(null, commands[command].mapResults(res.result));\n\t }\n\t\n\t cb(null, res.result);\n\t });\n\t\n\t if (!commands[command].getter) {\n\t return this;\n\t }\n\t };\n\t });\n\t})();\n\t\n\t/**\n\t *\n\t * @param {object} data - target data object\n\t * @param {boolean} getter - tells if the command is a getter one\n\t * @param {string} name - parameter name\n\t * @param {*} value - parameter value\n\t */\n\tfunction assignParameter(data, getter, name, value) {\n\t if (getter || name === '_id') {\n\t data[name] = value;\n\t }\n\t else {\n\t data.body[name] = value;\n\t }\n\t}\n\t\n\t/**\n\t * Assign the provided options for the georadius* redis functions\n\t * to the request object, as expected by Kuzzle API\n\t *\n\t * Mutates the provided data and options objects\n\t *\n\t * @param {object} data\n\t * @param {object} options\n\t */\n\tfunction assignGeoRadiusOptions(data, options) {\n\t var parsed = [];\n\t\n\t Object.keys(options)\n\t .filter(function (opt) {\n\t return options[opt] && ['withcoord', 'withdist', 'count', 'sort'].indexOf(opt) !== -1;\n\t })\n\t .forEach(function (opt) {\n\t if (opt === 'withcoord' || opt === 'withdist') {\n\t parsed.push(opt);\n\t delete options[opt];\n\t }\n\t else if (opt === 'count' || opt === 'sort') {\n\t if (opt === 'count') {\n\t parsed.push('count');\n\t }\n\t\n\t parsed.push(options[opt]);\n\t }\n\t\n\t delete options[opt];\n\t });\n\t\n\t if (parsed.length > 0) {\n\t data.options = parsed;\n\t }\n\t}\n\t\n\t/**\n\t * Force the WITHSCORES option on z*range* routes\n\t *\n\t * Mutates the provided data and options objects\n\t *\n\t * @param {object} data\n\t * @param {object} options\n\t */\n\tfunction assignZrangeOptions(data, options) {\n\t data.options = ['withscores'];\n\t\n\t if (options.limit) {\n\t data.limit = options.limit;\n\t delete options.limit;\n\t }\n\t}\n\t\n\t/**\n\t * Maps geopos results, from array> to array>\n\t *\n\t * @param {Array.>} results\n\t * @return {Array.>}\n\t */\n\tfunction mapGeoposResults(results) {\n\t return results.map(function (coords) {\n\t return coords.map(function (latlon) {\n\t return parseFloat(latlon);\n\t });\n\t });\n\t}\n\t\n\t\n\t/**\n\t * Maps georadius results to the format specified in the SDK documentation,\n\t * preventing different formats depending on the passed options\n\t *\n\t * Results can be either an array of point names, or an array\n\t * of arrays, each one of them containing the point name,\n\t * and additional informations depending on the passed options\n\t * (coordinates, distances)\n\t *\n\t * @param {Array} results\n\t * @return {Array.}\n\t */\n\tfunction mapGeoRadiusResults(results) {\n\t // Simple array of point names (no options provided)\n\t if (!Array.isArray(results[0])) {\n\t return results.map(function (point) {\n\t return {name: point};\n\t });\n\t }\n\t\n\t return results.map(function (point) {\n\t // The point id is always the first item\n\t var\n\t p = {\n\t name: point[0]\n\t },\n\t i;\n\t\n\t for (i = 1; i < point.length; i++) {\n\t // withcoord result are in an array...\n\t if (Array.isArray(point[i])) {\n\t p.coordinates = point[i].map(function (coord) {\n\t return parseFloat(coord);\n\t });\n\t }\n\t else {\n\t // ... and withdist are not\n\t p.distance = parseFloat(point[i]);\n\t }\n\t }\n\t\n\t return p;\n\t });\n\t}\n\t\n\t/**\n\t * Map a string result to an array of strings.\n\t * Used to uniformize polymorphic results from redis\n\t *\n\t * @param {Array|string} results\n\t * @return {Array.}\n\t */\n\tfunction mapStringToArray (results) {\n\t return Array.isArray(results) ? results : [results];\n\t}\n\t\n\t/**\n\t * Map an array of strings to an array of integers\n\t *\n\t * @param {Array.} results\n\t * @return {Array.}\n\t */\n\tfunction mapArrayStringToArrayInt(results) {\n\t return results.map(function (value) {\n\t return parseInt(value);\n\t });\n\t}\n\t\n\t/**\n\t * Map zrange results with WITHSCORES:\n\t * [\n\t * \"member1\",\n\t * \"score of member1\",\n\t * \"member2\",\n\t * \"score of member2\"\n\t * ]\n\t *\n\t * into the following format:\n\t * [\n\t * {\"member\": \"member1\", \"score\": },\n\t * {\"member\": \"member2\", \"score\": },\n\t * ]\n\t *\n\t *\n\t * @param {Array.} results\n\t * @return {Array.}\n\t */\n\tfunction mapZrangeResults(results) {\n\t var\n\t buffer = null,\n\t mapped = [];\n\t\n\t results.forEach(function (value) {\n\t if (buffer === null) {\n\t buffer = value;\n\t }\n\t else {\n\t mapped.push({member: buffer, score: parseFloat(value)});\n\t buffer = null;\n\t }\n\t });\n\t\n\t return mapped;\n\t}\n\t\n\tmodule.exports = MemoryStorage;\n\n\n/***/ },\n/* 11 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t uuid = __webpack_require__(5),\n\t Document = __webpack_require__(2);\n\t\n\t/**\n\t * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n\t *\n\t * @callback responseCallback\n\t * @param {Object} err - Error object, NULL if the query is successful\n\t * @param {Object} [data] - The content of the query response\n\t */\n\t\n\t/**\n\t * This object is the result of a subscription request, allowing to manipulate the subscription itself.\n\t *\n\t * In Kuzzle, you don’t exactly subscribe to a room or a topic but, instead, you subscribe to documents.\n\t *\n\t * What it means is that, to subscribe, you provide to Kuzzle a set of matching filters.\n\t * Once you have subscribed, if a pub/sub message is published matching your filters, or if a matching stored\n\t * document change (because it is created, updated or deleted), then you’ll receive a notification about it.\n\t *\n\t * @param {object} collection - an instantiated and valid kuzzle object\n\t * @param {object} [options] - subscription optional configuration\n\t * @constructor\n\t */\n\tfunction Room(collection, options) {\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t callback: {\n\t value: null,\n\t writable: true\n\t },\n\t channel: {\n\t value: null,\n\t writable: true\n\t },\n\t id: {\n\t value: uuid.v4()\n\t },\n\t lastRenewal: {\n\t value: null,\n\t writable: true\n\t },\n\t notifier: {\n\t value: null,\n\t writable: true\n\t },\n\t onDoneCB: {\n\t value: null,\n\t writable: true\n\t },\n\t queue: {\n\t value: [],\n\t writable: true\n\t },\n\t // Delay before allowing a subscription renewal\n\t renewalDelay: {\n\t value: 500\n\t },\n\t scope: {\n\t value: options && options.scope ? options.scope : 'all'\n\t },\n\t state: {\n\t value: options && options.state ? options.state : 'done'\n\t },\n\t subscribing: {\n\t value: false,\n\t writable: true\n\t },\n\t users: {\n\t value: options && options.users ? options.users : 'none'\n\t },\n\t // read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t kuzzle: {\n\t value: collection.kuzzle,\n\t enumerable: true\n\t },\n\t // writable properties\n\t filters: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t headers: {\n\t value: JSON.parse(JSON.stringify(collection.headers)),\n\t enumerable: true,\n\t writable: true\n\t },\n\t volatile: {\n\t value: (options && options.volatile) ? options.volatile : {},\n\t enumerable: true,\n\t writable: true\n\t },\n\t roomId: {\n\t value: null,\n\t enumerable: true,\n\t writable: true\n\t },\n\t subscribeToSelf: {\n\t value: options && typeof options.subscribeToSelf === 'boolean' ? options.subscribeToSelf : true,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['count'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * Returns the number of other subscriptions on that room.\n\t *\n\t * @param {responseCallback} cb - Handles the query response\n\t */\n\tRoom.prototype.count = function (cb) {\n\t var data;\n\t\n\t this.kuzzle.callbackRequired('Room.count', cb);\n\t\n\t data = this.kuzzle.addHeaders({body: {roomId: this.roomId}}, this.headers);\n\t\n\t if (!isReady.call(this)) {\n\t this.queue.push({action: 'count', args: [cb]});\n\t return;\n\t }\n\t\n\t if (!this.roomId) {\n\t throw new Error('Room.count: cannot count subscriptions on an inactive room');\n\t }\n\t\n\t this.kuzzle.query(this.collection.buildQueryArgs('realtime', 'count'), data, function (err, res) {\n\t cb(err, res && res.result.count);\n\t });\n\t};\n\t\n\t/**\n\t * Renew the subscription using new filters\n\t *\n\t * @param {object} [filters] - Filters in Kuzzle DSL format\n\t * @param {responseCallback} notificationCB - called for each new notification\n\t * @param {responseCallback} [cb] - handles the query response\n\t */\n\tRoom.prototype.renew = function (filters, notificationCB, cb) {\n\t var\n\t now = Date.now(),\n\t subscribeQuery = {\n\t scope: this.scope,\n\t state: this.state,\n\t users: this.users\n\t },\n\t self = this;\n\t\n\t if (typeof filters === 'function') {\n\t cb = notificationCB;\n\t notificationCB = filters;\n\t filters = null;\n\t }\n\t\n\t if (!cb) {\n\t cb = self.onDoneCB;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Room.renew', notificationCB);\n\t\n\t /*\n\t Skip subscription renewal if another one was performed a moment before\n\t */\n\t if (self.lastRenewal && (now - self.lastRenewal) <= self.renewalDelay) {\n\t return cb && cb(new Error('Subscription already renewed less than ' + self.renewalDelay + 'ms ago'));\n\t }\n\t\n\t if (filters) {\n\t self.filters = filters;\n\t }\n\t\n\t /*\n\t if not yet connected, register itself to the subscriptions list and wait for the\n\t main Kuzzle object to renew once online\n\t */\n\t if (self.kuzzle.state !== 'connected') {\n\t self.callback = notificationCB;\n\t self.onDoneCB = cb;\n\t self.kuzzle.subscriptions.pending[self.id] = self;\n\t return;\n\t }\n\t\n\t if (self.subscribing) {\n\t self.queue.push({action: 'renew', args: [filters, notificationCB, cb]});\n\t return;\n\t }\n\t\n\t self.unsubscribe();\n\t self.roomId = null;\n\t self.subscribing = true;\n\t self.callback = notificationCB;\n\t self.onDoneCB = cb;\n\t self.kuzzle.subscriptions.pending[self.id] = self;\n\t\n\t subscribeQuery.body = self.filters;\n\t subscribeQuery = self.kuzzle.addHeaders(subscribeQuery, this.headers);\n\t\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {volatile: self.volatile}, function (error, response) {\n\t delete self.kuzzle.subscriptions.pending[self.id];\n\t self.subscribing = false;\n\t\n\t if (error) {\n\t self.queue = [];\n\t return cb && cb(new Error('Error during Kuzzle subscription: ' + error.message));\n\t }\n\t\n\t self.lastRenewal = now;\n\t self.roomId = response.result.roomId;\n\t self.channel = response.result.channel;\n\t\n\t if (!self.kuzzle.subscriptions[self.roomId]) {\n\t self.kuzzle.subscriptions[self.roomId] = {};\n\t }\n\t\n\t self.kuzzle.subscriptions[self.roomId][self.id] = self;\n\t\n\t self.notifier = notificationCallback.bind(self);\n\t self.kuzzle.network.on(self.channel, self.notifier);\n\t\n\t dequeue.call(self);\n\t cb && cb(null, self);\n\t });\n\t};\n\t\n\t/**\n\t * Unsubscribes from Kuzzle.\n\t *\n\t * Stop listening immediately. If there is no listener left on that room, sends an unsubscribe request to Kuzzle, once\n\t * pending subscriptions reaches 0, and only if there is still no listener on that room.\n\t * We wait for pending subscriptions to finish to avoid unsubscribing while another subscription on that room is\n\t *\n\t * @return {*} this\n\t */\n\tRoom.prototype.unsubscribe = function () {\n\t var\n\t self = this,\n\t room = self.roomId,\n\t interval;\n\t\n\t if (!isReady.call(this)) {\n\t self.queue.push({action: 'unsubscribe', args: []});\n\t return self;\n\t }\n\t\n\t if (room) {\n\t self.kuzzle.network.off(self.channel, this.notifier);\n\t\n\t if (Object.keys(self.kuzzle.subscriptions[room]).length === 1) {\n\t delete self.kuzzle.subscriptions[room];\n\t\n\t if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n\t } else {\n\t interval = setInterval(function () {\n\t if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n\t if (!self.kuzzle.subscriptions[room]) {\n\t self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n\t }\n\t clearInterval(interval);\n\t }\n\t }, 100);\n\t }\n\t } else {\n\t delete self.kuzzle.subscriptions[room][self.id];\n\t }\n\t\n\t self.roomId = null;\n\t }\n\t\n\t return self;\n\t};\n\t\n\t/**\n\t * Helper function allowing to set headers while chaining calls.\n\t *\n\t * If the replace argument is set to true, replace the current headers with the provided content.\n\t * Otherwise, it appends the content to the current headers, only replacing already existing values\n\t *\n\t * @param content - new headers content\n\t * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n\t */\n\tRoom.prototype.setHeaders = function (content, replace) {\n\t this.kuzzle.setHeaders.call(this, content, replace);\n\t return this;\n\t};\n\t\n\t/**\n\t * Callback called by the network handler when a message is sent to the subscribed room ID\n\t * Calls the registered callback if the notification passes the subscription filters\n\t *\n\t * @param {object} data - data\n\t * @returns {*}\n\t */\n\tfunction notificationCallback (data) {\n\t if (data.error) {\n\t return this.callback(data.error);\n\t }\n\t\n\t if (data.action === 'jwtTokenExpired') {\n\t this.kuzzle.jwtToken = undefined;\n\t return this.kuzzle.emitEvent('jwtTokenExpired');\n\t }\n\t\n\t if (data.controller === 'document' || (data.controller === 'realtime' && data.action === 'publish')) {\n\t data.type = 'document';\n\t data.document = new Document(this.collection, data.result._id, data.result._source);\n\t delete data.result;\n\t }\n\t else if (data.controller === 'realtime') {\n\t data.type = 'user';\n\t data.user = {count: data.result.count};\n\t delete data.result;\n\t }\n\t\n\t if (this.kuzzle.requestHistory[data.requestId]) {\n\t if (this.subscribeToSelf) {\n\t this.callback(null, data);\n\t }\n\t delete this.kuzzle.requestHistory[data.requestId];\n\t } else {\n\t this.callback(null, data);\n\t }\n\t}\n\t\n\t\n\t/**\n\t * Dequeue actions performed while subscription was being renewed\n\t */\n\tfunction dequeue () {\n\t var element;\n\t\n\t while (this.queue.length > 0) {\n\t element = this.queue.shift();\n\t\n\t this[element.action].apply(this, element.args);\n\t }\n\t}\n\t\n\tfunction isReady() {\n\t return this.kuzzle.state === 'connected' && !this.subscribing;\n\t}\n\t\n\tmodule.exports = Room;\n\n\n/***/ },\n/* 12 */\n/***/ function(module, exports) {\n\n\t/**\n\t * @param {Collection} collection\n\t * @param {int} total\n\t * @param {Document[]} documents\n\t * @param {object} aggregations\n\t * @param {object} options\n\t * @param {object} filters\n\t * @param {SearchResult} previous\n\t * @property {Collection} collection\n\t * @property {number} total\n\t * @property {Document[]} documents\n\t * @property {object} aggregations\n\t * @property {object} options\n\t * @property {object} filters\n\t * @property {number} fetchedDocument\n\t * @constructor\n\t */\n\tfunction SearchResult (collection, total, documents, aggregations, options, filters, previous) {\n\t Object.defineProperties(this, {\n\t // read-only properties\n\t collection: {\n\t value: collection,\n\t enumerable: true\n\t },\n\t total: {\n\t value: total,\n\t enumerable: true\n\t },\n\t documents: {\n\t value: documents,\n\t enumerable: true\n\t },\n\t aggregations: {\n\t value: aggregations || {},\n\t enumerable: true\n\t },\n\t options: {\n\t value: options || {},\n\t enumerable: true\n\t },\n\t filters: {\n\t value: filters || {},\n\t enumerable: true\n\t },\n\t // writable properties\n\t fetchedDocument: {\n\t value: previous instanceof SearchResult ? documents.length + previous.fetchedDocument : documents.length,\n\t enumerable: true,\n\t writable: true\n\t }\n\t });\n\t\n\t // promisifying\n\t if (this.collection.kuzzle.bluebird) {\n\t return this.collection.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['fetchNext'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t/**\n\t * @param {function} cb\n\t */\n\tSearchResult.prototype.fetchNext = function (cb) {\n\t var\n\t filters,\n\t options = Object.assign({}, this.options);\n\t \n\t options.previous = this;\n\t\n\t // retrieve next results with scroll if original search use it\n\t if (options.scrollId) {\n\t if (this.fetchedDocument >= this.getTotal()) {\n\t cb(null, null);\n\t return;\n\t }\n\t\n\t // from and size parameters are not valid for a scroll action\n\t if (typeof options.from !== 'undefined') {\n\t delete options.from;\n\t }\n\t\n\t if (options.size) {\n\t delete options.size;\n\t }\n\t\n\t this.collection.scroll(options.scrollId, options, this.filters || {}, cb);\n\t\n\t return;\n\t }\n\t\n\t // retrieve next results with from/size if original search use it\n\t if (options.from !== undefined && options.size !== undefined) {\n\t filters = Object.assign({}, this.filters);\n\t\n\t // check if we need to do next request to fetch all matching documents\n\t options.from += options.size;\n\t\n\t if (options.from >= this.getTotal()) {\n\t cb(null, null);\n\t\n\t return;\n\t }\n\t\n\t this.collection.search(filters, options, cb);\n\t\n\t return;\n\t }\n\t\n\t cb(new Error('Unable to retrieve next results from search: missing scrollId or from/size params'));\n\t};\n\t\n\t/**\n\t * @returns {Document[]}\n\t */\n\tSearchResult.prototype.getDocuments = function () {\n\t return this.documents;\n\t};\n\t\n\t/**\n\t * @returns {number}\n\t */\n\tSearchResult.prototype.getTotal = function () {\n\t return this.total;\n\t};\n\t\n\t/**\n\t * @returns {object}\n\t */\n\tSearchResult.prototype.getAggregations = function () {\n\t return this.aggregations;\n\t};\n\t\n\t/**\n\t * @returns {Object}\n\t */\n\tSearchResult.prototype.getOptions = function() {\n\t return this.options;\n\t};\n\t\n\t/**\n\t * @returns {object}\n\t */\n\tSearchResult.prototype.getFilters = function() {\n\t return this.filters;\n\t};\n\t\n\t/**\n\t * @returns {object}\n\t */\n\tSearchResult.prototype.getCollection = function () {\n\t return this.collection;\n\t};\n\t\n\t/**\n\t * @returns {number}\n\t */\n\tSearchResult.prototype.getFetchedDocument = function () {\n\t return this.fetchedDocument;\n\t};\n\t\n\tmodule.exports = SearchResult;\n\n\n/***/ },\n/* 13 */\n/***/ function(module, exports) {\n\n\t/**\n\t * Sugar-code handling the result of a Room.renew call\n\t * @constructor\n\t */\n\tfunction SubscribeResult() {\n\t this.cbs = [];\n\t this.error = null;\n\t this.room = null;\n\t}\n\t\n\t/**\n\t * Registers a callback to be called with a subscription result\n\t * @param {Function} cb\n\t */\n\tSubscribeResult.prototype.onDone = function (cb) {\n\t if (this.error || this.room) {\n\t cb(this.error, this.room);\n\t }\n\t else {\n\t this.cbs.push(cb);\n\t }\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Calls all registered callbacks\n\t *\n\t * @param {Object} error object\n\t * @param {Room} room\n\t */\n\tSubscribeResult.prototype.done = function (error, room) {\n\t this.error = error;\n\t this.room = room;\n\t\n\t this.cbs.forEach(function (cb) {\n\t cb(error, room);\n\t });\n\t};\n\t\n\tmodule.exports = SubscribeResult;\n\n\n/***/ },\n/* 14 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/**\n\t *\n\t * @param host\n\t * @param port\n\t * @param sslConnection\n\t * @returns {Object} tnstantiated WebSocket/Socket.IO object\n\t */\n\t\n\tfunction network(host, port, sslConnection) {\n\t // Web browser / NodeJS websocket handling\n\t if (typeof window !== 'undefined') {\n\t // use native websockets if the browser supports it\n\t if (typeof WebSocket !== 'undefined') {\n\t return new (__webpack_require__(3))(host, port, sslConnection);\n\t }\n\t // otherwise fallback to socket.io, if available\n\t else if (window.io) {\n\t return new (__webpack_require__(15))(host, port, sslConnection);\n\t }\n\t\n\t throw new Error('Aborting: no websocket support detected and no socket.io library loaded either.');\n\t }\n\t\n\t return new (__webpack_require__(3))(host, port, sslConnection);\n\t}\n\t\n\tmodule.exports = network;\n\n\n/***/ },\n/* 15 */\n/***/ function(module, exports) {\n\n\tfunction SocketIO(host, port, ssl) {\n\t this.host = host;\n\t this.port = port;\n\t this.ssl = ssl;\n\t this.socket = null;\n\t\n\t /**\n\t * Creates a new socket from the provided arguments\n\t *\n\t * @constructor\n\t * @param {boolean} autoReconnect\n\t * @param {int} reconnectionDelay\n\t */\n\t this.connect = function (autoReconnect, reconnectionDelay) {\n\t this.socket = window.io((this.ssl ? 'https://' : 'http://') + this.host + ':' + this.port, {\n\t reconnection: autoReconnect,\n\t reconnectionDelay: reconnectionDelay,\n\t forceNew: true\n\t });\n\t };\n\t\n\t /**\n\t * Fires the provided callback whence a connection is established\n\t *\n\t * @param {function} callback\n\t */\n\t this.onConnect = function (callback) {\n\t this.socket.on('connect', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection error is received\n\t * @param {function} callback\n\t */\n\t this.onConnectError = function (callback) {\n\t this.socket.on('connect_error', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a disconnection occurred\n\t * @param {function} callback\n\t */\n\t this.onDisconnect = function (callback) {\n\t this.socket.on('disconnect', callback);\n\t };\n\t\n\t /**\n\t * Fires the provided callback whenever a connection has been reestablished\n\t * @param {function} callback\n\t */\n\t this.onReconnect = function (callback) {\n\t this.socket.on('reconnect', callback);\n\t };\n\t\n\t /**\n\t * Registers a callback on a room. Once 1 message is received, fires the\n\t * callback and unregister it afterward.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.once = function (roomId, callback) {\n\t this.socket.once(roomId, callback);\n\t };\n\t\n\t /**\n\t * Registers a callback on a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.on = function (roomId, callback) {\n\t this.socket.on(roomId, callback);\n\t };\n\t\n\t /**\n\t * Unregisters a callback from a room.\n\t *\n\t * @param {string} roomId\n\t * @param {function} callback\n\t */\n\t this.off = function (roomId, callback) {\n\t this.socket.off(roomId, callback);\n\t };\n\t\n\t\n\t /**\n\t * Sends a payload to the connected server\n\t *\n\t * @param {Object} payload\n\t */\n\t this.send = function (payload) {\n\t this.socket.emit('kuzzle', payload);\n\t };\n\t\n\t /**\n\t * Closes the connection\n\t */\n\t this.close = function () {\n\t this.socket.close();\n\t this.socket = null;\n\t };\n\t}\n\t\n\tmodule.exports = SocketIO;\n\n\n/***/ },\n/* 16 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar SecurityDocument = __webpack_require__(1);\n\t\n\tfunction Profile(Security, id, content) {\n\t\n\t SecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteProfile'\n\t },\n\t updateActionName: {\n\t value: 'updateProfile'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['hydrate', 'save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t}\n\t\n\tProfile.prototype = Object.create(SecurityDocument.prototype, {\n\t constructor: {\n\t value: Profile\n\t }\n\t});\n\t\n\t/**\n\t * Persist to the persistent layer the current profile\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.save = function (options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!this.content.policies) {\n\t throw new Error('Argument \"policies\" is mandatory in a profile. This argument contains an array of objects.');\n\t }\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = this.serialize();\n\t\n\t self.kuzzle.query(self.Security.buildQueryArgs('createOrReplaceProfile'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return self;\n\t};\n\t\n\t\n\t/**\n\t * Add a policy in the policies list\n\t * @param {Object} policy - must be an object containing at least a \"roleId\" member which must be a string.\n\t *\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.addPolicy = function (policy) {\n\t\n\t if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n\t throw new Error('Parameter \"policies\" must be an object containing at least a \"roleId\" member which must be a string.');\n\t }\n\t\n\t if (!this.content.policies) {\n\t this.content.policies = [];\n\t }\n\t\n\t this.content.policies.push(policy);\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Set policies list\n\t * @param {Array} policies - must be an array of objects containing at least a \"roleId\" member which must be a string\n\t *\n\t * @returns {Profile} this\n\t */\n\tProfile.prototype.setPolicies = function (policies) {\n\t\n\t if (!Array.isArray(policies)) {\n\t throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n\t }\n\t\n\t policies.map(function (policy) {\n\t if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n\t throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n\t }\n\t });\n\t\n\t this.content.policies = policies;\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Serialize this object into a JSON object\n\t *\n\t * @return {object} JSON object representing this securityDocument\n\t */\n\tProfile.prototype.serialize = function () {\n\t var\n\t data = {};\n\t\n\t if (this.id) {\n\t data._id = this.id;\n\t }\n\t\n\t data.body = this.content;\n\t\n\t return data;\n\t};\n\t\n\t/**\n\t * Returns the list of policies associated to this profile.\n\t * Each policy element is an array of objects containing at least a \"roleId\" member which must be a string\n\t *\n\t * @return {object} an array of policies\n\t */\n\tProfile.prototype.getPolicies = function () {\n\t return this.content.policies;\n\t};\n\t\n\tmodule.exports = Profile;\n\n\n/***/ },\n/* 17 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar SecurityDocument = __webpack_require__(1);\n\t\n\tfunction Role(Security, id, content) {\n\t\n\t SecurityDocument.call(this, Security, id, content);\n\t\n\t // Define properties\n\t Object.defineProperties(this, {\n\t // private properties\n\t deleteActionName: {\n\t value: 'deleteRole'\n\t },\n\t updateActionName: {\n\t value: 'updateRole'\n\t }\n\t });\n\t\n\t // promisifying\n\t if (Security.kuzzle.bluebird) {\n\t return Security.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var whitelist = ['save'];\n\t\n\t return passes && whitelist.indexOf(name) !== -1;\n\t }\n\t });\n\t }\n\t\n\t}\n\t\n\tRole.prototype = Object.create(SecurityDocument.prototype, {\n\t constructor: {\n\t value: Role\n\t }\n\t});\n\t\n\t/**\n\t * Saves this role into Kuzzle.\n\t *\n\t * If this is a new role, this function will create it in Kuzzle.\n\t * Otherwise, this method will replace the latest version of this role in Kuzzle by the current content\n\t * of this object.\n\t *\n\t * @param {object} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Role} this object\n\t */\n\tRole.prototype.save = function (options, cb) {\n\t var\n\t data = this.serialize(),\n\t self = this;\n\t\n\t if (options && cb === undefined && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceRole'), data, options, cb && function (error) {\n\t cb(error, error ? undefined : self);\n\t });\n\t\n\t return this;\n\t};\n\t\n\tmodule.exports = Role;\n\n\n/***/ },\n/* 18 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar\n\t Role = __webpack_require__(17),\n\t Profile = __webpack_require__(16),\n\t User = __webpack_require__(4);\n\t\n\t/**\n\t * Kuzzle security constructor\n\t *\n\t * @param kuzzle\n\t * @returns {Security}\n\t * @constructor\n\t */\n\tfunction Security(kuzzle) {\n\t\n\t Object.defineProperty(this, 'kuzzle', {\n\t value: kuzzle\n\t });\n\t\n\t Object.defineProperty(this, 'buildQueryArgs', {\n\t value: function (action) {\n\t return {\n\t controller: 'security',\n\t action: action\n\t };\n\t }\n\t });\n\t\n\t if (this.kuzzle.bluebird) {\n\t return this.kuzzle.bluebird.promisifyAll(this, {\n\t suffix: 'Promise',\n\t filter: function (name, func, target, passes) {\n\t var blacklist = ['role', 'profile', 'user', 'isActionAllowed'];\n\t\n\t return passes && blacklist.indexOf(name) === -1;\n\t }\n\t });\n\t }\n\t\n\t return this;\n\t}\n\t\n\t\n\t/**\n\t * Retrieve a single Role using its unique role ID.\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchRole = function (id, options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!id) {\n\t throw new Error('Id parameter is mandatory for fetchRole function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data = {_id: id};\n\t\n\t self.kuzzle.callbackRequired('Security.fetchRole', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getRole'), data, options, function (err, response) {\n\t cb(err, err ? undefined : new Role(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on roles according to a filter\n\t *\n\t * /!\\ There is a small delay between role creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a role that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - this object can contains an array `indexes` with a list of index id, a integer `from` and a integer `size`\n\t * @param {object|responseCallback} [options] - Optional parameters\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t *\n\t */\n\tSecurity.prototype.searchRoles = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchRoles', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchRoles'), {body: filters}, options, function (error, result) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = result.result.hits.map(function (doc) {\n\t return new Role(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: result.result.total, roles: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new role in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same role already exists: throw an error if sets to false.\n\t * Replace the existing role otherwise\n\t *\n\t * @param {string} id - role identifier\n\t * @param {object} content - a plain javascript object representing the role\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createRole = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'createRole';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createRole: cannot create a role without a role ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceRole' : 'createRole';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new Role(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update a role in Kuzzle.\n\t *\n\t * @param {string} id - role identifier\n\t * @param {object} content - a plain javascript object representing the role's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateRole = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content},\n\t action = 'updateRole';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateRole: cannot update a role without a role ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err) {\n\t cb(err, err ? undefined : new Role(self, id, content));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete role.\n\t *\n\t * There is a small delay between role deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a role that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Role id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteRole = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteRole'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new Role object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - role id\n\t * @param {object} content - role content\n\t * @constructor\n\t */\n\tSecurity.prototype.role = function(id, content) {\n\t return new Role(this, id, content);\n\t};\n\t\n\t\n\t/**\n\t * Get a specific profile from kuzzle\n\t *\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} cb - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchProfile = function (id, options, cb) {\n\t var\n\t data,\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Id parameter is mandatory for fetchProfile function');\n\t }\n\t\n\t\n\t data = {_id: id};\n\t\n\t self.kuzzle.callbackRequired('Security.fetchProfile', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getProfile'), data, options, function (error, response) {\n\t cb(error, error ? undefined : new Profile(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on profiles according to a filter\n\t *\n\t *\n\t * /!\\ There is a small delay between profile creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a profile that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - this object can contains an array `roles` with a list of roles id, a integer `from` and a integer `size`\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.searchProfiles = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchProfiles', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchProfiles'), {body: filters}, options, function (error, response) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = response.result.hits.map(function (doc) {\n\t return new Profile(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: response.result.total, profiles: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new profile in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same profile already exists: throw an error if sets to false.\n\t * Replace the existing profile otherwise\n\t *\n\t * @param {string} id - profile identifier\n\t * @param {object} content - attribute `roles` in `content` must only contains an array of role id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createProfile = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'createProfile';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createProfile: cannot create a profile without a profile ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceProfile' : 'createProfile';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new Profile(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update a profile in Kuzzle.\n\t *\n\t * @param {string} id - profile identifier\n\t * @param {object} content - a plain javascript object representing the profile's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateProfile = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'updateProfile';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateProfile: cannot update a profile without a profile ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t var updatedContent = {};\n\t\n\t if (err) {\n\t return cb(err);\n\t }\n\t\n\t Object.keys(res.result._source).forEach(function (property) {\n\t updatedContent[property] = res.result._source[property];\n\t });\n\t\n\t cb(null, new Profile(self, res.result._id, updatedContent));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete profile.\n\t *\n\t * There is a small delay between profile deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a profile that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Profile id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteProfile = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteProfile'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new Profile object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - profile id\n\t * @param {object} content - profile content\n\t * @constructor\n\t */\n\tSecurity.prototype.profile = function(id, content) {\n\t return new Profile(this, id, content);\n\t};\n\t\n\t/**\n\t * Get a specific user from kuzzle using its unique ID\n\t *\n\t * @param {string} id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} cb - returns Kuzzle's response\n\t */\n\tSecurity.prototype.fetchUser = function (id, options, cb) {\n\t var\n\t data = {_id: id},\n\t self = this;\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Id parameter is mandatory for fetchUser function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.fetchUser', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('getUser'), data, options, function (err, response) {\n\t cb(err, err ? undefined : new User(self, response.result._id, response.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Executes a search on user according to a filter\n\t *\n\t * /!\\ There is a small delay between user creation and their existence in our persistent search layer,\n\t * usually a couple of seconds.\n\t * That means that a user that was just been created won’t be returned by this function.\n\t *\n\t * @param {Object} filters - same filters as documents filters\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - returns Kuzzle's response\n\t */\n\tSecurity.prototype.searchUsers = function (filters, options, cb) {\n\t var\n\t self = this;\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Security.searchUsers', cb);\n\t\n\t self.kuzzle.query(this.buildQueryArgs('searchUsers'), {body: filters}, options, function (error, response) {\n\t var documents;\n\t\n\t if (error) {\n\t return cb(error);\n\t }\n\t\n\t documents = response.result.hits.map(function (doc) {\n\t return new User(self, doc._id, doc._source);\n\t });\n\t\n\t cb(null, { total: response.result.total, users: documents });\n\t });\n\t};\n\t\n\t/**\n\t * Create a new user in Kuzzle.\n\t *\n\t * Takes an optional argument object with the following property:\n\t * - replaceIfExist (boolean, default: false):\n\t * If the same user already exists: throw an error if sets to false.\n\t * Replace the existing user otherwise\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content},\n\t action = 'createUser';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createUser: cannot create a user without a user ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t if (options) {\n\t action = options.replaceIfExist ? 'createOrReplaceUser' : 'createUser';\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, null, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t/**\n\t * Create a new restricted user in Kuzzle.\n\t *\n\t * This function will create a new user. It is not usable to update an existing user.\n\t * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - attribute `profile` in `content` must only contains the profile id\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t */\n\tSecurity.prototype.createRestrictedUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {_id: id, body: content};\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.createRestrictedUser: cannot create a user without a user ID');\n\t }\n\t\n\t if (content.profileIds) {\n\t throw new Error('Security.createRestrictedUser: cannot provide profileIds');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.query(this.buildQueryArgs('createRestrictedUser'), data, null, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t};\n\t\n\t\n\t/**\n\t * Update an user in Kuzzle.\n\t *\n\t * @param {string} id - user identifier\n\t * @param {object} content - a plain javascript object representing the user's modification\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - (optional) Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.updateUser = function (id, content, options, cb) {\n\t var\n\t self = this,\n\t data = {},\n\t action = 'updateUser';\n\t\n\t if (!id || typeof id !== 'string') {\n\t throw new Error('Security.updateUser: cannot update an user without an user ID');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t data._id = id;\n\t data.body = content;\n\t\n\t self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Delete user.\n\t *\n\t * There is a small delay between user deletion and their deletion in our advanced search layer,\n\t * usually a couple of seconds.\n\t * That means that a user that was just been delete will be returned by this function\n\t *\n\t *\n\t * @param {string} id - Profile id to delete\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {responseCallback} [cb] - Handles the query response\n\t * @returns {Security} this object\n\t */\n\tSecurity.prototype.deleteUser = function (id, options, cb) {\n\t var data = {_id: id};\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t this.kuzzle.query(this.buildQueryArgs('deleteUser'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result._id);\n\t });\n\t\n\t return this;\n\t};\n\t\n\t/**\n\t * Instantiate a new User object. Workaround to the module.exports limitation, preventing multiple\n\t * constructors to be exposed without having to use a factory or a composed object.\n\t *\n\t * @param {string} id - user id\n\t * @param {object} content - user content\n\t * @constructor\n\t */\n\tSecurity.prototype.user = function(id, content) {\n\t return new User(this, id, content);\n\t};\n\t\n\t/**\n\t * Tells whether an action is allowed, denied or conditional based on the rights\n\t * rights provided as the first argument. An action is defined as a couple of\n\t * action and controller (mandatory), plus an index and a collection(optional).\n\t *\n\t * @param {object} rights - The rights rights associated to a user\n\t * (see getMyrights and getUserrights).\n\t * @param {string} controller - The controller to check the action onto.\n\t * @param {string} action - The action to perform.\n\t * @param {string} index - (optional) The name of index to perform the action onto.\n\t * @param {string} collection - (optional) The name of the collection to perform the action onto.\n\t *\n\t * @returns {string} ['allowed', 'denied', 'conditional'] where conditional cases\n\t * correspond to rights containing closures.\n\t * See also http://kuzzle.io/guide/#roles-definition\n\t */\n\tSecurity.prototype.isActionAllowed = function(rights, controller, action, index, collection) {\n\t var filteredRights;\n\t\n\t if (!rights || typeof rights !== 'object') {\n\t throw new Error('rights parameter is mandatory for isActionAllowed function');\n\t }\n\t if (!controller || typeof controller !== 'string') {\n\t throw new Error('controller parameter is mandatory for isActionAllowed function');\n\t }\n\t if (!action || typeof action !== 'string') {\n\t throw new Error('action parameter is mandatory for isActionAllowed function');\n\t }\n\t\n\t // We filter in all the rights that match the request (including wildcards).\n\t filteredRights = rights\n\t .filter(function (right) {\n\t return right.controller === controller || right.controller === '*';\n\t })\n\t .filter(function (right) {\n\t return right.action === action || right.action === '*';\n\t })\n\t .filter(function (right) {\n\t return right.index === index || right.index === '*';\n\t })\n\t .filter(function (right) {\n\t return right.collection === collection || right.collection === '*';\n\t });\n\t\n\t // Then, if at least one right allows the action, we return 'allowed'\n\t if (filteredRights.some(function (item) { return item.value === 'allowed'; })) {\n\t return 'allowed';\n\t }\n\t // If no right allows the action, we check for conditionals.\n\t if (filteredRights.some(function (item) { return item.value === 'conditional'; })) {\n\t return 'conditional';\n\t }\n\t // Otherwise we return 'denied'.\n\t return 'denied';\n\t};\n\t\n\t\n\t/**\n\t * Gets the rights array of a given user.\n\t *\n\t * @param {string} userId The id of the user.\n\t * @param {object|responseCallback} [options] - (optional) arguments\n\t * @param {function} cb The callback containing the normalized array of rights.\n\t */\n\tSecurity.prototype.getUserRights = function (userId, options, cb) {\n\t var\n\t data = {_id: userId},\n\t self = this;\n\t\n\t if (!userId || typeof userId !== 'string') {\n\t throw new Error('userId parameter is mandatory for getUserRights function');\n\t }\n\t\n\t if (!cb && typeof options === 'function') {\n\t cb = options;\n\t options = null;\n\t }\n\t\n\t self.kuzzle.callbackRequired('Kuzzle.getUserRights', cb);\n\t\n\t this.kuzzle.query(this.buildQueryArgs('getUserRights'), data, options, cb && function (err, res) {\n\t cb(err, err ? undefined : res.result.hits);\n\t });\n\t};\n\t\n\tmodule.exports = Security;\n\n\n/***/ },\n/* 19 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t// Unique ID creation requires a high quality random # generator. We feature\n\t// detect to determine the best RNG source, normalizing to a function that\n\t// returns 128-bits of randomness, since that's what's usually required\n\tvar rng = __webpack_require__(7);\n\tvar bytesToUuid = __webpack_require__(6);\n\t\n\t// **`v1()` - Generate time-based UUID**\n\t//\n\t// Inspired by https://github.com/LiosK/UUID.js\n\t// and http://docs.python.org/library/uuid.html\n\t\n\t// random #'s we need to init node and clockseq\n\tvar _seedBytes = rng();\n\t\n\t// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n\tvar _nodeId = [\n\t _seedBytes[0] | 0x01,\n\t _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]\n\t];\n\t\n\t// Per 4.2.2, randomize (14 bit) clockseq\n\tvar _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;\n\t\n\t// Previous uuid creation time\n\tvar _lastMSecs = 0, _lastNSecs = 0;\n\t\n\t// See https://github.com/broofa/node-uuid for API details\n\tfunction v1(options, buf, offset) {\n\t var i = buf && offset || 0;\n\t var b = buf || [];\n\t\n\t options = options || {};\n\t\n\t var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\t\n\t // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n\t // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n\t // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n\t // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n\t var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\t\n\t // Per 4.2.1.2, use count of uuid's generated during the current clock\n\t // cycle to simulate higher resolution clock\n\t var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\t\n\t // Time since last uuid creation (in msecs)\n\t var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\t\n\t // Per 4.2.1.2, Bump clockseq on clock regression\n\t if (dt < 0 && options.clockseq === undefined) {\n\t clockseq = clockseq + 1 & 0x3fff;\n\t }\n\t\n\t // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n\t // time interval\n\t if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n\t nsecs = 0;\n\t }\n\t\n\t // Per 4.2.1.2 Throw error if too many uuids are requested\n\t if (nsecs >= 10000) {\n\t throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n\t }\n\t\n\t _lastMSecs = msecs;\n\t _lastNSecs = nsecs;\n\t _clockseq = clockseq;\n\t\n\t // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n\t msecs += 12219292800000;\n\t\n\t // `time_low`\n\t var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n\t b[i++] = tl >>> 24 & 0xff;\n\t b[i++] = tl >>> 16 & 0xff;\n\t b[i++] = tl >>> 8 & 0xff;\n\t b[i++] = tl & 0xff;\n\t\n\t // `time_mid`\n\t var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n\t b[i++] = tmh >>> 8 & 0xff;\n\t b[i++] = tmh & 0xff;\n\t\n\t // `time_high_and_version`\n\t b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n\t b[i++] = tmh >>> 16 & 0xff;\n\t\n\t // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n\t b[i++] = clockseq >>> 8 | 0x80;\n\t\n\t // `clock_seq_low`\n\t b[i++] = clockseq & 0xff;\n\t\n\t // `node`\n\t var node = options.node || _nodeId;\n\t for (var n = 0; n < 6; ++n) {\n\t b[i + n] = node[n];\n\t }\n\t\n\t return buf ? buf : bytesToUuid(b);\n\t}\n\t\n\tmodule.exports = v1;\n\n\n/***/ },\n/* 20 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar rng = __webpack_require__(7);\n\tvar bytesToUuid = __webpack_require__(6);\n\t\n\tfunction v4(options, buf, offset) {\n\t var i = buf && offset || 0;\n\t\n\t if (typeof(options) == 'string') {\n\t buf = options == 'binary' ? new Array(16) : null;\n\t options = null;\n\t }\n\t options = options || {};\n\t\n\t var rnds = options.random || (options.rng || rng)();\n\t\n\t // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\t rnds[6] = (rnds[6] & 0x0f) | 0x40;\n\t rnds[8] = (rnds[8] & 0x3f) | 0x80;\n\t\n\t // Copy bytes to buffer, if provided\n\t if (buf) {\n\t for (var ii = 0; ii < 16; ++ii) {\n\t buf[i + ii] = rnds[ii];\n\t }\n\t }\n\t\n\t return buf || bytesToUuid(rnds);\n\t}\n\t\n\tmodule.exports = v4;\n\n\n/***/ }\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// kuzzle.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap f340330cbc588882f8a5","var\n uuid = require('uuid'),\n Collection = require('./Collection.js'),\n Security = require('./security/Security'),\n MemoryStorage = require('./MemoryStorage'),\n User = require('./security/User'),\n networkWrapper = require('./networkWrapper');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * Kuzzle object constructor.\n *\n * @constructor\n * @param host - Server name or IP Address to the Kuzzle instance\n * @param [options] - Connection options\n * @param {responseCallback} [cb] - Handles connection response\n * @constructor\n */\nfunction Kuzzle (host, options, cb) {\n var self = this;\n\n if (!(this instanceof Kuzzle)) {\n return new Kuzzle(host, options, cb);\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!host || host === '') {\n throw new Error('host argument missing');\n }\n\n Object.defineProperties(this, {\n // 'private' properties\n collections: {\n value: {},\n writable: true\n },\n connectCB: {\n value: cb\n },\n eventListeners: {\n value: {\n connected: {lastEmitted: null, listeners: []},\n error: {lastEmitted: null, listeners: []},\n disconnected: {lastEmitted: null, listeners: []},\n reconnected: {lastEmitted: null, listeners: []},\n jwtTokenExpired: {lastEmitted: null, listeners: []},\n loginAttempt: {lastEmitted: null, listeners: []},\n offlineQueuePush: {listeners: []},\n offlineQueuePop: {listeners: []},\n queryError: {listeners: []},\n discarded: {listeners: []}\n }\n },\n eventTimeout: {\n value: 200\n },\n queuing: {\n value: false,\n writable: true\n },\n requestHistory: {\n value: {},\n writable: true\n },\n state: {\n value: 'initializing',\n writable: true\n },\n subscriptions: {\n /*\n Contains the centralized subscription list in the following format:\n pending: \n 'roomId': {\n kuzzleRoomID_1: kuzzleRoomInstance_1,\n kuzzleRoomID_2: kuzzleRoomInstance_2,\n kuzzleRoomID_...: kuzzleRoomInstance_...\n }\n\n This was made to allow multiple subscriptions on the same set of filters, something that Kuzzle does not permit.\n This structure also allows renewing subscriptions after a connection loss\n */\n value: {\n pending: {}\n },\n writable: true\n },\n // configuration properties\n autoReconnect: {\n value: (options && typeof options.autoReconnect === 'boolean') ? options.autoReconnect : true,\n writable: true,\n enumerable: true\n },\n defaultIndex: {\n value: (options && typeof options.defaultIndex === 'string') ? options.defaultIndex : undefined,\n writable: true,\n enumerable: true\n },\n reconnectionDelay: {\n value: (options && typeof options.reconnectionDelay === 'number') ? options.reconnectionDelay : 1000,\n writable: true,\n enumerable: true\n },\n host: {\n value: host,\n writable: true,\n enumerable: true\n },\n port: {\n value: (options && typeof options.port === 'number') ? options.port : 7512,\n enumerable: true,\n writable: true\n },\n sslConnection: {\n value: (options && typeof options.sslConnection === 'boolean') ? options.sslConnection : false,\n writable: true,\n enumerable: true\n },\n autoQueue: {\n value: false,\n enumerable: true,\n writable: true\n },\n autoReplay: {\n value: false,\n enumerable: true,\n writable: true\n },\n autoResubscribe: {\n value: true,\n enumerable: true,\n writable: true\n },\n headers: {\n value: {},\n enumerable: true,\n writable: true\n },\n volatile: {\n value: {},\n enumerable: true,\n writable: true\n },\n /*\n Offline queue use the following format:\n [\n {\n ts: ,\n query: 'query',\n cb: callbackFunction\n }\n ]\n */\n offlineQueue: {\n value: [],\n enumerable: true,\n writable: true\n },\n queueFilter: {\n value: null,\n enumerable: true,\n writable: true\n },\n queueMaxSize: {\n value: 500,\n enumerable: true,\n writable: true\n },\n queueTTL: {\n value: 120000,\n enumerable: true,\n writable: true\n },\n replayInterval: {\n value: 10,\n enumerable: true,\n writable: true\n },\n jwtToken: {\n value: undefined,\n enumerable: true,\n writable: true\n },\n offlineQueueLoader: {\n value: null,\n enumerable: true,\n writable: true\n }\n });\n\n if (options) {\n Object.keys(options).forEach(function (opt) {\n if (self.hasOwnProperty(opt) && Object.getOwnPropertyDescriptor(self, opt).writable) {\n self[opt] = options[opt];\n }\n });\n\n if (options.offlineMode === 'auto' && this.autoReconnect) {\n this.autoQueue = this.autoReplay = this.autoResubscribe = true;\n }\n }\n\n // Helper function ensuring that this Kuzzle object is still valid before performing a query\n Object.defineProperty(this, 'isValid', {\n value: function () {\n if (self.state === 'disconnected') {\n throw new Error('This Kuzzle object has been invalidated. Did you try to access it after a disconnect call?');\n }\n }\n });\n\n // Helper function copying headers to the query data\n Object.defineProperty(this, 'addHeaders', {\n value: function (query, headers) {\n Object.keys(headers).forEach(function (header) {\n if (!query[header]) {\n query[header] = headers[header];\n }\n });\n\n return query;\n }\n });\n\n /**\n * Some methods (mainly read queries) require a callback function. This function exists to avoid repetition of code,\n * and is called by these methods\n */\n Object.defineProperty(this, 'callbackRequired', {\n value: function (errorMessagePrefix, callback) {\n if (!callback || typeof callback !== 'function') {\n throw new Error(errorMessagePrefix + ': a callback argument is required for read queries');\n }\n }\n });\n\n /**\n * Create an attribute security that embed all methods to manage Role, Profile and User\n */\n Object.defineProperty(this, 'security', {\n value: new Security(this),\n enumerable: true\n });\n\n /**\n * Emit an event to all registered listeners\n * An event cannot be emitted multiple times before a timeout has been reached.\n */\n Object.defineProperty(this, 'emitEvent', {\n value: function emitEvent(event) {\n var\n now = Date.now(),\n args = Array.prototype.slice.call(arguments, 1),\n eventProperties = this.eventListeners[event];\n\n if (eventProperties.lastEmitted && eventProperties.lastEmitted >= now - this.eventTimeout) {\n return false;\n }\n\n eventProperties.listeners.forEach(function (listener) {\n setTimeout(function () {\n listener.fn.apply(undefined, args);\n }, 0);\n });\n\n // Events without the 'lastEmitted' property can be emitted without minimum time between emissions\n if (eventProperties.lastEmitted !== undefined) {\n eventProperties.lastEmitted = now;\n }\n }\n });\n\n Object.defineProperty(this, 'memoryStorage', {\n value: new MemoryStorage(this),\n enumerable: true\n });\n\n\n if (!options || !options.connect || options.connect === 'auto') {\n this.connect();\n } else {\n this.state = 'ready';\n }\n\n cleanHistory(this.requestHistory);\n\n if (this.bluebird) {\n return this.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['getAllStatistics', 'getServerInfo', 'getStatistics',\n 'listCollections', 'listIndexes', 'login', 'logout', 'now', 'query',\n 'checkToken', 'whoAmI', 'updateSelf', 'getMyRights',\n 'refreshIndex', 'getAutoRefresh', 'setAutoRefresh'\n ];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\n/**\n * Connects to a Kuzzle instance using the provided host name.\n * @returns {Object} this\n */\nKuzzle.prototype.connect = function () {\n var self = this;\n\n if (self.network) {\n self.disconnect();\n }\n\n self.network = networkWrapper(self.host, self.port, self.sslConnection);\n\n if (['initializing', 'ready', 'disconnected', 'error', 'offline'].indexOf(this.state) === -1) {\n if (self.connectCB) {\n self.connectCB(null, self);\n }\n return self;\n }\n\n self.state = 'connecting';\n self.network.connect(self.autoReconnect, self.reconnectionDelay);\n\n self.network.onConnect(function () {\n self.state = 'connected';\n renewAllSubscriptions.call(self);\n dequeue.call(self);\n self.emitEvent('connected');\n\n if (self.connectCB) {\n self.connectCB(null, self);\n }\n });\n\n self.network.on('discarded', function (data) {\n self.emitEvent('discarded', data);\n });\n\n self.network.onConnectError(function (error) {\n var connectionError = new Error('Unable to connect to kuzzle proxy server at \"' + self.host + '\"');\n\n connectionError.internal = error;\n self.state = 'error';\n self.emitEvent('error', connectionError);\n\n if (self.connectCB) {\n self.connectCB(connectionError);\n }\n });\n\n self.network.onDisconnect(function () {\n self.state = 'offline';\n\n if (!self.autoReconnect) {\n self.disconnect();\n }\n\n if (self.autoQueue) {\n self.queuing = true;\n }\n\n self.emitEvent('disconnected');\n });\n\n self.network.onReconnect(function () {\n var reconnect = function () {\n // renew subscriptions\n if (self.autoResubscribe) {\n renewAllSubscriptions.call(self);\n }\n\n // replay queued requests\n if (self.autoReplay) {\n cleanQueue.call(self);\n dequeue.call(self);\n }\n\n // alert listeners\n self.emitEvent('reconnected');\n };\n\n self.state = 'connected';\n\n if (self.jwtToken) {\n self.checkToken(self.jwtToken, function (err, res) {\n // shouldn't obtain an error but let's invalidate the token anyway\n if (err || !res.valid) {\n self.jwtToken = undefined;\n self.emitEvent('jwtTokenExpired');\n }\n\n reconnect();\n });\n } else {\n reconnect();\n }\n });\n\n return this;\n};\n\n/**\n * Set the jwtToken used to query kuzzle\n * @param token\n * @returns {Kuzzle}\n */\nKuzzle.prototype.setJwtToken = function(token) {\n if (typeof token === 'string') {\n this.jwtToken = token;\n } else if (typeof token === 'object') {\n if (token.result && token.result.jwt && typeof token.result.jwt === 'string') {\n this.jwtToken = token.result.jwt;\n } else {\n this.emitEvent('loginAttempt', {\n success: false,\n error: 'Cannot find a valid JWT token in the following object: ' + JSON.stringify(token)\n });\n\n return this;\n }\n } else {\n this.emitEvent('loginAttempt', {success: false, error: 'Invalid token argument: ' + token});\n return this;\n }\n\n renewAllSubscriptions.call(this);\n this.emitEvent('loginAttempt', {success: true});\n return this;\n};\n\n/**\n * Unset the jwtToken used to query kuzzle\n * @returns {Kuzzle}\n */\nKuzzle.prototype.unsetJwtToken = function() {\n this.jwtToken = undefined;\n\n removeAllSubscriptions.call(this);\n\n return this;\n};\n\n/**\n * Get the jwtToken used by kuzzle\n * @returns {Kuzzle}\n */\nKuzzle.prototype.getJwtToken = function() {\n return this.jwtToken;\n};\n\n/**\n * Send login request to kuzzle with credentials\n * If login success, store the jwtToken into kuzzle object\n *\n * @param strategy\n * @param credentials\n * @param expiresIn\n * @param cb\n */\nKuzzle.prototype.login = function (strategy) {\n var\n self = this,\n request = {\n strategy: strategy\n },\n credentials,\n cb = null;\n\n // Handle arguments (credentials, expiresIn, cb)\n if (arguments[1]) {\n if (typeof arguments[1] === 'object') {\n credentials = arguments[1];\n } else if (typeof arguments[1] === 'number' || typeof arguments[1] === 'string') {\n request.expiresIn = arguments[1];\n } else if (typeof arguments[1] === 'function') {\n cb = arguments[1];\n }\n }\n if (arguments[2]) {\n if (typeof arguments[2] === 'number' || typeof arguments[2] === 'string') {\n request.expiresIn = arguments[2];\n } else if (typeof arguments[2] === 'function') {\n cb = arguments[2];\n }\n }\n if (arguments[3] && typeof arguments[3] === 'function') {\n cb = arguments[3];\n }\n\n if (typeof credentials === 'object') {\n Object.keys(credentials).forEach(function (key) {\n request[key] = credentials[key];\n });\n }\n\n this.query({controller: 'auth', action: 'login'}, {body: request}, {queuable: false}, function(error, response) {\n if (!error) {\n if (response.result.jwt) {\n self.setJwtToken(response.result.jwt);\n }\n\n cb && cb(null, response.result);\n }\n else {\n cb && cb(error);\n self.emitEvent('loginAttempt', {success: false, error: error.message});\n }\n });\n};\n\n/**\n * Create a kuzzle index\n *\n * @param {string} index\n * @param {object} [options]\n * @param {responseCallback} cb\n * @returns {Kuzzle}\n */\nKuzzle.prototype.createIndex = function (index, options, cb) {\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.createIndex: index required');\n }\n index = this.defaultIndex;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.query({controller: 'index', action: 'create'}, {index: index}, options, typeof cb !== 'function' ? null : cb);\n\n return this;\n};\n\n/**\n * Send logout request to kuzzle with jwtToken.\n *\n * @param cb\n * @returns {Kuzzle}\n */\nKuzzle.prototype.logout = function (cb) {\n var\n self = this,\n request = {\n action: 'logout',\n controller: 'auth',\n requestId: uuid.v4(),\n body: {}\n };\n\n this.query({controller: 'auth', action: 'logout'}, request, {queuable: false}, typeof cb !== 'function' ? null : function(error) {\n cb(error, self);\n });\n\n self.unsetJwtToken();\n\n return self;\n};\n\n/**\n * Checks whether a given jwt token still represents a valid session in Kuzzle.\n *\n * @param {string} token The jwt token to check\n * @param {function} callback The callback to be called when the response is\n * available. The signature is `function(error, response)`.\n */\nKuzzle.prototype.checkToken = function (token, callback) {\n var\n request = {\n body: {\n token: token\n }\n };\n\n this.callbackRequired('Kuzzle.checkToken', callback);\n\n this.query({controller: 'auth', action: 'checkToken'}, request, {queuable: false}, function (err, response) {\n if (err) {\n return callback(err);\n }\n\n callback(null, response.result);\n });\n};\n\n/**\n * Fetches the current user.\n *\n * @param {function} callback The callback to be called when the response is\n * available. The signature is `function(error, response)`.\n */\nKuzzle.prototype.whoAmI = function (callback) {\n var self = this;\n\n self.callbackRequired('Kuzzle.whoAmI', callback);\n\n self.query({controller: 'auth', action: 'getCurrentUser'}, {}, {}, function (err, response) {\n if (err) {\n return callback(err);\n }\n\n callback(null, new User(self.security, response.result._id, response.result._source));\n });\n};\n\n/**\n * Gets the rights array of the currently logged user.\n *\n * @param {object} [options] - Optional parameters\n * @param {function} cb The callback containing the normalized array of rights.\n */\nKuzzle.prototype.getMyRights = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.callbackRequired('Kuzzle.getMyRights', cb);\n\n self.query({controller: 'auth', action:'getMyRights'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.hits);\n });\n};\n\n/**\n * Update current user in Kuzzle.\n *\n * @param {object} content - a plain javascript object representing the user's modification\n * @param {object} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.updateSelf = function (content, options, cb) {\n var\n self = this,\n data = {},\n queryArgs = {controller: 'auth', action: 'updateSelf'};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data.body = content;\n\n self.query(queryArgs, data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result);\n });\n\n return this;\n};\n\n/**\n * Clean up the queue, ensuring the queryTTL and queryMaxSize properties are respected\n */\nfunction cleanQueue () {\n var\n self = this,\n now = Date.now(),\n lastDocumentIndex = -1;\n\n if (self.queueTTL > 0) {\n self.offlineQueue.forEach(function (query, index) {\n if (query.ts < now - self.queueTTL) {\n lastDocumentIndex = index;\n }\n });\n\n if (lastDocumentIndex !== -1) {\n self.offlineQueue\n .splice(0, lastDocumentIndex + 1)\n .forEach(function (droppedRequest) {\n self.emitEvent('offlineQueuePop', droppedRequest.query);\n });\n }\n }\n\n if (self.queueMaxSize > 0 && self.offlineQueue.length > self.queueMaxSize) {\n self.offlineQueue\n .splice(0, self.offlineQueue.length - self.queueMaxSize)\n .forEach(function (droppedRequest) {\n self.emitEvent('offlineQueuePop', droppedRequest.query);\n });\n }\n}\n\n\n/**\n * Clean history from requests made more than 10s ago\n */\nfunction cleanHistory (requestHistory) {\n var\n now = Date.now();\n\n Object.keys(requestHistory).forEach(function (key) {\n if (requestHistory[key] < now - 10000) {\n delete requestHistory[key];\n }\n });\n\n setTimeout(function () {\n cleanHistory(requestHistory);\n }, 1000);\n}\n\n/**\n * Emit a request to Kuzzle\n *\n * @param {object} request\n * @param {responseCallback} [cb]\n */\nfunction emitRequest (request, cb) {\n var\n self = this;\n\n if (self.jwtToken !== undefined || cb) {\n self.network.once(request.requestId, function (response) {\n var error = null;\n\n if (request.action !== 'logout' && response.error && response.error.message === 'Token expired') {\n self.jwtToken = undefined;\n self.emitEvent('jwtTokenExpired', request, cb);\n }\n\n if (response.error) {\n error = new Error(response.error.message);\n Object.assign(error, response.error);\n error.status = response.status;\n self.emitEvent('queryError', error, request, cb);\n }\n\n if (cb) {\n cb(error, response);\n }\n });\n }\n\n this.network.send(request);\n\n // Track requests made to allow Room.subscribeToSelf to work\n self.requestHistory[request.requestId] = Date.now();\n}\n\n/**\n * Play all queued requests, in order.\n */\nfunction dequeue () {\n var\n self = this,\n additionalQueue,\n uniqueQueue = {},\n dequeuingProcess = function () {\n if (self.offlineQueue.length > 0) {\n emitRequest.call(self, self.offlineQueue[0].query, self.offlineQueue[0].cb);\n self.emitEvent('offlineQueuePop', self.offlineQueue.shift());\n\n setTimeout(function () {\n dequeuingProcess();\n }, Math.max(0, self.replayInterval));\n } else {\n self.queuing = false;\n }\n };\n\n if (self.offlineQueueLoader) {\n if (typeof self.offlineQueueLoader !== 'function') {\n throw new Error('Invalid value for offlineQueueLoader property. Expected: function. Got: ' + typeof self.offlineQueueLoader);\n }\n\n additionalQueue = self.offlineQueueLoader();\n if (Array.isArray(additionalQueue)) {\n self.offlineQueue = additionalQueue\n .concat(self.offlineQueue)\n .filter(function (request) {\n // throws if the query object does not contain required attributes\n if (!request.query || request.query.requestId === undefined || !request.query.action || !request.query.controller) {\n throw new Error('Invalid offline queue request. One or more missing properties: requestId, action, controller.');\n }\n\n return uniqueQueue.hasOwnProperty(request.query.requestId) ? false : (uniqueQueue[request.query.requestId] = true);\n });\n } else {\n throw new Error('Invalid value returned by the offlineQueueLoader function. Expected: array. Got: ' + typeof additionalQueue);\n }\n }\n\n dequeuingProcess();\n}\n\n/**\n * Renew all registered subscriptions. Triggered either by a successful connection/reconnection or by a\n * successful login attempt\n */\nfunction renewAllSubscriptions() {\n var self = this;\n\n Object.keys(self.subscriptions).forEach(function (roomId) {\n Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n var subscription = self.subscriptions[roomId][subscriptionId];\n subscription.renew(subscription.callback);\n });\n });\n}\n\n/**\n * Remove all registered subscriptions. Triggered either by a logout query or by un-setting the token\n */\nfunction removeAllSubscriptions() {\n var self = this;\n\n Object.keys(self.subscriptions).forEach(function (roomId) {\n Object.keys(self.subscriptions[roomId]).forEach(function (subscriptionId) {\n var subscription = self.subscriptions[roomId][subscriptionId];\n subscription.unsubscribe();\n });\n });\n}\n\n/**\n * Adds a listener to a Kuzzle global event. When an event is fired, listeners are called in the order of their\n * insertion.\n *\n * The ID returned by this function is required to remove this listener at a later time.\n *\n * @param {string} event - name of the global event to subscribe to (see the 'eventListeners' object property)\n * @param {function} listener - callback to invoke each time an event is fired\n * @returns {string} Unique listener ID\n */\nKuzzle.prototype.addListener = function(event, listener) {\n var\n knownEvents = Object.keys(this.eventListeners),\n listenerType = typeof listener,\n listenerId;\n\n this.isValid();\n\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n if (listenerType !== 'function') {\n throw new Error('Invalid listener type: expected a function, got a ' + listenerType);\n }\n\n listenerId = uuid.v4();\n this.eventListeners[event].listeners.push({id: listenerId, fn: listener});\n return listenerId;\n};\n\n\n/**\n * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n * This method returns all available statistics from Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getAllStatistics = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.getAllStatistics', cb);\n\n this.query({controller:'server', action: 'getAllStats'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.hits);\n });\n};\n\n/**\n * Kuzzle monitors active connections, and ongoing/completed/failed requests.\n * This method allows getting either the last statistics frame, or a set of frames starting from a provided timestamp.\n *\n * @param {number} timestamp - Epoch time. Starting time from which the frames are to be retrieved\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getStatistics = function (timestamp, options, cb) {\n var\n queryCB,\n body;\n\n if (!cb) {\n if (arguments.length === 1) {\n cb = arguments[0];\n options = null;\n timestamp = null;\n } else {\n cb = arguments[1];\n if (typeof arguments[0] === 'object') {\n options = arguments[0];\n timestamp = null;\n } else {\n timestamp = arguments[0];\n options = null;\n }\n }\n }\n\n queryCB = function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, timestamp ? res.result.hits : [res.result]);\n };\n\n this.callbackRequired('Kuzzle.getStatistics', cb);\n\n body = timestamp ? {body: {startTime: timestamp}} : {};\n this.query({controller: 'server', action: timestamp ? 'getStats' : 'getLastStats'}, body, options, queryCB);\n};\n\n/**\n * Create a new instance of a Collection object.\n * If no index is specified, takes the default index.\n *\n * @param {string} collection - The name of the data collection you want to manipulate\n * @param {string} [index] - The name of the data index containing the data collection\n * @returns {Collection} A Collection instance\n */\nKuzzle.prototype.collection = function(collection, index) {\n this.isValid();\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Unable to create a new data collection object: no index specified');\n }\n\n index = this.defaultIndex;\n }\n\n if (typeof index !== 'string' || typeof collection !== 'string') {\n throw new Error('Invalid index or collection argument: string expected');\n }\n\n if (!this.collections[index]) {\n this.collections[index] = {};\n }\n\n if (!this.collections[index][collection]) {\n this.collections[index][collection] = new Collection(this, collection, index);\n }\n\n return this.collections[index][collection];\n};\n\n/**\n * Empties the offline queue without replaying it.\n *\n * @returns {Kuzzle}\n */\nKuzzle.prototype.flushQueue = function () {\n this.offlineQueue = [];\n return this;\n};\n\n/**\n * Returns the list of known persisted data collections.\n *\n * @param {string} [index] - Index containing collections to be listed\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.listCollections = function () {\n var\n collectionType = 'all',\n index,\n options,\n cb,\n args = Array.prototype.slice.call(arguments),\n query;\n\n args.forEach(function(arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.listCollections: index required');\n }\n\n index = this.defaultIndex;\n }\n\n this.callbackRequired('Kuzzle.listCollections', cb);\n\n if (options && options.type) {\n collectionType = options.type;\n }\n\n query = {body: {type: collectionType}};\n\n if (options && options.from) {\n query.body.from = options.from;\n }\n\n if (options && options.size) {\n query.body.size = options.size;\n }\n\n this.query({index: index, controller: 'collection', action: 'list'}, query, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.collections);\n });\n};\n\n/**\n * Returns the list of existing indexes in Kuzzle\n *\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.listIndexes = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.listIndexes', cb);\n\n this.query({controller: 'index', action: 'list'}, {}, options, function (err, res) {\n cb(err, err ? undefined : res.result.indexes);\n });\n};\n\n/**\n * Disconnects from Kuzzle and invalidate this instance.\n */\nKuzzle.prototype.disconnect = function () {\n var collection;\n\n this.state = 'disconnected';\n this.network.close();\n this.network = null;\n\n for (collection in this.collections) {\n if (this.collections.hasOwnProperty(collection)) {\n delete this.collections[collection];\n }\n }\n};\n\n/**\n * Returns the server informations\n *\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getServerInfo = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.getServerInfo', cb);\n\n this.query({controller: 'server', action: 'info'}, {}, options, function (err, res) {\n if (err) {\n return cb(err);\n }\n\n cb(null, res.result.serverInfo);\n });\n};\n\n/**\n * Forces an index refresh\n *\n * @param {string} index - The index to refresh. Defaults to Kuzzle.defaultIndex\n * @param {object} options - Optional arguments\n * @param {responseCallback} cb - Handles the query response\n * @returns {Kuzzle}\n */\nKuzzle.prototype.refreshIndex = function () {\n var\n index,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function(arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.refreshIndex: index required');\n }\n index = this.defaultIndex;\n }\n\n this.query({ index: index, controller: 'index', action: 'refresh'}, {}, options, cb);\n\n return this;\n};\n\n/**\n * Returns de current autoRefresh status for the given index\n *\n * @param {string} index - The index to get the status from. Defaults to Kuzzle.defaultIndex\n * @param {object} options - Optinal arguments\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.getAutoRefresh = function () {\n var\n index,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function (arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.getAutoRefresh: index required');\n }\n index = this.defaultIndex;\n }\n\n this.callbackRequired('Kuzzle.getAutoRefresh', cb);\n this.query({ index: index, controller: 'index', action: 'getAutoRefresh'}, {}, options, cb);\n};\n\n/**\n * (Un)Sets the autoRefresh flag on the given index\n *\n * @param {string} index - the index to modify. Defaults to Kuzzle.defaultIndex\n * @param {boolean} autoRefresh - The autoRefresh value to set\n * @param {object} options - Optional arguments\n * @param {responseCallback} cb - Handles the query result\n * @returns {object} this\n */\nKuzzle.prototype.setAutoRefresh = function () {\n var\n index,\n autoRefresh,\n options,\n cb;\n\n Array.prototype.slice.call(arguments).forEach(function (arg) {\n switch (typeof arg) {\n case 'string':\n index = arg;\n break;\n case 'boolean':\n autoRefresh = arg;\n break;\n case 'object':\n options = arg;\n break;\n case 'function':\n cb = arg;\n break;\n }\n });\n\n if (!index) {\n if (!this.defaultIndex) {\n throw new Error('Kuzzle.setAutoRefresh: index required');\n }\n index = this.defaultIndex;\n }\n\n if (autoRefresh === undefined) {\n throw new Error('Kuzzle.setAutoRefresh: autoRefresh value is required');\n }\n\n this.query({ index: index, controller: 'index', action: 'setAutoRefresh'}, { body: { autoRefresh: autoRefresh }}, options, cb);\n\n return this;\n};\n\n/**\n * Return the current Kuzzle's UTC Epoch time, in milliseconds\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nKuzzle.prototype.now = function (options, cb) {\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.callbackRequired('Kuzzle.now', cb);\n\n this.query({controller: 'server', action: 'now'}, {}, options, function (err, res) {\n cb(err, res && res.result.now);\n });\n};\n\n/**\n * This is a low-level method, exposed to allow advanced SDK users to bypass high-level methods.\n * Base method used to send read queries to Kuzzle\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} queryArgs - Query configuration\n * @param {object} query - The query data\n * @param {object} [options] - Optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n */\nKuzzle.prototype.query = function (queryArgs, query, options, cb) {\n var\n attr,\n object = {\n action: queryArgs.action,\n controller: queryArgs.controller,\n volatile: this.volatile\n },\n self = this;\n\n this.isValid();\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (options) {\n if (options.queuable === false && self.state === 'offline') {\n return self;\n }\n\n if (options.refresh) {\n object.refresh = options.refresh;\n }\n\n if (typeof options.from !== 'undefined' && options.from !== null) {\n object.from = options.from;\n }\n\n if (options.size) {\n object.size = options.size;\n }\n\n if (options.scroll) {\n object.scroll = options.scroll;\n }\n\n if (options.scrollId) {\n object.scrollId = options.scrollId;\n }\n\n if (options.volatile) {\n Object.keys(options.volatile).forEach(function (meta) {\n object.volatile[meta] = options.volatile[meta];\n });\n }\n }\n\n if (!query || typeof query !== 'object' || Array.isArray(query)) {\n throw new Error('Invalid query parameter: ' + query);\n }\n\n if (query.volatile) {\n Object.keys(query.volatile).forEach(function (meta) {\n object.volatile[meta] = query.volatile[meta];\n });\n }\n\n for (attr in query) {\n if (attr !== 'volatile' && query.hasOwnProperty(attr)) {\n object[attr] = query[attr];\n }\n }\n\n object = self.addHeaders(object, this.headers);\n\n /*\n * Do not add the token for the checkToken route, to avoid getting a token error when\n * a developer simply wish to verify his token\n */\n if (self.jwtToken !== undefined && !(object.controller === 'auth' && object.action === 'checkToken')) {\n object.jwt = self.jwtToken;\n }\n\n if (queryArgs.collection) {\n object.collection = queryArgs.collection;\n }\n\n if (queryArgs.index) {\n object.index = queryArgs.index;\n }\n\n if (!object.requestId) {\n object.requestId = uuid.v4();\n }\n\n if (self.state === 'connected' || (options && options.queuable === false)) {\n if (self.state === 'connected') {\n emitRequest.call(this, object, cb);\n } else {\n discardRequest(object, cb);\n }\n } else if (self.queuing || (options && options.queuable === true) || ['initializing', 'connecting'].indexOf(self.state) !== -1) {\n cleanQueue.call(this, object, cb);\n if (!self.queueFilter || self.queueFilter(object)) {\n self.offlineQueue.push({ts: Date.now(), query: object, cb: cb});\n self.emitEvent('offlineQueuePush', {query: object, cb: cb});\n }\n }\n else {\n discardRequest(object, cb);\n }\n\n return self;\n};\n\n/**\n * Removes all listeners, either from a specific event or from all events\n *\n * @param {string} event - One of the event described in the Event Handling section of this documentation\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.removeAllListeners = function (event) {\n var\n knownEvents = Object.keys(this.eventListeners),\n self = this;\n\n if (event) {\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n this.eventListeners[event].listeners = [];\n } else {\n knownEvents.forEach(function (eventName) {\n self.eventListeners[eventName].listeners = [];\n });\n }\n\n return this;\n};\n\n/**\n * Removes a listener from an event.\n *\n * @param {string} event - One of the event described in the Event Handling section of this documentation\n * @param {string} listenerId - The ID returned by addListener\n * @returns {Kuzzle} this object\n */\nKuzzle.prototype.removeListener = function (event, listenerId) {\n var\n knownEvents = Object.keys(this.eventListeners),\n self = this;\n\n if (knownEvents.indexOf(event) === -1) {\n throw new Error('[' + event + '] is not a known event. Known events: ' + knownEvents.toString());\n }\n\n this.eventListeners[event].listeners.forEach(function (listener, index) {\n if (listener.id === listenerId) {\n self.eventListeners[event].listeners.splice(index, 1);\n }\n });\n\n return this;\n};\n\n/**\n * Replays the requests queued during offline mode.\n * Works only if the SDK is not in a disconnected state, and if the autoReplay option is set to false.\n */\nKuzzle.prototype.replayQueue = function () {\n if (this.state !== 'offline' && !this.autoReplay) {\n cleanQueue.call(this);\n dequeue.call(this);\n }\n\n return this;\n};\n\n/**\n * Sets the default Kuzzle index\n *\n * @param index\n * @returns this\n */\nKuzzle.prototype.setDefaultIndex = function (index) {\n if (typeof index !== 'string') {\n throw new Error('Invalid default index: [' + index + '] (an index name is expected)');\n }\n\n if (index.length === 0) {\n throw new Error('Cannot set an empty index as the default index');\n }\n\n this.defaultIndex = index;\n\n return this;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nKuzzle.prototype.setHeaders = function (content, replace) {\n var self = this;\n\n if (typeof content !== 'object' || Array.isArray(content)) {\n throw new Error('Expected a content object, received a ' + typeof content);\n }\n\n if (replace) {\n self.headers = content;\n } else {\n Object.keys(content).forEach(function (key) {\n self.headers[key] = content[key];\n });\n }\n\n return self;\n};\n\n/**\n * Starts the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n */\nKuzzle.prototype.startQueuing = function () {\n if (this.state === 'offline' && !this.autoQueue) {\n this.queuing = true;\n }\n return this;\n};\n\n/**\n * Stops the requests queuing. Works only during offline mode, and if the autoQueue option is set to false.\n */\nKuzzle.prototype.stopQueuing = function () {\n if (this.state === 'offline' && !this.autoQueue) {\n this.queuing = false;\n }\n\n return this;\n};\n\nfunction discardRequest(object, cb) {\n if (cb) {\n cb(new Error('Unable to execute request: not connected to a Kuzzle server.\\nDiscarded request: ' + JSON.stringify(object)));\n }\n}\n\nmodule.exports = Kuzzle;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Kuzzle.js\n// module id = 0\n// module chunks = 0","function SecurityDocument(Security, id, content) {\n\n if (!id) {\n throw new Error('A security document must have an id');\n }\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n kuzzle: {\n value: Security.kuzzle\n },\n Security: {\n value: Security\n },\n // read-only properties\n // writable properties\n id: {\n value: id,\n enumerable: true\n },\n content: {\n value: {},\n writable: true,\n enumerable: true\n }\n });\n\n if (content) {\n this.setContent(content, true);\n }\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['delete', 'update'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\n/**\n * Replaces the current content with new data.\n * Changes made by this function won’t be applied until the save method is called.\n *\n * @param {Object} data - New securityDocument content\n * @return {SecurityDocument} this\n */\nSecurityDocument.prototype.setContent = function (data) {\n this.content = data;\n return this;\n};\n\n/**\n * Serialize this object into a pojo\n *\n * @return {object} pojo representing this securityDocument\n */\nSecurityDocument.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n\n return data;\n};\n\n/**\n * Delete the current KuzzleSecurityDocument into Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n */\nSecurityDocument.prototype.delete = function (options, cb) {\n var\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs(this.deleteActionName), {_id: this.id}, options, function (error, res) {\n if (error) {\n return cb ? cb(error) : false;\n }\n\n if (cb) {\n cb(null, res.result._id);\n }\n });\n};\n\n/**\n * Update the current KuzzleSecurityDocument into Kuzzle.\n *\n * @param {object} content - Content to add to KuzzleSecurityDocument\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {SecurityDocument} this\n */\nSecurityDocument.prototype.update = function (content, options, cb) {\n var\n data = {},\n self = this;\n\n if (typeof content !== 'object') {\n throw new Error('Parameter \"content\" must be a object');\n }\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = self.id;\n data.body = content;\n\n self.kuzzle.query(this.Security.buildQueryArgs(this.updateActionName), data, options, function (error, response) {\n if (error) {\n return cb ? cb(error) : false;\n }\n\n self.setContent(response.result._source);\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return this;\n};\n\nmodule.exports = SecurityDocument;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/SecurityDocument.js\n// module id = 1\n// module chunks = 0","/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * Kuzzle handles documents either as realtime messages or as stored documents.\n * Document is the object representation of one of these documents.\n *\n * Notes:\n * - this constructor may be called either with a documentId, a content, neither or both.\n * - providing a documentID to the constructor will automatically call refresh, unless a content is also provided\n *\n *\n * @param {Collection} collection - an instanciated Collection object\n * @param {string} [documentId] - ID of an existing document\n * @param {object} [content] - Initializes this document with the provided content\n * @constructor\n */\nfunction Document(collection, documentId, content) {\n Object.defineProperties(this, {\n // read-only properties\n collection: {\n value: collection.collection,\n enumerable: true\n },\n dataCollection: {\n value: collection,\n enumerable: false\n },\n kuzzle: {\n value: collection.kuzzle,\n enumerable: false\n },\n // writable properties\n id: {\n value: undefined,\n enumerable: true,\n writable: true\n },\n content: {\n value: {},\n writable: true,\n enumerable: true\n },\n headers: {\n value: JSON.parse(JSON.stringify(collection.headers)),\n enumerable: true,\n writable: true\n },\n version: {\n value: undefined,\n enumerable: true,\n writable: true\n }\n });\n\n // handling provided arguments\n if (!content && documentId && typeof documentId === 'object') {\n content = documentId;\n documentId = null;\n }\n\n if (content) {\n if (content._version) {\n this.version = content._version;\n delete content._version;\n }\n this.setContent(content, true);\n }\n\n if (documentId) {\n Object.defineProperty(this, 'id', {\n value: documentId,\n enumerable: true\n });\n }\n\n // promisifying\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['delete', 'refresh', 'save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this document\n */\nDocument.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n data._version = this.version;\n data = this.kuzzle.addHeaders(data, this.headers);\n\n return data;\n};\n\n/**\n * Overrides the toString() method in order to return a serialized version of the document\n *\n * @return {string} serialized version of this object\n */\nDocument.prototype.toString = function () {\n return JSON.stringify(this.serialize());\n};\n\n/**\n * Deletes this document in Kuzzle.\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.delete = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!self.id) {\n throw new Error('Document.delete: cannot delete a document without a document ID');\n }\n\n this.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'delete'), this.serialize(), options, cb && function (err) {\n cb(err, err ? undefined : self.id);\n });\n};\n\n/**\n * Replaces the current content with the last version of this document stored in Kuzzle.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.refresh = function (options, cb) {\n var self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!self.id) {\n throw new Error('Document.refresh: cannot retrieve a document if no ID has been provided');\n }\n\n this.kuzzle.callbackRequired('Document.refresh', cb);\n\n self.kuzzle.query(self.dataCollection.buildQueryArgs('document', 'get'), {_id: self.id}, options, function (error, res) {\n var newDocument;\n\n if (error) {\n return cb(error);\n }\n\n newDocument = new Document(self.dataCollection, self.id, res.result._source);\n newDocument.version = res.result._version;\n\n cb(null, newDocument);\n });\n};\n\n/**\n * Saves this document into Kuzzle.\n *\n * If this is a new document, this function will create it in Kuzzle and the id property will be made available.\n * Otherwise, this method will replace the latest version of this document in Kuzzle by the current content\n * of this object.\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nDocument.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.dataCollection.buildQueryArgs('document', 'createOrReplace'), data, options, function (error, res) {\n if (error) {\n return cb && cb(error);\n }\n\n self.id = res.result._id;\n self.version = res.result._version;\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return self;\n};\n\n/**\n * Sends the content of this document as a realtime message.\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} [options] - Optional parameters\n * @returns {*} this\n */\nDocument.prototype.publish = function (options) {\n var data = this.serialize();\n\n this.kuzzle.query(this.dataCollection.buildQueryArgs('realtime', 'publish'), data, options);\n\n return this;\n};\n\n/**\n * Replaces the current content with new data.\n * Changes made by this function won’t be applied until the save method is called.\n *\n * @param {object} data - New content\n * @param {boolean} replace - if true: replace this document content with the provided data\n */\nDocument.prototype.setContent = function (data, replace) {\n var self = this;\n\n if (replace) {\n this.content = data;\n }\n else {\n Object.keys(data).forEach(function (key) {\n self.content[key] = data[key];\n });\n }\n\n return this;\n};\n\n/**\n * Listens to events concerning this document. Has no effect if the document does not have an ID\n * (i.e. if the document has not yet been created as a persisted document).\n *\n * @param {object} [options] - subscription options\n * @param {responseCallback} cb - callback that will be called each time a change has been detected on this document\n */\nDocument.prototype.subscribe = function (options, cb) {\n var filters;\n\n if (options && !cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Document.subscribe', cb);\n\n if (!this.id) {\n throw new Error('Document.subscribe: cannot subscribe to a document if no ID has been provided');\n }\n\n filters = { ids: { values: [this.id] } };\n\n return this.dataCollection.subscribe(filters, options, cb);\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nDocument.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\n\nmodule.exports = Document;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Document.js\n// module id = 2\n// module chunks = 0","function WSNode(host, port, ssl) {\n var self = this;\n this.WebSocket = typeof WebSocket !== 'undefined' ? WebSocket : require('ws');\n this.host = host;\n this.port = port;\n this.ssl = ssl;\n this.client = null;\n this.wasConnected = false;\n this.retrying = false;\n this.lasturl = null;\n this.stopRetryingToConnect = false;\n\n /*\n Listeners are stored using the following format:\n roomId: {\n fn: callback_function,\n once: boolean\n }\n */\n this.listeners = {\n error: [],\n connect: [],\n disconnect: [],\n reconnect: []\n };\n\n /**\n * Creates a new socket from the provided arguments\n *\n * @constructor\n * @param {boolean} autoReconnect\n * @param {int} reconnectionDelay\n * @returns {Object} Socket\n */\n this.connect = function (autoReconnect, reconnectionDelay) {\n var\n url = (this.ssl ? 'wss://' : 'ws://') + this.host + ':' + this.port,\n options = typeof window !== 'undefined' ? undefined : {perMessageDeflate: false};\n\n if (url !== this.lasturl) {\n self.wasConnected = false;\n this.lasturl = url;\n }\n\n this.client = new this.WebSocket(url, options);\n\n this.client.onopen = function () {\n if (self.wasConnected) {\n poke(self.listeners, 'reconnect');\n }\n else {\n poke(self.listeners, 'connect');\n }\n self.wasConnected = true;\n self.stopRetryingToConnect = false;\n };\n\n this.client.onclose = function (code, message) {\n if (code === 1000) {\n poke(self.listeners, 'disconnect');\n }\n else {\n onClientError.call(self, autoReconnect, reconnectionDelay, message);\n }\n };\n\n this.client.onerror = function (error) {\n onClientError.call(self, autoReconnect, reconnectionDelay, error);\n };\n\n this.client.onmessage = function (payload) {\n var data = JSON.parse(payload.data || payload);\n\n if (data.room && self.listeners[data.room]) {\n poke(self.listeners, data.room, data);\n }\n else if (self.listeners.discarded) {\n poke(self.listeners, 'discarded', data);\n }\n };\n };\n\n /**\n * Fires the provided callback whence a connection is established\n *\n * @param {function} callback\n */\n this.onConnect = function (callback) {\n this.listeners.connect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a connection error is received\n * @param {function} callback\n */\n this.onConnectError = function (callback) {\n this.listeners.error.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a disconnection occurred\n * @param {function} callback\n */\n this.onDisconnect = function (callback) {\n this.listeners.disconnect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Fires the provided callback whenever a connection has been reestablished\n * @param {function} callback\n */\n this.onReconnect = function (callback) {\n this.listeners.reconnect.push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Registers a callback on a room. Once 1 message is received, fires the\n * callback and unregister it afterward.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.once = function (roomId, callback) {\n if (!this.listeners[roomId]) {\n this.listeners[roomId] = [];\n }\n\n this.listeners[roomId].push({\n fn: callback,\n keep: false\n });\n };\n\n /**\n * Registers a callback on a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.on = function (roomId, callback) {\n if (!this.listeners[roomId]) {\n this.listeners[roomId] = [];\n }\n\n this.listeners[roomId].push({\n fn: callback,\n keep: true\n });\n };\n\n /**\n * Unregisters a callback from a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.off = function (roomId, callback) {\n var index = -1;\n\n if (this.listeners[roomId]) {\n // Array.findIndex is not supported by internet explorer\n this.listeners[roomId].some(function (listener, i) {\n if (listener.fn === callback) {\n index = i;\n return true;\n }\n\n return false;\n });\n\n if (index !== -1) {\n if (this.listeners[roomId].length === 1 && ['error', 'connect', 'disconnect', 'reconnect'].indexOf(roomId) === -1) {\n delete this.listeners[roomId];\n }\n else {\n this.listeners[roomId].splice(index, 1);\n }\n }\n }\n };\n\n\n /**\n * Sends a payload to the connected server\n *\n * @param {Object} payload\n */\n this.send = function (payload) {\n if (this.client && this.client.readyState === this.client.OPEN) {\n this.client.send(JSON.stringify(payload));\n }\n };\n\n /**\n * Closes the connection\n */\n this.close = function () {\n this.listeners = {\n error: [],\n connect: [],\n disconnect: [],\n reconnect: []\n };\n\n this.wasConnected = false;\n this.client.close();\n this.client = null;\n self.stopRetryingToConnect = true;\n };\n}\n\n/**\n * Executes all registered listeners in the provided\n * \"listeners\" structure.\n *\n * Listeners are of the following format:\n * [\n * { fn: callback, once: boolean },\n * ...\n * ]\n *\n * @private\n * @param {Object} listeners\n * @param {string} roomId\n * @param {Object} [payload]\n */\nfunction poke (listeners, roomId, payload) {\n var\n i,\n length = listeners[roomId].length;\n\n for (i = 0; i < length; ++i) {\n listeners[roomId][i].fn(payload);\n\n if (!listeners[roomId][i].keep) {\n if (listeners[roomId].length > 1) {\n listeners[roomId].splice(i, 1);\n --i;\n --length;\n }\n else {\n delete listeners[roomId];\n }\n }\n }\n}\n\n/**\n * Called when the connection closes with an error state\n *\n * @param {boolean} autoReconnect\n * @param {number} reconnectionDelay\n * @param {string|Object} message\n */\nfunction onClientError(autoReconnect, reconnectionDelay, message) {\n var self = this;\n\n if (autoReconnect && !self.retrying && !self.stopRetryingToConnect) {\n self.retrying = true;\n setTimeout(function () {\n self.retrying = false;\n self.connect(autoReconnect, reconnectionDelay);\n }, reconnectionDelay);\n }\n\n poke(self.listeners, 'error', message);\n}\n\nmodule.exports = WSNode;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/wrappers/websocket.js\n// module id = 3\n// module chunks = 0","var\n KuzzleSecurityDocument = require('./SecurityDocument');\n\n/**\n * @param {Security} Security\n * @param {string} id\n * @param {Object} content\n * @constructor\n */\nfunction User(Security, id, content) {\n\n KuzzleSecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteUser'\n },\n updateActionName: {\n value: 'updateUser'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['save', 'saveRestricted'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n}\n\nUser.prototype = Object.create(KuzzleSecurityDocument.prototype, {\n constructor: {\n value: User\n }\n});\n\n/**\n * Set profiles in content\n * @param {array} profileIds - an array of profiles ids string\n *\n * @returns {User} this\n */\nUser.prototype.setProfiles = function (profileIds) {\n if (!Array.isArray(profileIds) || typeof profileIds[0] !== 'string') {\n throw new Error('Parameter \"profileIds\" must be an array of strings');\n }\n\n this.content.profileIds = profileIds;\n\n return this;\n};\n\n/**\n * Add a profile\n * @param {string} profileId - a profile ids string\n *\n * @returns {User} this\n */\nUser.prototype.addProfile = function (profileId) {\n if (typeof profileId !== 'string') {\n throw new Error('Parameter \"profileId\" must be a string');\n }\n\n if (!this.content.profileIds) {\n this.content.profileIds = [];\n }\n\n if (this.content.profileIds.indexOf(profileId) === -1) {\n this.content.profileIds.push(profileId);\n }\n\n return this;\n};\n\n/**\n * Saves this user into Kuzzle.\n *\n * If this is a new user, this function will create it in Kuzzle.\n * Otherwise, this method will replace the latest version of this user in Kuzzle by the current content\n * of this object.\n *\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {User} this\n */\nUser.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceUser'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n/**\n * Saves this user as restricted into Kuzzle.\n *\n * This function will create a new user. It is not usable to update an existing user.\n * The \"profileIds\" property must not be provided, or the request will be rejected by Kuzzle.\n * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n *\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {User} this\n */\nUser.prototype.saveRestricted = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createRestrictedUser'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this User\n */\nUser.prototype.serialize = function () {\n return {_id: this.id, body: this.content};\n};\n\n/**\n * Return the associated profiles IDs\n *\n * @return {array} the associated profiles IDs\n */\nUser.prototype.getProfiles = function () {\n return this.content.profileIds;\n};\n\nmodule.exports = User;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/User.js\n// module id = 4\n// module chunks = 0","var v1 = require('./v1');\nvar v4 = require('./v4');\n\nvar uuid = v4;\nuuid.v1 = v1;\nuuid.v4 = v4;\n\nmodule.exports = uuid;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/uuid/index.js\n// module id = 5\n// module chunks = 0","/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).substr(1);\n}\n\nfunction bytesToUuid(buf, offset) {\n var i = offset || 0;\n var bth = byteToHex;\n return bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] + '-' +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]] +\n bth[buf[i++]] + bth[buf[i++]];\n}\n\nmodule.exports = bytesToUuid;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/uuid/lib/bytesToUuid.js\n// module id = 6\n// module chunks = 0","// Unique ID creation requires a high quality random # generator. In the\n// browser this is a little complicated due to unknown quality of Math.random()\n// and inconsistent support for the `crypto` API. We do the best we can via\n// feature-detection\nvar rng;\n\nvar crypto = global.crypto || global.msCrypto; // for IE 11\nif (crypto && crypto.getRandomValues) {\n // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n var rnds8 = new Uint8Array(16);\n rng = function whatwgRNG() {\n crypto.getRandomValues(rnds8);\n return rnds8;\n };\n}\n\nif (!rng) {\n // Math.random()-based (RNG)\n //\n // If all else fails, use Math.random(). It's fast, but is of unspecified\n // quality.\n var rnds = new Array(16);\n rng = function() {\n for (var i = 0, r; i < 16; i++) {\n if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n }\n\n return rnds;\n };\n}\n\nmodule.exports = rng;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/uuid/lib/rng-browser.js\n// module id = 7\n// module chunks = 0","var\n KuzzleSearchResult = require('./SearchResult'),\n Document = require('./Document'),\n CollectionMapping = require('./CollectionMapping'),\n Room = require('./Room'),\n SubscribeResult = require('./SubscribeResult');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * A data collection is a set of data managed by Kuzzle. It acts like a data table for persistent documents,\n * or like a room for pub/sub messages.\n *\n * @property {string} collection\n * @property {string} index\n * @property {Kuzzle} kuzzle\n * @property {Array.} collection\n * @param {object} kuzzle - Kuzzle instance to inherit from\n * @param {string} collection - name of the data collection to handle\n * @param {string} index - Index containing the data collection\n * @constructor\n */\nfunction Collection(kuzzle, collection, index) {\n if (!index || !collection) {\n throw new Error('The Collection object constructor needs an index and a collection arguments');\n }\n\n Object.defineProperties(this, {\n // read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n index: {\n value: index,\n enumerable: true\n },\n kuzzle: {\n value: kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(kuzzle.headers)),\n enumerable: true,\n writable: true\n }\n });\n\n Object.defineProperty(this, 'buildQueryArgs', {\n value: function (controller, action) {\n return {\n controller: controller,\n action: action,\n collection: this.collection,\n index: this.index\n };\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['publishMessage', 'setHeaders', 'subscribe'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Returns the number of documents matching the provided set of filters.\n *\n * There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function\n *\n * @param {object} filters - Filters in Elasticsearch Query DSL format\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.count = function (filters, options, cb) {\n var\n query;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.count', cb);\n\n query = this.kuzzle.addHeaders({body: filters}, this.headers);\n\n this.kuzzle.query(this.buildQueryArgs('document', 'count'), query, options, function (error, result) {\n cb(error, result && result.result.count);\n });\n};\n\n/**\n * Create a new empty data collection, with no associated mapping.\n * Kuzzle automatically creates data collections when storing documents, but there are cases where we\n * want to create and prepare data collections before storing documents in it.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n * @returns {*} this\n */\nCollection.prototype.create = function (options, cb) {\n var data = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('collection', 'create'), data, options, cb);\n\n return this;\n};\n\n/**\n * Create a new document in Kuzzle.\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n * - ifExist (string, allowed values: \"error\" (default), \"replace\"):\n * If the same document already exists:\n * - resolves with an error if set to \"error\".\n * - replaces the existing document if set to \"replace\"\n *\n * @param {string} [id] - (optional) document identifier\n * @param {object} document - either an instance of a Document object, or a document\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Object} this\n */\nCollection.prototype.createDocument = function (id, document, options, cb) {\n var\n self = this,\n data = {},\n action = 'create';\n\n if (id && typeof id !== 'string') {\n cb = options;\n options = document;\n document = id;\n id = null;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (document instanceof Document) {\n data = document.serialize();\n } else {\n data.body = document;\n }\n\n if (options && options.ifExist) {\n if (options.ifExist === 'replace') {\n action = 'createOrReplace';\n }\n else if (options.ifExist !== 'error') {\n throw new Error('Invalid value for the \"ifExist\" option: ' + options.ifExist);\n }\n }\n\n if (id) {\n data._id = id;\n }\n\n data = self.kuzzle.addHeaders(data, self.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n var doc;\n\n if (err) {\n return cb(err);\n }\n\n doc = new Document(self, res.result._id, res.result._source);\n doc.version = res.result._version;\n cb(null, doc);\n });\n\n return this;\n};\n\n/**\n * Delete persistent documents.\n *\n * There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string|object} arg - Either a document ID (will delete only this particular document), or a set of filters\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Collection} this\n */\nCollection.prototype.deleteDocument = function (arg, options, cb) {\n var\n action,\n data = {};\n\n if (typeof arg === 'string') {\n data._id = arg;\n action = 'delete';\n } else {\n data.body = {query: arg};\n action = 'deleteByQuery';\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n\n this.kuzzle.query(this.buildQueryArgs('document', action), data, options, cb && function (err, res) {\n if (err) {\n cb(err);\n }\n else {\n cb(null, (action === 'delete' ? [res.result._id] : res.result.ids));\n }\n });\n\n return this;\n};\n\n/**\n * Retrieve a single stored document using its unique document ID.\n *\n * @param {string} documentId - Unique document identifier\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.fetchDocument = function (documentId, options, cb) {\n var\n data = {_id: documentId},\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Collection.fetch', cb);\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'get'), data, options, function (err, res) {\n var document;\n\n if (err) {\n return cb(err);\n }\n\n document = new Document(self, res.result._id, res.result._source);\n document.version = res.result._version;\n cb(null, document);\n });\n};\n\n/**\n * Retrieves all documents stored in this data collection\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\nCollection.prototype.fetchAllDocuments = function (options, cb) {\n var\n warnEmitted = false,\n documents = [],\n filters = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n // copying pagination options to the search filter\n if (!options) {\n options = {};\n }\n\n if (!options.from) {\n options.from = 0;\n }\n\n if (!options.size) {\n options.size = 1000;\n }\n\n this.kuzzle.callbackRequired('Collection.fetchAllDocuments', cb);\n\n this.search(filters, options, function fetchNextDocuments (error, searchResult) {\n if (error) {\n return cb(error);\n }\n\n if (searchResult instanceof KuzzleSearchResult) {\n if (searchResult.total > 10000 && !warnEmitted) {\n warnEmitted = true;\n console.warn('Collection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using Collection.search or Collection.scroll instead'); // eslint-disable-line no-console\n }\n\n searchResult.documents.forEach(function(document) {\n documents.push(document);\n });\n searchResult.fetchNext(fetchNextDocuments);\n }\n else {\n cb(null, documents);\n }\n });\n};\n\n\n/**\n * Instantiates a CollectionMapping object containing the current mapping of this collection.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Returns an instantiated CollectionMapping object\n */\nCollection.prototype.getMapping = function (options, cb) {\n var kuzzleMapping;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.getMapping', cb);\n\n kuzzleMapping = new CollectionMapping(this);\n kuzzleMapping.refresh(options, cb);\n};\n\n/**\n * Publish a realtime message\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {object} document - either a Document instance or a JSON object\n * @param {object} [options] - optional arguments\n * @param {responseCallback} [cb] - Returns a raw Kuzzle response\n * @returns {*} this\n */\nCollection.prototype.publishMessage = function (document, options, cb) {\n var data = {};\n\n if (document instanceof Document) {\n data = document.serialize();\n } else {\n data.body = document;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('realtime', 'publish'), data, options, cb);\n\n return this;\n};\n\n/**\n * Replace an existing document with a new one.\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string} documentId - Unique document identifier of the document to replace\n * @param {object} content - JSON object representing the new document version\n * @param {object} [options] - additional arguments\n * @param {responseCallback} [cb] - Returns an instantiated Document object\n * @return {object} this\n */\nCollection.prototype.replaceDocument = function (documentId, content, options, cb) {\n var\n self = this,\n data = {\n _id: documentId,\n body: content\n };\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'createOrReplace'), data, options, cb && function (err, res) {\n var document;\n\n if (err) {\n return cb(err);\n }\n\n document = new Document(self, res.result._id, res.result._source);\n document.version = res.result._version;\n cb(null, document);\n });\n\n return this;\n};\n\n/**\n * Executes an advanced search on the data collection.\n *\n * /!\\ There is a small delay between documents creation and their existence in our advanced search layer,\n * usually a couple of seconds.\n * That means that a document that was just been created won’t be returned by this function.\n *\n * @param {object} filters - Filters in Elasticsearch Query DSL format\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} cb - Handles the query response\n */\n\nCollection.prototype.search = function (filters, options, cb) {\n var\n query,\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n self.kuzzle.callbackRequired('Collection.search', cb);\n\n query = self.kuzzle.addHeaders({body: filters}, this.headers);\n\n\n self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) {\n var documents = [];\n\n if (error) {\n return cb(error);\n }\n\n result.result.hits.forEach(function (doc) {\n var newDocument = new Document(self, doc._id, doc._source);\n\n newDocument.version = doc._version;\n\n documents.push(newDocument);\n });\n\n if (result.result._scroll_id) {\n options.scrollId = result.result._scroll_id;\n }\n\n cb(null, new KuzzleSearchResult(\n self,\n result.result.total,\n documents,\n result.result.aggregations ? result.result.aggregations : {},\n options,\n filters,\n options.previous || null\n ));\n });\n};\n\n/**\n * A \"scroll\" option can be passed to search queries, creating persistent\n * paginated results.\n * This method can be used to manually get the next page of a search result,\n * instead of using KuzzleSearchResult.next()\n *\n * @param {string} scrollId\n * @param {object} [options]\n * @param {object} [filters]\n * @param {responseCallback} cb\n */\nCollection.prototype.scroll = function (scrollId, options, filters, cb) {\n var\n request = {},\n self = this;\n\n if (!scrollId) {\n throw new Error('Collection.scroll: scrollId is required');\n }\n\n if (!cb) {\n cb = filters;\n filters = null;\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = {};\n }\n\n this.kuzzle.callbackRequired('Collection.scroll', cb);\n\n request.scrollId = scrollId;\n\n if (options && options.scroll) {\n request.scroll = options.scroll;\n }\n\n this.kuzzle.query({controller: 'document', action: 'scroll'}, request, options, function (error, result) {\n var documents = [];\n\n if (error) {\n return cb(error);\n }\n\n result.result.hits.forEach(function (doc) {\n var newDocument = new Document(self, doc._id, doc._source);\n\n newDocument.version = doc._version;\n\n documents.push(newDocument);\n });\n\n if (result.result._scroll_id) {\n options.scrollId = result.result._scroll_id;\n }\n\n cb(null, new KuzzleSearchResult(\n self,\n result.result.total,\n documents,\n {},\n options,\n filters,\n options.previous || null\n ));\n });\n\n return this;\n};\n\n/**\n * Subscribes to this data collection with a set of filters.\n * To subscribe to the entire data collection, simply provide an empty filter.\n *\n * @param {object} filters - Filters in Kuzzle DSL format\n * @param {object} [options] - subscriptions options\n * @param {responseCallback} cb - called for each new notification\n * @returns {*} KuzzleSubscribeResult object\n */\nCollection.prototype.subscribe = function (filters, options, cb) {\n var\n room,\n subscribeResult;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.callbackRequired('Collection.subscribe', cb);\n\n subscribeResult = new SubscribeResult();\n room = new Room(this, options);\n\n room.renew(filters, cb, subscribeResult.done.bind(subscribeResult));\n\n return subscribeResult;\n};\n\n/**\n * Truncate the data collection, removing all stored documents but keeping all associated mappings.\n * This method is a lot faster than removing all documents using a query.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n * @returns {*} this\n */\nCollection.prototype.truncate = function (options, cb) {\n var data = {};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.kuzzle.addHeaders(data, this.headers);\n this.kuzzle.query(this.buildQueryArgs('collection', 'truncate'), data, options, cb);\n\n return this;\n};\n\n\n/**\n * Update parts of a document\n *\n * Takes an optional argument object with the following properties:\n * - volatile (object, default: null):\n * Additional information passed to notifications to other users\n *\n * @param {string} documentId - Unique document identifier of the document to update\n * @param {object} content - JSON object containing changes to perform on the document\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Returns an instantiated Document object\n * @return {object} this\n */\nCollection.prototype.updateDocument = function (documentId, content, options, cb) {\n var\n data = {\n _id: documentId,\n body: content\n },\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (options && options.retryOnConflict) {\n data.retryOnConflict = options.retryOnConflict;\n }\n\n data = self.kuzzle.addHeaders(data, this.headers);\n\n self.kuzzle.query(this.buildQueryArgs('document', 'update'), data, options, cb && function (err, res) {\n if (err) {\n return cb(err);\n }\n\n (new Document(self, res.result._id)).refresh(cb);\n });\n\n return self;\n};\n\n\n/**\n * Instantiate a new Document object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - document id\n * @param {object} content - document content\n * @constructor\n */\nCollection.prototype.document = function (id, content) {\n return new Document(this, id, content);\n};\n\n/**\n * Instantiate a new Room object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {object} [options] - subscription configuration\n * @constructor\n */\nCollection.prototype.room = function (options) {\n return new Room(this, options);\n};\n\n/**\n * Instantiate a new CollectionMapping object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {object} [mapping] - mapping to instantiate the CollectionMapping object with\n * @constructor\n */\nCollection.prototype.collectionMapping = function (mapping) {\n return new CollectionMapping(this, mapping);\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nCollection.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\nmodule.exports = Collection;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Collection.js\n// module id = 8\n// module chunks = 0","/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n\n/**\n * When creating a new data collection in the persistent data storage layer, Kuzzle uses a default mapping.\n * It means that, by default, you won’t be able to exploit the full capabilities of our persistent data storage layer\n * (currently handled by ElasticSearch), and your searches may suffer from below-average performances, depending on\n * the amount of data you stored in a collection and the complexity of your database.\n *\n * The CollectionMapping object allow to get the current mapping of a data collection and to modify it if needed.\n *\n * @param {object} collection - Instance of the inherited Collection object\n * @param {object} [mapping] - mappings\n * @constructor\n */\nfunction CollectionMapping(collection, mapping) {\n Object.defineProperties(this, {\n //read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n kuzzle: {\n value: collection.kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(collection.headers)),\n enumerable: true,\n writable: true\n },\n mapping: {\n value: mapping || {},\n enumerable: true,\n writable: true\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['set', 'setHeaders'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Applies the new mapping to the data collection.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n */\nCollectionMapping.prototype.apply = function (options, cb) {\n var\n self = this,\n data = this.kuzzle.addHeaders({body: {properties: this.mapping}}, this.headers);\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.collection.buildQueryArgs('collection', 'updateMapping'), data, options, function (err) {\n if (err) {\n return cb && cb(err);\n }\n\n self.refresh(options, cb);\n });\n\n return this;\n};\n\n/**\n * Replaces the current content with the mapping stored in Kuzzle\n *\n * Calling this function will discard any uncommited changes. You can commit changes by calling the “apply” function\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {*} this\n */\nCollectionMapping.prototype.refresh = function (options, cb) {\n var\n self = this,\n data = this.kuzzle.addHeaders({}, this.headers);\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.collection.buildQueryArgs('collection', 'getMapping'), data, options, function (err, res) {\n if (err) {\n return cb ? cb(err) : false;\n }\n\n if (res.result[self.collection.index]) {\n if (res.result[self.collection.index].mappings[self.collection.collection]) {\n self.mapping = res.result[self.collection.index].mappings[self.collection.collection].properties;\n\n // Mappings can be empty. The mapping property should never be \"undefined\"\n if (self.mapping === undefined) {\n self.mapping = {};\n }\n } else {\n return cb && cb(new Error('No mapping found for collection ' + self.collection.collection));\n }\n } else {\n return cb && cb(new Error('No mapping found for index ' + self.collection.index));\n }\n\n if (cb) {\n cb(null, self);\n }\n });\n\n return this;\n};\n\n\n/**\n * Adds or updates a field mapping.\n *\n * Changes made by this function won’t be applied until you call the apply method\n *\n * @param {string} field - Name of the field from which the mapping is to be added or updated\n * @param {object} mapping - corresponding field mapping\n * @returns {CollectionMapping}\n */\nCollectionMapping.prototype.set = function (field, mapping) {\n this.mapping[field] = mapping;\n\n return this;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nCollectionMapping.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\nmodule.exports = CollectionMapping;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/CollectionMapping.js\n// module id = 9\n// module chunks = 0","// Parameter mutualization\nvar\n getId = {getter: true, required: ['_id']},\n getIdField = {getter: true, required: ['_id', 'field']},\n getKeys = {getter: true, required: ['keys']},\n getMember = {getter: true, required: ['_id', 'member']},\n getxScan = {getter: true, required: ['_id', 'cursor'], opts: ['match', 'count']},\n getZrange = {\n getter: true,\n required: ['_id', 'start', 'stop'],\n opts: assignZrangeOptions,\n mapResults: mapZrangeResults\n },\n getZrangeBy = {\n getter: true,\n required: ['_id', 'min', 'max'],\n opts: assignZrangeOptions,\n mapResults: mapZrangeResults\n },\n setId = {required: ['_id']},\n setIdValue = {required: ['_id', 'value']},\n setIdFieldValue = {required: ['_id', 'field', 'value']},\n setEntries = {required: ['entries']};\n\n// Redis commands\nvar\n commands = {\n append: setIdValue,\n bitcount: {getter: true, required: ['_id'], opts: ['start', 'end']},\n bitop: {required: ['_id', 'operation', 'keys']},\n bitpos: {getter: true, required: ['_id', 'bit'], opts: ['start', 'end']},\n dbsize: {getter: true},\n decr: setId,\n decrby: setIdValue,\n del: {required: ['keys']},\n exists: getKeys,\n expire: {required: ['_id', 'seconds']},\n expireat: {required: ['_id', 'timestamp']},\n flushdb: {},\n geoadd: {required: ['_id', 'points']},\n geodist: {\n getter: true,\n required: ['_id', 'member1', 'member2'],\n opts: ['unit'],\n mapResults: parseFloat\n },\n geohash: {getter: true, required: ['_id', 'members']},\n geopos: {getter: true, required: ['_id', 'members'], mapResults: mapGeoposResults},\n georadius: {\n getter: true,\n required: ['_id', 'lon', 'lat', 'distance', 'unit'],\n opts: assignGeoRadiusOptions,\n mapResults: mapGeoRadiusResults\n },\n georadiusbymember: {\n getter: true,\n required: ['_id', 'member', 'distance', 'unit'],\n opts: assignGeoRadiusOptions,\n mapResults: mapGeoRadiusResults\n },\n get: getId,\n getbit: {getter: true, required: ['_id', 'offset']},\n getrange: {getter: true, required: ['_id', 'start', 'end']},\n getset: setIdValue,\n hdel: {required: ['_id', 'fields']},\n hexists: getIdField,\n hget: getIdField,\n hgetall: {getter: true, required: ['_id']},\n hincrby: setIdFieldValue,\n hincrbyfloat: {required: ['_id', 'field', 'value'], mapResults: parseFloat},\n hkeys: getId,\n hlen: getId,\n hmget: {getter: true, required: ['_id', 'fields']},\n hmset: {required: ['_id', 'entries']},\n hscan: getxScan,\n hset: setIdFieldValue,\n hsetnx: setIdFieldValue,\n hstrlen: getIdField,\n hvals: getId,\n incr: setId,\n incrby: setIdValue,\n incrbyfloat: {required: ['_id', 'value'], mapResults: parseFloat},\n keys: {getter: true, required: ['pattern']},\n lindex: {getter: true, required: ['_id', 'index']},\n linsert: {required: ['_id', 'position', 'pivot', 'value']},\n llen: getId,\n lpop: setId,\n lpush: {required: ['_id', 'values']},\n lpushx: setIdValue,\n lrange: {getter: true, required: ['_id', 'start', 'stop']},\n lrem: {required: ['_id', 'count', 'value']},\n lset: {required: ['_id', 'index', 'value']},\n ltrim: {required: ['_id', 'start', 'stop']},\n mget: getKeys,\n mset: setEntries,\n msetnx: setEntries,\n object: {getter: true, required: ['_id', 'subcommand']},\n persist: setId,\n pexpire: {required: ['_id', 'milliseconds']},\n pexpireat: {required: ['_id', 'timestamp']},\n pfadd: {required: ['_id', 'elements']},\n pfcount: getKeys,\n pfmerge: {required: ['_id', 'sources']},\n ping: {getter: true},\n psetex: {required: ['_id', 'value', 'milliseconds']},\n pttl: getId,\n randomkey: {getter: true},\n rename: {required: ['_id', 'newkey']},\n renamenx: {required: ['_id', 'newkey']},\n rpop: setId,\n rpoplpush: {required: ['source', 'destination']},\n rpush: {required: ['_id', 'values']},\n rpushx: setIdValue,\n sadd: {required: ['_id', 'members']},\n scan: {getter: true, required: ['cursor'], opts: ['match', 'count']},\n scard: getId,\n sdiff: {getter: true, required: ['_id', 'keys']},\n sdiffstore: {required: ['_id', 'keys', 'destination']},\n set: {required: ['_id', 'value'], opts: ['ex', 'px', 'nx', 'xx']},\n setex: {required: ['_id', 'value', 'seconds']},\n setnx: setIdValue,\n sinter: getKeys,\n sinterstore: {required: ['destination', 'keys']},\n sismember: getMember,\n smembers: getId,\n smove: {required: ['_id', 'destination', 'member']},\n sort: {getter: true, required: ['_id'], opts: ['alpha', 'by', 'direction', 'get', 'limit']},\n spop: {required: ['_id'], opts: ['count'], mapResults: mapStringToArray },\n srandmember: {getter: true, required: ['_id'], opts: ['count'], mapResults: mapStringToArray},\n srem: {required: ['_id', 'members']},\n sscan: getxScan,\n strlen: getId,\n sunion: getKeys,\n sunionstore: {required: ['destination', 'keys']},\n time: {getter: true, mapResults: mapArrayStringToArrayInt},\n touch: {required: ['keys']},\n ttl: getId,\n type: getId,\n zadd: {required: ['_id', 'elements'], opts: ['nx', 'xx', 'ch', 'incr']},\n zcard: getId,\n zcount: {getter: true, required: ['_id', 'min', 'max']},\n zincrby: {required: ['_id', 'member', 'value']},\n zinterstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']},\n zlexcount: {getter: true, required: ['_id', 'min', 'max']},\n zrange: getZrange,\n zrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']},\n zrevrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']},\n zrangebyscore: getZrangeBy,\n zrank: getMember,\n zrem: {required: ['_id', 'members']},\n zremrangebylex: {required: ['_id', 'min', 'max']},\n zremrangebyrank: {required: ['_id', 'start', 'stop']},\n zremrangebyscore: {required: ['_id', 'min', 'max']},\n zrevrange: getZrange,\n zrevrangebyscore: getZrangeBy,\n zrevrank: getMember,\n zscan: getxScan,\n zscore: {getter: true, required: ['_id', 'member'], mapResults: parseFloat},\n zunionstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']}\n };\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n\n/**\n * Kuzzle's memory storage is a separate data store from the database layer.\n * It is internaly based on Redis. You can access most of Redis functions (all\n * lowercased), except functions falling in the following categories:\n *\n * - blocking functions\n * - cluster commands\n * - configuration commands\n * - cursor functions\n * - database administration commands\n * - debugging functions\n * - script based functions\n * - transaction functions\n *\n * @param {object} kuzzle - Kuzzle instance to inherit from\n * @constructor\n */\nfunction MemoryStorage(kuzzle) {\n Object.defineProperties(this, {\n // read-only properties\n kuzzle: {\n value: kuzzle,\n enumerable: true\n },\n // writable properties\n headers: {\n value: JSON.parse(JSON.stringify(kuzzle.headers)),\n enumerable: true,\n writable: true\n }\n });\n\n this.setHeaders = kuzzle.setHeaders.bind(this);\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['setHeaders'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n// Dynamically builds this class' prototypes using the \"commands\" global variable\n(function () {\n Object.keys(commands).forEach(function (command) {\n MemoryStorage.prototype[command] = function () {\n var\n args = Array.prototype.slice.call(arguments),\n options = null,\n cb,\n query = {\n controller: 'ms',\n action: command\n },\n data = {};\n\n if (args.length && typeof args[args.length - 1] === 'function') {\n cb = args.pop();\n }\n\n commands[command].getter && this.kuzzle.callbackRequired('MemoryStorage.' + command, cb);\n\n if (!commands[command].getter) {\n data.body = {};\n }\n\n if (commands[command].required) {\n commands[command].required.forEach(function (param) {\n var value = args.shift();\n\n if (value === undefined) {\n throw new Error('MemoryStorage.' + command + ': Missing parameter \"' + param + '\"');\n }\n\n assignParameter(data, commands[command].getter, param, value);\n });\n }\n\n if (args.length > 1) {\n throw new Error('MemoryStorage.' + command + ': Too many parameters provided');\n }\n\n if (args.length === 1 && typeof args[0] !== 'object' || Array.isArray(args[0])) {\n throw new Error('MemoryStorage.' + command + ': Invalid optional parameter (expected an object)');\n }\n\n if (args.length) {\n options = Object.assign({}, args[0]);\n\n if (Array.isArray(commands[command].opts)) {\n commands[command].opts.forEach(function (opt) {\n if (options[opt] !== null && options[opt] !== undefined) {\n assignParameter(data, commands[command].getter, opt, options[opt]);\n delete options[opt];\n }\n });\n }\n }\n\n /*\n Options function mapper does not necessarily need\n options to be passed by clients.\n */\n if (typeof commands[command].opts === 'function') {\n commands[command].opts(data, options || {});\n }\n\n this.kuzzle.query(query, data, options, cb && function (err, res) {\n if (err) {\n return cb(err);\n }\n\n if (commands[command].mapResults) {\n return cb(null, commands[command].mapResults(res.result));\n }\n\n cb(null, res.result);\n });\n\n if (!commands[command].getter) {\n return this;\n }\n };\n });\n})();\n\n/**\n *\n * @param {object} data - target data object\n * @param {boolean} getter - tells if the command is a getter one\n * @param {string} name - parameter name\n * @param {*} value - parameter value\n */\nfunction assignParameter(data, getter, name, value) {\n if (getter || name === '_id') {\n data[name] = value;\n }\n else {\n data.body[name] = value;\n }\n}\n\n/**\n * Assign the provided options for the georadius* redis functions\n * to the request object, as expected by Kuzzle API\n *\n * Mutates the provided data and options objects\n *\n * @param {object} data\n * @param {object} options\n */\nfunction assignGeoRadiusOptions(data, options) {\n var parsed = [];\n\n Object.keys(options)\n .filter(function (opt) {\n return options[opt] && ['withcoord', 'withdist', 'count', 'sort'].indexOf(opt) !== -1;\n })\n .forEach(function (opt) {\n if (opt === 'withcoord' || opt === 'withdist') {\n parsed.push(opt);\n delete options[opt];\n }\n else if (opt === 'count' || opt === 'sort') {\n if (opt === 'count') {\n parsed.push('count');\n }\n\n parsed.push(options[opt]);\n }\n\n delete options[opt];\n });\n\n if (parsed.length > 0) {\n data.options = parsed;\n }\n}\n\n/**\n * Force the WITHSCORES option on z*range* routes\n *\n * Mutates the provided data and options objects\n *\n * @param {object} data\n * @param {object} options\n */\nfunction assignZrangeOptions(data, options) {\n data.options = ['withscores'];\n\n if (options.limit) {\n data.limit = options.limit;\n delete options.limit;\n }\n}\n\n/**\n * Maps geopos results, from array> to array>\n *\n * @param {Array.>} results\n * @return {Array.>}\n */\nfunction mapGeoposResults(results) {\n return results.map(function (coords) {\n return coords.map(function (latlon) {\n return parseFloat(latlon);\n });\n });\n}\n\n\n/**\n * Maps georadius results to the format specified in the SDK documentation,\n * preventing different formats depending on the passed options\n *\n * Results can be either an array of point names, or an array\n * of arrays, each one of them containing the point name,\n * and additional informations depending on the passed options\n * (coordinates, distances)\n *\n * @param {Array} results\n * @return {Array.}\n */\nfunction mapGeoRadiusResults(results) {\n // Simple array of point names (no options provided)\n if (!Array.isArray(results[0])) {\n return results.map(function (point) {\n return {name: point};\n });\n }\n\n return results.map(function (point) {\n // The point id is always the first item\n var\n p = {\n name: point[0]\n },\n i;\n\n for (i = 1; i < point.length; i++) {\n // withcoord result are in an array...\n if (Array.isArray(point[i])) {\n p.coordinates = point[i].map(function (coord) {\n return parseFloat(coord);\n });\n }\n else {\n // ... and withdist are not\n p.distance = parseFloat(point[i]);\n }\n }\n\n return p;\n });\n}\n\n/**\n * Map a string result to an array of strings.\n * Used to uniformize polymorphic results from redis\n *\n * @param {Array|string} results\n * @return {Array.}\n */\nfunction mapStringToArray (results) {\n return Array.isArray(results) ? results : [results];\n}\n\n/**\n * Map an array of strings to an array of integers\n *\n * @param {Array.} results\n * @return {Array.}\n */\nfunction mapArrayStringToArrayInt(results) {\n return results.map(function (value) {\n return parseInt(value);\n });\n}\n\n/**\n * Map zrange results with WITHSCORES:\n * [\n * \"member1\",\n * \"score of member1\",\n * \"member2\",\n * \"score of member2\"\n * ]\n *\n * into the following format:\n * [\n * {\"member\": \"member1\", \"score\": },\n * {\"member\": \"member2\", \"score\": },\n * ]\n *\n *\n * @param {Array.} results\n * @return {Array.}\n */\nfunction mapZrangeResults(results) {\n var\n buffer = null,\n mapped = [];\n\n results.forEach(function (value) {\n if (buffer === null) {\n buffer = value;\n }\n else {\n mapped.push({member: buffer, score: parseFloat(value)});\n buffer = null;\n }\n });\n\n return mapped;\n}\n\nmodule.exports = MemoryStorage;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/MemoryStorage.js\n// module id = 10\n// module chunks = 0","var\n uuid = require('uuid'),\n Document = require('./Document');\n\n/**\n * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object.\n *\n * @callback responseCallback\n * @param {Object} err - Error object, NULL if the query is successful\n * @param {Object} [data] - The content of the query response\n */\n\n/**\n * This object is the result of a subscription request, allowing to manipulate the subscription itself.\n *\n * In Kuzzle, you don’t exactly subscribe to a room or a topic but, instead, you subscribe to documents.\n *\n * What it means is that, to subscribe, you provide to Kuzzle a set of matching filters.\n * Once you have subscribed, if a pub/sub message is published matching your filters, or if a matching stored\n * document change (because it is created, updated or deleted), then you’ll receive a notification about it.\n *\n * @param {object} collection - an instantiated and valid kuzzle object\n * @param {object} [options] - subscription optional configuration\n * @constructor\n */\nfunction Room(collection, options) {\n // Define properties\n Object.defineProperties(this, {\n // private properties\n callback: {\n value: null,\n writable: true\n },\n channel: {\n value: null,\n writable: true\n },\n id: {\n value: uuid.v4()\n },\n lastRenewal: {\n value: null,\n writable: true\n },\n notifier: {\n value: null,\n writable: true\n },\n onDoneCB: {\n value: null,\n writable: true\n },\n queue: {\n value: [],\n writable: true\n },\n // Delay before allowing a subscription renewal\n renewalDelay: {\n value: 500\n },\n scope: {\n value: options && options.scope ? options.scope : 'all'\n },\n state: {\n value: options && options.state ? options.state : 'done'\n },\n subscribing: {\n value: false,\n writable: true\n },\n users: {\n value: options && options.users ? options.users : 'none'\n },\n // read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n kuzzle: {\n value: collection.kuzzle,\n enumerable: true\n },\n // writable properties\n filters: {\n value: null,\n enumerable: true,\n writable: true\n },\n headers: {\n value: JSON.parse(JSON.stringify(collection.headers)),\n enumerable: true,\n writable: true\n },\n volatile: {\n value: (options && options.volatile) ? options.volatile : {},\n enumerable: true,\n writable: true\n },\n roomId: {\n value: null,\n enumerable: true,\n writable: true\n },\n subscribeToSelf: {\n value: options && typeof options.subscribeToSelf === 'boolean' ? options.subscribeToSelf : true,\n enumerable: true,\n writable: true\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['count'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * Returns the number of other subscriptions on that room.\n *\n * @param {responseCallback} cb - Handles the query response\n */\nRoom.prototype.count = function (cb) {\n var data;\n\n this.kuzzle.callbackRequired('Room.count', cb);\n\n data = this.kuzzle.addHeaders({body: {roomId: this.roomId}}, this.headers);\n\n if (!isReady.call(this)) {\n this.queue.push({action: 'count', args: [cb]});\n return;\n }\n\n if (!this.roomId) {\n throw new Error('Room.count: cannot count subscriptions on an inactive room');\n }\n\n this.kuzzle.query(this.collection.buildQueryArgs('realtime', 'count'), data, function (err, res) {\n cb(err, res && res.result.count);\n });\n};\n\n/**\n * Renew the subscription using new filters\n *\n * @param {object} [filters] - Filters in Kuzzle DSL format\n * @param {responseCallback} notificationCB - called for each new notification\n * @param {responseCallback} [cb] - handles the query response\n */\nRoom.prototype.renew = function (filters, notificationCB, cb) {\n var\n now = Date.now(),\n subscribeQuery = {\n scope: this.scope,\n state: this.state,\n users: this.users\n },\n self = this;\n\n if (typeof filters === 'function') {\n cb = notificationCB;\n notificationCB = filters;\n filters = null;\n }\n\n if (!cb) {\n cb = self.onDoneCB;\n }\n\n self.kuzzle.callbackRequired('Room.renew', notificationCB);\n\n /*\n Skip subscription renewal if another one was performed a moment before\n */\n if (self.lastRenewal && (now - self.lastRenewal) <= self.renewalDelay) {\n return cb && cb(new Error('Subscription already renewed less than ' + self.renewalDelay + 'ms ago'));\n }\n\n if (filters) {\n self.filters = filters;\n }\n\n /*\n if not yet connected, register itself to the subscriptions list and wait for the\n main Kuzzle object to renew once online\n */\n if (self.kuzzle.state !== 'connected') {\n self.callback = notificationCB;\n self.onDoneCB = cb;\n self.kuzzle.subscriptions.pending[self.id] = self;\n return;\n }\n\n if (self.subscribing) {\n self.queue.push({action: 'renew', args: [filters, notificationCB, cb]});\n return;\n }\n\n self.unsubscribe();\n self.roomId = null;\n self.subscribing = true;\n self.callback = notificationCB;\n self.onDoneCB = cb;\n self.kuzzle.subscriptions.pending[self.id] = self;\n\n subscribeQuery.body = self.filters;\n subscribeQuery = self.kuzzle.addHeaders(subscribeQuery, this.headers);\n\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {volatile: self.volatile}, function (error, response) {\n delete self.kuzzle.subscriptions.pending[self.id];\n self.subscribing = false;\n\n if (error) {\n self.queue = [];\n return cb && cb(new Error('Error during Kuzzle subscription: ' + error.message));\n }\n\n self.lastRenewal = now;\n self.roomId = response.result.roomId;\n self.channel = response.result.channel;\n\n if (!self.kuzzle.subscriptions[self.roomId]) {\n self.kuzzle.subscriptions[self.roomId] = {};\n }\n\n self.kuzzle.subscriptions[self.roomId][self.id] = self;\n\n self.notifier = notificationCallback.bind(self);\n self.kuzzle.network.on(self.channel, self.notifier);\n\n dequeue.call(self);\n cb && cb(null, self);\n });\n};\n\n/**\n * Unsubscribes from Kuzzle.\n *\n * Stop listening immediately. If there is no listener left on that room, sends an unsubscribe request to Kuzzle, once\n * pending subscriptions reaches 0, and only if there is still no listener on that room.\n * We wait for pending subscriptions to finish to avoid unsubscribing while another subscription on that room is\n *\n * @return {*} this\n */\nRoom.prototype.unsubscribe = function () {\n var\n self = this,\n room = self.roomId,\n interval;\n\n if (!isReady.call(this)) {\n self.queue.push({action: 'unsubscribe', args: []});\n return self;\n }\n\n if (room) {\n self.kuzzle.network.off(self.channel, this.notifier);\n\n if (Object.keys(self.kuzzle.subscriptions[room]).length === 1) {\n delete self.kuzzle.subscriptions[room];\n\n if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n } else {\n interval = setInterval(function () {\n if (Object.keys(self.kuzzle.subscriptions.pending).length === 0) {\n if (!self.kuzzle.subscriptions[room]) {\n self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'unsubscribe'), {body: {roomId: room}});\n }\n clearInterval(interval);\n }\n }, 100);\n }\n } else {\n delete self.kuzzle.subscriptions[room][self.id];\n }\n\n self.roomId = null;\n }\n\n return self;\n};\n\n/**\n * Helper function allowing to set headers while chaining calls.\n *\n * If the replace argument is set to true, replace the current headers with the provided content.\n * Otherwise, it appends the content to the current headers, only replacing already existing values\n *\n * @param content - new headers content\n * @param [replace] - default: false = append the content. If true: replace the current headers with tj\n */\nRoom.prototype.setHeaders = function (content, replace) {\n this.kuzzle.setHeaders.call(this, content, replace);\n return this;\n};\n\n/**\n * Callback called by the network handler when a message is sent to the subscribed room ID\n * Calls the registered callback if the notification passes the subscription filters\n *\n * @param {object} data - data\n * @returns {*}\n */\nfunction notificationCallback (data) {\n if (data.error) {\n return this.callback(data.error);\n }\n\n if (data.action === 'jwtTokenExpired') {\n this.kuzzle.jwtToken = undefined;\n return this.kuzzle.emitEvent('jwtTokenExpired');\n }\n\n if (data.controller === 'document' || (data.controller === 'realtime' && data.action === 'publish')) {\n data.type = 'document';\n data.document = new Document(this.collection, data.result._id, data.result._source);\n delete data.result;\n }\n else if (data.controller === 'realtime') {\n data.type = 'user';\n data.user = {count: data.result.count};\n delete data.result;\n }\n\n if (this.kuzzle.requestHistory[data.requestId]) {\n if (this.subscribeToSelf) {\n this.callback(null, data);\n }\n delete this.kuzzle.requestHistory[data.requestId];\n } else {\n this.callback(null, data);\n }\n}\n\n\n/**\n * Dequeue actions performed while subscription was being renewed\n */\nfunction dequeue () {\n var element;\n\n while (this.queue.length > 0) {\n element = this.queue.shift();\n\n this[element.action].apply(this, element.args);\n }\n}\n\nfunction isReady() {\n return this.kuzzle.state === 'connected' && !this.subscribing;\n}\n\nmodule.exports = Room;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/Room.js\n// module id = 11\n// module chunks = 0","/**\n * @param {Collection} collection\n * @param {int} total\n * @param {Document[]} documents\n * @param {object} aggregations\n * @param {object} options\n * @param {object} filters\n * @param {SearchResult} previous\n * @property {Collection} collection\n * @property {number} total\n * @property {Document[]} documents\n * @property {object} aggregations\n * @property {object} options\n * @property {object} filters\n * @property {number} fetchedDocument\n * @constructor\n */\nfunction SearchResult (collection, total, documents, aggregations, options, filters, previous) {\n Object.defineProperties(this, {\n // read-only properties\n collection: {\n value: collection,\n enumerable: true\n },\n total: {\n value: total,\n enumerable: true\n },\n documents: {\n value: documents,\n enumerable: true\n },\n aggregations: {\n value: aggregations || {},\n enumerable: true\n },\n options: {\n value: options || {},\n enumerable: true\n },\n filters: {\n value: filters || {},\n enumerable: true\n },\n // writable properties\n fetchedDocument: {\n value: previous instanceof SearchResult ? documents.length + previous.fetchedDocument : documents.length,\n enumerable: true,\n writable: true\n }\n });\n\n // promisifying\n if (this.collection.kuzzle.bluebird) {\n return this.collection.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['fetchNext'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n return this;\n}\n\n/**\n * @param {function} cb\n */\nSearchResult.prototype.fetchNext = function (cb) {\n var\n filters,\n options = Object.assign({}, this.options);\n \n options.previous = this;\n\n // retrieve next results with scroll if original search use it\n if (options.scrollId) {\n if (this.fetchedDocument >= this.getTotal()) {\n cb(null, null);\n return;\n }\n\n // from and size parameters are not valid for a scroll action\n if (typeof options.from !== 'undefined') {\n delete options.from;\n }\n\n if (options.size) {\n delete options.size;\n }\n\n this.collection.scroll(options.scrollId, options, this.filters || {}, cb);\n\n return;\n }\n\n // retrieve next results with from/size if original search use it\n if (options.from !== undefined && options.size !== undefined) {\n filters = Object.assign({}, this.filters);\n\n // check if we need to do next request to fetch all matching documents\n options.from += options.size;\n\n if (options.from >= this.getTotal()) {\n cb(null, null);\n\n return;\n }\n\n this.collection.search(filters, options, cb);\n\n return;\n }\n\n cb(new Error('Unable to retrieve next results from search: missing scrollId or from/size params'));\n};\n\n/**\n * @returns {Document[]}\n */\nSearchResult.prototype.getDocuments = function () {\n return this.documents;\n};\n\n/**\n * @returns {number}\n */\nSearchResult.prototype.getTotal = function () {\n return this.total;\n};\n\n/**\n * @returns {object}\n */\nSearchResult.prototype.getAggregations = function () {\n return this.aggregations;\n};\n\n/**\n * @returns {Object}\n */\nSearchResult.prototype.getOptions = function() {\n return this.options;\n};\n\n/**\n * @returns {object}\n */\nSearchResult.prototype.getFilters = function() {\n return this.filters;\n};\n\n/**\n * @returns {object}\n */\nSearchResult.prototype.getCollection = function () {\n return this.collection;\n};\n\n/**\n * @returns {number}\n */\nSearchResult.prototype.getFetchedDocument = function () {\n return this.fetchedDocument;\n};\n\nmodule.exports = SearchResult;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/SearchResult.js\n// module id = 12\n// module chunks = 0","/**\n * Sugar-code handling the result of a Room.renew call\n * @constructor\n */\nfunction SubscribeResult() {\n this.cbs = [];\n this.error = null;\n this.room = null;\n}\n\n/**\n * Registers a callback to be called with a subscription result\n * @param {Function} cb\n */\nSubscribeResult.prototype.onDone = function (cb) {\n if (this.error || this.room) {\n cb(this.error, this.room);\n }\n else {\n this.cbs.push(cb);\n }\n\n return this;\n};\n\n/**\n * Calls all registered callbacks\n *\n * @param {Object} error object\n * @param {Room} room\n */\nSubscribeResult.prototype.done = function (error, room) {\n this.error = error;\n this.room = room;\n\n this.cbs.forEach(function (cb) {\n cb(error, room);\n });\n};\n\nmodule.exports = SubscribeResult;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/SubscribeResult.js\n// module id = 13\n// module chunks = 0","/**\n *\n * @param host\n * @param port\n * @param sslConnection\n * @returns {Object} tnstantiated WebSocket/Socket.IO object\n */\n\nfunction network(host, port, sslConnection) {\n // Web browser / NodeJS websocket handling\n if (typeof window !== 'undefined') {\n // use native websockets if the browser supports it\n if (typeof WebSocket !== 'undefined') {\n return new (require('./wrappers/websocket'))(host, port, sslConnection);\n }\n // otherwise fallback to socket.io, if available\n else if (window.io) {\n return new (require('./wrappers/socketio'))(host, port, sslConnection);\n }\n\n throw new Error('Aborting: no websocket support detected and no socket.io library loaded either.');\n }\n\n return new (require('./wrappers/websocket'))(host, port, sslConnection);\n}\n\nmodule.exports = network;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/index.js\n// module id = 14\n// module chunks = 0","function SocketIO(host, port, ssl) {\n this.host = host;\n this.port = port;\n this.ssl = ssl;\n this.socket = null;\n\n /**\n * Creates a new socket from the provided arguments\n *\n * @constructor\n * @param {boolean} autoReconnect\n * @param {int} reconnectionDelay\n */\n this.connect = function (autoReconnect, reconnectionDelay) {\n this.socket = window.io((this.ssl ? 'https://' : 'http://') + this.host + ':' + this.port, {\n reconnection: autoReconnect,\n reconnectionDelay: reconnectionDelay,\n forceNew: true\n });\n };\n\n /**\n * Fires the provided callback whence a connection is established\n *\n * @param {function} callback\n */\n this.onConnect = function (callback) {\n this.socket.on('connect', callback);\n };\n\n /**\n * Fires the provided callback whenever a connection error is received\n * @param {function} callback\n */\n this.onConnectError = function (callback) {\n this.socket.on('connect_error', callback);\n };\n\n /**\n * Fires the provided callback whenever a disconnection occurred\n * @param {function} callback\n */\n this.onDisconnect = function (callback) {\n this.socket.on('disconnect', callback);\n };\n\n /**\n * Fires the provided callback whenever a connection has been reestablished\n * @param {function} callback\n */\n this.onReconnect = function (callback) {\n this.socket.on('reconnect', callback);\n };\n\n /**\n * Registers a callback on a room. Once 1 message is received, fires the\n * callback and unregister it afterward.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.once = function (roomId, callback) {\n this.socket.once(roomId, callback);\n };\n\n /**\n * Registers a callback on a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.on = function (roomId, callback) {\n this.socket.on(roomId, callback);\n };\n\n /**\n * Unregisters a callback from a room.\n *\n * @param {string} roomId\n * @param {function} callback\n */\n this.off = function (roomId, callback) {\n this.socket.off(roomId, callback);\n };\n\n\n /**\n * Sends a payload to the connected server\n *\n * @param {Object} payload\n */\n this.send = function (payload) {\n this.socket.emit('kuzzle', payload);\n };\n\n /**\n * Closes the connection\n */\n this.close = function () {\n this.socket.close();\n this.socket = null;\n };\n}\n\nmodule.exports = SocketIO;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/networkWrapper/wrappers/socketio.js\n// module id = 15\n// module chunks = 0","var SecurityDocument = require('./SecurityDocument');\n\nfunction Profile(Security, id, content) {\n\n SecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteProfile'\n },\n updateActionName: {\n value: 'updateProfile'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['hydrate', 'save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n}\n\nProfile.prototype = Object.create(SecurityDocument.prototype, {\n constructor: {\n value: Profile\n }\n});\n\n/**\n * Persist to the persistent layer the current profile\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Profile} this\n */\nProfile.prototype.save = function (options, cb) {\n var\n data,\n self = this;\n\n if (!this.content.policies) {\n throw new Error('Argument \"policies\" is mandatory in a profile. This argument contains an array of objects.');\n }\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = this.serialize();\n\n self.kuzzle.query(self.Security.buildQueryArgs('createOrReplaceProfile'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return self;\n};\n\n\n/**\n * Add a policy in the policies list\n * @param {Object} policy - must be an object containing at least a \"roleId\" member which must be a string.\n *\n * @returns {Profile} this\n */\nProfile.prototype.addPolicy = function (policy) {\n\n if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n throw new Error('Parameter \"policies\" must be an object containing at least a \"roleId\" member which must be a string.');\n }\n\n if (!this.content.policies) {\n this.content.policies = [];\n }\n\n this.content.policies.push(policy);\n\n return this;\n};\n\n/**\n * Set policies list\n * @param {Array} policies - must be an array of objects containing at least a \"roleId\" member which must be a string\n *\n * @returns {Profile} this\n */\nProfile.prototype.setPolicies = function (policies) {\n\n if (!Array.isArray(policies)) {\n throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n }\n\n policies.map(function (policy) {\n if (typeof policy !== 'object' || typeof policy.roleId !== 'string') {\n throw new Error('Parameter \"policies\" must be an array of objects containing at least a \"roleId\" member which must be a string');\n }\n });\n\n this.content.policies = policies;\n\n return this;\n};\n\n/**\n * Serialize this object into a JSON object\n *\n * @return {object} JSON object representing this securityDocument\n */\nProfile.prototype.serialize = function () {\n var\n data = {};\n\n if (this.id) {\n data._id = this.id;\n }\n\n data.body = this.content;\n\n return data;\n};\n\n/**\n * Returns the list of policies associated to this profile.\n * Each policy element is an array of objects containing at least a \"roleId\" member which must be a string\n *\n * @return {object} an array of policies\n */\nProfile.prototype.getPolicies = function () {\n return this.content.policies;\n};\n\nmodule.exports = Profile;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Profile.js\n// module id = 16\n// module chunks = 0","var SecurityDocument = require('./SecurityDocument');\n\nfunction Role(Security, id, content) {\n\n SecurityDocument.call(this, Security, id, content);\n\n // Define properties\n Object.defineProperties(this, {\n // private properties\n deleteActionName: {\n value: 'deleteRole'\n },\n updateActionName: {\n value: 'updateRole'\n }\n });\n\n // promisifying\n if (Security.kuzzle.bluebird) {\n return Security.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var whitelist = ['save'];\n\n return passes && whitelist.indexOf(name) !== -1;\n }\n });\n }\n\n}\n\nRole.prototype = Object.create(SecurityDocument.prototype, {\n constructor: {\n value: Role\n }\n});\n\n/**\n * Saves this role into Kuzzle.\n *\n * If this is a new role, this function will create it in Kuzzle.\n * Otherwise, this method will replace the latest version of this role in Kuzzle by the current content\n * of this object.\n *\n * @param {object} [options] - Optional parameters\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Role} this object\n */\nRole.prototype.save = function (options, cb) {\n var\n data = this.serialize(),\n self = this;\n\n if (options && cb === undefined && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.Security.buildQueryArgs('createOrReplaceRole'), data, options, cb && function (error) {\n cb(error, error ? undefined : self);\n });\n\n return this;\n};\n\nmodule.exports = Role;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Role.js\n// module id = 17\n// module chunks = 0","var\n Role = require('./Role'),\n Profile = require('./Profile'),\n User = require('./User');\n\n/**\n * Kuzzle security constructor\n *\n * @param kuzzle\n * @returns {Security}\n * @constructor\n */\nfunction Security(kuzzle) {\n\n Object.defineProperty(this, 'kuzzle', {\n value: kuzzle\n });\n\n Object.defineProperty(this, 'buildQueryArgs', {\n value: function (action) {\n return {\n controller: 'security',\n action: action\n };\n }\n });\n\n if (this.kuzzle.bluebird) {\n return this.kuzzle.bluebird.promisifyAll(this, {\n suffix: 'Promise',\n filter: function (name, func, target, passes) {\n var blacklist = ['role', 'profile', 'user', 'isActionAllowed'];\n\n return passes && blacklist.indexOf(name) === -1;\n }\n });\n }\n\n return this;\n}\n\n\n/**\n * Retrieve a single Role using its unique role ID.\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.fetchRole = function (id, options, cb) {\n var\n data,\n self = this;\n\n if (!id) {\n throw new Error('Id parameter is mandatory for fetchRole function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data = {_id: id};\n\n self.kuzzle.callbackRequired('Security.fetchRole', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getRole'), data, options, function (err, response) {\n cb(err, err ? undefined : new Role(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on roles according to a filter\n *\n * /!\\ There is a small delay between role creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a role that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - this object can contains an array `indexes` with a list of index id, a integer `from` and a integer `size`\n * @param {object|responseCallback} [options] - Optional parameters\n * @param {responseCallback} [cb] - returns Kuzzle's response\n *\n */\nSecurity.prototype.searchRoles = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchRoles', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchRoles'), {body: filters}, options, function (error, result) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = result.result.hits.map(function (doc) {\n return new Role(self, doc._id, doc._source);\n });\n\n cb(null, { total: result.result.total, roles: documents });\n });\n};\n\n/**\n * Create a new role in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same role already exists: throw an error if sets to false.\n * Replace the existing role otherwise\n *\n * @param {string} id - role identifier\n * @param {object} content - a plain javascript object representing the role\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createRole = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'createRole';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createRole: cannot create a role without a role ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceRole' : 'createRole';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new Role(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update a role in Kuzzle.\n *\n * @param {string} id - role identifier\n * @param {object} content - a plain javascript object representing the role's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateRole = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content},\n action = 'updateRole';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateRole: cannot update a role without a role ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err) {\n cb(err, err ? undefined : new Role(self, id, content));\n });\n\n return this;\n};\n\n/**\n * Delete role.\n *\n * There is a small delay between role deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a role that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Role id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteRole = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteRole'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new Role object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - role id\n * @param {object} content - role content\n * @constructor\n */\nSecurity.prototype.role = function(id, content) {\n return new Role(this, id, content);\n};\n\n\n/**\n * Get a specific profile from kuzzle\n *\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} cb - returns Kuzzle's response\n */\nSecurity.prototype.fetchProfile = function (id, options, cb) {\n var\n data,\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (!id || typeof id !== 'string') {\n throw new Error('Id parameter is mandatory for fetchProfile function');\n }\n\n\n data = {_id: id};\n\n self.kuzzle.callbackRequired('Security.fetchProfile', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getProfile'), data, options, function (error, response) {\n cb(error, error ? undefined : new Profile(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on profiles according to a filter\n *\n *\n * /!\\ There is a small delay between profile creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a profile that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - this object can contains an array `roles` with a list of roles id, a integer `from` and a integer `size`\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.searchProfiles = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchProfiles', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchProfiles'), {body: filters}, options, function (error, response) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = response.result.hits.map(function (doc) {\n return new Profile(self, doc._id, doc._source);\n });\n\n cb(null, { total: response.result.total, profiles: documents });\n });\n};\n\n/**\n * Create a new profile in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same profile already exists: throw an error if sets to false.\n * Replace the existing profile otherwise\n *\n * @param {string} id - profile identifier\n * @param {object} content - attribute `roles` in `content` must only contains an array of role id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createProfile = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'createProfile';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createProfile: cannot create a profile without a profile ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceProfile' : 'createProfile';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new Profile(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update a profile in Kuzzle.\n *\n * @param {string} id - profile identifier\n * @param {object} content - a plain javascript object representing the profile's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateProfile = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'updateProfile';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateProfile: cannot update a profile without a profile ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n var updatedContent = {};\n\n if (err) {\n return cb(err);\n }\n\n Object.keys(res.result._source).forEach(function (property) {\n updatedContent[property] = res.result._source[property];\n });\n\n cb(null, new Profile(self, res.result._id, updatedContent));\n });\n\n return this;\n};\n\n/**\n * Delete profile.\n *\n * There is a small delay between profile deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a profile that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Profile id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteProfile = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteProfile'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new Profile object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - profile id\n * @param {object} content - profile content\n * @constructor\n */\nSecurity.prototype.profile = function(id, content) {\n return new Profile(this, id, content);\n};\n\n/**\n * Get a specific user from kuzzle using its unique ID\n *\n * @param {string} id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} cb - returns Kuzzle's response\n */\nSecurity.prototype.fetchUser = function (id, options, cb) {\n var\n data = {_id: id},\n self = this;\n\n if (!id || typeof id !== 'string') {\n throw new Error('Id parameter is mandatory for fetchUser function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.fetchUser', cb);\n\n self.kuzzle.query(this.buildQueryArgs('getUser'), data, options, function (err, response) {\n cb(err, err ? undefined : new User(self, response.result._id, response.result._source));\n });\n};\n\n/**\n * Executes a search on user according to a filter\n *\n * /!\\ There is a small delay between user creation and their existence in our persistent search layer,\n * usually a couple of seconds.\n * That means that a user that was just been created won’t be returned by this function.\n *\n * @param {Object} filters - same filters as documents filters\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - returns Kuzzle's response\n */\nSecurity.prototype.searchUsers = function (filters, options, cb) {\n var\n self = this;\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Security.searchUsers', cb);\n\n self.kuzzle.query(this.buildQueryArgs('searchUsers'), {body: filters}, options, function (error, response) {\n var documents;\n\n if (error) {\n return cb(error);\n }\n\n documents = response.result.hits.map(function (doc) {\n return new User(self, doc._id, doc._source);\n });\n\n cb(null, { total: response.result.total, users: documents });\n });\n};\n\n/**\n * Create a new user in Kuzzle.\n *\n * Takes an optional argument object with the following property:\n * - replaceIfExist (boolean, default: false):\n * If the same user already exists: throw an error if sets to false.\n * Replace the existing user otherwise\n *\n * @param {string} id - user identifier\n * @param {object} content - attribute `profileIds` in `content` must only contain an array of profile ids\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createUser = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content},\n action = 'createUser';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createUser: cannot create a user without a user ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n if (options) {\n action = options.replaceIfExist ? 'createOrReplaceUser' : 'createUser';\n }\n\n self.kuzzle.query(this.buildQueryArgs(action), data, null, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n};\n\n/**\n * Create a new restricted user in Kuzzle.\n *\n * This function will create a new user. It is not usable to update an existing user.\n * This function allows anonymous users to create a \"restricted\" user with predefined rights.\n *\n * @param {string} id - user identifier\n * @param {object} content - attribute `profile` in `content` must only contains the profile id\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n */\nSecurity.prototype.createRestrictedUser = function (id, content, options, cb) {\n var\n self = this,\n data = {_id: id, body: content};\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.createRestrictedUser: cannot create a user without a user ID');\n }\n\n if (content.profileIds) {\n throw new Error('Security.createRestrictedUser: cannot provide profileIds');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.query(this.buildQueryArgs('createRestrictedUser'), data, null, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n};\n\n\n/**\n * Update an user in Kuzzle.\n *\n * @param {string} id - user identifier\n * @param {object} content - a plain javascript object representing the user's modification\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - (optional) Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.updateUser = function (id, content, options, cb) {\n var\n self = this,\n data = {},\n action = 'updateUser';\n\n if (!id || typeof id !== 'string') {\n throw new Error('Security.updateUser: cannot update an user without an user ID');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n data._id = id;\n data.body = content;\n\n self.kuzzle.query(this.buildQueryArgs(action), data, options, cb && function (err, res) {\n cb(err, err ? undefined : new User(self, res.result._id, res.result._source));\n });\n\n return this;\n};\n\n/**\n * Delete user.\n *\n * There is a small delay between user deletion and their deletion in our advanced search layer,\n * usually a couple of seconds.\n * That means that a user that was just been delete will be returned by this function\n *\n *\n * @param {string} id - Profile id to delete\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {responseCallback} [cb] - Handles the query response\n * @returns {Security} this object\n */\nSecurity.prototype.deleteUser = function (id, options, cb) {\n var data = {_id: id};\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n this.kuzzle.query(this.buildQueryArgs('deleteUser'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result._id);\n });\n\n return this;\n};\n\n/**\n * Instantiate a new User object. Workaround to the module.exports limitation, preventing multiple\n * constructors to be exposed without having to use a factory or a composed object.\n *\n * @param {string} id - user id\n * @param {object} content - user content\n * @constructor\n */\nSecurity.prototype.user = function(id, content) {\n return new User(this, id, content);\n};\n\n/**\n * Tells whether an action is allowed, denied or conditional based on the rights\n * rights provided as the first argument. An action is defined as a couple of\n * action and controller (mandatory), plus an index and a collection(optional).\n *\n * @param {object} rights - The rights rights associated to a user\n * (see getMyrights and getUserrights).\n * @param {string} controller - The controller to check the action onto.\n * @param {string} action - The action to perform.\n * @param {string} index - (optional) The name of index to perform the action onto.\n * @param {string} collection - (optional) The name of the collection to perform the action onto.\n *\n * @returns {string} ['allowed', 'denied', 'conditional'] where conditional cases\n * correspond to rights containing closures.\n * See also http://kuzzle.io/guide/#roles-definition\n */\nSecurity.prototype.isActionAllowed = function(rights, controller, action, index, collection) {\n var filteredRights;\n\n if (!rights || typeof rights !== 'object') {\n throw new Error('rights parameter is mandatory for isActionAllowed function');\n }\n if (!controller || typeof controller !== 'string') {\n throw new Error('controller parameter is mandatory for isActionAllowed function');\n }\n if (!action || typeof action !== 'string') {\n throw new Error('action parameter is mandatory for isActionAllowed function');\n }\n\n // We filter in all the rights that match the request (including wildcards).\n filteredRights = rights\n .filter(function (right) {\n return right.controller === controller || right.controller === '*';\n })\n .filter(function (right) {\n return right.action === action || right.action === '*';\n })\n .filter(function (right) {\n return right.index === index || right.index === '*';\n })\n .filter(function (right) {\n return right.collection === collection || right.collection === '*';\n });\n\n // Then, if at least one right allows the action, we return 'allowed'\n if (filteredRights.some(function (item) { return item.value === 'allowed'; })) {\n return 'allowed';\n }\n // If no right allows the action, we check for conditionals.\n if (filteredRights.some(function (item) { return item.value === 'conditional'; })) {\n return 'conditional';\n }\n // Otherwise we return 'denied'.\n return 'denied';\n};\n\n\n/**\n * Gets the rights array of a given user.\n *\n * @param {string} userId The id of the user.\n * @param {object|responseCallback} [options] - (optional) arguments\n * @param {function} cb The callback containing the normalized array of rights.\n */\nSecurity.prototype.getUserRights = function (userId, options, cb) {\n var\n data = {_id: userId},\n self = this;\n\n if (!userId || typeof userId !== 'string') {\n throw new Error('userId parameter is mandatory for getUserRights function');\n }\n\n if (!cb && typeof options === 'function') {\n cb = options;\n options = null;\n }\n\n self.kuzzle.callbackRequired('Kuzzle.getUserRights', cb);\n\n this.kuzzle.query(this.buildQueryArgs('getUserRights'), data, options, cb && function (err, res) {\n cb(err, err ? undefined : res.result.hits);\n });\n};\n\nmodule.exports = Security;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/security/Security.js\n// module id = 18\n// module chunks = 0","// Unique ID creation requires a high quality random # generator. We feature\n// detect to determine the best RNG source, normalizing to a function that\n// returns 128-bits of randomness, since that's what's usually required\nvar rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\n\n// random #'s we need to init node and clockseq\nvar _seedBytes = rng();\n\n// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\nvar _nodeId = [\n _seedBytes[0] | 0x01,\n _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]\n];\n\n// Per 4.2.2, randomize (14 bit) clockseq\nvar _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;\n\n// Previous uuid creation time\nvar _lastMSecs = 0, _lastNSecs = 0;\n\n// See https://github.com/broofa/node-uuid for API details\nfunction v1(options, buf, offset) {\n var i = buf && offset || 0;\n var b = buf || [];\n\n options = options || {};\n\n var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\n // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\n // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\n // Time since last uuid creation (in msecs)\n var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\n // Per 4.2.1.2, Bump clockseq on clock regression\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n }\n\n // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n }\n\n // Per 4.2.1.2 Throw error if too many uuids are requested\n if (nsecs >= 10000) {\n throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq;\n\n // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n msecs += 12219292800000;\n\n // `time_low`\n var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff;\n\n // `time_mid`\n var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff;\n\n // `time_high_and_version`\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n b[i++] = tmh >>> 16 & 0xff;\n\n // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n b[i++] = clockseq >>> 8 | 0x80;\n\n // `clock_seq_low`\n b[i++] = clockseq & 0xff;\n\n // `node`\n var node = options.node || _nodeId;\n for (var n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf ? buf : bytesToUuid(b);\n}\n\nmodule.exports = v1;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/uuid/v1.js\n// module id = 19\n// module chunks = 0","var rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\nfunction v4(options, buf, offset) {\n var i = buf && offset || 0;\n\n if (typeof(options) == 'string') {\n buf = options == 'binary' ? new Array(16) : null;\n options = null;\n }\n options = options || {};\n\n var rnds = options.random || (options.rng || rng)();\n\n // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n\n // Copy bytes to buffer, if provided\n if (buf) {\n for (var ii = 0; ii < 16; ++ii) {\n buf[i + ii] = rnds[ii];\n }\n }\n\n return buf || bytesToUuid(rnds);\n}\n\nmodule.exports = v4;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/uuid/v4.js\n// module id = 20\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/package.json b/package.json index ae4166713..cce4b4ac3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kuzzle-sdk", - "version": "3.4.2", + "version": "4.0.0", "description": "Official Javascript SDK for Kuzzle", "author": "The Kuzzle Team ", "repository": { @@ -28,12 +28,14 @@ "license": "Apache-2.0", "dependencies": { "bluebird": "3.4.7", - "bufferutil": "^2.0.1", "eslint-loader": "^1.6.1", - "utf-8-validate": "^3.0.1", "uuid": "3.0.1", "ws": "^2.0.3" }, + "peerDependencies": { + "bufferutil": "^2.0.1", + "utf-8-validate": "^3.0.1" + }, "devDependencies": { "codecov": "^1.0.1", "eslint": "^3.15.0", @@ -52,4 +54,4 @@ "engines": { "node": ">= 6.9.1" } -} +} \ No newline at end of file diff --git a/src/Collection.js b/src/Collection.js index 412aa14a9..a431cdd59 100644 --- a/src/Collection.js +++ b/src/Collection.js @@ -3,7 +3,7 @@ var Document = require('./Document'), CollectionMapping = require('./CollectionMapping'), Room = require('./Room'), - KuzzleSubscribeResult = require('./SubscribeResult'); + SubscribeResult = require('./SubscribeResult'); /** * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object. @@ -134,11 +134,12 @@ Collection.prototype.create = function (options, cb) { * Create a new document in Kuzzle. * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users - * - updateIfExist (boolean, default: false): - * If the same document already exists: throw an error if sets to false. - * Update the existing document otherwise + * - ifExist (string, allowed values: "error" (default), "replace"): + * If the same document already exists: + * - resolves with an error if set to "error". + * - replaces the existing document if set to "replace" * * @param {string} [id] - (optional) document identifier * @param {object} document - either an instance of a Document object, or a document @@ -170,8 +171,13 @@ Collection.prototype.createDocument = function (id, document, options, cb) { data.body = document; } - if (options) { - action = options.updateIfExist ? 'createOrReplace' : 'create'; + if (options && options.ifExist) { + if (options.ifExist === 'replace') { + action = 'createOrReplace'; + } + else if (options.ifExist !== 'error') { + throw new Error('Invalid value for the "ifExist" option: ' + options.ifExist); + } } if (id) { @@ -203,7 +209,7 @@ Collection.prototype.createDocument = function (id, document, options, cb) { * That means that a document that was just been created won’t be returned by this function * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {string|object} arg - Either a document ID (will delete only this particular document), or a set of filters @@ -220,7 +226,7 @@ Collection.prototype.deleteDocument = function (arg, options, cb) { data._id = arg; action = 'delete'; } else { - data.body = arg; + data.body = {query: arg}; action = 'deleteByQuery'; } @@ -308,7 +314,7 @@ Collection.prototype.fetchAllDocuments = function (options, cb) { this.kuzzle.callbackRequired('Collection.fetchAllDocuments', cb); - this.search(filters, options, function getNextDocuments (error, searchResult) { + this.search(filters, options, function fetchNextDocuments (error, searchResult) { if (error) { return cb(error); } @@ -322,7 +328,7 @@ Collection.prototype.fetchAllDocuments = function (options, cb) { searchResult.documents.forEach(function(document) { documents.push(document); }); - searchResult.next(getNextDocuments); + searchResult.fetchNext(fetchNextDocuments); } else { cb(null, documents); @@ -355,7 +361,7 @@ Collection.prototype.getMapping = function (options, cb) { * Publish a realtime message * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {object} document - either a Document instance or a JSON object @@ -382,7 +388,7 @@ Collection.prototype.publishMessage = function (document, options, cb) { * Replace an existing document with a new one. * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {string} documentId - Unique document identifier of the document to replace @@ -471,8 +477,10 @@ Collection.prototype.search = function (filters, options, cb) { self, result.result.total, documents, - result.result.aggregations ? result.result.aggregations : [], - {options: options, filters: filters} + result.result.aggregations ? result.result.aggregations : {}, + options, + filters, + options.previous || null )); }); }; @@ -538,8 +546,10 @@ Collection.prototype.scroll = function (scrollId, options, filters, cb) { self, result.result.total, documents, - result.result.aggregations ? result.result.aggregations : [], - {options: options, filters: filters} + {}, + options, + filters, + options.previous || null )); }); @@ -567,7 +577,7 @@ Collection.prototype.subscribe = function (filters, options, cb) { this.kuzzle.callbackRequired('Collection.subscribe', cb); - subscribeResult = new KuzzleSubscribeResult(); + subscribeResult = new SubscribeResult(); room = new Room(this, options); room.renew(filters, cb, subscribeResult.done.bind(subscribeResult)); @@ -602,7 +612,7 @@ Collection.prototype.truncate = function (options, cb) { * Update parts of a document * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {string} documentId - Unique document identifier of the document to update @@ -624,6 +634,10 @@ Collection.prototype.updateDocument = function (documentId, content, options, cb options = null; } + if (options && options.retryOnConflict) { + data.retryOnConflict = options.retryOnConflict; + } + data = self.kuzzle.addHeaders(data, this.headers); self.kuzzle.query(this.buildQueryArgs('document', 'update'), data, options, cb && function (err, res) { diff --git a/src/Document.js b/src/Document.js index 878b30de7..3a52fcf84 100644 --- a/src/Document.js +++ b/src/Document.js @@ -15,24 +15,24 @@ * - providing a documentID to the constructor will automatically call refresh, unless a content is also provided * * - * @param {object} kuzzleDataCollection - an instanciated Collection object + * @param {Collection} collection - an instanciated Collection object * @param {string} [documentId] - ID of an existing document * @param {object} [content] - Initializes this document with the provided content * @constructor */ -function Document(kuzzleDataCollection, documentId, content) { +function Document(collection, documentId, content) { Object.defineProperties(this, { // read-only properties collection: { - value: kuzzleDataCollection.collection, + value: collection.collection, enumerable: true }, dataCollection: { - value: kuzzleDataCollection, + value: collection, enumerable: false }, kuzzle: { - value: kuzzleDataCollection.kuzzle, + value: collection.kuzzle, enumerable: false }, // writable properties @@ -47,7 +47,7 @@ function Document(kuzzleDataCollection, documentId, content) { enumerable: true }, headers: { - value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)), + value: JSON.parse(JSON.stringify(collection.headers)), enumerable: true, writable: true }, @@ -127,7 +127,7 @@ Document.prototype.toString = function () { * Deletes this document in Kuzzle. * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {object} [options] - Optional parameters @@ -194,7 +194,7 @@ Document.prototype.refresh = function (options, cb) { * of this object. * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {object} [options] - Optional parameters @@ -231,7 +231,7 @@ Document.prototype.save = function (options, cb) { * Sends the content of this document as a realtime message. * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {object} [options] - Optional parameters diff --git a/src/Kuzzle.js b/src/Kuzzle.js index 38578e784..40c26f24b 100644 --- a/src/Kuzzle.js +++ b/src/Kuzzle.js @@ -146,7 +146,7 @@ function Kuzzle (host, options, cb) { enumerable: true, writable: true }, - metadata: { + volatile: { value: {}, enumerable: true, writable: true @@ -268,9 +268,9 @@ function Kuzzle (host, options, cb) { } eventProperties.listeners.forEach(function (listener) { - process.nextTick(function () { + setTimeout(function () { listener.fn.apply(undefined, args); - }); + }, 0); }); // Events without the 'lastEmitted' property can be emitted without minimum time between emissions @@ -1252,7 +1252,7 @@ Kuzzle.prototype.now = function (options, cb) { * Base method used to send read queries to Kuzzle * * Takes an optional argument object with the following properties: - * - metadata (object, default: null): + * - volatile (object, default: null): * Additional information passed to notifications to other users * * @param {object} queryArgs - Query configuration @@ -1266,7 +1266,7 @@ Kuzzle.prototype.query = function (queryArgs, query, options, cb) { object = { action: queryArgs.action, controller: queryArgs.controller, - metadata: this.metadata + volatile: this.volatile }, self = this; @@ -1302,9 +1302,9 @@ Kuzzle.prototype.query = function (queryArgs, query, options, cb) { object.scrollId = options.scrollId; } - if (options.metadata) { - Object.keys(options.metadata).forEach(function (meta) { - object.metadata[meta] = options.metadata[meta]; + if (options.volatile) { + Object.keys(options.volatile).forEach(function (meta) { + object.volatile[meta] = options.volatile[meta]; }); } } @@ -1313,14 +1313,14 @@ Kuzzle.prototype.query = function (queryArgs, query, options, cb) { throw new Error('Invalid query parameter: ' + query); } - if (query.metadata) { - Object.keys(query.metadata).forEach(function (meta) { - object.metadata[meta] = query.metadata[meta]; + if (query.volatile) { + Object.keys(query.volatile).forEach(function (meta) { + object.volatile[meta] = query.volatile[meta]; }); } for (attr in query) { - if (attr !== 'metadata' && query.hasOwnProperty(attr)) { + if (attr !== 'volatile' && query.hasOwnProperty(attr)) { object[attr] = query[attr]; } } diff --git a/src/MemoryStorage.js b/src/MemoryStorage.js index 9cad00053..2a67b8195 100644 --- a/src/MemoryStorage.js +++ b/src/MemoryStorage.js @@ -1,3 +1,164 @@ +// Parameter mutualization +var + getId = {getter: true, required: ['_id']}, + getIdField = {getter: true, required: ['_id', 'field']}, + getKeys = {getter: true, required: ['keys']}, + getMember = {getter: true, required: ['_id', 'member']}, + getxScan = {getter: true, required: ['_id', 'cursor'], opts: ['match', 'count']}, + getZrange = { + getter: true, + required: ['_id', 'start', 'stop'], + opts: assignZrangeOptions, + mapResults: mapZrangeResults + }, + getZrangeBy = { + getter: true, + required: ['_id', 'min', 'max'], + opts: assignZrangeOptions, + mapResults: mapZrangeResults + }, + setId = {required: ['_id']}, + setIdValue = {required: ['_id', 'value']}, + setIdFieldValue = {required: ['_id', 'field', 'value']}, + setEntries = {required: ['entries']}; + +// Redis commands +var + commands = { + append: setIdValue, + bitcount: {getter: true, required: ['_id'], opts: ['start', 'end']}, + bitop: {required: ['_id', 'operation', 'keys']}, + bitpos: {getter: true, required: ['_id', 'bit'], opts: ['start', 'end']}, + dbsize: {getter: true}, + decr: setId, + decrby: setIdValue, + del: {required: ['keys']}, + exists: getKeys, + expire: {required: ['_id', 'seconds']}, + expireat: {required: ['_id', 'timestamp']}, + flushdb: {}, + geoadd: {required: ['_id', 'points']}, + geodist: { + getter: true, + required: ['_id', 'member1', 'member2'], + opts: ['unit'], + mapResults: parseFloat + }, + geohash: {getter: true, required: ['_id', 'members']}, + geopos: {getter: true, required: ['_id', 'members'], mapResults: mapGeoposResults}, + georadius: { + getter: true, + required: ['_id', 'lon', 'lat', 'distance', 'unit'], + opts: assignGeoRadiusOptions, + mapResults: mapGeoRadiusResults + }, + georadiusbymember: { + getter: true, + required: ['_id', 'member', 'distance', 'unit'], + opts: assignGeoRadiusOptions, + mapResults: mapGeoRadiusResults + }, + get: getId, + getbit: {getter: true, required: ['_id', 'offset']}, + getrange: {getter: true, required: ['_id', 'start', 'end']}, + getset: setIdValue, + hdel: {required: ['_id', 'fields']}, + hexists: getIdField, + hget: getIdField, + hgetall: {getter: true, required: ['_id']}, + hincrby: setIdFieldValue, + hincrbyfloat: {required: ['_id', 'field', 'value'], mapResults: parseFloat}, + hkeys: getId, + hlen: getId, + hmget: {getter: true, required: ['_id', 'fields']}, + hmset: {required: ['_id', 'entries']}, + hscan: getxScan, + hset: setIdFieldValue, + hsetnx: setIdFieldValue, + hstrlen: getIdField, + hvals: getId, + incr: setId, + incrby: setIdValue, + incrbyfloat: {required: ['_id', 'value'], mapResults: parseFloat}, + keys: {getter: true, required: ['pattern']}, + lindex: {getter: true, required: ['_id', 'index']}, + linsert: {required: ['_id', 'position', 'pivot', 'value']}, + llen: getId, + lpop: setId, + lpush: {required: ['_id', 'values']}, + lpushx: setIdValue, + lrange: {getter: true, required: ['_id', 'start', 'stop']}, + lrem: {required: ['_id', 'count', 'value']}, + lset: {required: ['_id', 'index', 'value']}, + ltrim: {required: ['_id', 'start', 'stop']}, + mget: getKeys, + mset: setEntries, + msetnx: setEntries, + object: {getter: true, required: ['_id', 'subcommand']}, + persist: setId, + pexpire: {required: ['_id', 'milliseconds']}, + pexpireat: {required: ['_id', 'timestamp']}, + pfadd: {required: ['_id', 'elements']}, + pfcount: getKeys, + pfmerge: {required: ['_id', 'sources']}, + ping: {getter: true}, + psetex: {required: ['_id', 'value', 'milliseconds']}, + pttl: getId, + randomkey: {getter: true}, + rename: {required: ['_id', 'newkey']}, + renamenx: {required: ['_id', 'newkey']}, + rpop: setId, + rpoplpush: {required: ['source', 'destination']}, + rpush: {required: ['_id', 'values']}, + rpushx: setIdValue, + sadd: {required: ['_id', 'members']}, + scan: {getter: true, required: ['cursor'], opts: ['match', 'count']}, + scard: getId, + sdiff: {getter: true, required: ['_id', 'keys']}, + sdiffstore: {required: ['_id', 'keys', 'destination']}, + set: {required: ['_id', 'value'], opts: ['ex', 'px', 'nx', 'xx']}, + setex: {required: ['_id', 'value', 'seconds']}, + setnx: setIdValue, + sinter: getKeys, + sinterstore: {required: ['destination', 'keys']}, + sismember: getMember, + smembers: getId, + smove: {required: ['_id', 'destination', 'member']}, + sort: {getter: true, required: ['_id'], opts: ['alpha', 'by', 'direction', 'get', 'limit']}, + spop: {required: ['_id'], opts: ['count'], mapResults: mapStringToArray }, + srandmember: {getter: true, required: ['_id'], opts: ['count'], mapResults: mapStringToArray}, + srem: {required: ['_id', 'members']}, + sscan: getxScan, + strlen: getId, + sunion: getKeys, + sunionstore: {required: ['destination', 'keys']}, + time: {getter: true, mapResults: mapArrayStringToArrayInt}, + touch: {required: ['keys']}, + ttl: getId, + type: getId, + zadd: {required: ['_id', 'elements'], opts: ['nx', 'xx', 'ch', 'incr']}, + zcard: getId, + zcount: {getter: true, required: ['_id', 'min', 'max']}, + zincrby: {required: ['_id', 'member', 'value']}, + zinterstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']}, + zlexcount: {getter: true, required: ['_id', 'min', 'max']}, + zrange: getZrange, + zrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, + zrevrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, + zrangebyscore: getZrangeBy, + zrank: getMember, + zrem: {required: ['_id', 'members']}, + zremrangebylex: {required: ['_id', 'min', 'max']}, + zremrangebyrank: {required: ['_id', 'start', 'stop']}, + zremrangebyscore: {required: ['_id', 'min', 'max']}, + zrevrange: getZrange, + zrevrangebyscore: getZrangeBy, + zrevrank: getMember, + zscan: getxScan, + zscore: {getter: true, required: ['_id', 'member'], mapResults: parseFloat}, + zunionstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']} + }; + /** * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object. * @@ -10,20 +171,16 @@ /** * Kuzzle's memory storage is a separate data store from the database layer. * It is internaly based on Redis. You can access most of Redis functions (all - * lowercased), excepting: - * * all cluster based functions - * * all script based functions - * * all cursors functions - * - * For instance: - * kuzzle.memoryStorage - * .set('myKey', 'myValue') - * .get('myKey', function (err, response) { - * console.log(response.result); - * - * // { _id: 'foo', body: { value: 'myValue' }} - * }); + * lowercased), except functions falling in the following categories: * + * - blocking functions + * - cluster commands + * - configuration commands + * - cursor functions + * - database administration commands + * - debugging functions + * - script based functions + * - transaction functions * * @param {object} kuzzle - Kuzzle instance to inherit from * @constructor @@ -59,119 +216,8 @@ function MemoryStorage(kuzzle) { return this; } - -/** - * constructs the memoryStorage functions. - */ -(function() { - - var - keyVal = ['id', 'value'], - idOrKeys = ['id', 'keys'], - commands = { - append: keyVal, - bgrewriteaof: [], - bgsave: [], - bitcount: ['id', 'start', 'end'], - bitop: ['operation', 'destkey', idOrKeys], - bitpos: ['id', 'bit', { __opts__: ['start', 'end']}], - blpop: [idOrKeys, 'timeout'], - brpoplpush: ['source', 'destination'], - dbsize: [], - decrby: keyVal, - del: [idOrKeys], - discard: [], - exec: [], - exists: [idOrKeys], - expire: ['id', 'seconds'], - expireat: ['id', 'timestamp'], - flushdb: [], - // @todo: implement geolocation methods once available in Redis stable release - getbit: ['id', 'offset'], - getrange: ['id', 'start', 'end'], - hdel: ['id', ['field', 'fields']], - hexists: ['id', 'field'], - hincrby: ['id', 'field', 'value'], - hmset: ['id', 'values'], - hset: ['id', 'field', 'value'], - info: ['section'], - keys: [ 'pattern' ], - lastsave: [], - lindex: ['id', 'idx'], - linsert: ['id', 'position', 'pivot', 'value'], - lpush: ['id', ['value', 'values']], - lrange: ['id', 'start', 'stop'], - lrem: ['id', 'count', 'value'], - lset: ['id', 'idx', 'value'], - ltrim: ['id', 'start', 'stop'], - mset: ['values'], - multi: [], - object: ['subcommand', 'args'], - pexpire: ['id', 'milliseconds'], - pexpireat: ['id', 'timestamp'], - pfadd: ['id', ['element', 'elements']], - pfmerge: ['destkey', ['sourcekey', 'sourcekeys']], - ping: [], - psetex: ['id', 'milliseconds', 'value'], - publish: ['channel', 'message'], - randomkey: [], - rename: ['id', 'newkey'], - renamenx: ['id', 'newkey'], - restore: ['id', 'ttl', 'content'], - rpoplpush: ['source', 'destination'], - sadd: ['id', ['member', 'members']], - save: [], - set: ['id', 'value', {__opts__:['ex', 'px', 'nx', 'xx']}], - sdiffstore: ['destination', idOrKeys], - setbit: ['id', 'offset', 'value'], - setex: ['id', 'seconds', 'value'], - setrange: ['id', 'offset', 'value'], - sinterstore: ['destination', idOrKeys], - sismember: ['id', 'member'], - smove: ['id', 'destination', 'member'], - sort: ['id', {__opts__:['by', 'offset', 'count', 'get', 'direction', 'alpha', 'store']}], - spop: ['id', 'count'], - srem: ['id', ['member', 'members']], - sunionstore: ['destination', idOrKeys], - unwatch: [], - wait: ['numslaves', 'timeout'], - zadd: ['id', {__opts__: ['nx', 'xx', 'ch', 'incr', 'score', 'member', 'members']}], - zcount: ['id', 'min', 'max'], - zincrby: ['id', 'value', 'member'], - zinterstore: ['destination', idOrKeys, {__opts__: ['weight', 'weights', 'aggregate']}], - zlexcount: ['id', 'min', 'max'], - zrange: ['id', 'start', 'stop', {__opts__: ['withscores']}], - zrangebylex: ['id', 'min', 'max', {__opts__: ['offset', 'count']}], - zrangebyscore: ['id', 'min', 'max', {__opts__: ['withscores', 'offset', 'count']}], - zrem: ['id', 'member'], - zremrangebylex: ['id', 'min', 'max'], - zremrangebyscore: ['id', 'min', 'max'], - zrevrangebylex: ['id', 'max', 'min', {__opts__: ['offset', 'count']}], - zrevrangebyscore: ['id', 'max', 'min', {__opts__: ['withscores', 'offset', 'count']}], - zrevrank: ['id', 'member'] - }; - - // unique argument key - commands.decr = commands.get = commands.dump = commands.hgetall = commands.hkeys = commands.hlen = commands.hstrlen = commands.hvals = commands.incr = commands.llen = commands.lpop = commands.persist = commands.pttl = commands.rpop = commands.scard = commands.smembers = commands.strlen = commands.ttl = commands.type = commands.zcard = ['id']; - - // key value - commands.getset = commands.lpushx = keyVal; - - // key key... - commands.del = commands.exists = commands.mget = commands.pfcount = commands.sdiff = commands.sinter = commands.sunion = commands.watch = [idOrKeys]; - - commands.incrby = commands.incrbyfloat = commands.decrby; - commands.brpop = commands.blpop; - commands.hget = commands.hexists; - commands.hmget = commands.hdel; - commands.hsetnx = commands.hset; - commands.msetnx = commands.mset; - commands.rpush = commands.lpush; - commands.hincrbyfloat = commands.hincrby; - commands.srandmember = commands.spop; - commands.zrevrange = commands.zrange; - commands.zscore = commands.zrevrank; - +// Dynamically builds this class' prototypes using the "commands" global variable +(function () { Object.keys(commands).forEach(function (command) { MemoryStorage.prototype[command] = function () { var @@ -184,51 +230,264 @@ function MemoryStorage(kuzzle) { }, data = {}; - if (typeof args[args.length - 1] === 'function') { + if (args.length && typeof args[args.length - 1] === 'function') { cb = args.pop(); } - if (args.length && typeof args[args.length - 1] === 'object' && Object.keys(args[args.length - 1]).length === 1 && args[args.length - 1].queuable !== undefined) { - options = args.pop(); + commands[command].getter && this.kuzzle.callbackRequired('MemoryStorage.' + command, cb); + + if (!commands[command].getter) { + data.body = {}; } - commands[command].forEach(function (v, i) { - if (args[i] === undefined) { - return; - } + if (commands[command].required) { + commands[command].required.forEach(function (param) { + var value = args.shift(); + + if (value === undefined) { + throw new Error('MemoryStorage.' + command + ': Missing parameter "' + param + '"'); + } + + assignParameter(data, commands[command].getter, param, value); + }); + } + + if (args.length > 1) { + throw new Error('MemoryStorage.' + command + ': Too many parameters provided'); + } + + if (args.length === 1 && typeof args[0] !== 'object' || Array.isArray(args[0])) { + throw new Error('MemoryStorage.' + command + ': Invalid optional parameter (expected an object)'); + } + + if (args.length) { + options = Object.assign({}, args[0]); - if (Array.isArray(v)) { - v = Array.isArray(args[i]) ? v[1] : v[0]; + if (Array.isArray(commands[command].opts)) { + commands[command].opts.forEach(function (opt) { + if (options[opt] !== null && options[opt] !== undefined) { + assignParameter(data, commands[command].getter, opt, options[opt]); + delete options[opt]; + } + }); } + } + + /* + Options function mapper does not necessarily need + options to be passed by clients. + */ + if (typeof commands[command].opts === 'function') { + commands[command].opts(data, options || {}); + } - if (v === 'id') { - data._id = args[i]; + this.kuzzle.query(query, data, options, cb && function (err, res) { + if (err) { + return cb(err); } - else { - if (!data.body) { - data.body = {}; - } - if (typeof v === 'object' && v.__opts__ !== undefined) { - v.__opts__.forEach(function (arg) { - if (args[i][arg] !== undefined) { - data.body[arg] = args[i][arg]; - } - }); - } - else { - data.body[v] = args[i]; - } + if (commands[command].mapResults) { + return cb(null, commands[command].mapResults(res.result)); } + + cb(null, res.result); }); - this.kuzzle.query(query, data, options, cb); + if (!commands[command].getter) { + return this; + } + }; + }); +})(); - return this; +/** + * + * @param {object} data - target data object + * @param {boolean} getter - tells if the command is a getter one + * @param {string} name - parameter name + * @param {*} value - parameter value + */ +function assignParameter(data, getter, name, value) { + if (getter || name === '_id') { + data[name] = value; + } + else { + data.body[name] = value; + } +} - }; +/** + * Assign the provided options for the georadius* redis functions + * to the request object, as expected by Kuzzle API + * + * Mutates the provided data and options objects + * + * @param {object} data + * @param {object} options + */ +function assignGeoRadiusOptions(data, options) { + var parsed = []; + + Object.keys(options) + .filter(function (opt) { + return options[opt] && ['withcoord', 'withdist', 'count', 'sort'].indexOf(opt) !== -1; + }) + .forEach(function (opt) { + if (opt === 'withcoord' || opt === 'withdist') { + parsed.push(opt); + delete options[opt]; + } + else if (opt === 'count' || opt === 'sort') { + if (opt === 'count') { + parsed.push('count'); + } + + parsed.push(options[opt]); + } + + delete options[opt]; + }); + + if (parsed.length > 0) { + data.options = parsed; + } +} + +/** + * Force the WITHSCORES option on z*range* routes + * + * Mutates the provided data and options objects + * + * @param {object} data + * @param {object} options + */ +function assignZrangeOptions(data, options) { + data.options = ['withscores']; + + if (options.limit) { + data.limit = options.limit; + delete options.limit; + } +} + +/** + * Maps geopos results, from array> to array> + * + * @param {Array.>} results + * @return {Array.>} + */ +function mapGeoposResults(results) { + return results.map(function (coords) { + return coords.map(function (latlon) { + return parseFloat(latlon); + }); }); +} -})(); + +/** + * Maps georadius results to the format specified in the SDK documentation, + * preventing different formats depending on the passed options + * + * Results can be either an array of point names, or an array + * of arrays, each one of them containing the point name, + * and additional informations depending on the passed options + * (coordinates, distances) + * + * @param {Array} results + * @return {Array.} + */ +function mapGeoRadiusResults(results) { + // Simple array of point names (no options provided) + if (!Array.isArray(results[0])) { + return results.map(function (point) { + return {name: point}; + }); + } + + return results.map(function (point) { + // The point id is always the first item + var + p = { + name: point[0] + }, + i; + + for (i = 1; i < point.length; i++) { + // withcoord result are in an array... + if (Array.isArray(point[i])) { + p.coordinates = point[i].map(function (coord) { + return parseFloat(coord); + }); + } + else { + // ... and withdist are not + p.distance = parseFloat(point[i]); + } + } + + return p; + }); +} + +/** + * Map a string result to an array of strings. + * Used to uniformize polymorphic results from redis + * + * @param {Array|string} results + * @return {Array.} + */ +function mapStringToArray (results) { + return Array.isArray(results) ? results : [results]; +} + +/** + * Map an array of strings to an array of integers + * + * @param {Array.} results + * @return {Array.} + */ +function mapArrayStringToArrayInt(results) { + return results.map(function (value) { + return parseInt(value); + }); +} + +/** + * Map zrange results with WITHSCORES: + * [ + * "member1", + * "score of member1", + * "member2", + * "score of member2" + * ] + * + * into the following format: + * [ + * {"member": "member1", "score": }, + * {"member": "member2", "score": }, + * ] + * + * + * @param {Array.} results + * @return {Array.} + */ +function mapZrangeResults(results) { + var + buffer = null, + mapped = []; + + results.forEach(function (value) { + if (buffer === null) { + buffer = value; + } + else { + mapped.push({member: buffer, score: parseFloat(value)}); + buffer = null; + } + }); + + return mapped; +} module.exports = MemoryStorage; diff --git a/src/Room.js b/src/Room.js index 0cc4b0f7c..eb2e48c8e 100644 --- a/src/Room.js +++ b/src/Room.js @@ -19,11 +19,11 @@ var * Once you have subscribed, if a pub/sub message is published matching your filters, or if a matching stored * document change (because it is created, updated or deleted), then you’ll receive a notification about it. * - * @param {object} kuzzleDataCollection - an instantiated and valid kuzzle object + * @param {object} collection - an instantiated and valid kuzzle object * @param {object} [options] - subscription optional configuration * @constructor */ -function Room(kuzzleDataCollection, options) { +function Room(collection, options) { // Define properties Object.defineProperties(this, { // private properties @@ -73,11 +73,11 @@ function Room(kuzzleDataCollection, options) { }, // read-only properties collection: { - value: kuzzleDataCollection, + value: collection, enumerable: true }, kuzzle: { - value: kuzzleDataCollection.kuzzle, + value: collection.kuzzle, enumerable: true }, // writable properties @@ -87,12 +87,12 @@ function Room(kuzzleDataCollection, options) { writable: true }, headers: { - value: JSON.parse(JSON.stringify(kuzzleDataCollection.headers)), + value: JSON.parse(JSON.stringify(collection.headers)), enumerable: true, writable: true }, - metadata: { - value: (options && options.metadata) ? options.metadata : {}, + volatile: { + value: (options && options.volatile) ? options.volatile : {}, enumerable: true, writable: true }, @@ -214,7 +214,7 @@ Room.prototype.renew = function (filters, notificationCB, cb) { subscribeQuery.body = self.filters; subscribeQuery = self.kuzzle.addHeaders(subscribeQuery, this.headers); - self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {metadata: self.metadata}, function (error, response) { + self.kuzzle.query(self.collection.buildQueryArgs('realtime', 'subscribe'), subscribeQuery, {volatile: self.volatile}, function (error, response) { delete self.kuzzle.subscriptions.pending[self.id]; self.subscribing = false; diff --git a/src/SearchResult.js b/src/SearchResult.js index 6525762b1..777e15e41 100644 --- a/src/SearchResult.js +++ b/src/SearchResult.js @@ -1,18 +1,26 @@ /** - * - * @param {Collection} dataCollection + * @param {Collection} collection * @param {int} total * @param {Document[]} documents - * @param {object} [aggregations] - * @param {object} [searchArgs] - * @param {KuzzleSearchResult} [previous] + * @param {object} aggregations + * @param {object} options + * @param {object} filters + * @param {SearchResult} previous + * @property {Collection} collection + * @property {number} total + * @property {Document[]} documents + * @property {object} aggregations + * @property {object} options + * @property {object} filters + * @property {number} fetchedDocument * @constructor */ -function KuzzleSearchResult (dataCollection, total, documents, aggregations, searchArgs, previous) { +function SearchResult (collection, total, documents, aggregations, options, filters, previous) { Object.defineProperties(this, { // read-only properties - dataCollection: { - value: dataCollection, + collection: { + value: collection, + enumerable: true }, total: { value: total, @@ -26,37 +34,28 @@ function KuzzleSearchResult (dataCollection, total, documents, aggregations, sea value: aggregations || {}, enumerable: true }, - searchArgs: { - value: searchArgs || {}, + options: { + value: options || {}, + enumerable: true + }, + filters: { + value: filters || {}, enumerable: true }, // writable properties fetchedDocument: { - value: documents.length, + value: previous instanceof SearchResult ? documents.length + previous.fetchedDocument : documents.length, enumerable: true, writable: true - }, - _previous: { - value: previous || null, - writable: true - }, - _next: { - value: null, - writable: true } }); - if (this._previous instanceof KuzzleSearchResult) { - this._previous._next = this; - this.fetchedDocument += this._previous.fetchedDocument; - } - // promisifying - if (this.dataCollection.kuzzle.bluebird) { - return this.dataCollection.kuzzle.bluebird.promisifyAll(this, { + if (this.collection.kuzzle.bluebird) { + return this.collection.kuzzle.bluebird.promisifyAll(this, { suffix: 'Promise', filter: function (name, func, target, passes) { - var whitelist = ['previous', 'next']; + var whitelist = ['fetchNext']; return passes && whitelist.indexOf(name) !== -1; } @@ -66,81 +65,51 @@ function KuzzleSearchResult (dataCollection, total, documents, aggregations, sea return this; } - -/** - * @param cb - * @returns {*} - */ -KuzzleSearchResult.prototype.previous = function (cb) { - cb(null, this._previous); - - return this; -}; - /** * @param {function} cb */ -KuzzleSearchResult.prototype.next = function (cb) { +SearchResult.prototype.fetchNext = function (cb) { var filters, - options = Object.assign({}, this.searchArgs.options), - self = this; - - if (!this._next) { - // retrieve next results with scroll if original search use it - if (options.scrollId) { - if (this.fetchedDocument >= this.total) { - cb(null, null); - return; - } - - // from and size parameters are not valid for a scroll action - if (typeof options.from !== 'undefined') { - delete options.from; - } - - if (options.size) { - delete options.size; - } + options = Object.assign({}, this.options); + + options.previous = this; + + // retrieve next results with scroll if original search use it + if (options.scrollId) { + if (this.fetchedDocument >= this.getTotal()) { + cb(null, null); + return; + } - this.dataCollection.scroll( - options.scrollId, - options, - this.searchArgs.filters || {}, - function(error, newSearchResults) { - handleNextSearchResults(error, self, newSearchResults, cb); - } - ); + // from and size parameters are not valid for a scroll action + if (typeof options.from !== 'undefined') { + delete options.from; + } - return; + if (options.size) { + delete options.size; } - // retrieve next results with from/size if original search use it - else if (options.from !== undefined && options.size !== undefined) { - filters = Object.assign({}, this.searchArgs.filters); - // check if we need to do next request to fetch all matching documents - options.from += options.size; + this.collection.scroll(options.scrollId, options, this.filters || {}, cb); + + return; + } - if (options.from >= this.total) { - cb(null, null); + // retrieve next results with from/size if original search use it + if (options.from !== undefined && options.size !== undefined) { + filters = Object.assign({}, this.filters); - return; - } + // check if we need to do next request to fetch all matching documents + options.from += options.size; - this.dataCollection.search( - filters, - options, - function(error, newSearchResults) { - handleNextSearchResults(error, self, newSearchResults, cb); - } - ); + if (options.from >= this.getTotal()) { + cb(null, null); return; } - } - if (this._next instanceof KuzzleSearchResult) { - cb(null, this._next); + this.collection.search(filters, options, cb); return; } @@ -149,24 +118,52 @@ KuzzleSearchResult.prototype.next = function (cb) { }; /** - * @param {Error} error - * @param {KuzzleSearchResult} currentSearchResults - * @param {KuzzleSearchResult} newSearchResults - * @param {Function} cb + * @returns {Document[]} */ -function handleNextSearchResults (error, currentSearchResults, newSearchResults, cb) { - if (error) { - cb(error); - return; - } +SearchResult.prototype.getDocuments = function () { + return this.documents; +}; - newSearchResults.fetchedDocument += currentSearchResults.fetchedDocument; +/** + * @returns {number} + */ +SearchResult.prototype.getTotal = function () { + return this.total; +}; - newSearchResults._previous = currentSearchResults; - currentSearchResults._next = newSearchResults; +/** + * @returns {object} + */ +SearchResult.prototype.getAggregations = function () { + return this.aggregations; +}; +/** + * @returns {Object} + */ +SearchResult.prototype.getOptions = function() { + return this.options; +}; - cb(null, newSearchResults); -} +/** + * @returns {object} + */ +SearchResult.prototype.getFilters = function() { + return this.filters; +}; + +/** + * @returns {object} + */ +SearchResult.prototype.getCollection = function () { + return this.collection; +}; + +/** + * @returns {number} + */ +SearchResult.prototype.getFetchedDocument = function () { + return this.fetchedDocument; +}; -module.exports = KuzzleSearchResult; +module.exports = SearchResult; diff --git a/src/SubscribeResult.js b/src/SubscribeResult.js index 0d245481a..92198b2d4 100644 --- a/src/SubscribeResult.js +++ b/src/SubscribeResult.js @@ -2,7 +2,7 @@ * Sugar-code handling the result of a Room.renew call * @constructor */ -function KuzzleSubscribeResult() { +function SubscribeResult() { this.cbs = []; this.error = null; this.room = null; @@ -12,7 +12,7 @@ function KuzzleSubscribeResult() { * Registers a callback to be called with a subscription result * @param {Function} cb */ -KuzzleSubscribeResult.prototype.onDone = function (cb) { +SubscribeResult.prototype.onDone = function (cb) { if (this.error || this.room) { cb(this.error, this.room); } @@ -29,7 +29,7 @@ KuzzleSubscribeResult.prototype.onDone = function (cb) { * @param {Object} error object * @param {Room} room */ -KuzzleSubscribeResult.prototype.done = function (error, room) { +SubscribeResult.prototype.done = function (error, room) { this.error = error; this.room = room; @@ -38,4 +38,4 @@ KuzzleSubscribeResult.prototype.done = function (error, room) { }); }; -module.exports = KuzzleSubscribeResult; +module.exports = SubscribeResult; diff --git a/src/networkWrapper/wrappers/websocket.js b/src/networkWrapper/wrappers/websocket.js index e8aa4d5b0..e8894b3d4 100644 --- a/src/networkWrapper/wrappers/websocket.js +++ b/src/networkWrapper/wrappers/websocket.js @@ -8,6 +8,7 @@ function WSNode(host, port, ssl) { this.wasConnected = false; this.retrying = false; this.lasturl = null; + this.stopRetryingToConnect = false; /* Listeners are stored using the following format: @@ -51,6 +52,7 @@ function WSNode(host, port, ssl) { poke(self.listeners, 'connect'); } self.wasConnected = true; + self.stopRetryingToConnect = false; }; this.client.onclose = function (code, message) { @@ -215,6 +217,7 @@ function WSNode(host, port, ssl) { this.wasConnected = false; this.client.close(); this.client = null; + self.stopRetryingToConnect = true; }; } @@ -264,7 +267,7 @@ function poke (listeners, roomId, payload) { function onClientError(autoReconnect, reconnectionDelay, message) { var self = this; - if (autoReconnect && !self.retrying) { + if (autoReconnect && !self.retrying && !self.stopRetryingToConnect) { self.retrying = true; setTimeout(function () { self.retrying = false; diff --git a/src/security/Profile.js b/src/security/Profile.js index f368afa7f..59c8366b7 100644 --- a/src/security/Profile.js +++ b/src/security/Profile.js @@ -1,5 +1,4 @@ -var - SecurityDocument = require('./SecurityDocument'); +var SecurityDocument = require('./SecurityDocument'); function Profile(Security, id, content) { diff --git a/src/security/Role.js b/src/security/Role.js index fbf4f67a9..55e66190b 100644 --- a/src/security/Role.js +++ b/src/security/Role.js @@ -1,8 +1,8 @@ -var KuzzleSecurityDocument = require('./SecurityDocument'); +var SecurityDocument = require('./SecurityDocument'); function Role(Security, id, content) { - KuzzleSecurityDocument.call(this, Security, id, content); + SecurityDocument.call(this, Security, id, content); // Define properties Object.defineProperties(this, { @@ -29,7 +29,7 @@ function Role(Security, id, content) { } -Role.prototype = Object.create(KuzzleSecurityDocument.prototype, { +Role.prototype = Object.create(SecurityDocument.prototype, { constructor: { value: Role } diff --git a/src/security/SecurityDocument.js b/src/security/SecurityDocument.js index 30fb8cfcb..78be6b001 100644 --- a/src/security/SecurityDocument.js +++ b/src/security/SecurityDocument.js @@ -1,4 +1,4 @@ -function KuzzleSecurityDocument(Security, id, content) { +function SecurityDocument(Security, id, content) { if (!id) { throw new Error('A security document must have an id'); @@ -48,9 +48,9 @@ function KuzzleSecurityDocument(Security, id, content) { * Changes made by this function won’t be applied until the save method is called. * * @param {Object} data - New securityDocument content - * @return {KuzzleSecurityDocument} this + * @return {SecurityDocument} this */ -KuzzleSecurityDocument.prototype.setContent = function (data) { +SecurityDocument.prototype.setContent = function (data) { this.content = data; return this; }; @@ -60,7 +60,7 @@ KuzzleSecurityDocument.prototype.setContent = function (data) { * * @return {object} pojo representing this securityDocument */ -KuzzleSecurityDocument.prototype.serialize = function () { +SecurityDocument.prototype.serialize = function () { var data = {}; @@ -79,7 +79,7 @@ KuzzleSecurityDocument.prototype.serialize = function () { * @param {object} [options] - Optional parameters * @param {responseCallback} [cb] - Handles the query response */ -KuzzleSecurityDocument.prototype.delete = function (options, cb) { +SecurityDocument.prototype.delete = function (options, cb) { var self = this; @@ -105,9 +105,9 @@ KuzzleSecurityDocument.prototype.delete = function (options, cb) { * @param {object} content - Content to add to KuzzleSecurityDocument * @param {object} [options] - Optional parameters * @param {responseCallback} [cb] - Handles the query response - * @returns {KuzzleSecurityDocument} this + * @returns {SecurityDocument} this */ -KuzzleSecurityDocument.prototype.update = function (content, options, cb) { +SecurityDocument.prototype.update = function (content, options, cb) { var data = {}, self = this; @@ -139,4 +139,4 @@ KuzzleSecurityDocument.prototype.update = function (content, options, cb) { return this; }; -module.exports = KuzzleSecurityDocument; +module.exports = SecurityDocument; diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 26eead292..083f8095f 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -7,6 +7,10 @@ "no-console": 0 }, "parserOptions": { - "ecmaVersion": 6 + "ecmaVersion": 5 + }, + "env": { + "browser": true, + "mocha": true } } \ No newline at end of file diff --git a/test/Collection/constructor.test.js b/test/Collection/constructor.test.js index f20c13132..5354a3bf4 100644 --- a/test/Collection/constructor.test.js +++ b/test/Collection/constructor.test.js @@ -10,11 +10,11 @@ describe('Collection constructor', function () { var kuzzle = new Kuzzle('foo'), index = 'barfoo', - collection = 'foobar', + collectionName = 'foobar', c; kuzzle.headers.some = 'headers'; - c = new Collection(kuzzle, collection, index); + c = new Collection(kuzzle, collectionName, index); // the collection "headers" should be a hard copy of the kuzzle ones kuzzle.headers = { someother: 'headers' }; @@ -25,34 +25,34 @@ describe('Collection constructor', function () { should(c).have.propertyWithDescriptor('kuzzle', { enumerable: true, writable: false, configurable: false }); should(c).have.propertyWithDescriptor('headers', { enumerable: true, writable: true, configurable: false }); should(c.index).be.exactly(index); - should(c.collection).be.exactly(collection); + should(c.collection).be.exactly(collectionName); should(c.kuzzle).be.exactly(kuzzle); should(c.headers.some).be.exactly('headers'); should(c.headers.someother).be.undefined(); }); - it('should promisify the right functions', () => { + it('should promisify the right functions', function () { var kuzzle, - dataCollection; + collection; Kuzzle.prototype.bluebird = bluebird; kuzzle = new Kuzzle('foo'); - dataCollection = new Collection(kuzzle, 'bar', 'foo'); + collection = new Collection(kuzzle, 'bar', 'foo'); - should.exist(dataCollection.countPromise); - should.exist(dataCollection.createPromise); - should.exist(dataCollection.createDocumentPromise); - should.exist(dataCollection.deleteDocumentPromise); - should.exist(dataCollection.fetchDocumentPromise); - should.exist(dataCollection.fetchAllDocumentsPromise); - should.exist(dataCollection.getMappingPromise); - should.not.exist(dataCollection.publishPromise); - should.exist(dataCollection.replaceDocumentPromise); - should.not.exist(dataCollection.setHeadersPromise); - should.not.exist(dataCollection.subscribePromise); - should.exist(dataCollection.truncatePromise); - should.exist(dataCollection.updateDocumentPromise); + should.exist(collection.countPromise); + should.exist(collection.createPromise); + should.exist(collection.createDocumentPromise); + should.exist(collection.deleteDocumentPromise); + should.exist(collection.fetchDocumentPromise); + should.exist(collection.fetchAllDocumentsPromise); + should.exist(collection.getMappingPromise); + should.not.exist(collection.publishPromise); + should.exist(collection.replaceDocumentPromise); + should.not.exist(collection.setHeadersPromise); + should.not.exist(collection.subscribePromise); + should.exist(collection.truncatePromise); + should.exist(collection.updateDocumentPromise); }); it('should set headers using setHeaders', function () { diff --git a/test/Collection/methods.test.js b/test/Collection/methods.test.js index acdbe796e..cc563271f 100644 --- a/test/Collection/methods.test.js +++ b/test/Collection/methods.test.js @@ -3,12 +3,12 @@ var rewire = require('rewire'), sinon = require('sinon'), Kuzzle = rewire('../../src/Kuzzle'), - KuzzleSearchResult = require('../../src/SearchResult'), + SearchResult = require('../../src/SearchResult'), Collection = rewire('../../src/Collection.js'), Document = require('../../src/Document'), CollectionMapping = require('../../src/CollectionMapping'), Room = require('../../src/Room'), - KuzzleSubscribeResult = require('../../src/SubscribeResult'); + SubscribeResult = require('../../src/SubscribeResult'); describe('Collection methods', function () { var @@ -79,11 +79,11 @@ describe('Collection methods', function () { collection.search(filters, options, function (err, res) { should(err).be.null(); - should(res).be.an.instanceOf(KuzzleSearchResult); + should(res).be.an.instanceOf(SearchResult); should(res.total).be.a.Number().and.be.exactly(result.result.total); should(res.documents).be.an.Array(); should(res.documents.length).be.exactly(result.result.hits.length); - should(res.searchArgs.options.scrollId).be.exactly('banana'); + should(res.options.scrollId).be.exactly('banana'); should(res.aggregations).be.deepEqual(result.result.aggregations); res.documents.forEach(function (item) { @@ -129,7 +129,7 @@ describe('Collection methods', function () { }); describe('#scroll', function () { - beforeEach(() => { + beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; emitted = false; @@ -144,24 +144,24 @@ describe('Collection methods', function () { }; }); - it('should throw an error if no scrollId is set', () => { + it('should throw an error if no scrollId is set', function () { var collection = kuzzle.collection(expectedQuery.collection); - should(() => { collection.scroll(); }).throw('Collection.scroll: scrollId is required'); + should(function () { collection.scroll(); }).throw('Collection.scroll: scrollId is required'); }); - it('should throw an error if no callback is given', () => { + it('should throw an error if no callback is given', function () { var collection = kuzzle.collection(expectedQuery.collection); - should(() => { collection.scroll('scrollId', {scroll: '1m'}); }).throw('Collection.scroll: a callback argument is required for read queries'); + should(function () { collection.scroll('scrollId'); }).throw('Collection.scroll: a callback argument is required for read queries'); }); - it('should parse the given parameters', done => { + it('should parse the given parameters', function (done) { var queryScrollStub, collection = kuzzle.collection(expectedQuery.collection), scrollId = 'scrollId', filters = {}, - options = {scroll: '30s'}, - cb = () => { + options = {}, + cb = function () { done(); }; @@ -419,13 +419,29 @@ describe('Collection methods', function () { should(emitted).be.true(); }); - it('should be able to handle the updateIfExist option', function () { + it('should be able to handle the ifExist=replace option', function () { var collection = kuzzle.collection(expectedQuery.collection); expectedQuery.action = 'createOrReplace'; - collection.createDocument(result.result._source, {updateIfExist: true}); + collection.createDocument(result.result._source, {ifExist: 'replace'}); + should(emitted).be.true(); + }); + + it('should be able to handle the ifExist=error option', function () { + var collection = kuzzle.collection(expectedQuery.collection); + expectedQuery.action = 'create'; + + collection.createDocument(result.result._source, {ifExist: 'error'}); should(emitted).be.true(); }); + + it('should throw an error if the ifExist option is invalid', function () { + var collection = kuzzle.collection(expectedQuery.collection); + + should(function () { + collection.createDocument(result.result._source, {ifExist: 'foobar'}); + }).throw(); + }); }); describe('#deleteDocument', function () { @@ -490,7 +506,7 @@ describe('Collection methods', function () { filters = { and: [ {term: {foo: 'bar'}}, { ids: ['baz', 'qux'] } ] }; this.timeout(50); - expectedQuery.body = filters; + expectedQuery.body = {query: filters}; expectedQuery.action = 'deleteByQuery'; result = { result: {ids: ['foo', 'bar'] }}; @@ -603,7 +619,7 @@ describe('Collection methods', function () { it('should handle the callback argument correctly', function () { var collection = kuzzle.collection('collection'), - mockSearchResult = new KuzzleSearchResult( + mockSearchResult = new SearchResult( collection, 1, [new Document(collection, 'banana', {answer: 42})], @@ -623,7 +639,7 @@ describe('Collection methods', function () { should(emitted).be.true(); }); - it('should handle the from and size options', () => { + it('should handle the from and size options', function () { var collection = kuzzle.collection('collection'), stub = sinon.stub(collection, 'search'); @@ -634,7 +650,7 @@ describe('Collection methods', function () { stub.restore(); }); - it('should handle the scroll options', () => { + it('should handle the scroll options', function () { var collection = kuzzle.collection('collection'), stub = sinon.stub(collection, 'search'); @@ -645,7 +661,7 @@ describe('Collection methods', function () { stub.restore(); }); - it('should transfer error if any', done => { + it('should transfer error if any', function (done) { var collection = kuzzle.collection('collection'); @@ -845,14 +861,14 @@ describe('Collection methods', function () { it('should instantiate a new Room object', function () { var collection = kuzzle.collection(expectedQuery.collection); - should(collection.subscribe(expectedQuery.body, {}, function () {})).be.instanceof(KuzzleSubscribeResult); + should(collection.subscribe(expectedQuery.body, {}, function () {})).be.instanceof(SubscribeResult); should(emitted).be.true(); }); it('should handle arguments correctly', function () { var collection = kuzzle.collection(expectedQuery.collection); - should(collection.subscribe(expectedQuery.body, function () {})).be.instanceof(KuzzleSubscribeResult); + should(collection.subscribe(expectedQuery.body, function () {})).be.instanceof(SubscribeResult); should(emitted).be.true(); }); @@ -949,8 +965,9 @@ describe('Collection methods', function () { it('should send the right updateDocument query to Kuzzle', function (done) { var collection = new Collection(kuzzle, expectedQuery.collection, expectedQuery.index), - options = { queuable: false }; + options = { queuable: false, retryOnConflict: 42 }; expectedQuery.options = options; + expectedQuery.retryOnConflict = 42; should(collection.updateDocument(result.result._id, result.result._source, options, function (err, res) { should(err).be.null(); diff --git a/test/CollectionMapping/methods.test.js b/test/CollectionMapping/methods.test.js index 3fe25066d..366d4b86a 100644 --- a/test/CollectionMapping/methods.test.js +++ b/test/CollectionMapping/methods.test.js @@ -44,13 +44,13 @@ describe('CollectionMapping methods', function () { }, emitted, kuzzle, - dataCollection; + collection; describe('#apply', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {_source: { properties: { foo: {type: 'date'}}}}}; error = null; @@ -66,7 +66,7 @@ describe('CollectionMapping methods', function () { it('should call the right updateMapping query when invoked', function (done) { var refreshed = false, - mapping = new CollectionMapping(dataCollection, result.result._source.properties); + mapping = new CollectionMapping(collection, result.result._source.properties); this.timeout(50); expectedQuery.options = { queuable: false}; @@ -87,7 +87,7 @@ describe('CollectionMapping methods', function () { it('should handle arguments correctly', function () { var refreshed = false, - mapping = new CollectionMapping(dataCollection, result.result._source.properties); + mapping = new CollectionMapping(collection, result.result._source.properties); mapping.refresh = function (options, cb) { refreshed = true; @@ -121,7 +121,7 @@ describe('CollectionMapping methods', function () { }); it('should invoke the callback with an error if one occurs', function (done) { - var mapping = new CollectionMapping(dataCollection, result.result._source.properties); + var mapping = new CollectionMapping(collection, result.result._source.properties); this.timeout(50); error = 'foobar'; @@ -130,7 +130,7 @@ describe('CollectionMapping methods', function () { should(emitted).be.true(); emitted = false; - mapping.apply((err, res) => { + mapping.apply(function (err, res) { should(emitted).be.true(); should(err).be.exactly('foobar'); should(res).be.undefined(); @@ -143,7 +143,7 @@ describe('CollectionMapping methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {bar: { mappings: { foo: { properties: { foo: {type: 'date'}}}}}}}; error = null; @@ -157,7 +157,7 @@ describe('CollectionMapping methods', function () { }); it('should call the right getMapping query when invoked', function (done) { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); this.timeout(50); expectedQuery.options = { queuable: false}; @@ -166,13 +166,13 @@ describe('CollectionMapping methods', function () { should(emitted).be.true(); should(err).be.null(); should(res).be.exactly(mapping); - should(res.mapping).match(result.result[dataCollection.index].mappings.foo.properties); + should(res.mapping).match(result.result[collection.index].mappings.foo.properties); done(); })).be.exactly(mapping); }); it('should handle arguments correctly', function () { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); mapping.refresh(function () {}); should(emitted).be.true(); @@ -191,7 +191,7 @@ describe('CollectionMapping methods', function () { }); it('should invoke the callback with an error if one occurs', function (done) { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); this.timeout(50); error = 'foobar'; @@ -200,7 +200,7 @@ describe('CollectionMapping methods', function () { should(emitted).be.true(); emitted = false; - mapping.refresh((err, res) => { + mapping.refresh(function (err, res) { should(emitted).be.true(); should(err).be.exactly('foobar'); should(res).be.undefined(); @@ -209,11 +209,11 @@ describe('CollectionMapping methods', function () { }); it('should return a "no mapping" error if the index is not found in the mapping', function (done) { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); result = { result: {foobar: { mappings: { foo: { properties: { foo: {type: 'date'}}}}}}}; - mapping.refresh((err, res) => { + mapping.refresh(function (err, res) { should(emitted).be.true(); should(err).be.an.Error(); should(err.message).startWith('No mapping found for index'); @@ -223,11 +223,11 @@ describe('CollectionMapping methods', function () { }); it('should return a "no mapping" error if the index is not found in the mapping', function (done) { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); result = { result: {bar: { mappings: { foobar: { properties: { foo: {type: 'date'}}}}}}}; - mapping.refresh((err, res) => { + mapping.refresh(function (err, res) { should(emitted).be.true(); should(err).be.an.Error(); should(err.message).startWith('No mapping found for collection'); @@ -236,12 +236,12 @@ describe('CollectionMapping methods', function () { }); }); - it('should return an empty mapping if the stored mapping is empty', done => { - var mapping = new CollectionMapping(dataCollection); + it('should return an empty mapping if the stored mapping is empty', function (done) { + var mapping = new CollectionMapping(collection); result = { result: {bar: { mappings: { foo: {}}}}}; - mapping.refresh((err, res) => { + mapping.refresh(function (err, res) { should(emitted).be.true(); should(err).be.null(); should(res).be.exactly(mapping); @@ -254,11 +254,11 @@ describe('CollectionMapping methods', function () { describe('#set', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should allow setting a field mapping', function () { - var mapping = new CollectionMapping(dataCollection); + var mapping = new CollectionMapping(collection); should(mapping.set('foo', { type: 'date'})).be.exactly(mapping); should(mapping.mapping.foo).match({type: 'date'}); @@ -274,12 +274,12 @@ describe('CollectionMapping methods', function () { describe('#setHeaders', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should allow setting headers', function () { var - mapping = new CollectionMapping(dataCollection), + mapping = new CollectionMapping(collection), header = {_id: 'foobar'}; should(mapping.setHeaders(header)).be.exactly(mapping); diff --git a/test/Document/constructor.test.js b/test/Document/constructor.test.js index 1867f9b2c..a60a3cddb 100644 --- a/test/Document/constructor.test.js +++ b/test/Document/constructor.test.js @@ -9,7 +9,7 @@ describe('Document constructor', function () { var kuzzle, refreshed = false, - dataCollection; + collection; before(function () { Kuzzle.prototype.bluebird = bluebird; @@ -24,11 +24,11 @@ describe('Document constructor', function () { refreshed = true; }; refreshed = false; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should handle provided arguments correctly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should(document).be.instanceof(Document); should(refreshed).be.false(); @@ -37,21 +37,21 @@ describe('Document constructor', function () { should(document.version).be.undefined(); should(document.collection).be.exactly('foo'); - document = new Document(dataCollection, { some: 'content' }); + document = new Document(collection, { some: 'content' }); should(refreshed).be.false(); should(document.id).be.undefined(); should(document.content).match({some: 'content'}); should(document.version).be.undefined(); should(document.collection).be.exactly('foo'); - document = new Document(dataCollection, 'id', { some: 'content', _version: 123 }); + document = new Document(collection, 'id', { some: 'content', _version: 123 }); should(refreshed).be.false(); should(document.id).be.exactly('id'); should(document.content).match({some: 'content'}); should(document.version).be.exactly(123); should(document.collection).be.exactly('foo'); - document = new Document(dataCollection, 'id'); + document = new Document(collection, 'id'); should(refreshed).be.false(); should(document.id).be.exactly('id'); should(document.content).be.empty(); @@ -60,7 +60,7 @@ describe('Document constructor', function () { }); it('should expose documented properties with the right permissions', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should(document).have.propertyWithDescriptor('collection', { enumerable: true, writable: false, configurable: false }); should(document).have.propertyWithDescriptor('content', { enumerable: true, writable: true, configurable: false }); @@ -70,7 +70,7 @@ describe('Document constructor', function () { }); it('should promisify the right functions', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should.exist(document.deletePromise); should.not.exist(document.publishPromise); diff --git a/test/Document/methods.test.js b/test/Document/methods.test.js index f9daea019..0b2c0c566 100644 --- a/test/Document/methods.test.js +++ b/test/Document/methods.test.js @@ -3,7 +3,7 @@ var rewire = require('rewire'), Kuzzle = rewire('../../src/Kuzzle'), Document = rewire('../../src/Document'), - KuzzleSubscribeResult = require('../../src/SubscribeResult'); + SubscribeResult = require('../../src/SubscribeResult'); describe('Document methods', function () { var @@ -45,17 +45,17 @@ describe('Document methods', function () { }, emitted, kuzzle, - dataCollection; + collection; describe('#toJSON', function () { before(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should serialize itself properly', function () { var - document = new Document(dataCollection, {some: 'content'}), + document = new Document(collection, {some: 'content'}), serialized = document.serialize(); should(serialized._id).be.undefined(); @@ -79,12 +79,12 @@ describe('Document methods', function () { describe('#toString', function () { before(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should stringify itself properly', function () { var - document = new Document(dataCollection, 'id', {some: 'content', _version: 42}), + document = new Document(collection, 'id', {some: 'content', _version: 42}), serialized = document.serialize(), stringified = document.toString(); @@ -97,7 +97,7 @@ describe('Document methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = {}; error = null; @@ -114,7 +114,7 @@ describe('Document methods', function () { it('should send the right query to Kuzzle', function () { var options = { queuable: false }, - document = new Document(dataCollection); + document = new Document(collection); expectedQuery.options = options; document.id = 'foo'; @@ -123,7 +123,7 @@ describe('Document methods', function () { }); it('should handle arguments correctly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.id = 'foo'; document.delete(function () {}); @@ -143,14 +143,14 @@ describe('Document methods', function () { }); it('should throw an error if no ID has been set', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should(function () { document.delete(); }).throw(Error); should(emitted).be.false(); }); it('should resolve the callback with its own id as a result', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); document.id = 'foo'; @@ -164,7 +164,7 @@ describe('Document methods', function () { }); it('should revolve the callback with an error if one occurs', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); document.id = 'foo'; @@ -183,7 +183,7 @@ describe('Document methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {_id: 'foo', _version: 42, _source: {some: 'content'}}}; error = null; @@ -200,7 +200,7 @@ describe('Document methods', function () { it('should send the right query to Kuzzle', function () { var options = { queuable: false }, - document = new Document(dataCollection); + document = new Document(collection); expectedQuery.options = options; document.id = 'foo'; @@ -210,14 +210,14 @@ describe('Document methods', function () { it('should throw an error if no callback is provided', function () { var - document = new Document(dataCollection); + document = new Document(collection); document.id = 'foo'; should(function () { document.refresh(); }).throw(); }); it('should handle arguments correctly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.id = 'foo'; document.refresh(function () {}); @@ -229,14 +229,14 @@ describe('Document methods', function () { }); it('should throw an error if no ID has been set', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should(function () { document.refresh(); }).throw(Error); should(emitted).be.false(); }); it('should resolve the callback with itself as a result', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); document.id = 'foo'; @@ -253,7 +253,7 @@ describe('Document methods', function () { }); it('should revolve the callback with an error if one occurs', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); document.id = 'foo'; @@ -272,7 +272,7 @@ describe('Document methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = {result: { _id: 'foo', _version: 42}}; error = null; @@ -288,7 +288,7 @@ describe('Document methods', function () { it('should send the right query to Kuzzle', function () { var options = { queuable: false }, - document = new Document(dataCollection); + document = new Document(collection); expectedQuery.options = options; document.id = 'foo'; @@ -297,7 +297,7 @@ describe('Document methods', function () { }); it('should handle arguments correctly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.save(function () {}); should(emitted).be.true(); @@ -316,7 +316,7 @@ describe('Document methods', function () { }); it('should resolve the callback with itself as a result', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); @@ -331,7 +331,7 @@ describe('Document methods', function () { }); it('should revolve the callback with an error if one occurs', function (done) { - var document = new Document(dataCollection); + var document = new Document(collection); this.timeout(50); error = 'foobar'; @@ -349,7 +349,7 @@ describe('Document methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = {}; error = null; @@ -365,7 +365,7 @@ describe('Document methods', function () { it('should send the right query to Kuzzle', function () { var options = { queuable: false }, - document = new Document(dataCollection); + document = new Document(collection); expectedQuery.options = options; should(document.publish(options)).be.exactly(document); @@ -373,7 +373,7 @@ describe('Document methods', function () { }); it('should handle arguments correctly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.publish(); should(emitted).be.true(); @@ -387,11 +387,11 @@ describe('Document methods', function () { describe('#setContent', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should update the content if "replace" is falsey', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.content = { foo: 'foo', bar: 'bar' }; should(document.setContent({foo: 'foobar'})).be.exactly(document); @@ -400,7 +400,7 @@ describe('Document methods', function () { }); it('should replace the current content if "replace" is true', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.content = { foo: 'foo', bar: 'bar' }; should(document.setContent({foo: 'foobar'}, true)).be.exactly(document); @@ -413,7 +413,7 @@ describe('Document methods', function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; kuzzle.state = 'connected'; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {roomId: 'foo', channel: 'bar'}}; error = null; @@ -428,15 +428,15 @@ describe('Document methods', function () { it('should return a new Room object', function () { var - document = new Document(dataCollection); + document = new Document(collection); document.id = 'foo'; - should(document.subscribe({}, function () {})).be.instanceof(KuzzleSubscribeResult); + should(document.subscribe({}, function () {})).be.instanceof(SubscribeResult); should(emitted).be.true(); }); it('should handle arguments properly', function () { - var document = new Document(dataCollection); + var document = new Document(collection); document.id = 'foo'; document.subscribe(function () {}); @@ -444,7 +444,7 @@ describe('Document methods', function () { }); it('should throw an error if no ID is provided', function () { - var document = new Document(dataCollection); + var document = new Document(collection); should(function () { document.subscribe(function () {}); }).throw(Error); should(emitted).be.false(); @@ -454,12 +454,12 @@ describe('Document methods', function () { describe('#setHeaders', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should properly set headers', function () { var - document = new Document(dataCollection), + document = new Document(collection), header = {_id: 'foobar'}; should(document.setHeaders(header)).be.exactly(document); diff --git a/test/MemoryStorage/constructor.test.js b/test/MemoryStorage/constructor.test.js index 6b7184023..3ad08fccf 100644 --- a/test/MemoryStorage/constructor.test.js +++ b/test/MemoryStorage/constructor.test.js @@ -6,7 +6,7 @@ var Kuzzle = rewire('../../src/Kuzzle'); describe('MemoryStorage constructor', function () { - it('should initialize properties and return a valid MemoryStorage object', () => { + it('should initialize properties and return a valid MemoryStorage object', function () { var kuzzle = new Kuzzle('foo'), ms; @@ -24,7 +24,7 @@ describe('MemoryStorage constructor', function () { should(ms.headers.someother).be.undefined(); }); - it('should promisify all methods', () => { + it('should promisify all methods', function () { var kuzzle, ms, @@ -35,9 +35,13 @@ describe('MemoryStorage constructor', function () { kuzzle = new Kuzzle('foo'); ms = new MemoryStorage(kuzzle); - functions = Object.getOwnPropertyNames(Object.getPrototypeOf(ms)).filter(p => (typeof ms[p] === 'function' && ['constructor', 'setHeaders'].indexOf(p) === -1)); - should(functions.length).be.eql(119); - functions.forEach(f => { + functions = Object.getOwnPropertyNames(Object.getPrototypeOf(ms)).filter(function (p) { + return (typeof ms[p] === 'function' && ['constructor', 'setHeaders'].indexOf(p) === -1); + }); + + should(functions.length).be.eql(117); + + functions.forEach(function (f) { should(ms[f + 'Promise']).be.a.Function(); }); @@ -56,4 +60,14 @@ describe('MemoryStorage constructor', function () { should(ms.headers).match({foo: 'bar', bar: 'foobar'}); }); + it('auto-generated functions should throw if the wrong number of parameters is provided', function () { + var + emptyFunc = function () {}, + kuzzle = new Kuzzle('foo'), + ms = new MemoryStorage(kuzzle); + + should(function () {ms.dbsize('foo', {}, emptyFunc);}).throw('MemoryStorage.dbsize: Too many parameters provided'); + should(function () {ms.mget(emptyFunc);}).throw('MemoryStorage.mget: Missing parameter "keys"'); + should(function () {ms.ping(['foo', 'bar'], emptyFunc);}).throw('MemoryStorage.ping: Invalid optional parameter (expected an object)'); + }); }); diff --git a/test/MemoryStorage/methods.test.js b/test/MemoryStorage/methods.test.js index 3a4471bfb..9d516d87f 100644 --- a/test/MemoryStorage/methods.test.js +++ b/test/MemoryStorage/methods.test.js @@ -1,101 +1,1507 @@ var should = require('should'), Kuzzle = require('../stubs/kuzzle.stub'), - MemoryStorage = require('../../src/MemoryStorage'); + MemoryStorage = require('../../src/MemoryStorage'), + sinon = require('sinon'); -describe('MemoryStorage methods', () => { +describe('MemoryStorage methods', function () { var - kuzzle = new Kuzzle('foo'), + kuzzle, + ms, + sandbox = sinon.sandbox.create(), + emptyFunc = function () {}, + queryStub; + + before(function () { + kuzzle = new Kuzzle('foo'); + kuzzle.bluebird = require('bluebird'); ms = new MemoryStorage(kuzzle); + }); - describe('#regular case', () => { - it('should parse the given arguments (no options)', () => { - ms.append('foo', 'bar', (err, r) => { - should(r.args).match({ - controller: 'ms', - action: 'append' - }); - should(r.query).match({ - _id: 'foo', - body: { value: 'bar' } - }); - should(r.cb).be.a.Function(); - }); - }); - - it('should parse the given arguments (w options)', () => { - ms.append('foo', 'bar', { queuable: true}, (err, r) => { - should(r.args).match({ - controller: 'ms', - action: 'append' - }); - should(r.query).match({ - _id: 'foo', - body: { value: 'bar' } - }); - should(r.options).match({ queuable: true }); - should(r.cb).be.a.Function(); + beforeEach(function () { + sandbox.restore(); + queryStub = sandbox.stub(kuzzle, 'query'); + }); + + function testReadCommand(command, args, opts, expArgs, expOpts, result, expected, defaultOpts) { + var + query = {controller: 'ms', action: command}, + expectedQueryArgs = Object.assign({}, expArgs, defaultOpts || {}), + expectedQueryArgsWithOpts = Object.assign({}, expectedQueryArgs, expOpts); + + should(function () {ms[command].apply(ms, args);}).throw('MemoryStorage.' + command + ': a callback argument is required for read queries'); + should(function () {ms[command].apply(ms, args.concat(opts));}).throw('MemoryStorage.' + command + ': a callback argument is required for read queries'); + + ms[command].apply(ms, args.concat(emptyFunc)); + should(queryStub).calledWith(query, expectedQueryArgs, null, sinon.match.func); + + ms[command].apply(ms, args.concat(opts, emptyFunc)); + should(queryStub).calledWith(query, expectedQueryArgsWithOpts, {}, sinon.match.func); + + queryStub.yields(null, {result: result}); + return ms[command + 'Promise'].apply(ms, args) + .then(function (res) { + should(res).be.eql(expected); }); - }); - - it('should handle arguments with multiple cardinality', () => { - ms.sinter('foo', (err, r) => { - should(r.args).match({ - controller: 'ms', - action: 'sinter' - }); - should(r.query).match({ - _id: 'foo' - }); - should.not.exist(r.query.body); + } + + function testWriteCommand(command, args, opts, expArgs, expOpts, result, expected) { + var + query = {controller: 'ms', action: command}, + expectedQueryArgsWithOpts = Object.assign({}, expArgs); + + if (!expArgs.body) { + expArgs.body = {}; + } + + expectedQueryArgsWithOpts.body = Object.assign({}, expArgs.body, expOpts); + + ms[command].apply(ms, args); + should(queryStub).calledWith(query, expArgs, null, undefined); + + ms[command].apply(ms, args.concat(opts)); + should(queryStub).calledWith(query, expectedQueryArgsWithOpts, {}, undefined); + + ms[command].apply(ms, args.concat(emptyFunc)); + should(queryStub).calledWith(query, expArgs, null, sinon.match.func); + + ms[command].apply(ms, args.concat(opts, emptyFunc)); + should(queryStub).calledWith(query, expectedQueryArgsWithOpts, {}, sinon.match.func); + + queryStub.yields(null, {result: result}); + return ms[command + 'Promise'].apply(ms, args) + .then(function (res) { + should(res).be.eql(expected); }); + } + + it('#append', function () { + return testWriteCommand( + 'append', + ['key', 'value'], + {}, + {_id: 'key', body: {value: 'value'}}, + {}, + 123, + 123 + ); + }); + + it('#bitcount', function () { + return testReadCommand( + 'bitcount', + ['key'], + {start: 2, end: 42}, + {_id: 'key'}, + {start: 2, end: 42}, + 123, + 123 + ); + }); + + it('#bitop', function () { + return testWriteCommand( + 'bitop', + ['key', 'and', ['foo', 'bar']], + {}, + {_id: 'key', body: {operation: 'and', keys: ['foo', 'bar']}}, + {}, + 123, + 123 + ); + }); + + it('#bitpos', function () { + return testReadCommand( + 'bitpos', + ['key', 0], + {start: 2, end: 42}, + {_id: 'key', bit: 0}, + {start: 2, end: 42}, + 123, + 123 + ); + }); + + it('#dbsize', function () { + return testReadCommand('dbsize', [], {}, {}, {}, 123, 123); + }); + + it('#decr', function () { + return testWriteCommand( + 'decr', + ['key'], + {}, + {_id: 'key'}, + {}, + 123, + 123 + ); + }); + + it('#decrby', function () { + return testWriteCommand( + 'decrby', + ['key', 42], + {}, + {_id: 'key', body: {value: 42}}, + {}, + 123, + 123 + ); + }); + + it('#del', function () { + return testWriteCommand( + 'del', + [['key1', 'key2', 'key3']], + {}, + {body: {keys: ['key1', 'key2', 'key3']}}, + {}, + 123, + 123 + ); + }); + + it('#exists', function () { + return testReadCommand( + 'exists', + [['key1', 'key2', 'key3']], + {}, + {keys: ['key1', 'key2', 'key3']}, + {}, + 123, + 123 + ); + }); + + it('#expire', function () { + return testWriteCommand( + 'expire', + ['key', 42], + {}, + {_id: 'key', body: {seconds: 42}}, + {}, + 1, + 1 + ); + }); + + it('#expireat', function () { + return testWriteCommand( + 'expireat', + ['key', 123456789], + {}, + {_id: 'key', body: {timestamp: 123456789}}, + {}, + 1, + 1 + ); + }); + + it('#flushdb', function () { + return testWriteCommand('flushdb', [], {}, {}, {}, 'OK', 'OK'); + }); + + it('#geoadd', function () { + var points = [ + { + lon: 13.361389, + lat: 38.115556, + name: 'Palermo' + }, + { + lon: 15.087269, + lat: 37.502669, + name: 'Catania' + } + ]; + + return testWriteCommand( + 'geoadd', + ['key', points], + {}, + {_id: 'key', body: {points: points}}, + {}, + 1, + 1 + ); + }); + + it('#geodist', function () { + return testReadCommand( + 'geodist', + ['key', 'Palermo', 'Catania'], + {unit: 'ft'}, + {_id: 'key', member1: 'Palermo', member2: 'Catania'}, + {unit: 'ft'}, + '12345.678', + 12345.678 + ); + }); + + it('#geohash', function () { + return testReadCommand( + 'geohash', + ['key', ['Palermo', 'Catania']], + {}, + {_id: 'key', members: ['Palermo', 'Catania']}, + {}, + ['foo', 'bar'], + ['foo', 'bar'] + ); + }); - ms.sinter(['foo', 'bar'], (err, r) => { - should(r.args).match({ - controller: 'ms', - action: 'sinter' - }); - should(r.query).match({ - body: {keys: ['foo', 'bar']} - }); + it('#geopos', function () { + return testReadCommand( + 'geopos', + ['key', ['Palermo', 'Catania']], + {}, + {_id: 'key', members: ['Palermo', 'Catania']}, + {}, + [['123.45', '67.89'], ['3.14', '6.98']], + [[123.45, 67.89], [3.14, 6.98]] + ); + }); + + it('#georadius', function () { + return testReadCommand( + 'georadius', + ['key', 15, 37, 200, 'km'], + {count: 12, sort: 'ASC', withcoord: true, withdist: true}, + {_id: 'key', lon: 15, lat: 37, distance: 200, unit: 'km'}, + {options: ['count', 12, 'ASC', 'withcoord', 'withdist']}, + [['Palermo', '190.4424', ['13.36', '38.11']], ['Catania', '56.44', ['15.08', '37.5']]], + [ + {name: 'Palermo', distance: 190.4424, coordinates: [13.36, 38.11]}, + {name: 'Catania', distance: 56.44, coordinates: [15.08, 37.5]} + ] + ) + .then(function () { + return testReadCommand( + 'georadius', + ['key', 15, 37, 200, 'km'], + {}, + {_id: 'key', lon: 15, lat: 37, distance: 200, unit: 'km'}, + {}, + ['Palermo', 'Catania'], + [{name: 'Palermo'}, {name: 'Catania'}] + ); }); - }); - }); - - describe('#functions with optional parameters', () => { - it('should parse all given arguments', () => { - ms.zadd('foo', { - nx: true, - xx: true, - ch: true, - incr: 2, - score: 'score', - member: 'member', - members: [ - {score: 's1', member: 'm1'}, - {score: 's2', member: 'm2'} - ] - }, (err, r) => { - should(r.args).match({ - controller: 'ms', - action: 'zadd' - }); - should(r.query).match({ - _id: 'foo', - body: { - nx: true, - xx: true, - ch: true, - incr: 2, - score: 'score', - member: 'member', - members: [ - {score: 's1', member: 'm1'}, - {score: 's2', member: 'm2'} - ] - } - }); + }); + + it('#georadiusbymember', function () { + return testReadCommand( + 'georadiusbymember', + ['key', 'Palermo', 200, 'km'], + {count: 12, sort: 'ASC', withcoord: true, withdist: true}, + {_id: 'key', member: 'Palermo', distance: 200, unit: 'km'}, + {options: ['count', 12, 'ASC', 'withcoord', 'withdist']}, + [['Palermo', '190.4424', ['13.36', '38.11']], ['Catania', '56.44', ['15.08', '37.5']]], + [ + {name: 'Palermo', distance: 190.4424, coordinates: [13.36, 38.11]}, + {name: 'Catania', distance: 56.44, coordinates: [15.08, 37.5]} + ] + ) + .then(function () { + return testReadCommand( + 'georadiusbymember', + ['key', 'Palermo', 200, 'km'], + {}, + {_id: 'key', member: 'Palermo', distance: 200, unit: 'km'}, + {}, + ['Palermo', 'Catania'], + [{name: 'Palermo'}, {name: 'Catania'}] + ); }); - }); + }); + + it('#get', function () { + return testReadCommand( + 'get', + ['key'], + {}, + {_id: 'key'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#getbit', function () { + return testReadCommand( + 'getbit', + ['key', 10], + {}, + {_id: 'key', offset: 10}, + {}, + 1, + 1 + ); + }); + + it('#getrange', function () { + return testReadCommand( + 'getrange', + ['key', 2, 4], + {}, + {_id: 'key', start: 2, end: 4}, + {}, + 'bar', + 'bar' + ); + }); + + it('#getset', function () { + return testWriteCommand( + 'getset', + ['key', 'foobar'], + {}, + {_id: 'key', body: {value: 'foobar'}}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#hdel', function () { + return testWriteCommand( + 'hdel', + ['key', ['f1', 'f2', 'f3']], + {}, + {_id: 'key', body: {fields: ['f1', 'f2', 'f3']}}, + {}, + 2, + 2 + ); + }); + + it('#hexists', function () { + return testReadCommand( + 'hexists', + ['key', 'field'], + {}, + {_id: 'key', field: 'field'}, + {}, + 1, + 1 + ); + }); + + it('#hget', function () { + return testReadCommand( + 'hget', + ['key', 'field'], + {}, + {_id: 'key', field: 'field'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#hgetall', function () { + return testReadCommand( + 'hgetall', + ['key'], + {}, + {_id: 'key'}, + {}, + {foo: 'bar', baz: 'qux'}, + {foo: 'bar', baz: 'qux'} + ); + }); + + it('#hincrby', function () { + return testWriteCommand( + 'hincrby', + ['key', 'field', 42], + {}, + {_id: 'key', body: {field: 'field', value: 42}}, + {}, + 2, + 2 + ); + }); + + it('#hincrbyfloat', function () { + return testWriteCommand( + 'hincrbyfloat', + ['key', 'field', 3.14159], + {}, + {_id: 'key', body: {field: 'field', value: 3.14159}}, + {}, + '3.14159', + 3.14159 + ); + }); + + it('#hkeys', function () { + return testReadCommand( + 'hkeys', + ['key'], + {}, + {_id: 'key'}, + {}, + ['foo', 'bar', 'baz', 'qux'], + ['foo', 'bar', 'baz', 'qux'] + ); + }); + + it('#hlen', function () { + return testReadCommand( + 'hlen', + ['key'], + {}, + {_id: 'key'}, + {}, + 10, + 10 + ); + }); + + it('#hmget', function () { + return testReadCommand( + 'hmget', + ['key', ['f1', 'f2', 'f3']], + {}, + {_id: 'key', fields: ['f1', 'f2', 'f3']}, + {}, + ['foo', 'bar', 'baz', 'qux'], + ['foo', 'bar', 'baz', 'qux'] + ); + }); + + it('#hmset', function () { + var entries = [ + {field: 'foo', value: 'bar'}, + {field: 'baz', value: 'qux'} + ]; + + return testWriteCommand( + 'hmset', + ['key', entries], + {}, + {_id: 'key', body: {entries: entries}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#hscan', function () { + return testReadCommand( + 'hscan', + ['key', 0], + {count: 42, match: 'foo*'}, + {_id: 'key', cursor: 0}, + {count: 42, match: 'foo*'}, + [42, ['bar', 'baz', 'qux']], + [42, ['bar', 'baz', 'qux']] + ); + }); + + it('#hset', function () { + return testWriteCommand( + 'hset', + ['key', 'field', 'value'], + {}, + {_id: 'key', body: {field: 'field', value: 'value'}}, + {}, + 1, + 1 + ); + }); + + it('#hsetnx', function () { + return testWriteCommand( + 'hsetnx', + ['key', 'field', 'value'], + {}, + {_id: 'key', body: {field: 'field', value: 'value'}}, + {}, + 1, + 1 + ); + }); + + it('#hstrlen', function () { + return testReadCommand( + 'hstrlen', + ['key', 'field'], + {}, + {_id: 'key', field: 'field'}, + {}, + 10, + 10 + ); + }); + + it('#hvals', function () { + return testReadCommand( + 'hvals', + ['key'], + {}, + {_id: 'key'}, + {}, + ['foo', 'bar', 'baz', 'qux'], + ['foo', 'bar', 'baz', 'qux'] + ); + }); + + it('#incr', function () { + return testWriteCommand( + 'incr', + ['key'], + {}, + {_id: 'key'}, + {}, + 123, + 123 + ); + }); + + it('#incrby', function () { + return testWriteCommand( + 'incrby', + ['key', -3], + {}, + {_id: 'key', body: {value: -3}}, + {}, + 123, + 123 + ); + }); + + it('#incrbyfloat', function () { + return testWriteCommand( + 'incrbyfloat', + ['key', -3.14], + {}, + {_id: 'key', body: {value: -3.14}}, + {}, + '123.12', + 123.12 + ); + }); + + it('#keys', function () { + return testReadCommand( + 'keys', + ['pattern'], + {}, + {pattern: 'pattern'}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#lindex', function () { + return testReadCommand( + 'lindex', + ['key', 3], + {}, + {_id: 'key', index: 3}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#linsert', function () { + return testWriteCommand( + 'linsert', + ['key', 'after', 'foo', 'bar'], + {}, + {_id: 'key', body: {position: 'after', pivot: 'foo', value: 'bar'}}, + {}, + 4, + 4 + ); + }); + + it('#llen', function () { + return testReadCommand( + 'llen', + ['key'], + {}, + {_id: 'key'}, + {}, + 4, + 4 + ); + }); + + it('#lpop', function () { + return testWriteCommand( + 'lpop', + ['key'], + {}, + {_id: 'key'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#lpush', function () { + return testWriteCommand( + 'lpush', + ['key', ['foo', 'bar', 'baz']], + {}, + {_id: 'key', body: {values: ['foo', 'bar', 'baz']}}, + {}, + 4, + 4 + ); + }); + + it('#lpushx', function () { + return testWriteCommand( + 'lpushx', + ['key', 'foo'], + {}, + {_id: 'key', body: {value: 'foo'}}, + {}, + 4, + 4 + ); + }); + + it('#lrange', function () { + return testReadCommand( + 'lrange', + ['key', 0, 1], + {}, + {_id: 'key', start: 0, stop: 1}, + {}, + ['foo', 'bar'], + ['foo', 'bar'] + ); + }); + + it('#lrem', function () { + return testWriteCommand( + 'lrem', + ['key', 1, 'foo'], + {}, + {_id: 'key', body: {count: 1, value: 'foo'}}, + {}, + 1, + 1 + ); + }); + + it('#lset', function () { + return testWriteCommand( + 'lset', + ['key', 1, 'foo'], + {}, + {_id: 'key', body: {index: 1, value: 'foo'}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#ltrim', function () { + return testWriteCommand( + 'ltrim', + ['key', 1, 2], + {}, + {_id: 'key', body: {start: 1, stop: 2}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#mget', function () { + return testReadCommand( + 'mget', + [['k1', 'k2', 'k3']], + {}, + {keys: ['k1', 'k2', 'k3']}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#mset', function () { + var entries = [ + {key: 'foo', value: 'bar'}, + {key: 'baz', value: 'qux'} + ]; + + return testWriteCommand( + 'mset', + [entries], + {}, + {body: {entries: entries}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#msetnx', function () { + var entries = [ + {key: 'foo', value: 'bar'}, + {key: 'baz', value: 'qux'} + ]; + + return testWriteCommand( + 'mset', + [entries], + {}, + {body: {entries: entries}}, + {}, + 1, + 1 + ); + }); + + it('#object', function () { + return testReadCommand( + 'object', + ['key', 'encoding'], + {}, + {_id: 'key', subcommand: 'encoding'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#persist', function () { + return testWriteCommand( + 'persist', + ['key'], + {}, + {_id: 'key'}, + {}, + 1, + 1 + ); + }); + + it('#pexpire', function () { + return testWriteCommand( + 'pexpire', + ['key', 42000], + {}, + {_id: 'key', body: {milliseconds: 42000}}, + {}, + 1, + 1 + ); + }); + + it('#pexpireat', function () { + return testWriteCommand( + 'pexpireat', + ['key', 123456789], + {}, + {_id: 'key', body: {timestamp: 123456789}}, + {}, + 1, + 1 + ); + }); + + it('#pfadd', function () { + return testWriteCommand( + 'pfadd', + ['key', ['foo', 'bar', 'baz']], + {}, + {_id: 'key', body: {elements: ['foo', 'bar', 'baz']}}, + {}, + 1, + 1 + ); + }); + + it('#pfcount', function () { + return testReadCommand( + 'pfcount', + [['k1', 'k2', 'k3']], + {}, + {keys: ['k1', 'k2', 'k3']}, + {}, + 42, + 42 + ); + }); + + it('#pfmerge', function () { + return testWriteCommand( + 'pfmerge', + ['key', ['key1', 'key2', 'key3']], + {}, + {_id: 'key', body: {sources: ['key1', 'key2', 'key3']}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#ping', function () { + return testReadCommand('ping', [], {}, {}, {}, 'PONG', 'PONG'); + }); + + it('#psetex', function () { + return testWriteCommand( + 'psetex', + ['key', 'value', 42000], + {}, + {_id: 'key', body: {value: 'value', milliseconds: 42000}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#pttl', function () { + return testReadCommand( + 'pttl', + ['key'], + {}, + {_id: 'key'}, + {}, + 42000, + 42000 + ); + }); + + it('#randomkey', function () { + return testReadCommand('randomkey', [], {}, {}, {}, 'key', 'key'); + }); + + it('#rename', function () { + return testWriteCommand( + 'rename', + ['key', 'newId'], + {}, + {_id: 'key', body: {newkey: 'newId'}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#renamenx', function () { + return testWriteCommand( + 'renamenx', + ['key', 'newId'], + {}, + {_id: 'key', body: {newkey: 'newId'}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#rpop', function () { + return testWriteCommand( + 'rpop', + ['key'], + {}, + {_id: 'key'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#rpoplpush', function () { + return testWriteCommand( + 'rpoplpush', + ['src', 'dest'], + {}, + {body: {source: 'src', destination: 'dest'}}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#rpush', function () { + return testWriteCommand( + 'rpush', + ['key', ['foo', 'bar', 'baz']], + {}, + {_id: 'key', body: {values: ['foo', 'bar', 'baz']}}, + {}, + 4, + 4 + ); + }); + + it('#rpushx', function () { + return testWriteCommand( + 'rpushx', + ['key', 'foo'], + {}, + {_id: 'key', body: {value: 'foo'}}, + {}, + 4, + 4 + ); + }); + + it('#sadd', function () { + return testWriteCommand( + 'sadd', + ['key', ['foo', 'bar', 'baz']], + {}, + {_id: 'key', body: {members: ['foo', 'bar', 'baz']}}, + {}, + 4, + 4 + ); + }); + + it('#scan', function () { + return testReadCommand( + 'scan', + [0], + {count: 42, match: 'foo*'}, + {cursor: 0}, + {count: 42, match: 'foo*'}, + [42, ['bar', 'baz', 'qux']], + [42, ['bar', 'baz', 'qux']] + ); + }); + + it('#scard', function () { + return testReadCommand( + 'scard', + ['key'], + {}, + {_id: 'key'}, + {}, + 3, + 3 + ); + }); + + it('#sdiff', function () { + return testReadCommand( + 'sdiff', + ['key', ['foo', 'bar', 'baz']], + {}, + {_id: 'key', keys: ['foo', 'bar', 'baz']}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#sdiffstore', function () { + return testWriteCommand( + 'sdiffstore', + ['key', ['foo', 'bar', 'baz'], 'dest'], + {}, + {_id: 'key', body: {keys: ['foo', 'bar', 'baz'], destination: 'dest'}}, + {}, + 4, + 4 + ); + }); + + it('#set', function () { + return testWriteCommand( + 'set', + ['key', 'foo'], + {ex: 0, nx: true, px: 42, xx: true}, + {_id: 'key', body: {value: 'foo'}}, + {ex: 0, nx: true, px: 42, xx: true}, + 'OK', + 'OK' + ); + }); + + it('#setex', function () { + return testWriteCommand( + 'setex', + ['key', 'foo', 42], + {}, + {_id: 'key', body: {value: 'foo', seconds: 42}}, + {}, + 'OK', + 'OK' + ); + }); + + it('#setnx', function () { + return testWriteCommand( + 'setnx', + ['key', 'foo'], + {}, + {_id: 'key', body: {value: 'foo'}}, + {}, + 1, + 1 + ); + }); + + it('#sinter', function () { + return testReadCommand( + 'sinter', + [['k1', 'k2', 'k3']], + {}, + {keys: ['k1', 'k2', 'k3']}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#sinterstore', function () { + return testWriteCommand( + 'sinterstore', + ['key', ['k1', 'k2', 'k3']], + {}, + {body: {destination: 'key', keys: ['k1', 'k2', 'k3']}}, + {}, + 1, + 1 + ); + }); + + it('#sismember', function () { + return testReadCommand( + 'sismember', + ['key', 'foobar'], + {}, + {_id: 'key', member: 'foobar'}, + {}, + 123, + 123 + ); + }); + + it('#smembers', function () { + return testReadCommand( + 'smembers', + ['key'], + {}, + {_id: 'key'}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#smove', function () { + return testWriteCommand( + 'smove', + ['key', 'dest', 'member'], + {}, + {_id: 'key', body: {destination: 'dest', member: 'member'}}, + {}, + 1, + 1 + ); + }); + + it('#sort', function () { + return testReadCommand( + 'sort', + ['key'], + {alpha: true, by: 'foo', direction: 'asc', get: ['foo', 'bar'], limit: {count: 0, offset: 1}}, + {_id: 'key'}, + {alpha: true, by: 'foo', direction: 'asc', get: ['foo', 'bar'], limit: {count: 0, offset: 1}}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#spop', function () { + return testWriteCommand( + 'spop', + ['key'], + {count: 2}, + {_id: 'key'}, + {count: 2}, + ['foo', 'bar'], + ['foo', 'bar'] + ); + }); + + it('#srandmember', function () { + return testReadCommand( + 'srandmember', + ['key'], + {count: 2}, + {_id: 'key'}, + {count: 2}, + ['foo', 'bar'], + ['foo', 'bar'] + ); + }); + + it('#srem', function () { + return testWriteCommand( + 'srem', + ['key', ['m1', 'm2', 'm3']], + {}, + {_id: 'key', body: {members: ['m1', 'm2', 'm3']}}, + {}, + 3, + 3 + ); + }); + + it('#sscan', function () { + return testReadCommand( + 'sscan', + ['key', 0], + {count: 42, match: 'foo*'}, + {_id: 'key', cursor: 0}, + {count: 42, match: 'foo*'}, + [42, ['bar', 'baz', 'qux']], + [42, ['bar', 'baz', 'qux']] + ); + }); + + it('#strlen', function () { + return testReadCommand( + 'strlen', + ['key'], + {}, + {_id: 'key'}, + {}, + 10, + 10 + ); + }); + + it('#sunion', function () { + return testReadCommand( + 'sunion', + [['k1', 'k2', 'k3']], + {}, + {keys: ['k1', 'k2', 'k3']}, + {}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#sunionstore', function () { + return testWriteCommand( + 'sunionstore', + ['key', ['k1', 'k2', 'k3']], + {}, + {body: {destination: 'key', keys: ['k1', 'k2', 'k3']}}, + {}, + 1, + 1 + ); + }); + + it('#time', function () { + return testReadCommand('time', [], {}, {}, {}, [123, 45], [123, 45]); + }); + + it('#touch', function () { + return testWriteCommand( + 'touch', + [['k1', 'k2', 'k3']], + {}, + {body: {keys: ['k1', 'k2', 'k3']}}, + {}, + 3, + 3 + ); + }); + + it('#ttl', function () { + return testReadCommand( + 'ttl', + ['key'], + {}, + {_id: 'key'}, + {}, + 42, + 42 + ); + }); + + it('#type', function () { + return testReadCommand( + 'type', + ['key'], + {}, + {_id: 'key'}, + {}, + 'foobar', + 'foobar' + ); + }); + + it('#zadd', function () { + var elements = [ + {'score': 1, 'member': 'foo'}, + {'score': 2, 'member': 'bar'}, + {'score': 3, 'member': 'baz'} + ]; + + return testWriteCommand( + 'zadd', + ['key', elements], + {ch: true, incr: false, nx: true, xx: true}, + {_id: 'key', body: {elements: elements}}, + {ch: true, incr: false, nx: true, xx: true}, + 3, + 3 + ); + }); + + it('#zcard', function () { + return testReadCommand( + 'zcard', + ['key'], + {}, + {_id: 'key'}, + {}, + 3, + 3 + ); + }); + + it('#zcount', function () { + return testReadCommand( + 'zcount', + ['key', 2, 3], + {}, + {_id: 'key', min: 2, max: 3}, + {}, + 3, + 3 + ); + }); + + it('#zincrby', function () { + return testWriteCommand( + 'zincrby', + ['key', 'foo', 42], + {}, + {_id: 'key', body: {member: 'foo', value: 42}}, + {}, + 2, + 2 + ); + }); + + it('#zinterstore', function () { + return testWriteCommand( + 'zinterstore', + ['key', ['k1', 'k2', 'k3']], + {aggregate: 'min', weights: [1, 2, 3]}, + {_id: 'key', body: {keys: ['k1', 'k2', 'k3']}}, + {aggregate: 'min', weights: [1, 2, 3]}, + 1, + 1 + ); + }); + + it('#zlexcount', function () { + return testReadCommand( + 'zlexcount', + ['key', 'foo', 'bar'], + {}, + {_id: 'key', min: 'foo', max: 'bar'}, + {}, + 3, + 3 + ); + }); + + it('#zrange', function () { + return testReadCommand( + 'zrange', + ['key', 0, -1], + {}, + {_id: 'key', start: 0, stop: -1}, + {}, + ['foo', 123, 'bar', 456], + [{member: 'foo', score: 123}, {member: 'bar', score: 456}], + {options: ['withscores']} + ); + }); + + it('#zrangebylex', function () { + return testReadCommand( + 'zrangebylex', + ['key', 'a', 'z'], + {limit: [0, 1]}, + {_id: 'key', min: 'a', max: 'z'}, + {limit: [0, 1]}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#zrevrangebylex', function () { + return testReadCommand( + 'zrevrangebylex', + ['key', 'a', 'z'], + {limit: [0, 1]}, + {_id: 'key', min: 'a', max: 'z'}, + {limit: [0, 1]}, + ['foo', 'bar', 'baz'], + ['foo', 'bar', 'baz'] + ); + }); + + it('#zrangebyscore', function () { + return testReadCommand( + 'zrangebyscore', + ['key', 0, 1000], + {limit: [0, 1]}, + {_id: 'key', min: 0, max: 1000}, + {limit: [0, 1]}, + ['foo', 123, 'bar', 456], + [{member: 'foo', score: 123}, {member: 'bar', score: 456}], + {options: ['withscores']} + ); + }); + + it('#zrank', function () { + return testReadCommand( + 'zrank', + ['key', 'foo'], + {}, + {_id: 'key', member: 'foo'}, + {}, + 3, + 3 + ); + }); + + it('#zrem', function () { + return testWriteCommand( + 'zrem', + ['key', ['m1', 'm2', 'm3']], + {}, + {_id: 'key', body: {members: ['m1', 'm2', 'm3']}}, + {}, + 3, + 3 + ); + }); + + it('#zremrangebylex', function () { + return testWriteCommand( + 'zremrangebylex', + ['key', 'a', 'z'], + {}, + {_id: 'key', body: {min: 'a', max: 'z'}}, + {}, + 3, + 3 + ); + }); + + it('#zremrangebyrank', function () { + return testWriteCommand( + 'zremrangebyrank', + ['key', 0, 3], + {}, + {_id: 'key', body: {start: 0, stop: 3}}, + {}, + 3, + 3 + ); + }); + + it('#zremrangebyscore', function () { + return testWriteCommand( + 'zremrangebyscore', + ['key', 0, 3], + {}, + {_id: 'key', body: {min: 0, max: 3}}, + {}, + 3, + 3 + ); + }); + + it('#zrevrange', function () { + return testReadCommand( + 'zrevrange', + ['key', 0, -1], + {}, + {_id: 'key', start: 0, stop: -1}, + {}, + ['foo', 123, 'bar', 456], + [{member: 'foo', score: 123}, {member: 'bar', score: 456}], + {options: ['withscores']} + ); + }); + + it('#zrevrangebyscore', function () { + return testReadCommand( + 'zrangebyscore', + ['key', 0, 1000], + {limit: [0, 1]}, + {_id: 'key', min: 0, max: 1000}, + {limit: [0, 1]}, + ['foo', 123, 'bar', 456], + [{member: 'foo', score: 123}, {member: 'bar', score: 456}], + {options: ['withscores']} + ); + }); + + it('#zrevrank', function () { + return testReadCommand( + 'zrevrank', + ['key', 'foo'], + {}, + {_id: 'key', member: 'foo'}, + {}, + 3, + 3 + ); + }); + + it('#zscan', function () { + return testReadCommand( + 'zscan', + ['key', 0], + {count: 42, match: 'foo*'}, + {_id: 'key', cursor: 0}, + {count: 42, match: 'foo*'}, + [42, ['bar', 'baz', 'qux']], + [42, ['bar', 'baz', 'qux']] + ); + }); + + it('#zscore', function () { + return testReadCommand( + 'zscore', + ['key', 'foo'], + {}, + {_id: 'key', member: 'foo'}, + {}, + '3.14159', + 3.14159 + ); + }); + + it('#zunionstore', function () { + return testWriteCommand( + 'zunionstore', + ['key', ['k1', 'k2', 'k3']], + {aggregate: 'min', weights: [1, 2, 3]}, + {_id: 'key', body: {keys: ['k1', 'k2', 'k3']}}, + {aggregate: 'min', weights: [1, 2, 3]}, + 1, + 1 + ); }); }); diff --git a/test/Room/constructor.test.js b/test/Room/constructor.test.js index 98f08d28f..7ec70840a 100644 --- a/test/Room/constructor.test.js +++ b/test/Room/constructor.test.js @@ -8,38 +8,38 @@ var describe('Room constructor', function () { var kuzzle, - dataCollection; + collection; before(function () { Kuzzle.prototype.bluebird = bluebird; kuzzle = new Kuzzle('nowhere', {defaultIndex: 'bar'}); kuzzle.headers = {foo: 'bar'}; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); }); it('should handle provided arguments correctly', function () { - var room = new Room(dataCollection); + var room = new Room(collection); - should(room.metadata).be.an.Object().and.be.empty(); + should(room.volatile).be.an.Object().and.be.empty(); should(room.subscribeToSelf).be.true(); should(room.scope).be.exactly('all'); should(room.state).be.exactly('done'); should(room.users).be.exactly('none'); - should(room.collection).be.exactly(dataCollection); + should(room.collection).be.exactly(collection); should(room.filters).be.null(); should(room.headers).match({foo: 'bar'}); should(room.roomId).be.null(); - room = new Room(dataCollection, { + room = new Room(collection, { scope: 'in', state: 'pending', users: 'all', - metadata: {some: 'metadata'}, + volatile: {some: 'metadata'}, subscribeToSelf: false }); - should(room.metadata).match({some: 'metadata'}); + should(room.volatile).match({some: 'metadata'}); should(room.subscribeToSelf).be.false(); should(room.scope).be.exactly('in'); should(room.state).be.exactly('pending'); @@ -47,7 +47,7 @@ describe('Room constructor', function () { }); it('should expose documented properties with the right permissions', function () { - var room = new Room(dataCollection); + var room = new Room(collection); should(room).have.propertyWithDescriptor('collection', {enumerable: true, writable: false, configurable: false}); should(room).have.propertyWithDescriptor('filters', {enumerable: true, writable: true, configurable: false}); @@ -55,7 +55,7 @@ describe('Room constructor', function () { should(room).have.propertyWithDescriptor('scope', {enumerable: false, writable: false, configurable: false}); should(room).have.propertyWithDescriptor('state', {enumerable: false, writable: false, configurable: false}); should(room).have.propertyWithDescriptor('users', {enumerable: false, writable: false, configurable: false}); - should(room).have.propertyWithDescriptor('metadata', {enumerable: true, writable: true, configurable: false}); + should(room).have.propertyWithDescriptor('volatile', {enumerable: true, writable: true, configurable: false}); should(room).have.propertyWithDescriptor('subscribeToSelf', { enumerable: true, writable: true, @@ -65,7 +65,7 @@ describe('Room constructor', function () { }); it('should promisify the right functions', function () { - var room = new Room(dataCollection); + var room = new Room(collection); should.exist(room.countPromise); should.not.exist(room.renewPromise); diff --git a/test/Room/methods.test.js b/test/Room/methods.test.js index 24036f86e..a6e274a7f 100644 --- a/test/Room/methods.test.js +++ b/test/Room/methods.test.js @@ -1,6 +1,4 @@ -'use strict'; - -const +var should = require('should'), rewire = require('rewire'), sinon = require('sinon'), @@ -9,7 +7,7 @@ const Room = rewire('../../src/Room'); describe('Room methods', function () { - let + var expectedQuery, error, result, @@ -54,7 +52,7 @@ describe('Room methods', function () { }, emitted, kuzzle, - dataCollection; + collection; describe('#count', function () { @@ -64,7 +62,7 @@ describe('Room methods', function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.query = queryStub; kuzzle.state = 'connected'; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {count: 42 }}; error = null; @@ -75,7 +73,7 @@ describe('Room methods', function () { controller: 'realtime', body: {} }; - room = new Room(dataCollection); + room = new Room(collection); room.roomId = 'foobar'; }); @@ -136,7 +134,7 @@ describe('Room methods', function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); kuzzle.state = 'connected'; kuzzle.query = queryStub; - dataCollection = kuzzle.collection('foo'); + collection = kuzzle.collection('foo'); emitted = false; result = { result: {roomId: 'foobar', channel: 'barfoo' }}; error = null; @@ -147,7 +145,7 @@ describe('Room methods', function () { controller: 'realtime', body: {} }; - room = new Room(dataCollection); + room = new Room(collection); }); afterEach(function () { @@ -198,7 +196,7 @@ describe('Room methods', function () { it('should start dequeuing if subscribed successfully', function (done) { room.renew({}, function () {}); - setTimeout(() => { + setTimeout(function () { should(dequeued).be.true(); done(); }, 10); @@ -221,7 +219,7 @@ describe('Room methods', function () { it('should register itself to Kuzzle and skip subscription if not connected', function (done) { kuzzle.state = 'foo'; room.renew({}, function () {}); - setTimeout(() => { + setTimeout(function () { should(dequeued).be.false(); should(emitted).be.false(); should(room.lastRenewal).be.null(); @@ -242,7 +240,7 @@ describe('Room methods', function () { room.renew({}, function () {}); room.renew({}, function () {}); - setTimeout(() => { + setTimeout(function () { should(renewals).be.eql(1); should(room.lastRenewal).be.within(before, after); done(); @@ -255,8 +253,8 @@ describe('Room methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); - room = new Room(dataCollection); + collection = kuzzle.collection('foo'); + room = new Room(collection); }); it('should set headers properly', function () { @@ -290,8 +288,8 @@ describe('Room methods', function () { body: {} }; - dataCollection = kuzzle.collection('foo'); - room = new Room(dataCollection); + collection = kuzzle.collection('foo'); + room = new Room(collection); room.roomId = 'foobar'; kuzzle.subscriptions.foobar = {}; kuzzle.subscriptions.foobar[room.id] = room; @@ -321,7 +319,7 @@ describe('Room methods', function () { should(emitted).be.false(); should(kuzzle.subscriptions.foobar).be.undefined(); kuzzle.subscriptions.pending = {}; - setTimeout(() => { + setTimeout(function () { should(emitted).be.true(); done(); }, 100); @@ -336,7 +334,7 @@ describe('Room methods', function () { kuzzle.subscriptions.pending = {}; kuzzle.subscriptions.foobar = {}; kuzzle.subscriptions.foobar.foo = {}; - setTimeout(() => { + setTimeout(function () { should(emitted).be.false(); done(); }, 100); @@ -359,8 +357,8 @@ describe('Room methods', function () { var stub = function () { dequeued++; }; kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); - room = new Room(dataCollection); + collection = kuzzle.collection('foo'); + room = new Room(collection); room.count = stub; room.renew = stub; room.unsubscribe = stub; @@ -381,15 +379,15 @@ describe('Room methods', function () { }); describe('#notificationCallback', function () { - let + var notifCB = Room.__get__('notificationCallback'), room; beforeEach(function () { error = result = undefined; kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - dataCollection = kuzzle.collection('foo'); - room = new Room(dataCollection); + collection = kuzzle.collection('foo'); + room = new Room(collection); room.callback = sinon.spy(); }); @@ -402,7 +400,7 @@ describe('Room methods', function () { .have.length(1); }); - it('should handle document notifications', () => { + it('should handle document notifications', function () { notifCB.call(room, { controller: 'document', result: { @@ -429,7 +427,7 @@ describe('Room methods', function () { .be.an.instanceOf(Document); }); - it('should handle realtime publish notifications', () => { + it('should handle realtime publish notifications', function () { notifCB.call(room, { controller: 'realtime', action: 'publish', @@ -457,7 +455,7 @@ describe('Room methods', function () { .be.an.instanceOf(Document); }); - it('should handle user notifications', () => { + it('should handle user notifications', function () { notifCB.call(room, { controller: 'realtime', result: { count: 3 } @@ -473,7 +471,7 @@ describe('Room methods', function () { }); }); - it('should delete the result from history if emitted by this instance', () => { + it('should delete the result from history if emitted by this instance', function () { room.subscribeToSelf = true; kuzzle.requestHistory.bar = {}; notifCB.call(room, {error: null, result: {}, action: 'foo', requestId: 'bar'}); @@ -498,7 +496,7 @@ describe('Room methods', function () { eventEmitted = null, context = { kuzzle: { - emitEvent: event => { + emitEvent: function (event) { eventEmitted = event; } } diff --git a/test/SearchResult/constructor.test.js b/test/SearchResult/constructor.test.js index 066d97f24..fdb6293f0 100644 --- a/test/SearchResult/constructor.test.js +++ b/test/SearchResult/constructor.test.js @@ -4,15 +4,16 @@ var bluebird = require('bluebird'), Kuzzle = rewire('../../src/Kuzzle'), Document = require('../../src/Document'), - KuzzleSearchResult = rewire('../../src/SearchResult'); + SearchResult = rewire('../../src/SearchResult'); -describe('Document constructor', function () { +describe('SearchResult constructor', function () { var kuzzle, - searchArgs, + searchOptions, + searchFilters, document, aggregations, - dataCollection; + collection; before(function () { Kuzzle.prototype.bluebird = bluebird; @@ -20,41 +21,49 @@ describe('Document constructor', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - searchArgs = {options: {}, filters: {from:0, size: 1}}; - dataCollection = kuzzle.collection('foo'); - document = new Document(dataCollection, 'banana', {foo: 'bar'}); - aggregations = {}; + searchOptions = {from:0, size: 1}; + searchFilters = {}; + collection = kuzzle.collection('foo'); + document = new Document(collection, 'banana', {foo: 'bar'}); + aggregations = {foo: 'bar'}; }); - it('should handle provided arguments correctly', function () { - var searchResult = new KuzzleSearchResult(dataCollection, 2, [document], aggregations, searchArgs); + it('should handle provided arguments correctly and define proper getters', function () { + var searchResult = new SearchResult(collection, 2, [document], aggregations, searchOptions, searchFilters); - should(searchResult).be.instanceof(KuzzleSearchResult); + should(searchResult).be.instanceof(SearchResult); + should(searchResult.collection).be.exactly(collection); + should(searchResult.getCollection()).be.exactly(collection); should(searchResult.total).be.exactly(2); + should(searchResult.getTotal()).be.exactly(2); should(searchResult.documents).be.an.Array(); + should(searchResult.getDocuments()).be.an.Array(); should(searchResult.documents[0]).be.deepEqual(document); - should(searchResult.searchArgs).be.deepEqual(searchArgs); + should(searchResult.getDocuments()[0]).be.deepEqual(document); + should(searchResult.options).be.deepEqual(searchOptions); + should(searchResult.getOptions()).be.deepEqual(searchOptions); + should(searchResult.filters).be.deepEqual(searchFilters); + should(searchResult.getFilters()).be.deepEqual(searchFilters); + should(searchResult.aggregations).be.deepEqual(aggregations); + should(searchResult.getAggregations()).be.deepEqual(aggregations); should(searchResult.fetchedDocument).be.deepEqual(1); - should(searchResult._previous).be.exactly(null); - should(searchResult._next).be.exactly(null); + should(searchResult.getFetchedDocument()).be.deepEqual(1); }); it('should expose documented properties with the right permissions', function () { - var searchResult = new KuzzleSearchResult(dataCollection, 2, [document], aggregations, searchArgs); + var searchResult = new SearchResult(collection, 2, [document], aggregations, searchOptions, searchFilters); - should(searchResult).have.propertyWithDescriptor('dataCollection', { enumerable: false, writable: false, configurable: false }); + should(searchResult).have.propertyWithDescriptor('collection', { enumerable: true, writable: false, configurable: false }); should(searchResult).have.propertyWithDescriptor('total', { enumerable: true, writable: false, configurable: false }); should(searchResult).have.propertyWithDescriptor('documents', { enumerable: true, writable: false, configurable: false }); - should(searchResult).have.propertyWithDescriptor('searchArgs', { enumerable: true, writable: false, configurable: false }); + should(searchResult).have.propertyWithDescriptor('options', { enumerable: true, writable: false, configurable: false }); + should(searchResult).have.propertyWithDescriptor('filters', { enumerable: true, writable: false, configurable: false }); should(searchResult).have.propertyWithDescriptor('fetchedDocument', { enumerable: true, writable: true, configurable: false }); - should(searchResult).have.propertyWithDescriptor('_previous', { enumerable: false, writable: true, configurable: false }); - should(searchResult).have.propertyWithDescriptor('_next', { enumerable: false, writable: true, configurable: false }); }); it('should promisify the right functions', function () { - var searchResult = new KuzzleSearchResult(dataCollection, 2, [document], aggregations, searchArgs); + var searchResult = new SearchResult(collection, 2, [document], aggregations, searchOptions, searchFilters); - should.exist(searchResult.nextPromise); - should.exist(searchResult.previousPromise); + should.exist(searchResult.fetchNextPromise); }); }); diff --git a/test/SearchResult/methods.test.js b/test/SearchResult/methods.test.js index 3a9ddeac1..add4740a3 100644 --- a/test/SearchResult/methods.test.js +++ b/test/SearchResult/methods.test.js @@ -4,15 +4,16 @@ var bluebird = require('bluebird'), Kuzzle = rewire('../../src/Kuzzle'), Document = require('../../src/Document'), - KuzzleSearchResult = rewire('../../src/SearchResult'); + SearchResult = rewire('../../src/SearchResult'); -describe('KuzzleSearchResult methods', function () { +describe('SearchResult methods', function () { var kuzzle, - dataCollection, + collection, firstDocument, secondDocument, - searchArgs; + searchOptions, + searchFilters; before(function () { Kuzzle.prototype.bluebird = bluebird; @@ -20,50 +21,37 @@ describe('KuzzleSearchResult methods', function () { beforeEach(function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); - searchArgs = {options: {from:0, size: 1}, filters: {}}; - dataCollection = kuzzle.collection('foo'); - firstDocument = new Document(dataCollection, 'banana', {foo: 'bar'}); - secondDocument = new Document(dataCollection, 'papagayo', {foo: 'bar'}); + searchOptions = {from:0, size: 1}; + searchFilters = {}; + collection = kuzzle.collection('foo'); + firstDocument = new Document(collection, 'banana', {foo: 'bar'}); + secondDocument = new Document(collection, 'papagayo', {foo: 'bar'}); }); - describe('#next', function () { - it('should return the next SearchResult if it has already fetched', function (done) { - var - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs), - secondSearchResult = new KuzzleSearchResult(dataCollection, 2, [secondDocument], {}, searchArgs, firstSearchResult); - - firstSearchResult.next(function(error, next) { - should(error).be.exactly(null); - should(next).be.exactly(secondSearchResult); - done(); - }); - - }); - + describe('#fetchNext', function () { it('should be able to do a scroll request', function (done) { var - mockScrollResult = new KuzzleSearchResult( - dataCollection, + mockScrollResult = new SearchResult( + collection, 1, - [new Document(dataCollection, 'papagayo', {foo: 'bar'})], + [new Document(collection, 'papagayo', {foo: 'bar'})], {}, - {options: {scrollId: 'papagayo', from: 0, size: 1}} + {options: {scrollId: 'papagayo', scroll: '1m', from: 0, size: 1}} ), firstSearchResult; - dataCollection.scroll = function(scrollId, options, filters, cb) { + collection.scroll = function(scrollId, options, filters, cb) { cb(null, mockScrollResult); }; - searchArgs.options.scrollId = 'banana'; + searchOptions.scrollId = 'banana'; - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 2, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error, result) { - should(result).be.an.instanceOf(KuzzleSearchResult); - should(result.documents).be.an.Array(); - should(result.documents.length).be.exactly(1); - should(result._previous).be.exactly(firstSearchResult); + firstSearchResult.fetchNext(function(error, result) { + should(result).be.an.instanceOf(SearchResult); + should(result.getDocuments()).be.an.Array(); + should(result.getDocuments().length).be.exactly(1); done(); }); }); @@ -72,15 +60,15 @@ describe('KuzzleSearchResult methods', function () { var firstSearchResult; - dataCollection.scroll = function(scrollId, options, filters, cb) { + collection.scroll = function(scrollId, options, filters, cb) { cb(new Error('foobar scroll')); }; - searchArgs.options.scrollId = 'banana'; + searchOptions.scrollId = 'banana'; - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 2, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error) { + firstSearchResult.fetchNext(function(error) { should(error).be.an.instanceOf(Error); should(error.message).be.exactly('foobar scroll'); done(); @@ -91,17 +79,17 @@ describe('KuzzleSearchResult methods', function () { var firstSearchResult; - dataCollection.search = function(filters, options, cb) { - cb(null, new KuzzleSearchResult(dataCollection, 2, [secondDocument], {}, {options: options, filters: filters})); + collection.search = function(filters, options, cb) { + cb(null, new SearchResult(collection, 2, [secondDocument], {}, options, filters)); }; - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 2, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error, result) { - should(result).be.an.instanceOf(KuzzleSearchResult); + firstSearchResult.fetchNext(function(error, result) { + should(result).be.an.instanceOf(SearchResult); should(result.documents).be.an.Array(); should(result.documents.length).be.exactly(1); - should(result.searchArgs.options.from).be.exactly(1); + should(result.options.from).be.exactly(1); done(); }); }); @@ -110,13 +98,13 @@ describe('KuzzleSearchResult methods', function () { var firstSearchResult; - dataCollection.search = function(filters, options, cb) { + collection.search = function(filters, options, cb) { cb(new Error('foobar search')); }; - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 2, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error) { + firstSearchResult.fetchNext(function(error) { should(error).be.an.instanceOf(Error); should(error.message).be.exactly('foobar search'); done(); @@ -125,9 +113,9 @@ describe('KuzzleSearchResult methods', function () { it('should be resolve null if all documents is fetched', function (done) { var - firstSearchResult = new KuzzleSearchResult(dataCollection, 1, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 1, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error, result) { + firstSearchResult.fetchNext(function(error, result) { should(result).be.null(); done(); }); @@ -137,11 +125,12 @@ describe('KuzzleSearchResult methods', function () { var firstSearchResult; - searchArgs.options.scrollId = 'banana'; + searchOptions.scrollId = 'banana'; + searchOptions.scroll = '1m'; - firstSearchResult = new KuzzleSearchResult(dataCollection, 1, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 1, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error, result) { + firstSearchResult.fetchNext(function(error, result) { should(result).be.null(); done(); }); @@ -151,29 +140,15 @@ describe('KuzzleSearchResult methods', function () { var firstSearchResult; - searchArgs.options = {}; + searchOptions = {}; - firstSearchResult = new KuzzleSearchResult(dataCollection, 1, [firstDocument], {}, searchArgs); + firstSearchResult = new SearchResult(collection, 1, [firstDocument], {}, searchOptions, searchFilters); - firstSearchResult.next(function(error) { + firstSearchResult.fetchNext(function(error) { should(error).be.an.instanceOf(Error); should(error.message).be.exactly('Unable to retrieve next results from search: missing scrollId or from/size params'); done(); }); }); }); - - describe('#previous', function () { - it('should call the callback with the previous SearchResult', function (done) { - var - firstSearchResult = new KuzzleSearchResult(dataCollection, 2, [firstDocument], {}, searchArgs), - secondSearchResult = new KuzzleSearchResult(dataCollection, 2, [secondDocument], {}, searchArgs, firstSearchResult); - - secondSearchResult.previous(function(error, previous) { - should(error).be.exactly(null); - should(previous).be.exactly(firstSearchResult); - done(); - }); - }); - }); }); diff --git a/test/SubscribeResult/kuzzleSubscribeResult.test.js b/test/SubscribeResult/kuzzleSubscribeResult.test.js index 31953be86..9505ae1cf 100644 --- a/test/SubscribeResult/kuzzleSubscribeResult.test.js +++ b/test/SubscribeResult/kuzzleSubscribeResult.test.js @@ -1,12 +1,12 @@ var should = require('should'), - KuzzleSubscribeResult = require('../../src/SubscribeResult'); + SubscribeResult = require('../../src/SubscribeResult'); describe('KuzzleSubscribeResult object', function () { var ksr; beforeEach(function () { - ksr = new KuzzleSubscribeResult(); + ksr = new SubscribeResult(); }); it('should expose the right prototypes', function() { diff --git a/test/kuzzle/constructor.test.js b/test/kuzzle/constructor.test.js index e03ae71f0..b135357ea 100644 --- a/test/kuzzle/constructor.test.js +++ b/test/kuzzle/constructor.test.js @@ -7,7 +7,7 @@ var NetworkWrapper = require('../../src/networkWrapper/wrappers/websocket'), kuzzleSource = '../../src/Kuzzle'; -describe('Kuzzle constructor', () => { +describe('Kuzzle constructor', function () { var Kuzzle, networkStub; @@ -25,7 +25,7 @@ describe('Kuzzle constructor', () => { }); }); - it('should expose the documented functions', () => { + it('should expose the documented functions', function () { var kuzzle; kuzzle = new Kuzzle('nowhere'); @@ -52,7 +52,7 @@ describe('Kuzzle constructor', () => { should.exist(kuzzle.unsetJwtToken); }); - it('should expose the documented properties', () => { + it('should expose the documented properties', function () { var kuzzle = new Kuzzle('nowhere'); should(kuzzle).have.propertyWithDescriptor('autoQueue', { enumerable: true, writable: true, configurable: false }); @@ -65,7 +65,7 @@ describe('Kuzzle constructor', () => { should(kuzzle).have.propertyWithDescriptor('queueMaxSize', { enumerable: true, writable: true, configurable: false }); should(kuzzle).have.propertyWithDescriptor('queueTTL', { enumerable: true, writable: true, configurable: false }); should(kuzzle).have.propertyWithDescriptor('headers', { enumerable: true, writable: true, configurable: false }); - should(kuzzle).have.propertyWithDescriptor('metadata', { enumerable: true, writable: true, configurable: false }); + should(kuzzle).have.propertyWithDescriptor('volatile', { enumerable: true, writable: true, configurable: false }); should(kuzzle).have.propertyWithDescriptor('replayInterval', { enumerable: true, writable: true, configurable: false }); should(kuzzle).have.propertyWithDescriptor('reconnectionDelay', { enumerable: true, writable: true, configurable: false }); should(kuzzle).have.propertyWithDescriptor('jwtToken', { enumerable: true, writable: true, configurable: false }); @@ -74,7 +74,7 @@ describe('Kuzzle constructor', () => { should(kuzzle).have.propertyWithDescriptor('sslConnection', { enumerable: true, writable: true, configurable: false }); }); - it('should have properties with the documented default values', () => { + it('should have properties with the documented default values', function () { var kuzzle = new Kuzzle('nowhere'); should(kuzzle.autoQueue).be.false(); @@ -84,7 +84,7 @@ describe('Kuzzle constructor', () => { should(kuzzle.queueTTL).be.exactly(120000); should(kuzzle.queueMaxSize).be.exactly(500); should(kuzzle.headers).be.an.Object().and.be.empty(); - should(kuzzle.metadata).be.an.Object().and.be.empty(); + should(kuzzle.volatile).be.an.Object().and.be.empty(); should(kuzzle.replayInterval).be.exactly(10); should(kuzzle.reconnectionDelay).be.exactly(1000); should(kuzzle.defaultIndex).be.undefined(); @@ -92,7 +92,7 @@ describe('Kuzzle constructor', () => { should(kuzzle.sslConnection).be.false(); }); - it('should initialize correctly properties using the "options" argument', () => { + it('should initialize correctly properties using the "options" argument', function () { var options = { autoQueue: true, @@ -102,7 +102,7 @@ describe('Kuzzle constructor', () => { queueTTL: 123, queueMaxSize: 42, headers: {foo: 'bar'}, - metadata: {foo: ['bar', 'baz', 'qux'], bar: 'foo'}, + volatile: {foo: ['bar', 'baz', 'qux'], bar: 'foo'}, replayInterval: 99999, reconnectionDelay: 666, defaultIndex: 'foobar', @@ -119,14 +119,14 @@ describe('Kuzzle constructor', () => { should(kuzzle.queueTTL).be.exactly(options.queueTTL); should(kuzzle.queueMaxSize).be.exactly(options.queueMaxSize); should(kuzzle.headers).be.an.Object().and.match(options.headers); - should(kuzzle.metadata).be.an.Object().and.match(options.metadata); + should(kuzzle.volatile).be.an.Object().and.match(options.volatile); should(kuzzle.replayInterval).be.exactly(options.replayInterval); should(kuzzle.reconnectionDelay).be.exactly(options.reconnectionDelay); should(kuzzle.port).be.exactly(options.port); should(kuzzle.sslConnection).be.exactly(options.sslConnection); }); - it('should handle the offlineMode option properly', () => { + it('should handle the offlineMode option properly', function () { var kuzzle = new Kuzzle('nowhere', {offlineMode: 'auto'}); should(kuzzle.autoQueue).be.true(); @@ -135,7 +135,7 @@ describe('Kuzzle constructor', () => { should(kuzzle.autoResubscribe).be.true(); }); - it('should handle the connect option properly', () => { + it('should handle the connect option properly', function () { var kuzzle = new Kuzzle('nowhere', {connect: 'manual'}); should(kuzzle.state).be.exactly('ready'); @@ -146,7 +146,7 @@ describe('Kuzzle constructor', () => { should(networkStub.connect.called).be.true(); }); - it('should return a new instance even if not called with "new"', () => { + it('should return a new instance even if not called with "new"', function () { var kuzzle = Kuzzle('nowhere'); kuzzle.should.be.instanceof(Kuzzle); @@ -163,7 +163,7 @@ describe('Kuzzle constructor', () => { }); }; - kuzzle = new Kuzzle('nowhere', () => { + kuzzle = new Kuzzle('nowhere', function () { kuzzle.state = 'disconnected'; try { kuzzle.isValid(); @@ -175,7 +175,7 @@ describe('Kuzzle constructor', () => { }); }); - it('should promisify the right functions', () => { + it('should promisify the right functions', function () { var kuzzle; Kuzzle.prototype.bluebird = bluebird; @@ -207,8 +207,8 @@ describe('Kuzzle constructor', () => { should.not.exist(kuzzle.stopQueuingPromise); }); - it('should throw an error if no URL is provided', () => { - should(() => { + it('should throw an error if no URL is provided', function () { + should(function () { new Kuzzle(); }).throw(); }); @@ -219,7 +219,7 @@ describe('Kuzzle constructor', () => { this.timeout(200); - kuzzle = new Kuzzle('nowhere', {connect: 'manual'}, (err, res) => { + kuzzle = new Kuzzle('nowhere', {connect: 'manual'}, function (err, res) { should(err).be.null(); should(res).be.exactly(kuzzle); should(res.state).be.exactly('connected'); @@ -235,7 +235,7 @@ describe('Kuzzle constructor', () => { this.timeout(200); - kuzzle = new Kuzzle('nowhere', {connect: 'manual'}, (err, res) => { + kuzzle = new Kuzzle('nowhere', {connect: 'manual'}, function (err, res) { should(err).be.null(); should(res).be.exactly(kuzzle); should(res.state).be.exactly('reconnecting'); @@ -247,7 +247,7 @@ describe('Kuzzle constructor', () => { }); it('should try to connect when the instance is in a not-connected state', function () { - ['initializing', 'ready', 'disconnected', 'error', 'offline'].forEach(state => { + ['initializing', 'ready', 'disconnected', 'error', 'offline'].forEach(function (state) { var kuzzle = new Kuzzle('nowhere', {connect: 'manual'}); kuzzle.state = state; @@ -272,7 +272,7 @@ describe('Kuzzle constructor', () => { kuzzle.connect(); - setTimeout(() => { + setTimeout(function () { should(listenerCalled).be.true(); done(); }, 10); @@ -291,17 +291,17 @@ describe('Kuzzle constructor', () => { should(kuzzle.disconnect.called).be.true(); }); - describe('=> on connection error', () => { + describe('=> on connection error', function () { beforeEach(function () { networkStub.onConnectError = function (cb) { - process.nextTick(() => cb('error')); + process.nextTick(function () { cb('error'); }); }; }); it('should call the provided callback on a connection error', function (done) { var kuzzle; - this.timeout(50); + this.timeout(200); kuzzle = new Kuzzle('nowhere', function (err, res) { try { @@ -325,7 +325,7 @@ describe('Kuzzle constructor', () => { kuzzle.addListener('error', function () { listenerCalled = true; }); - setTimeout(() => { + setTimeout(function () { try { should(listenerCalled).be.true(); done(); @@ -337,13 +337,15 @@ describe('Kuzzle constructor', () => { }); }); - describe('=> on connection success', () => { - beforeEach(() => { - networkStub.onConnect = cb => process.nextTick(() => cb()); + describe('=> on connection success', function () { + beforeEach(function () { + networkStub.onConnect = function (cb) { + setTimeout(function () { cb(); }, 0); + }; }); it('should call the provided callback on a connection success', function (done) { - this.timeout(50); + this.timeout(200); new Kuzzle('nowhere', function (err, res) { try { @@ -363,7 +365,7 @@ describe('Kuzzle constructor', () => { kuzzle, renewed = false; - this.timeout(50); + this.timeout(200); kuzzle = new Kuzzle('nowhere', {connect: 'manual', autoResubscribe: false}); kuzzle.subscriptions.foo = { @@ -375,7 +377,7 @@ describe('Kuzzle constructor', () => { kuzzle.connect(); should(kuzzle.state).be.exactly('connecting'); - setTimeout(() => { + setTimeout(function () { should(renewed).be.true(); done(); }, 20); @@ -405,9 +407,11 @@ describe('Kuzzle constructor', () => { }); }); - describe('=> on disconnection', () => { + describe('=> on disconnection', function () { beforeEach(function () { - networkStub.onDisconnect = cb => process.nextTick(() => cb()); + networkStub.onDisconnect = function (cb) { + setTimeout(function () { cb(); }, 0); + }; }); it('should enter offline mode and call listeners', function (done) { @@ -419,7 +423,7 @@ describe('Kuzzle constructor', () => { kuzzle.addListener('disconnected', function () { listenerCalled = true; }); - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('offline'); should(kuzzle.queuing).be.false(); @@ -430,14 +434,14 @@ describe('Kuzzle constructor', () => { catch (e) { done(e); } - }, 10); + }, 100); }); it('should enable queuing if autoQueue is set to true', function (done) { var kuzzle = new Kuzzle('nowhere', {autoQueue: true}); this.timeout(200); - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('offline'); should(kuzzle.queuing).be.true(); @@ -455,7 +459,7 @@ describe('Kuzzle constructor', () => { this.timeout(200); - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('offline'); should(kuzzle.queuing).be.false(); @@ -469,9 +473,11 @@ describe('Kuzzle constructor', () => { }); }); - describe('=> on reconnection', () => { + describe('=> on reconnection', function () { beforeEach(function () { - networkStub.onReconnect = cb => process.nextTick(() => cb()); + networkStub.onReconnect = function (cb) { + setTimeout(function () { cb(); }, 0); + }; }); it('should exit offline mode when reconnecting', function (done) { @@ -484,7 +490,7 @@ describe('Kuzzle constructor', () => { kuzzle.addListener('reconnected', function () { listenersCalled = true; }); kuzzle.queuing = true; - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('connected'); should(listenersCalled).be.true(); @@ -513,7 +519,7 @@ describe('Kuzzle constructor', () => { kuzzle.subscriptions.foo = { bar: stubKuzzleRoom }; - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('connected'); should(renewCalled).be.true(); @@ -541,7 +547,7 @@ describe('Kuzzle constructor', () => { bar: stubKuzzleRoom }; - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('connected'); should(renewCalled).be.false(); @@ -562,7 +568,7 @@ describe('Kuzzle constructor', () => { kuzzle.queuing = true; - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('connected'); should(kuzzle.queuing).be.false(); @@ -589,7 +595,7 @@ describe('Kuzzle constructor', () => { cb(null, {valid: false}); }; - setTimeout(() => { + setTimeout(function () { try { should(kuzzle.state).be.exactly('connected'); should(kuzzle.jwtToken).be.undefined(); @@ -604,7 +610,7 @@ describe('Kuzzle constructor', () => { }); }); - describe('#login', () => { + describe('#login', function () { var loginStub = function(strategy, credentials, expiresIn, cb) { if (typeof cb === 'function') { @@ -617,9 +623,14 @@ describe('Kuzzle constructor', () => { } }; - beforeEach(() => { - networkStub.onConnect = cb => process.nextTick(() => cb()); - networkStub.on = (event, cb) => cb(); + beforeEach(function () { + networkStub.onConnect = function (cb) { + setTimeout(function () { cb(); }, 0); + }; + + networkStub.on = function (event, cb) { + cb(); + }; }); it('should call the provided callback on a connection & login success', function (done) { @@ -666,13 +677,13 @@ describe('Kuzzle constructor', () => { } }, function (err, res) { try { - process.nextTick(() => { + setTimeout(function () { should(err).be.null(); should(res).be.instanceof(Kuzzle); should(res.state).be.exactly('connected'); should(listenerConnected).be.exactly(true); done(); - }); + }, 0); } catch (e) { done(e); @@ -838,7 +849,7 @@ describe('Kuzzle constructor', () => { cb({message: 'foobar'}); }; - kuzzle.addListener('loginAttempt', status => { + kuzzle.addListener('loginAttempt', function (status) { should(status.success).be.false(); should(status.error).be.eql('foobar'); eventEmitted = true; @@ -846,10 +857,10 @@ describe('Kuzzle constructor', () => { kuzzle.login('local', {}); - process.nextTick(() => { + setTimeout(function () { should(eventEmitted).be.true(); done(); - }); + }, 0); }); it('should not forward an event if there is no JWT token in the response', function (done) { @@ -860,15 +871,15 @@ describe('Kuzzle constructor', () => { cb(null, {result: {}}); }; - kuzzle.addListener('loginAttempt', () => { + kuzzle.addListener('loginAttempt', function () { done('test failed'); }); kuzzle.login('local', {}); - process.nextTick(() => { + setTimeout(function () { done(); - }); + }, 0); }); it('should handle optional arguments correctly', function (done) { @@ -928,7 +939,7 @@ describe('Kuzzle constructor', () => { cb(null, {}); }; - kuzzle.logout(() => {}); + kuzzle.logout(function () {}); should(unsetJwtToken).be.exactly(true); }); diff --git a/test/kuzzle/emitEvent.test.js b/test/kuzzle/emitEvent.test.js index 5de76ac34..63617e5e6 100644 --- a/test/kuzzle/emitEvent.test.js +++ b/test/kuzzle/emitEvent.test.js @@ -3,7 +3,7 @@ var Kuzzle = require('../../src/Kuzzle'); -describe('Event emitter', () => { +describe('Event emitter', function () { var kuzzle, emitEvent; @@ -34,10 +34,10 @@ describe('Event emitter', () => { emitEvent.call(context, 'foo'); - process.nextTick(() => { + setTimeout(function () { should(listenersCalled).be.eql(3); done(); - }); + }, 0); }); it('should allow providing any number of arguments', function (done) { @@ -60,27 +60,27 @@ describe('Event emitter', () => { emitEvent.call(context, 'foo'); - process.nextTick(() => { + setTimeout(function () { should(argsCount).be.eql(0); emitEvent.call(context, 'foo', 'bar'); - process.nextTick(() => { + setTimeout(function () { should(argsCount).be.eql(1); argsCount = 0; emitEvent.call(context, 'foo', 'bar', ['foo', 'bar']); - process.nextTick(() => { + setTimeout(function () { should(argsCount).be.eql(2); argsCount = 0; emitEvent.call(context, 'foo', {foo: 'bar'}, 'bar', ['foo', 'bar']); - process.nextTick(() => { + setTimeout(function () { should(argsCount).be.eql(3); done(); - }); - }); - }); - }); + }, 0); + }, 0); + }, 0); + }, 0); }); it('should not re-emit an event before event timeout', function (done) { @@ -106,17 +106,17 @@ describe('Event emitter', () => { emitEvent.call(context, 'foo'); emitEvent.call(context, 'foo'); - process.nextTick(() => { + setTimeout(function () { should(listenerCalled).be.eql(1); - setTimeout(() => { + setTimeout(function () { emitEvent.call(context, 'foo'); - process.nextTick(() => { + setTimeout(function () { should(listenerCalled).be.eql(2); done(); - }); + }, 0); }, 30); - }); + }, 0); }); }); diff --git a/test/kuzzle/listenersManagement.test.js b/test/kuzzle/listenersManagement.test.js index 097660521..1d30340c5 100644 --- a/test/kuzzle/listenersManagement.test.js +++ b/test/kuzzle/listenersManagement.test.js @@ -3,7 +3,7 @@ var rewire = require('rewire'), Kuzzle = rewire('../../src/Kuzzle'); -describe('Listeners management', () => { +describe('Listeners management', function () { var kuzzle, listenerIds; @@ -35,13 +35,13 @@ describe('Listeners management', () => { }); it('should throw an error if trying to adding a listener to an unknown event', function () { - should(() => { + should(function () { kuzzle.addListener('foo', function () {}); }).throw(); }); it('should throw an error when providing a non-function listener argument', function () { - should(() => { + should(function () { kuzzle.addListener('connected', 'bar'); }).throw(); }); @@ -82,11 +82,15 @@ describe('Listeners management', () => { describe('#removeListener', function () { it('should remove any one listener from the listener list', function () { - var listener = kuzzle.eventListeners.connected.listeners.filter(l => l.id === listenerIds[2]); + var listener = kuzzle.eventListeners.connected.listeners.filter(function (l) { + return l.id === listenerIds[2]; + }); should(listener.length).be.exactly(1); kuzzle.removeListener('connected', listenerIds[2]); - listener = kuzzle.eventListeners.connected.listeners.filter(l => l.id === listenerIds[2]); + listener = kuzzle.eventListeners.connected.listeners.filter(function (l) { + return l.id === listenerIds[2]; + }); should(listener.length).be.exactly(0); should(kuzzle.eventListeners.connected.listeners.length).be.exactly(3); should(kuzzle.eventListeners.error.listeners.length).be.exactly(3); diff --git a/test/kuzzle/methods.test.js b/test/kuzzle/methods.test.js index 97f4a6d05..58afc4580 100644 --- a/test/kuzzle/methods.test.js +++ b/test/kuzzle/methods.test.js @@ -41,7 +41,7 @@ describe('Kuzzle methods', function () { emitted, kuzzle; - afterEach(() => { + afterEach(function () { sandbox.restore(); }); @@ -71,7 +71,7 @@ describe('Kuzzle methods', function () { should(emitted).be.true(); emitted = false; - passedOptions = {queuable: true, metadata: {foo: 'bar'}}; + passedOptions = {queuable: true, volatile: {foo: 'bar'}}; kuzzle.getAllStatistics(passedOptions, function () {}); }); @@ -173,7 +173,7 @@ describe('Kuzzle methods', function () { kuzzle = new Kuzzle('foo'); }); - it('should throw an error if arguments are not strings', () => { + it('should throw an error if arguments are not strings', function () { kuzzle.defaultIndex = 'foobar'; should(function () { kuzzle.collection(undefined); }).throw(/string expected/); should(function () { kuzzle.collection(undefined, 'foo'); }).throw(/string expected/); @@ -218,7 +218,7 @@ describe('Kuzzle methods', function () { should(collection.index).be.eql(defaultIndex); }); - it('should throw an error if no index is provided and no default index has been set', () => { + it('should throw an error if no index is provided and no default index has been set', function () { should(function () { kuzzle.collection('foo'); }).throw(/no index specified/); }); }); @@ -341,17 +341,17 @@ describe('Kuzzle methods', function () { it('should handle type option correctly', function (done) { expectedQuery.body.type = 'foobar'; - kuzzle.listCollections('foo', {type: 'foobar'}, () => done()); + kuzzle.listCollections('foo', {type: 'foobar'}, function () { done(); }); }); it('should handle from option correctly', function (done) { expectedQuery.from = 'foobar'; - kuzzle.listCollections('foo', {from: 'foobar'}, () => done()); + kuzzle.listCollections('foo', {from: 'foobar'}, function () { done(); }); }); it('should handle size option correctly', function (done) { expectedQuery.size = 'foobar'; - kuzzle.listCollections('foo', {size: 'foobar'}, () => done()); + kuzzle.listCollections('foo', {size: 'foobar'}, function () { done(); }); }); it('should use the default index if none is provided', function () { @@ -715,7 +715,7 @@ describe('Kuzzle methods', function () { kuzzle.unsetJwtToken(); - process.nextTick(() => { + process.nextTick(function () { should(kuzzle.getJwtToken()).be.eql(undefined); should(subscriptionsRemoved).be.true(); revert(); @@ -738,10 +738,10 @@ describe('Kuzzle methods', function () { kuzzle.unsetJwtToken(); - process.nextTick(() => { + setTimeout(function () { should(unsubscribeCalled).be.true(); done(); - }); + }, 0); }); }); @@ -758,7 +758,7 @@ describe('Kuzzle methods', function () { beforeEach(function () { kuzzle = new Kuzzle('nowhere', {connect: 'manual'}); - kuzzle.addListener('loginAttempt', status => { + kuzzle.addListener('loginAttempt', function (status) { eventEmitted = true; loginStatus = status; }); @@ -773,64 +773,64 @@ describe('Kuzzle methods', function () { it('should set the token when provided with a string argument', function (done) { kuzzle.setJwtToken('foobar'); - process.nextTick(() => { + setTimeout(function () { should(kuzzle.getJwtToken()).be.eql('foobar'); should(subscriptionsRenewed).be.true(); should(eventEmitted).be.true(); should(loginStatus.success).be.true(); done(); - }); + }, 0); }); it('should set the token when provided with a kuzzle response argument', function (done) { kuzzle.setJwtToken({result:{jwt: 'foobar'}}); - process.nextTick(() => { + setTimeout(function () { should(kuzzle.getJwtToken()).be.eql('foobar'); should(subscriptionsRenewed).be.true(); should(eventEmitted).be.true(); should(loginStatus.success).be.true(); done(); - }); + }, 0); }); it('should send an "attempt failed" event if provided with an invalid argument type', function (done) { kuzzle.setJwtToken(); - process.nextTick(() => { + setTimeout(function () { should(kuzzle.getJwtToken()).be.undefined(); should(subscriptionsRenewed).be.false(); should(eventEmitted).be.true(); should(loginStatus.success).be.false(); should(loginStatus.error).not.be.undefined(); done(); - }); + }, 0); }); it('should send an "attempt failed" event if the provided kuzzle response does not contain a token', function (done) { kuzzle.setJwtToken({foo: 'bar'}); - process.nextTick(() => { + setTimeout(function () { should(kuzzle.getJwtToken()).be.undefined(); should(subscriptionsRenewed).be.false(); should(eventEmitted).be.true(); should(loginStatus.success).be.false(); should(loginStatus.error).not.be.undefined(); done(); - }); + }, 0); }); }); describe('#refreshIndex', function () { - beforeEach(() => { + beforeEach(function () { kuzzle = new Kuzzle('foo'); }); - it('should throw an error if no index is set', () => { - should(() => {kuzzle.refreshIndex();}).throw('Kuzzle.refreshIndex: index required'); + it('should throw an error if no index is set', function () { + should(function () {kuzzle.refreshIndex();}).throw('Kuzzle.refreshIndex: index required'); }); - it('should use the default index if no index is given', () => { + it('should use the default index if no index is given', function () { var spy = sandbox.stub(kuzzle, 'query').returns(); @@ -841,12 +841,12 @@ describe('Kuzzle methods', function () { should(spy.firstCall.args[0].index).be.exactly(kuzzle.defaultIndex); }); - it('should parse the given parameters', () => { + it('should parse the given parameters', function () { var spy = sandbox.stub(kuzzle, 'query').returns(), index = 'index', options = {foo: 'bar'}, - cb = () => {}, + cb = function () {}, args; kuzzle.refreshIndex(index, options, cb); @@ -864,15 +864,15 @@ describe('Kuzzle methods', function () { }); describe('#createIndex', function () { - beforeEach(() => { + beforeEach(function () { kuzzle = new Kuzzle('foo'); }); - it('should throw an error if no index is set', () => { - should(() => { kuzzle.createIndex(); }).throw('Kuzzle.createIndex: index required'); + it('should throw an error if no index is set', function () { + should(function () { kuzzle.createIndex(); }).throw('Kuzzle.createIndex: index required'); }); - it('should use the default index if no index is given', () => { + it('should use the default index if no index is given', function () { var spy = sandbox.stub(kuzzle, 'query').returns(); @@ -883,12 +883,12 @@ describe('Kuzzle methods', function () { should(spy.firstCall.args[1].index).be.exactly(kuzzle.defaultIndex); }); - it('should parse the given parameters', () => { + it('should parse the given parameters', function () { var spy = sandbox.stub(kuzzle, 'query').returns(), index = 'index', options = {foo: 'bar'}, - cb = () => {}, + cb = function () {}, args; kuzzle.createIndex(index, options, cb); @@ -903,11 +903,11 @@ describe('Kuzzle methods', function () { should(args[3]).be.exactly(cb); }); - it('should parse the given parameters even if no options is given', () => { + it('should parse the given parameters even if no options is given', function () { var spy = sandbox.stub(kuzzle, 'query').returns(), index = 'index', - cb = () => {}, + cb = function () {}, args; kuzzle.createIndex(index, cb); @@ -924,38 +924,38 @@ describe('Kuzzle methods', function () { }); - describe('#getAutoRefresh', () => { - beforeEach(() => { + describe('#getAutoRefresh', function () { + beforeEach(function () { kuzzle = new Kuzzle('foo'); }); - it('should throw an error if no index is given', () => { - should(() => { kuzzle.getAutoRefresh(); }).throw('Kuzzle.getAutoRefresh: index required'); + it('should throw an error if no index is given', function () { + should(function () { kuzzle.getAutoRefresh(); }).throw('Kuzzle.getAutoRefresh: index required'); }); - it('should use kuzzle default index if no index is provided', () => { + it('should use kuzzle default index if no index is provided', function () { var spy = sandbox.stub(kuzzle, 'query').returns(); kuzzle.defaultIndex = 'defaultIndex'; - kuzzle.getAutoRefresh(() => {}); + kuzzle.getAutoRefresh(function () {}); should(spy.calledOnce).be.true(); should(spy.firstCall.args[0].index).be.exactly(kuzzle.defaultIndex); }); - it('should throw an error if no callback is given', () => { - should(() => { kuzzle.getAutoRefresh('index'); }).throw('Kuzzle.getAutoRefresh: a callback argument is required for read queries'); + it('should throw an error if no callback is given', function () { + should(function () { kuzzle.getAutoRefresh('index'); }).throw('Kuzzle.getAutoRefresh: a callback argument is required for read queries'); }); - it('should parse the given arguments', () => { + it('should parse the given arguments', function () { var spy = sandbox.stub(kuzzle, 'query').returns(), index = 'index', options = { foo: 'bar'}, - cb = () => {}; + cb = function () {}; kuzzle.getAutoRefresh(index, options, cb); should(spy.calledOnce).be.true(); @@ -980,19 +980,19 @@ describe('Kuzzle methods', function () { }); - describe('#setAutoRefresh', () => { - beforeEach(() => { + describe('#setAutoRefresh', function () { + beforeEach(function () { kuzzle = new Kuzzle('foo'); }); - it('should throw an error if no index is given', () => { - should(() => { kuzzle.setAutoRefresh(); }).throw('Kuzzle.setAutoRefresh: index required'); + it('should throw an error if no index is given', function () { + should(function () { kuzzle.setAutoRefresh(); }).throw('Kuzzle.setAutoRefresh: index required'); }); - it('should use kuzzle default index if none is provided', () => { + it('should use kuzzle default index if none is provided', function () { var spy = sandbox.stub(kuzzle, 'query').returns(), - cb = () => {}; + cb = function () {}; kuzzle.defaultIndex = 'defaultIndex'; kuzzle.setAutoRefresh(true, cb); @@ -1006,18 +1006,18 @@ describe('Kuzzle methods', function () { }); - it('should throw an error is now autorefresh value is given', () => { - should(() => { + it('should throw an error is now autorefresh value is given', function () { + should(function () { kuzzle.setAutoRefresh('index'); }).throw('Kuzzle.setAutoRefresh: autoRefresh value is required'); }); - it('should parse the given arguments', () => { + it('should parse the given arguments', function () { var index = 'index', autoRefresh = true, options = { foo: 'bar'}, - cb = () => {}, + cb = function () {}, spy = sandbox.stub(kuzzle, 'query').returns(); kuzzle.defaultIndex = 'defaultIndex'; diff --git a/test/kuzzle/offlineQueue.test.js b/test/kuzzle/offlineQueue.test.js index bf4d8c0be..40e225b71 100644 --- a/test/kuzzle/offlineQueue.test.js +++ b/test/kuzzle/offlineQueue.test.js @@ -4,7 +4,7 @@ var sinon = require('sinon'), Kuzzle = rewire('../../src/Kuzzle'); -describe('Offline queue management', () => { +describe('Offline queue management', function () { describe('#cleanQueue', function () { var cleanQueue = Kuzzle.__get__('cleanQueue'), @@ -30,14 +30,14 @@ describe('Offline queue management', () => { // setting the request TTL to 5s kuzzle.queueTTL = 5000; - kuzzle.addListener('offlineQueuePop', () => { + kuzzle.addListener('offlineQueuePop', function () { eventFired = true; }); cleanQueue.call(kuzzle); // should keep only the latest requests, dating from a few ms ago - setTimeout(() => { + setTimeout(function () { should(kuzzle.offlineQueue.length).be.exactly(1); should(kuzzle.offlineQueue[0].ts).be.above(now - kuzzle.queueTTL); should(eventFired).be.true(); @@ -59,17 +59,17 @@ describe('Offline queue management', () => { eventFired = false; kuzzle.queueMaxSize = 1; - kuzzle.addListener('offlineQueuePop', () => { + kuzzle.addListener('offlineQueuePop', function () { eventFired = true; }); cleanQueue.call(kuzzle); - process.nextTick(() => { + setTimeout(function () { should(kuzzle.offlineQueue.length).be.exactly(1); should(kuzzle.offlineQueue[0]).match(lastRequest); should(eventFired).be.true(); done(); - }); + }, 0); }); it('should not remove any request if queueMaxSize is 0', function () { @@ -108,10 +108,10 @@ describe('Offline queue management', () => { eventFired = 0; this.timeout(200); - kuzzle.addListener('offlineQueuePop', () => eventFired++); + kuzzle.addListener('offlineQueuePop', function () { eventFired++; }); dequeue.call(kuzzle); - setTimeout(() => { + setTimeout(function () { should(kuzzle.network.send.callCount).be.exactly(numRequests); should(kuzzle.offlineQueue).be.an.Array(); should(kuzzle.offlineQueue.length).be.exactly(0); @@ -133,10 +133,10 @@ describe('Offline queue management', () => { {query: {requestId: 'foo2', action: 'action', controller: 'controller'}} ]; }; - kuzzle.addListener('offlineQueuePop', () => eventFired++); + kuzzle.addListener('offlineQueuePop', function () {eventFired++; }); dequeue.call(kuzzle); - setTimeout(() => { + setTimeout(function () { should(kuzzle.network.send.callCount).be.exactly(numRequests + 2); should(kuzzle.offlineQueue).be.an.Array(); should(kuzzle.offlineQueue.length).be.exactly(0); @@ -158,10 +158,10 @@ describe('Offline queue management', () => { {query: {requestId: '50000', action: 'action', controller: 'controller'}} ]; }; - kuzzle.addListener('offlineQueuePop', () => eventFired++); + kuzzle.addListener('offlineQueuePop', function () { eventFired++; }); dequeue.call(kuzzle); - setTimeout(() => { + setTimeout(function () { should(kuzzle.network.send.callCount).be.exactly(numRequests + 1); should(kuzzle.offlineQueue).be.an.Array(); should(kuzzle.offlineQueue.length).be.exactly(0); diff --git a/test/kuzzle/query.test.js b/test/kuzzle/query.test.js index b1caae19c..727432e8e 100644 --- a/test/kuzzle/query.test.js +++ b/test/kuzzle/query.test.js @@ -32,11 +32,15 @@ describe('Query management', function () { it('should fire a jwtTokenExpired event if the token has expired', function (done) { var listenerJwtTokenExpired = false; - kuzzle.network.send = () => process.nextTick(() => kuzzle.network.emit('bar', { - error: { - message: 'Token expired' - } - })); + kuzzle.network.send = function () { + setTimeout(function () { + kuzzle.network.emit('bar', { + error: { + message: 'Token expired' + } + }); + }, 0); + }; kuzzle.addListener('jwtTokenExpired', function() { listenerJwtTokenExpired = true; @@ -45,22 +49,26 @@ describe('Query management', function () { this.timeout(150); emitRequest.call(kuzzle, {requestId: 'bar'}, function(error) { - process.nextTick(() => { + setTimeout(function () { should(listenerJwtTokenExpired).be.exactly(true); should(error.message).be.exactly('Token expired'); done(); - }); + }, 0); }); }); it('should fire a queryError if an error occurred', function (done) { var listenerQueryError = false; - kuzzle.network.send = () => process.nextTick(() => kuzzle.network.emit('bar', { - error: { - message: 'foo-bar' - } - })); + kuzzle.network.send = function () { + setTimeout(function () { + kuzzle.network.emit('bar', { + error: { + message: 'foo-bar' + } + }); + }, 0); + }; kuzzle.addListener('queryError', function() { listenerQueryError = true; @@ -69,11 +77,11 @@ describe('Query management', function () { this.timeout(150); emitRequest.call(kuzzle, {requestId: 'bar'}, function(error) { - process.nextTick(() => { + setTimeout(function () { should(listenerQueryError).be.exactly(true); should(error.message).be.exactly('foo-bar'); done(); - }); + }, 0); }); }); @@ -93,7 +101,12 @@ describe('Query management', function () { this.timeout(50); - kuzzle.network.send = () => process.nextTick(() => kuzzle.network.emit(request.requestId, response)); + kuzzle.network.send = function () { + setTimeout(function () { + kuzzle.network.emit(request.requestId, response); + }, 0); + }; + emitRequest.call(kuzzle, request, cb); }); }); @@ -146,22 +159,22 @@ describe('Query management', function () { should(callback).be.exactly(cb); }); - it('should invoke the callback with an error if no query is provided', () => { - should(() => kuzzle.query(queryArgs, () => {})).throw(Error); - should(() => kuzzle.query(queryArgs, ['foo', 'bar'])).throw(Error); - should(() => kuzzle.query(queryArgs)).throw(Error); - should(() => kuzzle.query(queryArgs, 'foobar')).throw(Error); + it('should invoke the callback with an error if no query is provided', function () { + should(function () { kuzzle.query(queryArgs, function () {}); }).throw(Error); + should(function () { kuzzle.query(queryArgs, ['foo', 'bar']); }).throw(Error); + should(function () { kuzzle.query(queryArgs); }).throw(Error); + should(function () { kuzzle.query(queryArgs, 'foobar'); }).throw(Error); }); - it('should handle options metadata properly', function () { + it('should handle options volatile properly', function () { var - metadata = { + volatile = { foo: 'bar', baz: ['foo', 'bar', 'qux'] }; - kuzzle.query(queryArgs, { body: { some: 'query'}}, {metadata: metadata}); - should(requestObject.metadata).match(metadata); + kuzzle.query(queryArgs, { body: { some: 'query'}}, {volatile: volatile}); + should(requestObject.volatile).match(volatile); }); it('should handle option refresh properly', function () { @@ -194,16 +207,16 @@ describe('Query management', function () { should(emitted).be.false(); }); - it('should copy query local metadata over optional ones', function () { + it('should copy query local volatile over optional ones', function () { var - metadata = { + volatile = { foo: 'bar', baz: ['foo', 'bar', 'qux'] }; - kuzzle.query(queryArgs, { body: { some: 'query'}, metadata: {foo: 'foo'}}, {metadata: metadata}); - should(requestObject.metadata.foo).be.exactly('foo'); - should(requestObject.metadata.baz).match(metadata.baz); + kuzzle.query(queryArgs, { body: { some: 'query'}, volatile: {foo: 'foo'}}, {volatile: volatile}); + should(requestObject.volatile.foo).be.exactly('foo'); + should(requestObject.volatile.baz).match(volatile.baz); }); it('should not define optional members if none was provided', function () { @@ -239,7 +252,7 @@ describe('Query management', function () { var errorRaised = false; - callback = () => { + callback = function () { errorRaised = true; }; @@ -259,7 +272,7 @@ describe('Query management', function () { var errorRaised = false; - callback = () => { + callback = function () { errorRaised = true; }; @@ -279,14 +292,14 @@ describe('Query management', function () { kuzzle.state = 'offline'; kuzzle.queuing = true; - kuzzle.addListener('offlineQueuePush', object => { + kuzzle.addListener('offlineQueuePush', function (object) { eventFired = true; should(object.query.body).be.eql(query.body); }); kuzzle.query(queryArgs, query, cb); - process.nextTick(() => { + setTimeout(function () { should(emitted).be.false(); should(kuzzle.offlineQueue.length).be.exactly(1); should(kuzzle.offlineQueue[0].ts).not.be.undefined().and.be.approximately(now, 10); @@ -294,7 +307,7 @@ describe('Query management', function () { should(kuzzle.offlineQueue[0].cb).be.exactly(cb); should(eventFired).be.true(); done(); - }); + }, 0); }); it('should queue the request during offline mode, if queuable is set to true', function (done) { @@ -306,14 +319,14 @@ describe('Query management', function () { kuzzle.state = 'offline'; kuzzle.queuing = false; - kuzzle.addListener('offlineQueuePush', object => { + kuzzle.addListener('offlineQueuePush', function (object) { eventFired = true; should(object.query.body).be.eql(query.body); }); kuzzle.query(queryArgs, query, {queuable: true}, cb); - process.nextTick(() => { + setTimeout(function () { should(emitted).be.false(); should(kuzzle.offlineQueue.length).be.exactly(1); should(kuzzle.offlineQueue[0].ts).not.be.undefined().and.be.approximately(now, 10); @@ -321,7 +334,7 @@ describe('Query management', function () { should(kuzzle.offlineQueue[0].cb).be.exactly(cb); should(eventFired).be.true(); done(); - }); + }, 0); }); it('should queue the request if a queue filter has been defined and if it allows queuing', function (done) { @@ -331,7 +344,7 @@ describe('Query management', function () { now = Date.now(), eventFired = false; - kuzzle.addListener('offlineQueuePush', object => { + kuzzle.addListener('offlineQueuePush', function (object) { eventFired = true; should(object.query.body).be.eql(query.body); }); @@ -341,7 +354,7 @@ describe('Query management', function () { kuzzle.queuing = true; kuzzle.query(queryArgs, query, cb); - process.nextTick(() => { + setTimeout(function () { should(emitted).be.false(); should(kuzzle.offlineQueue.length).be.exactly(1); should(kuzzle.offlineQueue[0].ts).not.be.undefined().and.be.approximately(now, 10); @@ -349,7 +362,7 @@ describe('Query management', function () { should(kuzzle.offlineQueue[0].cb).be.exactly(cb); should(eventFired).be.true(); done(); - }); + }, 0); }); it('should discard the request if a queue filter has been defined and if it does not allows queuing', function (done) { @@ -358,7 +371,7 @@ describe('Query management', function () { cb = function () {}, eventFired = false; - kuzzle.addListener('offlineQueuePush', () => { + kuzzle.addListener('offlineQueuePush', function () { eventFired = true; }); kuzzle.state = 'offline'; @@ -366,12 +379,12 @@ describe('Query management', function () { kuzzle.queuing = true; kuzzle.query(queryArgs, query, cb); - process.nextTick(() => { + setTimeout(function () { should(emitted).be.false(); should(kuzzle.offlineQueue.length).be.exactly(0); should(eventFired).be.false(); done(); - }); + }, 0); }); it('should discard the request if in offline mode but queuing has not yet been activated', function (done) { @@ -380,19 +393,19 @@ describe('Query management', function () { cb = function () {}, eventFired = false; - kuzzle.addListener('offlineQueuePush', () => { + kuzzle.addListener('offlineQueuePush', function () { eventFired = true; }); kuzzle.state = 'offline'; kuzzle.queuing = false; kuzzle.query(queryArgs, query, cb); - process.nextTick(() => { + setTimeout(function () { should(emitted).be.false(); should(kuzzle.offlineQueue.length).be.exactly(0); should(eventFired).be.false(); done(); - }); + }, 0); }); it('should not set jwtToken if we execute auth/checkToken', function () { diff --git a/test/network/networkWrapper.test.js b/test/network/networkWrapper.test.js index 2dfedd31a..c00970ff6 100644 --- a/test/network/networkWrapper.test.js +++ b/test/network/networkWrapper.test.js @@ -8,29 +8,29 @@ var * @global window */ -describe('Network Wrapper', () => { - afterEach(() => { - window = undefined; - WebSocket = undefined; +describe('Network Wrapper', function () { + afterEach(function () { + window = undefined; // eslint-disable-line + WebSocket = undefined; // eslint-disable-line }); - it('should instantiate a WebSocket object if not in a Web Browser', () => { + it('should instantiate a WebSocket object if not in a Web Browser', function () { should(Wrapper()).be.instanceof(WS); }); - it('should instantiate a WebSocket object if in a Web Browser with WS support', () => { - window = 'foo'; - WebSocket = 'bar'; + it('should instantiate a WebSocket object if in a Web Browser with WS support', function () { + window = 'foo'; // eslint-disable-line + WebSocket = 'bar'; // eslint-disable-line should(Wrapper()).be.instanceof(WS); }); - it('should instantiate a SocketIO object if in a Web Browser without WS support', () => { - window = { io: 'foobar' }; + it('should instantiate a SocketIO object if in a Web Browser without WS support', function () { + window = { io: 'foobar' }; // eslint-disable-line should(Wrapper()).be.instanceof(SocketIO); }); - it('should throw if in WebBrowser without WS support nor SocketIO library', () => { - window = 'foo'; - should(() => Wrapper()).throw('Aborting: no websocket support detected and no socket.io library loaded either.'); + it('should throw if in WebBrowser without WS support nor SocketIO library', function () { + window = 'foo'; // eslint-disable-line + should(function () { Wrapper(); }).throw('Aborting: no websocket support detected and no socket.io library loaded either.'); }); }); diff --git a/test/network/socketio.test.js b/test/network/socketio.test.js index eb096b4e7..89ac95fd8 100644 --- a/test/network/socketio.test.js +++ b/test/network/socketio.test.js @@ -7,12 +7,12 @@ var * @global window */ -describe('SocketIO networking module', () => { +describe('SocketIO networking module', function () { var socketIO, socketStub; - beforeEach(() => { + beforeEach(function () { socketStub = { once: sinon.stub(), on: sinon.stub(), @@ -25,8 +25,8 @@ describe('SocketIO networking module', () => { socketIO.socket = socketStub; }); - it('should connect with the right parameters', () => { - window = {io: sinon.stub()}; + it('should connect with the right parameters', function () { + window = {io: sinon.stub()}; // eslint-disable-line socketIO.connect('autoReconnectValue', 'reconnectionDelayValue'); should(window.io.calledOnce).be.true(); should(window.io.calledWithMatch('http://address:port', { @@ -35,11 +35,11 @@ describe('SocketIO networking module', () => { forceNew: true })).be.true(); - window = undefined; + window = undefined; // eslint-disable-line }); - it('should connect with the secure connection', () => { - window = {io: sinon.stub()}; + it('should connect with the secure connection', function () { + window = {io: sinon.stub()}; // eslint-disable-line socketIO.ssl = true; socketIO.connect('autoReconnectValue', 'reconnectionDelayValue'); should(window.io.calledWithMatch('https://address:port', { @@ -48,65 +48,65 @@ describe('SocketIO networking module', () => { forceNew: true })).be.true(); - window = undefined; + window = undefined; // eslint-disable-line }); - it('should plug onConnect callbacks to the right event', () => { - var cb = () => {}; + it('should plug onConnect callbacks to the right event', function () { + var cb = function () {}; socketIO.onConnect(cb); should(socketStub.on.calledOnce).be.true(); should(socketStub.on.calledWith('connect', cb)).be.true(); }); - it('should plug onConnectError callbacks to the right event', () => { - var cb = () => {}; + it('should plug onConnectError callbacks to the right event', function () { + var cb = function () {}; socketIO.onConnectError(cb); should(socketStub.on.calledOnce).be.true(); should(socketStub.on.calledWith('connect_error', cb)).be.true(); }); - it('should plug onDisconnect callbacks to the right event', () => { - var cb = () => {}; + it('should plug onDisconnect callbacks to the right event', function () { + var cb = function () {}; socketIO.onDisconnect(cb); should(socketStub.on.calledOnce).be.true(); should(socketStub.on.calledWith('disconnect', cb)).be.true(); }); - it('should plug onReconnect callbacks to the right event', () => { - var cb = () => {}; + it('should plug onReconnect callbacks to the right event', function () { + var cb = function () {}; socketIO.onReconnect(cb); should(socketStub.on.calledOnce).be.true(); should(socketStub.on.calledWith('reconnect', cb)).be.true(); }); - it('should be able to listen to an event just once', () => { - var cb = () => {}; + it('should be able to listen to an event just once', function () { + var cb = function () {}; socketIO.once('event', cb); should(socketStub.once.calledOnce).be.true(); should(socketStub.once.calledWith('event', cb)).be.true(); }); - it('should be able to listen to an event', () => { - var cb = () => {}; + it('should be able to listen to an event', function () { + var cb = function () {}; socketIO.on('event', cb); should(socketStub.on.calledOnce).be.true(); should(socketStub.on.calledWith('event', cb)).be.true(); }); - it('should be able to remove an event listener', () => { - var cb = () => {}; + it('should be able to remove an event listener', function () { + var cb = function () {}; socketIO.off('event', cb); should(socketStub.off.calledOnce).be.true(); should(socketStub.off.calledWith('event', cb)).be.true(); }); - it('should be able to send a payload', () => { + it('should be able to send a payload', function () { socketIO.send('some data'); should(socketStub.emit.calledOnce).be.true(); should(socketStub.emit.calledWith('kuzzle', 'some data')).be.true(); }); - it('should be able to be closed', () => { + it('should be able to be closed', function () { socketIO.close(); should(socketStub.close.calledOnce).be.true(); should(socketIO.socket).be.null(); diff --git a/test/network/websocket.test.js b/test/network/websocket.test.js index bf2286607..8b67003a1 100644 --- a/test/network/websocket.test.js +++ b/test/network/websocket.test.js @@ -3,20 +3,20 @@ var sinon = require('sinon'), WS = require('../../src/networkWrapper/wrappers/websocket'); -describe('WebSocket networking module', () => { +describe('WebSocket networking module', function () { var websocket, wsargs, clientStub; - beforeEach(() => { + beforeEach(function () { clientStub = { send: sinon.stub(), close: sinon.stub() }; - window = 'foobar'; - WebSocket = function () { + window = 'foobar'; // eslint-disable-line + WebSocket = function () { // eslint-disable-line wsargs = Array.prototype.slice.call(arguments); return clientStub; }; @@ -24,12 +24,12 @@ describe('WebSocket networking module', () => { websocket = new WS('address', 'port', false); }); - afterEach(() => { - WebSocket = undefined; - window = undefined; + afterEach(function () { + WebSocket = undefined; // eslint-disable-line + window = undefined; // eslint-disable-line }); - it('should initialize a WS connection properly', () => { + it('should initialize a WS connection properly', function () { clientStub.on = sinon.stub(); websocket.connect('autoReconnect', 'reconnectionDelay'); should(wsargs).match(['ws://address:port']); @@ -39,19 +39,19 @@ describe('WebSocket networking module', () => { should(clientStub.onmessage).not.be.undefined(); }); - it('should initialize a WS secure connection', () => { + it('should initialize a WS secure connection', function () { clientStub.on = sinon.stub(); websocket.ssl = true; websocket.connect('autoReconnect', 'reconnectionDelay'); should(wsargs).match(['wss://address:port']); }); - it('should call listeners on a "open" event', () => { + it('should call listeners on a "open" event', function () { var cb = sinon.stub(); websocket.retrying = false; websocket.onConnect(cb); - websocket.listeners.reconnect.push(() => {throw (new Error('wrong event called'));}); + websocket.listeners.reconnect.push(function () {throw (new Error('wrong event called'));}); should(websocket.listeners.connect.length).be.eql(1); websocket.connect(); @@ -61,13 +61,13 @@ describe('WebSocket networking module', () => { should(websocket.listeners.connect.length).be.eql(1); }); - it('should call listeners on a "reconnect" event', () => { + it('should call listeners on a "reconnect" event', function () { var cb = sinon.stub(); websocket.wasConnected = true; websocket.lasturl = 'ws://address:port'; websocket.onReconnect(cb); - websocket.listeners.connect.push({fn: () => {throw (new Error('wrong event called'));}}); + websocket.listeners.connect.push({fn: function () {throw (new Error('wrong event called'));}}); should(websocket.listeners.reconnect.length).be.eql(1); websocket.connect(); @@ -77,7 +77,7 @@ describe('WebSocket networking module', () => { should(websocket.listeners.reconnect.length).be.eql(1); }); - it('should try to reconnect on a connection error with autoReconnect = true', () => { + it('should try to reconnect on a connection error with autoReconnect = true', function () { var cb = sinon.stub(), clock = sinon.useFakeTimers(); @@ -99,7 +99,7 @@ describe('WebSocket networking module', () => { clock.restore(); }); - it('should not try to reconnect on a connection error with autoReconnect = false', () => { + it('should not try to reconnect on a connection error with autoReconnect = false', function () { var cb = sinon.stub(), clock = sinon.useFakeTimers(); @@ -120,7 +120,7 @@ describe('WebSocket networking module', () => { clock.restore(); }); - it('should call listeners on a "disconnect" event', () => { + it('should call listeners on a "disconnect" event', function () { var cb = sinon.stub(); websocket.retrying = false; @@ -134,7 +134,7 @@ describe('WebSocket networking module', () => { should(websocket.listeners.disconnect.length).be.eql(1); }); - it('should call error listeners on a disconnect event with an abnormal websocket code', () => { + it('should call error listeners on a disconnect event with an abnormal websocket code', function () { var cb = sinon.stub(); websocket.retrying = false; @@ -149,7 +149,7 @@ describe('WebSocket networking module', () => { should(websocket.listeners.error.length).be.eql(1); }); - it('should be able to register ephemeral callbacks on an event', () => { + it('should be able to register ephemeral callbacks on an event', function () { var cb = sinon.stub(), payload = {room: 'foobar'}; @@ -170,7 +170,7 @@ describe('WebSocket networking module', () => { should(cb.alwaysCalledWithMatch(payload)).be.true(); }); - it('should be able to register persistent callbacks on an event', () => { + it('should be able to register persistent callbacks on an event', function () { var cb = sinon.stub(), payload = {room: 'foobar'}; @@ -188,7 +188,7 @@ describe('WebSocket networking module', () => { should(cb.alwaysCalledWithMatch(payload)).be.true(); }); - it('should send the message on room "discarded" if no room specified', () => { + it('should send the message on room "discarded" if no room specified', function () { var cb = sinon.stub(), payload = {}; @@ -202,7 +202,7 @@ describe('WebSocket networking module', () => { should(cb.alwaysCalledWithMatch(payload)).be.true(); }); - it('should be able to unregister a callback on an event', () => { + it('should be able to unregister a callback on an event', function () { var cb = sinon.stub(); @@ -219,7 +219,7 @@ describe('WebSocket networking module', () => { should(websocket.listeners.foobar).be.undefined(); }); - it('should do nothing if trying to unregister an non-existent event/callback', () => { + it('should do nothing if trying to unregister an non-existent event/callback', function () { var cb = sinon.stub(); @@ -236,7 +236,7 @@ describe('WebSocket networking module', () => { should(websocket.listeners.foobar).match([{fn: cb, keep: true}, {fn: cb, keep: true}]); }); - it('should send data payload through websocket', () => { + it('should send data payload through websocket', function () { var data = {foo: 'bar'}; clientStub.readyState = clientStub.OPEN = true; @@ -247,7 +247,7 @@ describe('WebSocket networking module', () => { should(clientStub.send.calledWith(JSON.stringify(data))).be.true(); }); - it('should discard messages if the socket is not ready', () => { + it('should discard messages if the socket is not ready', function () { var data = {foo: 'bar'}; clientStub.readyState = 'foo'; @@ -258,7 +258,7 @@ describe('WebSocket networking module', () => { should(clientStub.send.called).be.false(); }); - it('should properly close a connection when asked', () => { + it('should properly close a connection when asked', function () { var cb = sinon.stub(); diff --git a/test/security/kuzzleRole/constructor.test.js b/test/security/kuzzleRole/constructor.test.js index 527117dfa..262cbeca3 100644 --- a/test/security/kuzzleRole/constructor.test.js +++ b/test/security/kuzzleRole/constructor.test.js @@ -17,7 +17,7 @@ describe('Role constructor', function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); }); - it('should throw an error if no id is provided', done => { + it('should throw an error if no id is provided', function (done) { try { new Role(kuzzle.security, null, null); } diff --git a/test/security/kuzzleSecurity/constructor.test.js b/test/security/kuzzleSecurity/constructor.test.js index 3af02a13b..39b2a5e24 100644 --- a/test/security/kuzzleSecurity/constructor.test.js +++ b/test/security/kuzzleSecurity/constructor.test.js @@ -16,7 +16,7 @@ describe('Security constructor', function () { should(kuzzle.security.kuzzle).be.exactly(kuzzle); }); - it('should promisify the right functions', () => { + it('should promisify the right functions', function () { var kuzzle; diff --git a/test/security/kuzzleSecurityDocument/constructor.test.js b/test/security/kuzzleSecurityDocument/constructor.test.js index 56e803e3c..3fad7f838 100644 --- a/test/security/kuzzleSecurityDocument/constructor.test.js +++ b/test/security/kuzzleSecurityDocument/constructor.test.js @@ -3,7 +3,7 @@ var bluebird = require('bluebird'), rewire = require('rewire'), Kuzzle = rewire('../../../src/Kuzzle'), - KuzzleSecurityDocument = require('../../../src/security/SecurityDocument'); + SecurityDocument = require('../../../src/security/SecurityDocument'); describe('KuzzleSecurityDocument constructor', function () { var @@ -17,9 +17,9 @@ describe('KuzzleSecurityDocument constructor', function () { kuzzle = new Kuzzle('foo', {defaultIndex: 'bar'}); }); - it('should throw an error if no id is provided', done => { + it('should throw an error if no id is provided', function (done) { try { - new KuzzleSecurityDocument(kuzzle.security, null, null); + new SecurityDocument(kuzzle.security, null, null); } catch (e) { should(e).be.Error(); @@ -31,7 +31,7 @@ describe('KuzzleSecurityDocument constructor', function () { it('should expose securityDocument properties with the right permissions', function () { - var securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'test', {}); + var securityDocument = new SecurityDocument(kuzzle.security, 'test', {}); should(securityDocument).have.propertyWithDescriptor('kuzzle', { enumerable: false, writable: false, configurable: false }); should(securityDocument).have.propertyWithDescriptor('Security', { enumerable: false, writable: false, configurable: false }); @@ -40,20 +40,20 @@ describe('KuzzleSecurityDocument constructor', function () { }); it('should expose functions', function () { - var securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'test', {}); + var securityDocument = new SecurityDocument(kuzzle.security, 'test', {}); should.exist(securityDocument.setContent); should.exist(securityDocument.serialize); }); it('should handle provided arguments correctly', function () { - var securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'test', {}); + var securityDocument = new SecurityDocument(kuzzle.security, 'test', {}); - should(securityDocument).be.instanceof(KuzzleSecurityDocument); + should(securityDocument).be.instanceof(SecurityDocument); should(securityDocument.id).be.exactly('test'); should(securityDocument.content).be.empty(); - securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'test', {some: 'content'}); + securityDocument = new SecurityDocument(kuzzle.security, 'test', {some: 'content'}); should(securityDocument.id).be.exactly('test'); should(securityDocument.content).match({some: 'content'}); }); diff --git a/test/security/kuzzleSecurityDocument/methods.test.js b/test/security/kuzzleSecurityDocument/methods.test.js index 9ed0647ce..be391ce4b 100644 --- a/test/security/kuzzleSecurityDocument/methods.test.js +++ b/test/security/kuzzleSecurityDocument/methods.test.js @@ -1,7 +1,7 @@ var should = require('should'), Kuzzle = require('../../../src/Kuzzle'), - KuzzleSecurityDocument = require('../../../src/security/SecurityDocument'); + SecurityDocument = require('../../../src/security/SecurityDocument'); describe('KuzzleSecurityDocument methods', function () { var @@ -10,7 +10,7 @@ describe('KuzzleSecurityDocument methods', function () { describe('#toJSON', function () { before(function () { - securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'myId', {some: 'content'}); + securityDocument = new SecurityDocument(kuzzle.security, 'myId', {some: 'content'}); }); it('should serialize itself properly', function () { @@ -25,7 +25,7 @@ describe('KuzzleSecurityDocument methods', function () { describe('#setContent', function () { before(function () { - securityDocument = new KuzzleSecurityDocument(kuzzle.security, 'myId', {some: 'content'}); + securityDocument = new SecurityDocument(kuzzle.security, 'myId', {some: 'content'}); }); it('should replace the current security document', function () { diff --git a/test/security/kuzzleUser/methods.test.js b/test/security/kuzzleUser/methods.test.js index 529a6b6cf..650474e28 100644 --- a/test/security/kuzzleUser/methods.test.js +++ b/test/security/kuzzleUser/methods.test.js @@ -319,7 +319,7 @@ describe('User methods', function () { it('should return the associated profiles', function () { var profileIds = ['profile']; kuzzle = new Kuzzle('http://localhost:7512'); - kuzzleUser = new User(kuzzle.security, 'user', {some: 'content', profileIds}); + kuzzleUser = new User(kuzzle.security, 'user', {some: 'content', profileIds: profileIds}); should(kuzzleUser.getProfiles()).be.eql(profileIds); }); });