UNPKG

229 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (factory((global.ZetaPush = {})));
5}(this, (function (exports) { 'use strict';
6
7var classCallCheck = function (instance, Constructor) {
8 if (!(instance instanceof Constructor)) {
9 throw new TypeError("Cannot call a class as a function");
10 }
11};
12
13var createClass = function () {
14 function defineProperties(target, props) {
15 for (var i = 0; i < props.length; i++) {
16 var descriptor = props[i];
17 descriptor.enumerable = descriptor.enumerable || false;
18 descriptor.configurable = true;
19 if ("value" in descriptor) descriptor.writable = true;
20 Object.defineProperty(target, descriptor.key, descriptor);
21 }
22 }
23
24 return function (Constructor, protoProps, staticProps) {
25 if (protoProps) defineProperties(Constructor.prototype, protoProps);
26 if (staticProps) defineProperties(Constructor, staticProps);
27 return Constructor;
28 };
29}();
30
31
32
33
34
35var defineProperty = function (obj, key, value) {
36 if (key in obj) {
37 Object.defineProperty(obj, key, {
38 value: value,
39 enumerable: true,
40 configurable: true,
41 writable: true
42 });
43 } else {
44 obj[key] = value;
45 }
46
47 return obj;
48};
49
50var get = function get(object, property, receiver) {
51 if (object === null) object = Function.prototype;
52 var desc = Object.getOwnPropertyDescriptor(object, property);
53
54 if (desc === undefined) {
55 var parent = Object.getPrototypeOf(object);
56
57 if (parent === null) {
58 return undefined;
59 } else {
60 return get(parent, property, receiver);
61 }
62 } else if ("value" in desc) {
63 return desc.value;
64 } else {
65 var getter = desc.get;
66
67 if (getter === undefined) {
68 return undefined;
69 }
70
71 return getter.call(receiver);
72 }
73};
74
75var inherits = function (subClass, superClass) {
76 if (typeof superClass !== "function" && superClass !== null) {
77 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
78 }
79
80 subClass.prototype = Object.create(superClass && superClass.prototype, {
81 constructor: {
82 value: subClass,
83 enumerable: false,
84 writable: true,
85 configurable: true
86 }
87 });
88 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
89};
90
91
92
93
94
95
96
97
98
99
100
101var possibleConstructorReturn = function (self, call) {
102 if (!self) {
103 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
104 }
105
106 return call && (typeof call === "object" || typeof call === "function") ? call : self;
107};
108
109/**
110 * @access protected
111 */
112var Service = function Service(_ref) {
113 var $publish = _ref.$publish;
114 classCallCheck(this, Service);
115
116 this.$publish = $publish;
117};
118
119/**
120 * Delegating authentication
121 *
122 * This authentication delegates authentication to an external auth provider
123 * <br>When a zetapush client handshakes with a delegated authentication, the 'token' field given by the client is sent to the configured remote server as part of the URL
124 * <br>The response must be in JSON format
125 * Each key of the response will be considered a user information field name
126 * <br>The handshake from the server will return the primary key in a field named 'login' (regardless of the actual key name you might have chosen)
127 * */
128/**
129 * End-user API for the delegating authentication
130 *
131 * Provisionning verbs.
132 * @access public
133 * */
134var Delegating = function (_Service) {
135 inherits(Delegating, _Service);
136
137 function Delegating() {
138 classCallCheck(this, Delegating);
139 return possibleConstructorReturn(this, (Delegating.__proto__ || Object.getPrototypeOf(Delegating)).apply(this, arguments));
140 }
141
142 createClass(Delegating, null, [{
143 key: 'DEFAULT_DEPLOYMENT_ID',
144
145 /**
146 * Get default deployment id associated to Delegating service
147 * @return {string}
148 */
149 get: function get$$1() {
150 return 'delegating_0';
151 }
152 }]);
153 return Delegating;
154}(Service);
155/**
156 * Local authentication
157 *
158 * Zetapush local authentication
159 * The configurer can choose the primary key and mandatory user fields for account creation
160 * The field 'zetapushKey' is generated by the server and MUST not be used : it contains the unique key of the user inside a sandbox (it can be obtained from inside a macro with the <b>__userKey</b> pseudo-constant)
161 * */
162/**
163 * End-user API for the simple local authentication
164 *
165 * These API verbs allow end-users to manage their account.
166 * @access public
167 * */
168var Simple = function (_Service2) {
169 inherits(Simple, _Service2);
170
171 function Simple() {
172 classCallCheck(this, Simple);
173 return possibleConstructorReturn(this, (Simple.__proto__ || Object.getPrototypeOf(Simple)).apply(this, arguments));
174 }
175
176 createClass(Simple, null, [{
177 key: 'DEFAULT_DEPLOYMENT_ID',
178
179 /**
180 * Get default deployment id associated to Simple service
181 * @return {string}
182 */
183 get: function get$$1() {
184 return 'simple_0';
185 }
186 }]);
187 return Simple;
188}(Service);
189/**
190 * Weak authentication
191 *
192 * The weak authentication allows for anonymous authentication of devices
193 * Such devices can display a qrcode to allow regular users to take control of them
194 * */
195/**
196 * User API for weak devices control
197 *
198 * User API for control and release of weakly authenticated user sessions.
199 * @access public
200 * */
201var Weak = function (_Service3) {
202 inherits(Weak, _Service3);
203
204 function Weak() {
205 classCallCheck(this, Weak);
206 return possibleConstructorReturn(this, (Weak.__proto__ || Object.getPrototypeOf(Weak)).apply(this, arguments));
207 }
208
209 createClass(Weak, [{
210 key: 'control',
211
212 /**
213 * Controls a session
214 *
215 * Takes control of a weak user session, identified by the given public token.
216 * The public token has been previously made available by the controlled device, for example by displaying a QRCode.
217 * Upon control notification, the client SDK of the controlled session is expected to re-handshake.
218 * */
219 value: function control(_ref) {
220 var publicToken = _ref.publicToken,
221 fullRights = _ref.fullRights;
222 return this.$publish('control', { publicToken: publicToken, fullRights: fullRights });
223 }
224 /**
225 * Returns the current token
226 *
227 * Returns your current session's private token. The token field may be null, if you did not log in with this authentication.
228 * The token can be used to log in as the same weak user another time.
229 * */
230
231 }, {
232 key: 'getToken',
233 value: function getToken() {
234 return this.$publish('getToken', {});
235 }
236 /**
237 * Releases a session
238 *
239 * Releases control of a weak user session, identified by the given public token.
240 * The weak user session must have been previously controlled by a call to 'control'.
241 * */
242
243 }, {
244 key: 'release',
245 value: function release(_ref2) {
246 var publicToken = _ref2.publicToken,
247 fullRights = _ref2.fullRights;
248 return this.$publish('release', { publicToken: publicToken, fullRights: fullRights });
249 }
250 }], [{
251 key: 'DEFAULT_DEPLOYMENT_ID',
252
253 /**
254 * Get default deployment id associated to Weak service
255 * @return {string}
256 */
257 get: function get$$1() {
258 return 'weak_0';
259 }
260 }]);
261 return Weak;
262}(Service);
263
264/**
265 * ZetaPush deployables names
266 */
267var DeployableNames = {
268 AUTH_SIMPLE: 'simple',
269 AUTH_WEAK: 'weak',
270 AUTH_DELEGATING: 'delegating'
271
272 /**
273 * Provide abstraction over CometD handshake data structure
274 * @access protected
275 */
276};
277var AbstractHandshake = function () {
278 /**
279 * Create a new handshake manager
280 * @param {{authType: string, sandboxId: string, deploymentId: string}} parameters
281 */
282 function AbstractHandshake(_ref) {
283 var authType = _ref.authType,
284 sandboxId = _ref.sandboxId,
285 deploymentId = _ref.deploymentId;
286 classCallCheck(this, AbstractHandshake);
287
288 /**
289 * @access protected
290 * @type {string}
291 */
292 this.authType = authType;
293 /**
294 * @access protected
295 * @type {string}
296 */
297 this.sandboxId = sandboxId;
298 /**
299 * @access protected
300 * @type {string}
301 */
302 this.deploymentId = deploymentId;
303 }
304 /**
305 * @param {ClientHelper} client
306 * @return {Object}
307 */
308
309
310 createClass(AbstractHandshake, [{
311 key: 'getHandshakeFields',
312 value: function getHandshakeFields(client) {
313 var authentication = {
314 data: this.authData,
315 type: client.getSandboxId() + '.' + this.deploymentId + '.' + this.authType,
316 version: this.authVersion
317 };
318 if (client.getResource()) {
319 authentication.resource = client.getResource();
320 }
321 return {
322 ext: {
323 authentication: authentication
324 }
325 };
326 }
327 /**
328 * Get auth version
329 * @return {string}
330 */
331
332 }, {
333 key: 'authVersion',
334 get: function get$$1() {
335 return 'none';
336 }
337 }]);
338 return AbstractHandshake;
339}();
340
341/**
342 * Provide abstraction over CometD token base handshake data structure
343 * @access protected
344 * @extends {AbstractHandshake}
345 */
346
347
348var TokenHandshake = function (_AbstractHandshake) {
349 inherits(TokenHandshake, _AbstractHandshake);
350
351 /**
352 * @param {{authType: string, deploymentId: string, token: string}} parameters
353 */
354 function TokenHandshake(_ref2) {
355 var authType = _ref2.authType,
356 deploymentId = _ref2.deploymentId,
357 token = _ref2.token;
358 classCallCheck(this, TokenHandshake);
359
360 /**
361 * @access private
362 * @type {string}
363 */
364 var _this = possibleConstructorReturn(this, (TokenHandshake.__proto__ || Object.getPrototypeOf(TokenHandshake)).call(this, { deploymentId: deploymentId, authType: authType }));
365
366 _this.token = token;
367 return _this;
368 }
369 /**
370 * @return {token: string}
371 */
372
373
374 createClass(TokenHandshake, [{
375 key: 'authData',
376 get: function get$$1() {
377 var token = this.token;
378
379 return {
380 token: token
381 };
382 }
383 }]);
384 return TokenHandshake;
385}(AbstractHandshake);
386
387/**
388 * Provide abstraction over CometD credentials based handshake data structure
389 * @access protected
390 * @extends {AbstractHandshake}
391 */
392
393
394var CredentialsHandshake = function (_AbstractHandshake2) {
395 inherits(CredentialsHandshake, _AbstractHandshake2);
396
397 /**
398 * @param {{authType: string, deploymentId: string, login: string, password: string}} parameters
399 */
400 function CredentialsHandshake(_ref3) {
401 var authType = _ref3.authType,
402 deploymentId = _ref3.deploymentId,
403 login = _ref3.login,
404 password = _ref3.password;
405 classCallCheck(this, CredentialsHandshake);
406
407 /**
408 * @access private
409 * @type {string}
410 */
411 var _this2 = possibleConstructorReturn(this, (CredentialsHandshake.__proto__ || Object.getPrototypeOf(CredentialsHandshake)).call(this, { authType: authType, deploymentId: deploymentId }));
412
413 _this2.login = login;
414 /**
415 * @access private
416 * @type {string}
417 */
418 _this2.password = password;
419 return _this2;
420 }
421 /**
422 * Get auth data
423 * @return {login: string, password: string}
424 */
425
426
427 createClass(CredentialsHandshake, [{
428 key: 'authData',
429 get: function get$$1() {
430 var login = this.login,
431 password = this.password;
432
433 return {
434 login: login, password: password
435 };
436 }
437 }]);
438 return CredentialsHandshake;
439}(AbstractHandshake);
440
441/**
442 * Factory to create handshake
443 * @access public
444 */
445
446
447var Authentication = function () {
448 function Authentication() {
449 classCallCheck(this, Authentication);
450 }
451
452 createClass(Authentication, null, [{
453 key: 'simple',
454
455 /**
456 * @param {{deploymentId: string, login: string, password: string}} parameters
457 * @return {CredentialsHandshake}
458 * @example
459 * // Explicit deploymentId
460 * // Authentication provide optional deployment id, according to the following convention `${ServiceType.toLowerCase()_0}`
461 * Authentication.delegating({
462 * deploymentId: '<YOUR-SIMPLE-AUTHENTICATION-DEPLOYMENT-ID>',
463 * login: <USER-LOGIN>,
464 * password: '<USER-PASSWORD>'
465 * })
466 */
467 value: function simple(_ref4) {
468 var _ref4$deploymentId = _ref4.deploymentId,
469 deploymentId = _ref4$deploymentId === undefined ? Simple.DEFAULT_DEPLOYMENT_ID : _ref4$deploymentId,
470 login = _ref4.login,
471 password = _ref4.password;
472
473 return Authentication.create({
474 authType: DeployableNames.AUTH_SIMPLE,
475 deploymentId: deploymentId,
476 login: login,
477 password: password
478 });
479 }
480 /**
481 * @param {{deploymentId: string, token: string}} parameters
482 * @return {TokenHandshake}
483 * @example
484 * // Explicit deploymentId
485 * // Authentication provide optional deployment id, according to the following convention `${ServiceType.toLowerCase()_0}`
486 * Authentication.delegating({
487 * deploymentId: '<YOUR-WEAK-AUTHENTICATION-DEPLOYMENT-ID>',
488 * token: null
489 * })
490 */
491
492 }, {
493 key: 'weak',
494 value: function weak(_ref5) {
495 var _ref5$deploymentId = _ref5.deploymentId,
496 deploymentId = _ref5$deploymentId === undefined ? Weak.DEFAULT_DEPLOYMENT_ID : _ref5$deploymentId,
497 token = _ref5.token;
498
499 return Authentication.create({
500 authType: DeployableNames.AUTH_WEAK,
501 deploymentId: deploymentId,
502 login: token,
503 password: null
504 });
505 }
506 /**
507 * @param {{deploymentId: string, token: string}} parameters
508 * @return {TokenHandshake}
509 * @example
510 * // Explicit deploymentId
511 * // Authentication provide optional deployment id, according to the following convention `${ServiceType.toLowerCase()_0}`
512 * Authentication.delegating({
513 * deploymentId: '<YOUR-DELEGATING-AUTHENTICATION-DEPLOYMENT-ID>',
514 * token: null
515 * })
516 */
517
518 }, {
519 key: 'delegating',
520 value: function delegating(_ref6) {
521 var _ref6$deploymentId = _ref6.deploymentId,
522 deploymentId = _ref6$deploymentId === undefined ? Delegating.DEFAULT_DEPLOYMENT_ID : _ref6$deploymentId,
523 token = _ref6.token;
524
525 return Authentication.create({
526 authType: DeployableNames.AUTH_DELEGATING,
527 deploymentId: deploymentId,
528 login: token,
529 password: null
530 });
531 }
532 /**
533 * @param {{authType: string, deploymentId: string, login: string, password: string}} parameters
534 * @return {TokenHandshake|CredentialsHandshake}
535 */
536
537 }, {
538 key: 'create',
539 value: function create(_ref7) {
540 var authType = _ref7.authType,
541 deploymentId = _ref7.deploymentId,
542 login = _ref7.login,
543 password = _ref7.password;
544
545 if (password === null) {
546 return new TokenHandshake({ authType: authType, deploymentId: deploymentId, token: login });
547 }
548 return new CredentialsHandshake({ authType: authType, deploymentId: deploymentId, login: login, password: password });
549 }
550 }]);
551 return Authentication;
552}();
553
554/**
555 * Define life cycle connection methods
556 * @access public
557 */
558var ConnectionStatusListener = function () {
559 function ConnectionStatusListener() {
560 classCallCheck(this, ConnectionStatusListener);
561 }
562
563 createClass(ConnectionStatusListener, [{
564 key: "onConnectionBroken",
565
566 /**
567 * Callback fired when connection is broken
568 */
569 value: function onConnectionBroken() {}
570 /**
571 * Callback fired when connection is closed
572 */
573
574 }, {
575 key: "onConnectionClosed",
576 value: function onConnectionClosed() {}
577 /**
578 * Callback fired when connection is established
579 */
580
581 }, {
582 key: "onConnectionEstablished",
583 value: function onConnectionEstablished() {}
584 /**
585 * Callback fired when an error occurs in connection to server step
586 * @param {Object} failure
587 */
588
589 }, {
590 key: "onConnectionToServerFail",
591 value: function onConnectionToServerFail(failure) {}
592 /**
593 * Callback fired when negociation with server failed
594 * @param {Object} failure
595 */
596
597 }, {
598 key: "onNegotiationFailed",
599 value: function onNegotiationFailed(failure) {}
600 /**
601 * Callback no server url avaibale
602 */
603
604 }, {
605 key: "onNoServerUrlAvailable",
606 value: function onNoServerUrlAvailable() {}
607 /**
608 * Callback fired when connection will close
609 */
610
611 }, {
612 key: "onConnectionWillClose",
613 value: function onConnectionWillClose() {}
614 /**
615 * Callback fired when an error occurs in handshake step
616 * @param {Object} failure
617 */
618
619 }, {
620 key: "onFailedHandshake",
621 value: function onFailedHandshake(failure) {}
622 /**
623 * Callback fired when a message is lost
624 */
625
626 }, {
627 key: "onMessageLost",
628 value: function onMessageLost() {}
629 /**
630 * Callback fired when handshake step succeed
631 * @param {Object} authentication
632 */
633
634 }, {
635 key: "onSuccessfulHandshake",
636 value: function onSuccessfulHandshake(authentication) {}
637 }]);
638 return ConnectionStatusListener;
639}();
640
641/**
642 * A registry for transports used by the CometD object.
643 */
644var TransportRegistry = function TransportRegistry() {
645 var _types = [];
646 var _transports = {};
647
648 this.getTransportTypes = function() {
649 return _types.slice(0);
650 };
651
652 this.findTransportTypes = function(version, crossDomain, url) {
653 var result = [];
654 for (var i = 0; i < _types.length; ++i) {
655 var type = _types[i];
656 if (_transports[type].accept(version, crossDomain, url) === true) {
657 result.push(type);
658 }
659 }
660 return result;
661 };
662
663 this.negotiateTransport = function(types, version, crossDomain, url) {
664 for (var i = 0; i < _types.length; ++i) {
665 var type = _types[i];
666 for (var j = 0; j < types.length; ++j) {
667 if (type === types[j]) {
668 var transport = _transports[type];
669 if (transport.accept(version, crossDomain, url) === true) {
670 return transport;
671 }
672 }
673 }
674 }
675 return null;
676 };
677
678 this.add = function(type, transport, index) {
679 var existing = false;
680 for (var i = 0; i < _types.length; ++i) {
681 if (_types[i] === type) {
682 existing = true;
683 break;
684 }
685 }
686
687 if (!existing) {
688 if (typeof index !== 'number') {
689 _types.push(type);
690 } else {
691 _types.splice(index, 0, type);
692 }
693 _transports[type] = transport;
694 }
695
696 return !existing;
697 };
698
699 this.find = function(type) {
700 for (var i = 0; i < _types.length; ++i) {
701 if (_types[i] === type) {
702 return _transports[type];
703 }
704 }
705 return null;
706 };
707
708 this.remove = function(type) {
709 for (var i = 0; i < _types.length; ++i) {
710 if (_types[i] === type) {
711 _types.splice(i, 1);
712 var transport = _transports[type];
713 delete _transports[type];
714 return transport;
715 }
716 }
717 return null;
718 };
719
720 this.clear = function() {
721 _types = [];
722 _transports = {};
723 };
724
725 this.reset = function(init) {
726 for (var i = 0; i < _types.length; ++i) {
727 _transports[_types[i]].reset(init);
728 }
729 };
730};
731
732var isString = function (value) {
733 if (value === undefined || value === null) {
734 return false;
735 }
736 return typeof value === 'string' || value instanceof String;
737};
738
739var isArray = function (value) {
740 if (value === undefined || value === null) {
741 return false;
742 }
743 return value instanceof Array;
744};
745
746/**
747 * Returns whether the given element is contained into the given array.
748 * @param element the element to check presence for
749 * @param array the array to check for the element presence
750 * @return the index of the element, if present, or a negative index if the element is not present
751 */
752var inArray = function (element, array) {
753 for (var i = 0; i < array.length; ++i) {
754 if (element === array[i]) {
755 return i;
756 }
757 }
758 return -1;
759};
760
761var setTimeout_1 = function (cometd, funktion, delay) {
762 return setTimeout(function() {
763 try {
764 cometd._debug('Invoking timed function', funktion);
765 funktion();
766 } catch (x) {
767 cometd._debug('Exception invoking timed function', funktion, x);
768 }
769 }, delay);
770};
771
772var clearTimeout_1 = function (timeoutHandle) {
773 clearTimeout(timeoutHandle);
774};
775
776var Utils = {
777 isString: isString,
778 isArray: isArray,
779 inArray: inArray,
780 setTimeout: setTimeout_1,
781 clearTimeout: clearTimeout_1
782};
783
784/**
785 * The constructor for a CometD object, identified by an optional name.
786 * The default name is the string 'default'.
787 * In the rare case a page needs more than one Bayeux conversation,
788 * a new instance can be created via:
789 * <pre>
790 * var bayeuxUrl2 = ...;
791 *
792 * // Dojo style
793 * var cometd2 = new dojox.CometD('another_optional_name');
794 *
795 * // jQuery style
796 * var cometd2 = new $.CometD('another_optional_name');
797 *
798 * cometd2.init({url: bayeuxUrl2});
799 * </pre>
800 * @param name the optional name of this cometd object
801 */
802var CometD$1 = function CometD(name) {
803 var _cometd = this;
804 var _name = name || 'default';
805 var _crossDomain = false;
806 var _transports = new TransportRegistry();
807 var _transport;
808 var _status = 'disconnected';
809 var _messageId = 0;
810 var _clientId = null;
811 var _batch = 0;
812 var _messageQueue = [];
813 var _internalBatch = false;
814 var _listeners = {};
815 var _backoff = 0;
816 var _scheduledSend = null;
817 var _extensions = [];
818 var _advice = {};
819 var _handshakeProps;
820 var _handshakeCallback;
821 var _callbacks = {};
822 var _remoteCalls = {};
823 var _reestablish = false;
824 var _connected = false;
825 var _unconnectTime = 0;
826 var _handshakeMessages = 0;
827 var _config = {
828 protocol: null,
829 stickyReconnect: true,
830 connectTimeout: 0,
831 maxConnections: 2,
832 backoffIncrement: 1000,
833 maxBackoff: 60000,
834 logLevel: 'info',
835 reverseIncomingExtensions: true,
836 maxNetworkDelay: 10000,
837 requestHeaders: {},
838 appendMessageTypeToURL: true,
839 autoBatch: false,
840 urls: {},
841 maxURILength: 2000,
842 advice: {
843 timeout: 60000,
844 interval: 0,
845 reconnect: 'retry',
846 maxInterval: 0
847 }
848 };
849
850 function _fieldValue(object, name) {
851 try {
852 return object[name];
853 } catch (x) {
854 return undefined;
855 }
856 }
857
858 /**
859 * Mixes in the given objects into the target object by copying the properties.
860 * @param deep if the copy must be deep
861 * @param target the target object
862 * @param objects the objects whose properties are copied into the target
863 */
864 this._mixin = function(deep, target, objects) {
865 var result = target || {};
866
867 // Skip first 2 parameters (deep and target), and loop over the others
868 for (var i = 2; i < arguments.length; ++i) {
869 var object = arguments[i];
870
871 if (object === undefined || object === null) {
872 continue;
873 }
874
875 for (var propName in object) {
876 if (object.hasOwnProperty(propName)) {
877 var prop = _fieldValue(object, propName);
878 var targ = _fieldValue(result, propName);
879
880 // Avoid infinite loops
881 if (prop === target) {
882 continue;
883 }
884 // Do not mixin undefined values
885 if (prop === undefined) {
886 continue;
887 }
888
889 if (deep && typeof prop === 'object' && prop !== null) {
890 if (prop instanceof Array) {
891 result[propName] = this._mixin(deep, targ instanceof Array ? targ : [], prop);
892 } else {
893 var source = typeof targ === 'object' && !(targ instanceof Array) ? targ : {};
894 result[propName] = this._mixin(deep, source, prop);
895 }
896 } else {
897 result[propName] = prop;
898 }
899 }
900 }
901 }
902
903 return result;
904 };
905
906 function _isString(value) {
907 return Utils.isString(value);
908 }
909
910 function _isFunction(value) {
911 if (value === undefined || value === null) {
912 return false;
913 }
914 return typeof value === 'function';
915 }
916
917 function _zeroPad(value, length) {
918 var result = '';
919 while (--length > 0) {
920 if (value >= Math.pow(10, length)) {
921 break;
922 }
923 result += '0';
924 }
925 result += value;
926 return result;
927 }
928
929 function _log(level, args) {
930 if ('undefined' !== typeof console) {
931 var logger = console[level];
932 if (_isFunction(logger)) {
933 var now = new Date();
934 [].splice.call(args, 0, 0, _zeroPad(now.getHours(), 2) + ':' + _zeroPad(now.getMinutes(), 2) + ':' +
935 _zeroPad(now.getSeconds(), 2) + '.' + _zeroPad(now.getMilliseconds(), 3));
936 logger.apply(console, args);
937 }
938 }
939 }
940
941 this._warn = function() {
942 _log('warn', arguments);
943 };
944
945 this._info = function() {
946 if (_config.logLevel !== 'warn') {
947 _log('info', arguments);
948 }
949 };
950
951 this._debug = function() {
952 if (_config.logLevel === 'debug') {
953 _log('debug', arguments);
954 }
955 };
956
957 function _splitURL(url) {
958 // [1] = protocol://,
959 // [2] = host:port,
960 // [3] = host,
961 // [4] = IPv6_host,
962 // [5] = IPv4_host,
963 // [6] = :port,
964 // [7] = port,
965 // [8] = uri,
966 // [9] = rest (query / fragment)
967 return /(^https?:\/\/)?(((\[[^\]]+\])|([^:\/\?#]+))(:(\d+))?)?([^\?#]*)(.*)?/.exec(url);
968 }
969
970 /**
971 * Returns whether the given hostAndPort is cross domain.
972 * The default implementation checks against window.location.host
973 * but this function can be overridden to make it work in non-browser
974 * environments.
975 *
976 * @param hostAndPort the host and port in format host:port
977 * @return whether the given hostAndPort is cross domain
978 */
979 this._isCrossDomain = function(hostAndPort) {
980 var host = typeof location === 'undefined' ? hostAndPort : location.host;
981 return hostAndPort && hostAndPort !== host;
982 };
983
984 function _configure(configuration) {
985 _cometd._debug('Configuring cometd object with', configuration);
986 // Support old style param, where only the Bayeux server URL was passed
987 if (_isString(configuration)) {
988 configuration = { url: configuration };
989 }
990 if (!configuration) {
991 configuration = {};
992 }
993
994 _config = _cometd._mixin(false, _config, configuration);
995
996 var url = _cometd.getURL();
997 if (!url) {
998 throw 'Missing required configuration parameter \'url\' specifying the Bayeux server URL';
999 }
1000
1001 // Check if we're cross domain.
1002 var urlParts = _splitURL(url);
1003 var hostAndPort = urlParts[2];
1004 var uri = urlParts[8];
1005 var afterURI = urlParts[9];
1006 _crossDomain = _cometd._isCrossDomain(hostAndPort);
1007
1008 // Check if appending extra path is supported
1009 if (_config.appendMessageTypeToURL) {
1010 if (afterURI !== undefined && afterURI.length > 0) {
1011 _cometd._info('Appending message type to URI ' + uri + afterURI + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
1012 _config.appendMessageTypeToURL = false;
1013 } else {
1014 var uriSegments = uri.split('/');
1015 var lastSegmentIndex = uriSegments.length - 1;
1016 if (uri.match(/\/$/)) {
1017 lastSegmentIndex -= 1;
1018 }
1019 if (uriSegments[lastSegmentIndex].indexOf('.') >= 0) {
1020 // Very likely the CometD servlet's URL pattern is mapped to an extension, such as *.cometd
1021 // It will be difficult to add the extra path in this case
1022 _cometd._info('Appending message type to URI ' + uri + ' is not supported, disabling \'appendMessageTypeToURL\' configuration');
1023 _config.appendMessageTypeToURL = false;
1024 }
1025 }
1026 }
1027 }
1028
1029 function _removeListener(subscription) {
1030 if (subscription) {
1031 var subscriptions = _listeners[subscription.channel];
1032 if (subscriptions && subscriptions[subscription.id]) {
1033 delete subscriptions[subscription.id];
1034 _cometd._debug('Removed', subscription.listener ? 'listener' : 'subscription', subscription);
1035 }
1036 }
1037 }
1038
1039 function _removeSubscription(subscription) {
1040 if (subscription && !subscription.listener) {
1041 _removeListener(subscription);
1042 }
1043 }
1044
1045 function _clearSubscriptions() {
1046 for (var channel in _listeners) {
1047 if (_listeners.hasOwnProperty(channel)) {
1048 var subscriptions = _listeners[channel];
1049 if (subscriptions) {
1050 for (var i = 0; i < subscriptions.length; ++i) {
1051 _removeSubscription(subscriptions[i]);
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058 function _setStatus(newStatus) {
1059 if (_status !== newStatus) {
1060 _cometd._debug('Status', _status, '->', newStatus);
1061 _status = newStatus;
1062 }
1063 }
1064
1065 function _isDisconnected() {
1066 return _status === 'disconnecting' || _status === 'disconnected';
1067 }
1068
1069 function _nextMessageId() {
1070 var result = ++_messageId;
1071 return '' + result;
1072 }
1073
1074 function _applyExtension(scope, callback, name, message, outgoing) {
1075 try {
1076 return callback.call(scope, message);
1077 } catch (x) {
1078 var handler = _cometd.onExtensionException;
1079 if (_isFunction(handler)) {
1080 _cometd._debug('Invoking extension exception handler', name, x);
1081 try {
1082 handler.call(_cometd, x, name, outgoing, message);
1083 } catch (xx) {
1084 _cometd._info('Exception during execution of extension exception handler', name, xx);
1085 }
1086 } else {
1087 _cometd._info('Exception during execution of extension', name, x);
1088 }
1089 return message;
1090 }
1091 }
1092
1093 function _applyIncomingExtensions(message) {
1094 for (var i = 0; i < _extensions.length; ++i) {
1095 if (message === undefined || message === null) {
1096 break;
1097 }
1098
1099 var index = _config.reverseIncomingExtensions ? _extensions.length - 1 - i : i;
1100 var extension = _extensions[index];
1101 var callback = extension.extension.incoming;
1102 if (_isFunction(callback)) {
1103 var result = _applyExtension(extension.extension, callback, extension.name, message, false);
1104 message = result === undefined ? message : result;
1105 }
1106 }
1107 return message;
1108 }
1109
1110 function _applyOutgoingExtensions(message) {
1111 for (var i = 0; i < _extensions.length; ++i) {
1112 if (message === undefined || message === null) {
1113 break;
1114 }
1115
1116 var extension = _extensions[i];
1117 var callback = extension.extension.outgoing;
1118 if (_isFunction(callback)) {
1119 var result = _applyExtension(extension.extension, callback, extension.name, message, true);
1120 message = result === undefined ? message : result;
1121 }
1122 }
1123 return message;
1124 }
1125
1126 function _notify(channel, message) {
1127 var subscriptions = _listeners[channel];
1128 if (subscriptions && subscriptions.length > 0) {
1129 for (var i = 0; i < subscriptions.length; ++i) {
1130 var subscription = subscriptions[i];
1131 // Subscriptions may come and go, so the array may have 'holes'
1132 if (subscription) {
1133 try {
1134 subscription.callback.call(subscription.scope, message);
1135 } catch (x) {
1136 var handler = _cometd.onListenerException;
1137 if (_isFunction(handler)) {
1138 _cometd._debug('Invoking listener exception handler', subscription, x);
1139 try {
1140 handler.call(_cometd, x, subscription, subscription.listener, message);
1141 } catch (xx) {
1142 _cometd._info('Exception during execution of listener exception handler', subscription, xx);
1143 }
1144 } else {
1145 _cometd._info('Exception during execution of listener', subscription, message, x);
1146 }
1147 }
1148 }
1149 }
1150 }
1151 }
1152
1153 function _notifyListeners(channel, message) {
1154 // Notify direct listeners
1155 _notify(channel, message);
1156
1157 // Notify the globbing listeners
1158 var channelParts = channel.split('/');
1159 var last = channelParts.length - 1;
1160 for (var i = last; i > 0; --i) {
1161 var channelPart = channelParts.slice(0, i).join('/') + '/*';
1162 // We don't want to notify /foo/* if the channel is /foo/bar/baz,
1163 // so we stop at the first non recursive globbing
1164 if (i === last) {
1165 _notify(channelPart, message);
1166 }
1167 // Add the recursive globber and notify
1168 channelPart += '*';
1169 _notify(channelPart, message);
1170 }
1171 }
1172
1173 function _cancelDelayedSend() {
1174 if (_scheduledSend !== null) {
1175 Utils.clearTimeout(_scheduledSend);
1176 }
1177 _scheduledSend = null;
1178 }
1179
1180 function _delayedSend(operation, delay) {
1181 if ('undefined' === typeof delay) {
1182 delay = _backoff;
1183 }
1184 _cancelDelayedSend();
1185 var time = _advice.interval + delay;
1186 _cometd._debug('Function scheduled in', time, 'ms, interval =', _advice.interval, 'backoff =', _backoff, operation);
1187 _scheduledSend = Utils.setTimeout(_cometd, operation, time);
1188 }
1189
1190 // Needed to break cyclic dependencies between function definitions
1191 var _handleMessages;
1192 var _handleFailure;
1193
1194 /**
1195 * Delivers the messages to the CometD server
1196 * @param sync whether the send is synchronous
1197 * @param messages the array of messages to send
1198 * @param metaConnect true if this send is on /meta/connect
1199 * @param extraPath an extra path to append to the Bayeux server URL
1200 */
1201 function _send(sync, messages, metaConnect, extraPath) {
1202 // We must be sure that the messages have a clientId.
1203 // This is not guaranteed since the handshake may take time to return
1204 // (and hence the clientId is not known yet) and the application
1205 // may create other messages.
1206 for (var i = 0; i < messages.length; ++i) {
1207 var message = messages[i];
1208 var messageId = message.id;
1209
1210 if (_clientId) {
1211 message.clientId = _clientId;
1212 }
1213
1214 message = _applyOutgoingExtensions(message);
1215 if (message !== undefined && message !== null) {
1216 // Extensions may have modified the message id, but we need to own it.
1217 message.id = messageId;
1218 messages[i] = message;
1219 } else {
1220 delete _callbacks[messageId];
1221 messages.splice(i--, 1);
1222 }
1223 }
1224
1225 if (messages.length === 0) {
1226 return;
1227 }
1228
1229 var url = _cometd.getURL();
1230 if (_config.appendMessageTypeToURL) {
1231 // If url does not end with '/', then append it
1232 if (!url.match(/\/$/)) {
1233 url = url + '/';
1234 }
1235 if (extraPath) {
1236 url = url + extraPath;
1237 }
1238 }
1239
1240 var envelope = {
1241 url: url,
1242 sync: sync,
1243 messages: messages,
1244 onSuccess: function(rcvdMessages) {
1245 try {
1246 _handleMessages.call(_cometd, rcvdMessages);
1247 } catch (x) {
1248 _cometd._info('Exception during handling of messages', x);
1249 }
1250 },
1251 onFailure: function(conduit, messages, failure) {
1252 try {
1253 var transport = _cometd.getTransport();
1254 failure.connectionType = transport ? transport.getType() : "unknown";
1255 _handleFailure.call(_cometd, conduit, messages, failure);
1256 } catch (x) {
1257 _cometd._info('Exception during handling of failure', x);
1258 }
1259 }
1260 };
1261 _cometd._debug('Send', envelope);
1262 _transport.send(envelope, metaConnect);
1263 }
1264
1265 function _queueSend(message) {
1266 if (_batch > 0 || _internalBatch === true) {
1267 _messageQueue.push(message);
1268 } else {
1269 _send(false, [message], false);
1270 }
1271 }
1272
1273 /**
1274 * Sends a complete bayeux message.
1275 * This method is exposed as a public so that extensions may use it
1276 * to send bayeux message directly, for example in case of re-sending
1277 * messages that have already been sent but that for some reason must
1278 * be resent.
1279 */
1280 this.send = _queueSend;
1281
1282 function _resetBackoff() {
1283 _backoff = 0;
1284 }
1285
1286 function _increaseBackoff() {
1287 if (_backoff < _config.maxBackoff) {
1288 _backoff += _config.backoffIncrement;
1289 }
1290 return _backoff;
1291 }
1292
1293 /**
1294 * Starts a the batch of messages to be sent in a single request.
1295 * @see #_endBatch(sendMessages)
1296 */
1297 function _startBatch() {
1298 ++_batch;
1299 _cometd._debug('Starting batch, depth', _batch);
1300 }
1301
1302 function _flushBatch() {
1303 var messages = _messageQueue;
1304 _messageQueue = [];
1305 if (messages.length > 0) {
1306 _send(false, messages, false);
1307 }
1308 }
1309
1310 /**
1311 * Ends the batch of messages to be sent in a single request,
1312 * optionally sending messages present in the message queue depending
1313 * on the given argument.
1314 * @see #_startBatch()
1315 */
1316 function _endBatch() {
1317 --_batch;
1318 _cometd._debug('Ending batch, depth', _batch);
1319 if (_batch < 0) {
1320 throw 'Calls to startBatch() and endBatch() are not paired';
1321 }
1322
1323 if (_batch === 0 && !_isDisconnected() && !_internalBatch) {
1324 _flushBatch();
1325 }
1326 }
1327
1328 /**
1329 * Sends the connect message
1330 */
1331 function _connect() {
1332 if (!_isDisconnected()) {
1333 var bayeuxMessage = {
1334 id: _nextMessageId(),
1335 channel: '/meta/connect',
1336 connectionType: _transport.getType()
1337 };
1338
1339 // In case of reload or temporary loss of connection
1340 // we want the next successful connect to return immediately
1341 // instead of being held by the server, so that connect listeners
1342 // can be notified that the connection has been re-established
1343 if (!_connected) {
1344 bayeuxMessage.advice = { timeout: 0 };
1345 }
1346
1347 _setStatus('connecting');
1348 _cometd._debug('Connect sent', bayeuxMessage);
1349 _send(false, [bayeuxMessage], true, 'connect');
1350 _setStatus('connected');
1351 }
1352 }
1353
1354 function _delayedConnect(delay) {
1355 _setStatus('connecting');
1356 _delayedSend(function() {
1357 _connect();
1358 }, delay);
1359 }
1360
1361 function _updateAdvice(newAdvice) {
1362 if (newAdvice) {
1363 _advice = _cometd._mixin(false, {}, _config.advice, newAdvice);
1364 _cometd._debug('New advice', _advice);
1365 }
1366 }
1367
1368 function _disconnect(abort) {
1369 _cancelDelayedSend();
1370 if (abort && _transport) {
1371 _transport.abort();
1372 }
1373 _clientId = null;
1374 _setStatus('disconnected');
1375 _batch = 0;
1376 _resetBackoff();
1377 _transport = null;
1378
1379 // Fail any existing queued message
1380 if (_messageQueue.length > 0) {
1381 var messages = _messageQueue;
1382 _messageQueue = [];
1383 _handleFailure.call(_cometd, undefined, messages, {
1384 reason: 'Disconnected'
1385 });
1386 }
1387 }
1388
1389 function _notifyTransportFailure(oldTransport, newTransport, failure) {
1390 var handler = _cometd.onTransportException;
1391 if (_isFunction(handler)) {
1392 _cometd._debug('Invoking transport exception handler', oldTransport, newTransport, failure);
1393 try {
1394 handler.call(_cometd, failure, oldTransport, newTransport);
1395 } catch (x) {
1396 _cometd._info('Exception during execution of transport exception handler', x);
1397 }
1398 }
1399 }
1400
1401 /**
1402 * Sends the initial handshake message
1403 */
1404 function _handshake(handshakeProps, handshakeCallback) {
1405 if (_isFunction(handshakeProps)) {
1406 handshakeCallback = handshakeProps;
1407 handshakeProps = undefined;
1408 }
1409
1410 _clientId = null;
1411
1412 _clearSubscriptions();
1413
1414 // Reset the transports if we're not retrying the handshake
1415 if (_isDisconnected()) {
1416 _transports.reset(true);
1417 _updateAdvice(_config.advice);
1418 } else {
1419 // We are retrying the handshake, either because another handshake failed
1420 // and we're backing off, or because the server timed us out and asks us to
1421 // re-handshake: in both cases, make sure that if the handshake succeeds
1422 // the next action is a connect.
1423 _updateAdvice(_cometd._mixin(false, _advice, {reconnect: 'retry'}));
1424 }
1425
1426 _batch = 0;
1427
1428 // Mark the start of an internal batch.
1429 // This is needed because handshake and connect are async.
1430 // It may happen that the application calls init() then subscribe()
1431 // and the subscribe message is sent before the connect message, if
1432 // the subscribe message is not held until the connect message is sent.
1433 // So here we start a batch to hold temporarily any message until
1434 // the connection is fully established.
1435 _internalBatch = true;
1436
1437 // Save the properties provided by the user, so that
1438 // we can reuse them during automatic re-handshake
1439 _handshakeProps = handshakeProps;
1440 _handshakeCallback = handshakeCallback;
1441
1442 var version = '1.0';
1443
1444 // Figure out the transports to send to the server
1445 var url = _cometd.getURL();
1446 var transportTypes = _transports.findTransportTypes(version, _crossDomain, url);
1447
1448 var bayeuxMessage = {
1449 id: _nextMessageId(),
1450 version: version,
1451 minimumVersion: version,
1452 channel: '/meta/handshake',
1453 supportedConnectionTypes: transportTypes,
1454 advice: {
1455 timeout: _advice.timeout,
1456 interval: _advice.interval
1457 }
1458 };
1459 // Do not allow the user to override important fields.
1460 var message = _cometd._mixin(false, {}, _handshakeProps, bayeuxMessage);
1461
1462 // Save the callback.
1463 _cometd._putCallback(message.id, handshakeCallback);
1464
1465 // Pick up the first available transport as initial transport
1466 // since we don't know if the server supports it
1467 if (!_transport) {
1468 _transport = _transports.negotiateTransport(transportTypes, version, _crossDomain, url);
1469 if (!_transport) {
1470 var failure = 'Could not find initial transport among: ' + _transports.getTransportTypes();
1471 _cometd._warn(failure);
1472 throw failure;
1473 }
1474 }
1475
1476 _cometd._debug('Initial transport is', _transport.getType());
1477
1478 // We started a batch to hold the application messages,
1479 // so here we must bypass it and send immediately.
1480 _setStatus('handshaking');
1481 _cometd._debug('Handshake sent', message);
1482 _send(false, [message], false, 'handshake');
1483 }
1484
1485 function _delayedHandshake(delay) {
1486 _setStatus('handshaking');
1487
1488 // We will call _handshake() which will reset _clientId, but we want to avoid
1489 // that between the end of this method and the call to _handshake() someone may
1490 // call publish() (or other methods that call _queueSend()).
1491 _internalBatch = true;
1492
1493 _delayedSend(function() {
1494 _handshake(_handshakeProps, _handshakeCallback);
1495 }, delay);
1496 }
1497
1498 function _notifyCallback(callback, message) {
1499 try {
1500 callback.call(_cometd, message);
1501 } catch (x) {
1502 var handler = _cometd.onCallbackException;
1503 if (_isFunction(handler)) {
1504 _cometd._debug('Invoking callback exception handler', x);
1505 try {
1506 handler.call(_cometd, x, message);
1507 } catch (xx) {
1508 _cometd._info('Exception during execution of callback exception handler', xx);
1509 }
1510 } else {
1511 _cometd._info('Exception during execution of message callback', x);
1512 }
1513 }
1514 }
1515
1516 this._getCallback = function(messageId) {
1517 return _callbacks[messageId];
1518 };
1519
1520 this._putCallback = function(messageId, callback) {
1521 var result = this._getCallback(messageId);
1522 if (_isFunction(callback)) {
1523 _callbacks[messageId] = callback;
1524 }
1525 return result;
1526 };
1527
1528 function _handleCallback(message) {
1529 var callback = _cometd._getCallback([message.id]);
1530 if (_isFunction(callback)) {
1531 delete _callbacks[message.id];
1532 _notifyCallback(callback, message);
1533 }
1534 }
1535
1536 function _handleRemoteCall(message) {
1537 var context = _remoteCalls[message.id];
1538 delete _remoteCalls[message.id];
1539 _cometd._debug('Handling remote call response for', message, 'with context', context);
1540 if (context) {
1541 // Clear the timeout, if present.
1542 var timeout = context.timeout;
1543 if (timeout) {
1544 Utils.clearTimeout(timeout);
1545 }
1546
1547 var callback = context.callback;
1548 if (_isFunction(callback)) {
1549 _notifyCallback(callback, message);
1550 return true;
1551 }
1552 }
1553 return false;
1554 }
1555
1556 function _failHandshake(message) {
1557 _handleCallback(message);
1558 _notifyListeners('/meta/handshake', message);
1559 _notifyListeners('/meta/unsuccessful', message);
1560
1561 // Only try again if we haven't been disconnected and
1562 // the advice permits us to retry the handshake
1563 var retry = !_isDisconnected() && _advice.reconnect !== 'none';
1564 if (retry) {
1565 _increaseBackoff();
1566 _delayedHandshake();
1567 } else {
1568 _disconnect(true);
1569 }
1570 }
1571
1572 function _handshakeResponse(message) {
1573 if (message.successful) {
1574 // Save clientId, figure out transport, then follow the advice to connect
1575 _clientId = message.clientId;
1576
1577 var url = _cometd.getURL();
1578 var newTransport = _transports.negotiateTransport(message.supportedConnectionTypes, message.version, _crossDomain, url);
1579 if (newTransport === null) {
1580 var failure = 'Could not negotiate transport with server; client=[' +
1581 _transports.findTransportTypes(message.version, _crossDomain, url) +
1582 '], server=[' + message.supportedConnectionTypes + ']';
1583 var oldTransport = _cometd.getTransport();
1584 _notifyTransportFailure(oldTransport.getType(), null, {
1585 reason: failure,
1586 connectionType: oldTransport.getType(),
1587 transport: oldTransport
1588 });
1589 _cometd._warn(failure);
1590 _disconnect(true);
1591 return;
1592 } else if (_transport !== newTransport) {
1593 _cometd._debug('Transport', _transport.getType(), '->', newTransport.getType());
1594 _transport = newTransport;
1595 }
1596
1597 // End the internal batch and allow held messages from the application
1598 // to go to the server (see _handshake() where we start the internal batch).
1599 _internalBatch = false;
1600 _flushBatch();
1601
1602 // Here the new transport is in place, as well as the clientId, so
1603 // the listeners can perform a publish() if they want.
1604 // Notify the listeners before the connect below.
1605 message.reestablish = _reestablish;
1606 _reestablish = true;
1607
1608 _handleCallback(message);
1609 _notifyListeners('/meta/handshake', message);
1610
1611 var action = _isDisconnected() ? 'none' : _advice.reconnect;
1612 switch (action) {
1613 case 'retry':
1614 _resetBackoff();
1615 _delayedConnect();
1616 break;
1617 case 'none':
1618 _disconnect(true);
1619 break;
1620 default:
1621 throw 'Unrecognized advice action ' + action;
1622 }
1623 } else {
1624 _failHandshake(message);
1625 }
1626 }
1627
1628 function _handshakeFailure(message) {
1629 var version = '1.0';
1630 var url = _cometd.getURL();
1631 var oldTransport = _cometd.getTransport();
1632 var transportTypes = _transports.findTransportTypes(version, _crossDomain, url);
1633 var newTransport = _transports.negotiateTransport(transportTypes, version, _crossDomain, url);
1634 if (!newTransport) {
1635 _notifyTransportFailure(oldTransport.getType(), null, message.failure);
1636 _cometd._warn('Could not negotiate transport; client=[' + transportTypes + ']');
1637 _disconnect(true);
1638 _failHandshake(message);
1639 } else {
1640 _cometd._debug('Transport', oldTransport.getType(), '->', newTransport.getType());
1641 _notifyTransportFailure(oldTransport.getType(), newTransport.getType(), message.failure);
1642 _failHandshake(message);
1643 _transport = newTransport;
1644 }
1645 }
1646
1647 function _failConnect(message) {
1648 // Notify the listeners after the status change but before the next action
1649 _notifyListeners('/meta/connect', message);
1650 _notifyListeners('/meta/unsuccessful', message);
1651
1652 // This may happen when the server crashed, the current clientId
1653 // will be invalid, and the server will ask to handshake again
1654 // Listeners can call disconnect(), so check the state after they run
1655 var action = _isDisconnected() ? 'none' : _advice.reconnect;
1656 switch (action) {
1657 case 'retry':
1658 _delayedConnect();
1659 _increaseBackoff();
1660 break;
1661 case 'handshake':
1662 // The current transport may be failed (e.g. network disconnection)
1663 // Reset the transports so the new handshake picks up the right one
1664 _transports.reset(true);
1665 _resetBackoff();
1666 _delayedHandshake();
1667 break;
1668 case 'none':
1669 _disconnect(true);
1670 break;
1671 default:
1672 throw 'Unrecognized advice action' + action;
1673 }
1674 }
1675
1676 function _connectResponse(message) {
1677 _connected = message.successful;
1678
1679 if (_connected) {
1680 _notifyListeners('/meta/connect', message);
1681
1682 // Normally, the advice will say "reconnect: 'retry', interval: 0"
1683 // and the server will hold the request, so when a response returns
1684 // we immediately call the server again (long polling)
1685 // Listeners can call disconnect(), so check the state after they run
1686 var action = _isDisconnected() ? 'none' : _advice.reconnect;
1687 switch (action) {
1688 case 'retry':
1689 _resetBackoff();
1690 _delayedConnect();
1691 break;
1692 case 'none':
1693 // Wait for the /meta/disconnect to arrive.
1694 _disconnect(false);
1695 break;
1696 default:
1697 throw 'Unrecognized advice action ' + action;
1698 }
1699 } else {
1700 _failConnect(message);
1701 }
1702 }
1703
1704 function _connectFailure(message) {
1705 _connected = false;
1706 _failConnect(message);
1707 }
1708
1709 function _failDisconnect(message) {
1710 _disconnect(true);
1711 _handleCallback(message);
1712 _notifyListeners('/meta/disconnect', message);
1713 _notifyListeners('/meta/unsuccessful', message);
1714 }
1715
1716 function _disconnectResponse(message) {
1717 if (message.successful) {
1718 // Wait for the /meta/connect to arrive.
1719 _disconnect(false);
1720 _handleCallback(message);
1721 _notifyListeners('/meta/disconnect', message);
1722 } else {
1723 _failDisconnect(message);
1724 }
1725 }
1726
1727 function _disconnectFailure(message) {
1728 _failDisconnect(message);
1729 }
1730
1731 function _failSubscribe(message) {
1732 var subscriptions = _listeners[message.subscription];
1733 if (subscriptions) {
1734 for (var i = subscriptions.length - 1; i >= 0; --i) {
1735 var subscription = subscriptions[i];
1736 if (subscription && !subscription.listener) {
1737 delete subscriptions[i];
1738 _cometd._debug('Removed failed subscription', subscription);
1739 break;
1740 }
1741 }
1742 }
1743 _handleCallback(message);
1744 _notifyListeners('/meta/subscribe', message);
1745 _notifyListeners('/meta/unsuccessful', message);
1746 }
1747
1748 function _subscribeResponse(message) {
1749 if (message.successful) {
1750 _handleCallback(message);
1751 _notifyListeners('/meta/subscribe', message);
1752 } else {
1753 _failSubscribe(message);
1754 }
1755 }
1756
1757 function _subscribeFailure(message) {
1758 _failSubscribe(message);
1759 }
1760
1761 function _failUnsubscribe(message) {
1762 _handleCallback(message);
1763 _notifyListeners('/meta/unsubscribe', message);
1764 _notifyListeners('/meta/unsuccessful', message);
1765 }
1766
1767 function _unsubscribeResponse(message) {
1768 if (message.successful) {
1769 _handleCallback(message);
1770 _notifyListeners('/meta/unsubscribe', message);
1771 } else {
1772 _failUnsubscribe(message);
1773 }
1774 }
1775
1776 function _unsubscribeFailure(message) {
1777 _failUnsubscribe(message);
1778 }
1779
1780 function _failMessage(message) {
1781 if (!_handleRemoteCall(message)) {
1782 _handleCallback(message);
1783 _notifyListeners('/meta/publish', message);
1784 _notifyListeners('/meta/unsuccessful', message);
1785 }
1786 }
1787
1788 function _messageResponse(message) {
1789 if (message.data !== undefined) {
1790 if (!_handleRemoteCall(message)) {
1791 _notifyListeners(message.channel, message);
1792 if (_handshakeMessages > 0) {
1793 --_handshakeMessages;
1794 if (_handshakeMessages === 0) {
1795 _cometd._debug('Processed last handshake-delivered message');
1796 _delayedConnect(0);
1797 }
1798 }
1799 }
1800 } else {
1801 if (message.successful === undefined) {
1802 _cometd._warn('Unknown Bayeux Message', message);
1803 } else {
1804 if (message.successful) {
1805 _handleCallback(message);
1806 _notifyListeners('/meta/publish', message);
1807 } else {
1808 _failMessage(message);
1809 }
1810 }
1811 }
1812 }
1813
1814 function _messageFailure(failure) {
1815 _failMessage(failure);
1816 }
1817
1818 function _receive(message) {
1819 _unconnectTime = 0;
1820
1821 message = _applyIncomingExtensions(message);
1822 if (message === undefined || message === null) {
1823 return;
1824 }
1825
1826 _updateAdvice(message.advice);
1827
1828 var channel = message.channel;
1829 switch (channel) {
1830 case '/meta/handshake':
1831 _handshakeResponse(message);
1832 break;
1833 case '/meta/connect':
1834 _connectResponse(message);
1835 break;
1836 case '/meta/disconnect':
1837 _disconnectResponse(message);
1838 break;
1839 case '/meta/subscribe':
1840 _subscribeResponse(message);
1841 break;
1842 case '/meta/unsubscribe':
1843 _unsubscribeResponse(message);
1844 break;
1845 default:
1846 _messageResponse(message);
1847 break;
1848 }
1849 }
1850
1851 /**
1852 * Receives a message.
1853 * This method is exposed as a public so that extensions may inject
1854 * messages simulating that they had been received.
1855 */
1856 this.receive = _receive;
1857
1858 _handleMessages = function(rcvdMessages) {
1859 _cometd._debug('Received', rcvdMessages);
1860
1861 for (var i = 0; i < rcvdMessages.length; ++i) {
1862 var message = rcvdMessages[i];
1863 _receive(message);
1864 }
1865 };
1866
1867 _handleFailure = function(conduit, messages, failure) {
1868 _cometd._debug('handleFailure', conduit, messages, failure);
1869
1870 failure.transport = conduit;
1871 for (var i = 0; i < messages.length; ++i) {
1872 var message = messages[i];
1873 var failureMessage = {
1874 id: message.id,
1875 successful: false,
1876 channel: message.channel,
1877 failure: failure
1878 };
1879 failure.message = message;
1880 switch (message.channel) {
1881 case '/meta/handshake':
1882 _handshakeFailure(failureMessage);
1883 break;
1884 case '/meta/connect':
1885 _connectFailure(failureMessage);
1886 break;
1887 case '/meta/disconnect':
1888 _disconnectFailure(failureMessage);
1889 break;
1890 case '/meta/subscribe':
1891 failureMessage.subscription = message.subscription;
1892 _subscribeFailure(failureMessage);
1893 break;
1894 case '/meta/unsubscribe':
1895 failureMessage.subscription = message.subscription;
1896 _unsubscribeFailure(failureMessage);
1897 break;
1898 default:
1899 _messageFailure(failureMessage);
1900 break;
1901 }
1902 }
1903 };
1904
1905 function _hasSubscriptions(channel) {
1906 var subscriptions = _listeners[channel];
1907 if (subscriptions) {
1908 for (var i = 0; i < subscriptions.length; ++i) {
1909 if (subscriptions[i]) {
1910 return true;
1911 }
1912 }
1913 }
1914 return false;
1915 }
1916
1917 function _resolveScopedCallback(scope, callback) {
1918 var delegate = {
1919 scope: scope,
1920 method: callback
1921 };
1922 if (_isFunction(scope)) {
1923 delegate.scope = undefined;
1924 delegate.method = scope;
1925 } else {
1926 if (_isString(callback)) {
1927 if (!scope) {
1928 throw 'Invalid scope ' + scope;
1929 }
1930 delegate.method = scope[callback];
1931 if (!_isFunction(delegate.method)) {
1932 throw 'Invalid callback ' + callback + ' for scope ' + scope;
1933 }
1934 } else if (!_isFunction(callback)) {
1935 throw 'Invalid callback ' + callback;
1936 }
1937 }
1938 return delegate;
1939 }
1940
1941 function _addListener(channel, scope, callback, isListener) {
1942 // The data structure is a map<channel, subscription[]>, where each subscription
1943 // holds the callback to be called and its scope.
1944
1945 var delegate = _resolveScopedCallback(scope, callback);
1946 _cometd._debug('Adding', isListener ? 'listener' : 'subscription', 'on', channel, 'with scope', delegate.scope, 'and callback', delegate.method);
1947
1948 var subscription = {
1949 channel: channel,
1950 scope: delegate.scope,
1951 callback: delegate.method,
1952 listener: isListener
1953 };
1954
1955 var subscriptions = _listeners[channel];
1956 if (!subscriptions) {
1957 subscriptions = [];
1958 _listeners[channel] = subscriptions;
1959 }
1960
1961 // Pushing onto an array appends at the end and returns the id associated with the element increased by 1.
1962 // Note that if:
1963 // a.push('a'); var hb=a.push('b'); delete a[hb-1]; var hc=a.push('c');
1964 // then:
1965 // hc==3, a.join()=='a',,'c', a.length==3
1966 subscription.id = subscriptions.push(subscription) - 1;
1967
1968 _cometd._debug('Added', isListener ? 'listener' : 'subscription', subscription);
1969
1970 // For backward compatibility: we used to return [channel, subscription.id]
1971 subscription[0] = channel;
1972 subscription[1] = subscription.id;
1973
1974 return subscription;
1975 }
1976
1977 //
1978 // PUBLIC API
1979 //
1980
1981 /**
1982 * Registers the given transport under the given transport type.
1983 * The optional index parameter specifies the "priority" at which the
1984 * transport is registered (where 0 is the max priority).
1985 * If a transport with the same type is already registered, this function
1986 * does nothing and returns false.
1987 * @param type the transport type
1988 * @param transport the transport object
1989 * @param index the index at which this transport is to be registered
1990 * @return true if the transport has been registered, false otherwise
1991 * @see #unregisterTransport(type)
1992 */
1993 this.registerTransport = function(type, transport, index) {
1994 var result = _transports.add(type, transport, index);
1995 if (result) {
1996 this._debug('Registered transport', type);
1997
1998 if (_isFunction(transport.registered)) {
1999 transport.registered(type, this);
2000 }
2001 }
2002 return result;
2003 };
2004
2005 /**
2006 * Unregisters the transport with the given transport type.
2007 * @param type the transport type to unregister
2008 * @return the transport that has been unregistered,
2009 * or null if no transport was previously registered under the given transport type
2010 */
2011 this.unregisterTransport = function(type) {
2012 var transport = _transports.remove(type);
2013 if (transport !== null) {
2014 this._debug('Unregistered transport', type);
2015
2016 if (_isFunction(transport.unregistered)) {
2017 transport.unregistered();
2018 }
2019 }
2020 return transport;
2021 };
2022
2023 this.unregisterTransports = function() {
2024 _transports.clear();
2025 };
2026
2027 /**
2028 * @return an array of all registered transport types
2029 */
2030 this.getTransportTypes = function() {
2031 return _transports.getTransportTypes();
2032 };
2033
2034 this.findTransport = function(name) {
2035 return _transports.find(name);
2036 };
2037
2038 /**
2039 * @returns the TransportRegistry object
2040 */
2041 this.getTransportRegistry = function() {
2042 return _transports;
2043 };
2044
2045 /**
2046 * Configures the initial Bayeux communication with the Bayeux server.
2047 * Configuration is passed via an object that must contain a mandatory field <code>url</code>
2048 * of type string containing the URL of the Bayeux server.
2049 * @param configuration the configuration object
2050 */
2051 this.configure = function(configuration) {
2052 _configure.call(this, configuration);
2053 };
2054
2055 /**
2056 * Configures and establishes the Bayeux communication with the Bayeux server
2057 * via a handshake and a subsequent connect.
2058 * @param configuration the configuration object
2059 * @param handshakeProps an object to be merged with the handshake message
2060 * @see #configure(configuration)
2061 * @see #handshake(handshakeProps)
2062 */
2063 this.init = function(configuration, handshakeProps) {
2064 this.configure(configuration);
2065 this.handshake(handshakeProps);
2066 };
2067
2068 /**
2069 * Establishes the Bayeux communication with the Bayeux server
2070 * via a handshake and a subsequent connect.
2071 * @param handshakeProps an object to be merged with the handshake message
2072 * @param handshakeCallback a function to be invoked when the handshake is acknowledged
2073 */
2074 this.handshake = function(handshakeProps, handshakeCallback) {
2075 _setStatus('disconnected');
2076 _reestablish = false;
2077 _handshake(handshakeProps, handshakeCallback);
2078 };
2079
2080 /**
2081 * Disconnects from the Bayeux server.
2082 * It is possible to suggest to attempt a synchronous disconnect, but this feature
2083 * may only be available in certain transports (for example, long-polling may support
2084 * it, callback-polling certainly does not).
2085 * @param sync whether attempt to perform a synchronous disconnect
2086 * @param disconnectProps an object to be merged with the disconnect message
2087 * @param disconnectCallback a function to be invoked when the disconnect is acknowledged
2088 */
2089 this.disconnect = function(sync, disconnectProps, disconnectCallback) {
2090 if (_isDisconnected()) {
2091 return;
2092 }
2093
2094 if (typeof sync !== 'boolean') {
2095 disconnectCallback = disconnectProps;
2096 disconnectProps = sync;
2097 sync = false;
2098 }
2099 if (_isFunction(disconnectProps)) {
2100 disconnectCallback = disconnectProps;
2101 disconnectProps = undefined;
2102 }
2103
2104 var bayeuxMessage = {
2105 id: _nextMessageId(),
2106 channel: '/meta/disconnect'
2107 };
2108 // Do not allow the user to override important fields.
2109 var message = this._mixin(false, {}, disconnectProps, bayeuxMessage);
2110
2111 // Save the callback.
2112 _cometd._putCallback(message.id, disconnectCallback);
2113
2114 _setStatus('disconnecting');
2115 _send(sync === true, [message], false, 'disconnect');
2116 };
2117
2118 /**
2119 * Marks the start of a batch of application messages to be sent to the server
2120 * in a single request, obtaining a single response containing (possibly) many
2121 * application reply messages.
2122 * Messages are held in a queue and not sent until {@link #endBatch()} is called.
2123 * If startBatch() is called multiple times, then an equal number of endBatch()
2124 * calls must be made to close and send the batch of messages.
2125 * @see #endBatch()
2126 */
2127 this.startBatch = function() {
2128 _startBatch();
2129 };
2130
2131 /**
2132 * Marks the end of a batch of application messages to be sent to the server
2133 * in a single request.
2134 * @see #startBatch()
2135 */
2136 this.endBatch = function() {
2137 _endBatch();
2138 };
2139
2140 /**
2141 * Executes the given callback in the given scope, surrounded by a {@link #startBatch()}
2142 * and {@link #endBatch()} calls.
2143 * @param scope the scope of the callback, may be omitted
2144 * @param callback the callback to be executed within {@link #startBatch()} and {@link #endBatch()} calls
2145 */
2146 this.batch = function(scope, callback) {
2147 var delegate = _resolveScopedCallback(scope, callback);
2148 this.startBatch();
2149 try {
2150 delegate.method.call(delegate.scope);
2151 this.endBatch();
2152 } catch (x) {
2153 this._info('Exception during execution of batch', x);
2154 this.endBatch();
2155 throw x;
2156 }
2157 };
2158
2159 /**
2160 * Adds a listener for bayeux messages, performing the given callback in the given scope
2161 * when a message for the given channel arrives.
2162 * @param channel the channel the listener is interested to
2163 * @param scope the scope of the callback, may be omitted
2164 * @param callback the callback to call when a message is sent to the channel
2165 * @returns the subscription handle to be passed to {@link #removeListener(object)}
2166 * @see #removeListener(subscription)
2167 */
2168 this.addListener = function(channel, scope, callback) {
2169 if (arguments.length < 2) {
2170 throw 'Illegal arguments number: required 2, got ' + arguments.length;
2171 }
2172 if (!_isString(channel)) {
2173 throw 'Illegal argument type: channel must be a string';
2174 }
2175
2176 return _addListener(channel, scope, callback, true);
2177 };
2178
2179 /**
2180 * Removes the subscription obtained with a call to {@link #addListener(string, object, function)}.
2181 * @param subscription the subscription to unsubscribe.
2182 * @see #addListener(channel, scope, callback)
2183 */
2184 this.removeListener = function(subscription) {
2185 // Beware of subscription.id == 0, which is falsy => cannot use !subscription.id
2186 if (!subscription || !subscription.channel || !("id" in subscription)) {
2187 throw 'Invalid argument: expected subscription, not ' + subscription;
2188 }
2189
2190 _removeListener(subscription);
2191 };
2192
2193 /**
2194 * Removes all listeners registered with {@link #addListener(channel, scope, callback)} or
2195 * {@link #subscribe(channel, scope, callback)}.
2196 */
2197 this.clearListeners = function() {
2198 _listeners = {};
2199 };
2200
2201 /**
2202 * Subscribes to the given channel, performing the given callback in the given scope
2203 * when a message for the channel arrives.
2204 * @param channel the channel to subscribe to
2205 * @param scope the scope of the callback, may be omitted
2206 * @param callback the callback to call when a message is sent to the channel
2207 * @param subscribeProps an object to be merged with the subscribe message
2208 * @param subscribeCallback a function to be invoked when the subscription is acknowledged
2209 * @return the subscription handle to be passed to {@link #unsubscribe(object)}
2210 */
2211 this.subscribe = function(channel, scope, callback, subscribeProps, subscribeCallback) {
2212 if (arguments.length < 2) {
2213 throw 'Illegal arguments number: required 2, got ' + arguments.length;
2214 }
2215 if (!_isString(channel)) {
2216 throw 'Illegal argument type: channel must be a string';
2217 }
2218 if (_isDisconnected()) {
2219 throw 'Illegal state: already disconnected';
2220 }
2221
2222 // Normalize arguments
2223 if (_isFunction(scope)) {
2224 subscribeCallback = subscribeProps;
2225 subscribeProps = callback;
2226 callback = scope;
2227 scope = undefined;
2228 }
2229 if (_isFunction(subscribeProps)) {
2230 subscribeCallback = subscribeProps;
2231 subscribeProps = undefined;
2232 }
2233
2234 // Only send the message to the server if this client has not yet subscribed to the channel
2235 var send = !_hasSubscriptions(channel);
2236
2237 var subscription = _addListener(channel, scope, callback, false);
2238
2239 if (send) {
2240 // Send the subscription message after the subscription registration to avoid
2241 // races where the server would send a message to the subscribers, but here
2242 // on the client the subscription has not been added yet to the data structures
2243 var bayeuxMessage = {
2244 id: _nextMessageId(),
2245 channel: '/meta/subscribe',
2246 subscription: channel
2247 };
2248 // Do not allow the user to override important fields.
2249 var message = this._mixin(false, {}, subscribeProps, bayeuxMessage);
2250
2251 // Save the callback.
2252 _cometd._putCallback(message.id, subscribeCallback);
2253
2254 _queueSend(message);
2255 }
2256
2257 return subscription;
2258 };
2259
2260 /**
2261 * Unsubscribes the subscription obtained with a call to {@link #subscribe(string, object, function)}.
2262 * @param subscription the subscription to unsubscribe.
2263 * @param unsubscribeProps an object to be merged with the unsubscribe message
2264 * @param unsubscribeCallback a function to be invoked when the unsubscription is acknowledged
2265 */
2266 this.unsubscribe = function(subscription, unsubscribeProps, unsubscribeCallback) {
2267 if (arguments.length < 1) {
2268 throw 'Illegal arguments number: required 1, got ' + arguments.length;
2269 }
2270 if (_isDisconnected()) {
2271 throw 'Illegal state: already disconnected';
2272 }
2273
2274 if (_isFunction(unsubscribeProps)) {
2275 unsubscribeCallback = unsubscribeProps;
2276 unsubscribeProps = undefined;
2277 }
2278
2279 // Remove the local listener before sending the message
2280 // This ensures that if the server fails, this client does not get notifications
2281 this.removeListener(subscription);
2282
2283 var channel = subscription.channel;
2284 // Only send the message to the server if this client unsubscribes the last subscription
2285 if (!_hasSubscriptions(channel)) {
2286 var bayeuxMessage = {
2287 id: _nextMessageId(),
2288 channel: '/meta/unsubscribe',
2289 subscription: channel
2290 };
2291 // Do not allow the user to override important fields.
2292 var message = this._mixin(false, {}, unsubscribeProps, bayeuxMessage);
2293
2294 // Save the callback.
2295 _cometd._putCallback(message.id, unsubscribeCallback);
2296
2297 _queueSend(message);
2298 }
2299 };
2300
2301 this.resubscribe = function(subscription, subscribeProps) {
2302 _removeSubscription(subscription);
2303 if (subscription) {
2304 return this.subscribe(subscription.channel, subscription.scope, subscription.callback, subscribeProps);
2305 }
2306 return undefined;
2307 };
2308
2309 /**
2310 * Removes all subscriptions added via {@link #subscribe(channel, scope, callback, subscribeProps)},
2311 * but does not remove the listeners added via {@link addListener(channel, scope, callback)}.
2312 */
2313 this.clearSubscriptions = function() {
2314 _clearSubscriptions();
2315 };
2316
2317 /**
2318 * Publishes a message on the given channel, containing the given content.
2319 * @param channel the channel to publish the message to
2320 * @param content the content of the message
2321 * @param publishProps an object to be merged with the publish message
2322 * @param publishCallback a function to be invoked when the publish is acknowledged by the server
2323 */
2324 this.publish = function(channel, content, publishProps, publishCallback) {
2325 if (arguments.length < 1) {
2326 throw 'Illegal arguments number: required 1, got ' + arguments.length;
2327 }
2328 if (!_isString(channel)) {
2329 throw 'Illegal argument type: channel must be a string';
2330 }
2331 if (/^\/meta\//.test(channel)) {
2332 throw 'Illegal argument: cannot publish to meta channels';
2333 }
2334 if (_isDisconnected()) {
2335 throw 'Illegal state: already disconnected';
2336 }
2337
2338 if (_isFunction(content)) {
2339 publishCallback = content;
2340 content = publishProps = {};
2341 } else if (_isFunction(publishProps)) {
2342 publishCallback = publishProps;
2343 publishProps = {};
2344 }
2345
2346 var bayeuxMessage = {
2347 id: _nextMessageId(),
2348 channel: channel,
2349 data: content
2350 };
2351 // Do not allow the user to override important fields.
2352 var message = this._mixin(false, {}, publishProps, bayeuxMessage);
2353
2354 // Save the callback.
2355 _cometd._putCallback(message.id, publishCallback);
2356
2357 _queueSend(message);
2358 };
2359
2360 this.remoteCall = function(target, content, timeout, callback) {
2361 if (arguments.length < 1) {
2362 throw 'Illegal arguments number: required 1, got ' + arguments.length;
2363 }
2364 if (!_isString(target)) {
2365 throw 'Illegal argument type: target must be a string';
2366 }
2367 if (_isDisconnected()) {
2368 throw 'Illegal state: already disconnected';
2369 }
2370
2371 if (_isFunction(content)) {
2372 callback = content;
2373 content = {};
2374 timeout = _config.maxNetworkDelay;
2375 } else if (_isFunction(timeout)) {
2376 callback = timeout;
2377 timeout = _config.maxNetworkDelay;
2378 }
2379
2380 if (typeof timeout !== 'number') {
2381 throw 'Illegal argument type: timeout must be a number';
2382 }
2383
2384 if (!target.match(/^\//)) {
2385 target = '/' + target;
2386 }
2387 var channel = '/service' + target;
2388
2389 var bayeuxMessage = {
2390 id: _nextMessageId(),
2391 channel: channel,
2392 data: content
2393 };
2394
2395 var context = {
2396 callback: callback
2397 };
2398 if (timeout > 0) {
2399 context.timeout = Utils.setTimeout(_cometd, function() {
2400 _cometd._debug('Timing out remote call', bayeuxMessage, 'after', timeout, 'ms');
2401 _failMessage({
2402 id: bayeuxMessage.id,
2403 error: '406::timeout',
2404 successful: false,
2405 failure: {
2406 message : bayeuxMessage,
2407 reason: 'Remote Call Timeout'
2408 }
2409 });
2410 }, timeout);
2411 _cometd._debug('Scheduled remote call timeout', bayeuxMessage, 'in', timeout, 'ms');
2412 }
2413 _remoteCalls[bayeuxMessage.id] = context;
2414
2415 _queueSend(bayeuxMessage);
2416 };
2417
2418 /**
2419 * Returns a string representing the status of the bayeux communication with the Bayeux server.
2420 */
2421 this.getStatus = function() {
2422 return _status;
2423 };
2424
2425 /**
2426 * Returns whether this instance has been disconnected.
2427 */
2428 this.isDisconnected = _isDisconnected;
2429
2430 /**
2431 * Sets the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
2432 * Default value is 1 second, which means if there is a persistent failure the retries will happen
2433 * after 1 second, then after 2 seconds, then after 3 seconds, etc. So for example with 15 seconds of
2434 * elapsed time, there will be 5 retries (at 1, 3, 6, 10 and 15 seconds elapsed).
2435 * @param period the backoff period to set
2436 * @see #getBackoffIncrement()
2437 */
2438 this.setBackoffIncrement = function(period) {
2439 _config.backoffIncrement = period;
2440 };
2441
2442 /**
2443 * Returns the backoff period used to increase the backoff time when retrying an unsuccessful or failed message.
2444 * @see #setBackoffIncrement(period)
2445 */
2446 this.getBackoffIncrement = function() {
2447 return _config.backoffIncrement;
2448 };
2449
2450 /**
2451 * Returns the backoff period to wait before retrying an unsuccessful or failed message.
2452 */
2453 this.getBackoffPeriod = function() {
2454 return _backoff;
2455 };
2456
2457 /**
2458 * Increases the backoff period up to the maximum value configured.
2459 * @returns the backoff period after increment
2460 * @see getBackoffIncrement
2461 */
2462 this.increaseBackoffPeriod = function() {
2463 return _increaseBackoff();
2464 };
2465
2466 /**
2467 * Resets the backoff period to zero.
2468 */
2469 this.resetBackoffPeriod = function() {
2470 _resetBackoff();
2471 };
2472
2473 /**
2474 * Sets the log level for console logging.
2475 * Valid values are the strings 'error', 'warn', 'info' and 'debug', from
2476 * less verbose to more verbose.
2477 * @param level the log level string
2478 */
2479 this.setLogLevel = function(level) {
2480 _config.logLevel = level;
2481 };
2482
2483 /**
2484 * Registers an extension whose callbacks are called for every incoming message
2485 * (that comes from the server to this client implementation) and for every
2486 * outgoing message (that originates from this client implementation for the
2487 * server).
2488 * The format of the extension object is the following:
2489 * <pre>
2490 * {
2491 * incoming: function(message) { ... },
2492 * outgoing: function(message) { ... }
2493 * }
2494 * </pre>
2495 * Both properties are optional, but if they are present they will be called
2496 * respectively for each incoming message and for each outgoing message.
2497 * @param name the name of the extension
2498 * @param extension the extension to register
2499 * @return true if the extension was registered, false otherwise
2500 * @see #unregisterExtension(name)
2501 */
2502 this.registerExtension = function(name, extension) {
2503 if (arguments.length < 2) {
2504 throw 'Illegal arguments number: required 2, got ' + arguments.length;
2505 }
2506 if (!_isString(name)) {
2507 throw 'Illegal argument type: extension name must be a string';
2508 }
2509
2510 var existing = false;
2511 for (var i = 0; i < _extensions.length; ++i) {
2512 var existingExtension = _extensions[i];
2513 if (existingExtension.name === name) {
2514 existing = true;
2515 break;
2516 }
2517 }
2518 if (!existing) {
2519 _extensions.push({
2520 name: name,
2521 extension: extension
2522 });
2523 this._debug('Registered extension', name);
2524
2525 // Callback for extensions
2526 if (_isFunction(extension.registered)) {
2527 extension.registered(name, this);
2528 }
2529
2530 return true;
2531 } else {
2532 this._info('Could not register extension with name', name, 'since another extension with the same name already exists');
2533 return false;
2534 }
2535 };
2536
2537 /**
2538 * Unregister an extension previously registered with
2539 * {@link #registerExtension(name, extension)}.
2540 * @param name the name of the extension to unregister.
2541 * @return true if the extension was unregistered, false otherwise
2542 */
2543 this.unregisterExtension = function(name) {
2544 if (!_isString(name)) {
2545 throw 'Illegal argument type: extension name must be a string';
2546 }
2547
2548 var unregistered = false;
2549 for (var i = 0; i < _extensions.length; ++i) {
2550 var extension = _extensions[i];
2551 if (extension.name === name) {
2552 _extensions.splice(i, 1);
2553 unregistered = true;
2554 this._debug('Unregistered extension', name);
2555
2556 // Callback for extensions
2557 var ext = extension.extension;
2558 if (_isFunction(ext.unregistered)) {
2559 ext.unregistered();
2560 }
2561
2562 break;
2563 }
2564 }
2565 return unregistered;
2566 };
2567
2568 /**
2569 * Find the extension registered with the given name.
2570 * @param name the name of the extension to find
2571 * @return the extension found or null if no extension with the given name has been registered
2572 */
2573 this.getExtension = function(name) {
2574 for (var i = 0; i < _extensions.length; ++i) {
2575 var extension = _extensions[i];
2576 if (extension.name === name) {
2577 return extension.extension;
2578 }
2579 }
2580 return null;
2581 };
2582
2583 /**
2584 * Returns the name assigned to this CometD object, or the string 'default'
2585 * if no name has been explicitly passed as parameter to the constructor.
2586 */
2587 this.getName = function() {
2588 return _name;
2589 };
2590
2591 /**
2592 * Returns the clientId assigned by the Bayeux server during handshake.
2593 */
2594 this.getClientId = function() {
2595 return _clientId;
2596 };
2597
2598 /**
2599 * Returns the URL of the Bayeux server.
2600 */
2601 this.getURL = function() {
2602 if (_transport) {
2603 var url = _transport.getURL();
2604 if (url) {
2605 return url;
2606 }
2607 url = _config.urls[_transport.getType()];
2608 if (url) {
2609 return url;
2610 }
2611 }
2612 return _config.url;
2613 };
2614
2615 this.getTransport = function() {
2616 return _transport;
2617 };
2618
2619 this.getConfiguration = function() {
2620 return this._mixin(true, {}, _config);
2621 };
2622
2623 this.getAdvice = function() {
2624 return this._mixin(true, {}, _advice);
2625 };
2626};
2627
2628var TransportTypes = {
2629 LONG_POLLING: 'long-polling',
2630 WEBSOCKET: 'websocket'
2631};
2632
2633/**
2634 * Base object with the common functionality for transports.
2635 */
2636var Transport = function Transport() {
2637 var _type;
2638 var _cometd;
2639 var _url;
2640
2641 /**
2642 * Function invoked just after a transport has been successfully registered.
2643 * @param type the type of transport (for example 'long-polling')
2644 * @param cometd the cometd object this transport has been registered to
2645 * @see #unregistered()
2646 */
2647 this.registered = function(type, cometd) {
2648 _type = type;
2649 _cometd = cometd;
2650 };
2651
2652 /**
2653 * Function invoked just after a transport has been successfully unregistered.
2654 * @see #registered(type, cometd)
2655 */
2656 this.unregistered = function() {
2657 _type = null;
2658 _cometd = null;
2659 };
2660
2661 this._debug = function() {
2662 _cometd._debug.apply(_cometd, arguments);
2663 };
2664
2665 this._mixin = function() {
2666 return _cometd._mixin.apply(_cometd, arguments);
2667 };
2668
2669 this.getConfiguration = function() {
2670 return _cometd.getConfiguration();
2671 };
2672
2673 this.getAdvice = function() {
2674 return _cometd.getAdvice();
2675 };
2676
2677 this.setTimeout = function(funktion, delay) {
2678 return Utils.setTimeout(_cometd, funktion, delay);
2679 };
2680
2681 this.clearTimeout = function(handle) {
2682 Utils.clearTimeout(handle);
2683 };
2684
2685 /**
2686 * Converts the given response into an array of bayeux messages
2687 * @param response the response to convert
2688 * @return an array of bayeux messages obtained by converting the response
2689 */
2690 this.convertToMessages = function(response) {
2691 if (Utils.isString(response)) {
2692 try {
2693 return JSON.parse(response);
2694 } catch (x) {
2695 this._debug('Could not convert to JSON the following string', '"' + response + '"');
2696 throw x;
2697 }
2698 }
2699 if (Utils.isArray(response)) {
2700 return response;
2701 }
2702 if (response === undefined || response === null) {
2703 return [];
2704 }
2705 if (response instanceof Object) {
2706 return [response];
2707 }
2708 throw 'Conversion Error ' + response + ', typeof ' + (typeof response);
2709 };
2710
2711 /**
2712 * Returns whether this transport can work for the given version and cross domain communication case.
2713 * @param version a string indicating the transport version
2714 * @param crossDomain a boolean indicating whether the communication is cross domain
2715 * @param url the URL to connect to
2716 * @return true if this transport can work for the given version and cross domain communication case,
2717 * false otherwise
2718 */
2719 this.accept = function(version, crossDomain, url) {
2720 throw 'Abstract';
2721 };
2722
2723 /**
2724 * Returns the type of this transport.
2725 * @see #registered(type, cometd)
2726 */
2727 this.getType = function() {
2728 return _type;
2729 };
2730
2731 this.getURL = function() {
2732 return _url;
2733 };
2734
2735 this.setURL = function(url) {
2736 _url = url;
2737 };
2738
2739 this.send = function(envelope, metaConnect) {
2740 throw 'Abstract';
2741 };
2742
2743 this.reset = function(init) {
2744 this._debug('Transport', _type, 'reset', init ? 'initial' : 'retry');
2745 };
2746
2747 this.abort = function() {
2748 this._debug('Transport', _type, 'aborted');
2749 };
2750
2751 this.toString = function() {
2752 return this.getType();
2753 };
2754};
2755
2756var derive = function(baseObject) {
2757 function F() {
2758 }
2759
2760 F.prototype = baseObject;
2761 return new F();
2762};
2763
2764Transport.derive = derive;
2765
2766/**
2767 * Base object with the common functionality for transports based on requests.
2768 * The key responsibility is to allow at most 2 outstanding requests to the server,
2769 * to avoid that requests are sent behind a long poll.
2770 * To achieve this, we have one reserved request for the long poll, and all other
2771 * requests are serialized one after the other.
2772 */
2773var RequestTransport = function RequestTransport() {
2774 var _super = new Transport();
2775 var _self = Transport.derive(_super);
2776 var _requestIds = 0;
2777 var _metaConnectRequest = null;
2778 var _requests = [];
2779 var _envelopes = [];
2780
2781 function _coalesceEnvelopes(envelope) {
2782 while (_envelopes.length > 0) {
2783 var envelopeAndRequest = _envelopes[0];
2784 var newEnvelope = envelopeAndRequest[0];
2785 var newRequest = envelopeAndRequest[1];
2786 if (newEnvelope.url === envelope.url &&
2787 newEnvelope.sync === envelope.sync) {
2788 _envelopes.shift();
2789 envelope.messages = envelope.messages.concat(newEnvelope.messages);
2790 this._debug('Coalesced', newEnvelope.messages.length, 'messages from request', newRequest.id);
2791 continue;
2792 }
2793 break;
2794 }
2795 }
2796
2797 function _transportSend(envelope, request) {
2798 this.transportSend(envelope, request);
2799 request.expired = false;
2800
2801 if (!envelope.sync) {
2802 var maxDelay = this.getConfiguration().maxNetworkDelay;
2803 var delay = maxDelay;
2804 if (request.metaConnect === true) {
2805 delay += this.getAdvice().timeout;
2806 }
2807
2808 this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for the response, maxNetworkDelay', maxDelay);
2809
2810 var self = this;
2811 request.timeout = self.setTimeout(function() {
2812 request.expired = true;
2813 var errorMessage = 'Request ' + request.id + ' of transport ' + self.getType() + ' exceeded ' + delay + ' ms max network delay';
2814 var failure = {
2815 reason: errorMessage
2816 };
2817 var xhr = request.xhr;
2818 failure.httpCode = self.xhrStatus(xhr);
2819 self.abortXHR(xhr);
2820 self._debug(errorMessage);
2821 self.complete(request, false, request.metaConnect);
2822 envelope.onFailure(xhr, envelope.messages, failure);
2823 }, delay);
2824 }
2825 }
2826
2827 function _queueSend(envelope) {
2828 var requestId = ++_requestIds;
2829 var request = {
2830 id: requestId,
2831 metaConnect: false,
2832 envelope: envelope
2833 };
2834
2835 // Consider the metaConnect requests which should always be present
2836 if (_requests.length < this.getConfiguration().maxConnections - 1) {
2837 _requests.push(request);
2838 _transportSend.call(this, envelope, request);
2839 } else {
2840 this._debug('Transport', this.getType(), 'queueing request', requestId, 'envelope', envelope);
2841 _envelopes.push([envelope, request]);
2842 }
2843 }
2844
2845 function _metaConnectComplete(request) {
2846 var requestId = request.id;
2847 this._debug('Transport', this.getType(), 'metaConnect complete, request', requestId);
2848 if (_metaConnectRequest !== null && _metaConnectRequest.id !== requestId) {
2849 throw 'Longpoll request mismatch, completing request ' + requestId;
2850 }
2851
2852 // Reset metaConnect request
2853 _metaConnectRequest = null;
2854 }
2855
2856 function _complete(request, success) {
2857 var index = Utils.inArray(request, _requests);
2858 // The index can be negative if the request has been aborted
2859 if (index >= 0) {
2860 _requests.splice(index, 1);
2861 }
2862
2863 if (_envelopes.length > 0) {
2864 var envelopeAndRequest = _envelopes.shift();
2865 var nextEnvelope = envelopeAndRequest[0];
2866 var nextRequest = envelopeAndRequest[1];
2867 this._debug('Transport dequeued request', nextRequest.id);
2868 if (success) {
2869 if (this.getConfiguration().autoBatch) {
2870 _coalesceEnvelopes.call(this, nextEnvelope);
2871 }
2872 _queueSend.call(this, nextEnvelope);
2873 this._debug('Transport completed request', request.id, nextEnvelope);
2874 } else {
2875 // Keep the semantic of calling response callbacks asynchronously after the request
2876 var self = this;
2877 self.setTimeout(function() {
2878 self.complete(nextRequest, false, nextRequest.metaConnect);
2879 var failure = {
2880 reason: 'Previous request failed'
2881 };
2882 var xhr = nextRequest.xhr;
2883 failure.httpCode = self.xhrStatus(xhr);
2884 nextEnvelope.onFailure(xhr, nextEnvelope.messages, failure);
2885 }, 0);
2886 }
2887 }
2888 }
2889
2890 _self.complete = function(request, success, metaConnect) {
2891 if (metaConnect) {
2892 _metaConnectComplete.call(this, request);
2893 } else {
2894 _complete.call(this, request, success);
2895 }
2896 };
2897
2898 /**
2899 * Performs the actual send depending on the transport type details.
2900 * @param envelope the envelope to send
2901 * @param request the request information
2902 */
2903 _self.transportSend = function(envelope, request) {
2904 throw 'Abstract';
2905 };
2906
2907 _self.transportSuccess = function(envelope, request, responses) {
2908 if (!request.expired) {
2909 this.clearTimeout(request.timeout);
2910 this.complete(request, true, request.metaConnect);
2911 if (responses && responses.length > 0) {
2912 envelope.onSuccess(responses);
2913 } else {
2914 envelope.onFailure(request.xhr, envelope.messages, {
2915 httpCode: 204
2916 });
2917 }
2918 }
2919 };
2920
2921 _self.transportFailure = function(envelope, request, failure) {
2922 if (!request.expired) {
2923 this.clearTimeout(request.timeout);
2924 this.complete(request, false, request.metaConnect);
2925 envelope.onFailure(request.xhr, envelope.messages, failure);
2926 }
2927 };
2928
2929 function _metaConnectSend(envelope) {
2930 if (_metaConnectRequest !== null) {
2931 throw 'Concurrent metaConnect requests not allowed, request id=' + _metaConnectRequest.id + ' not yet completed';
2932 }
2933
2934 var requestId = ++_requestIds;
2935 this._debug('Transport', this.getType(), 'metaConnect send, request', requestId, 'envelope', envelope);
2936 var request = {
2937 id: requestId,
2938 metaConnect: true,
2939 envelope: envelope
2940 };
2941 _transportSend.call(this, envelope, request);
2942 _metaConnectRequest = request;
2943 }
2944
2945 _self.send = function(envelope, metaConnect) {
2946 if (metaConnect) {
2947 _metaConnectSend.call(this, envelope);
2948 } else {
2949 _queueSend.call(this, envelope);
2950 }
2951 };
2952
2953 _self.abort = function() {
2954 _super.abort();
2955 for (var i = 0; i < _requests.length; ++i) {
2956 var request = _requests[i];
2957 if (request) {
2958 this._debug('Aborting request', request);
2959 if (!this.abortXHR(request.xhr)) {
2960 this.transportFailure(request.envelope, request, {reason: 'abort'});
2961 }
2962 }
2963 }
2964 if (_metaConnectRequest) {
2965 this._debug('Aborting metaConnect request', _metaConnectRequest);
2966 if (!this.abortXHR(_metaConnectRequest.xhr)) {
2967 this.transportFailure(_metaConnectRequest.envelope, _metaConnectRequest, {reason: 'abort'});
2968 }
2969 }
2970 this.reset(true);
2971 };
2972
2973 _self.reset = function(init) {
2974 _super.reset(init);
2975 _metaConnectRequest = null;
2976 _requests = [];
2977 _envelopes = [];
2978 };
2979
2980 _self.abortXHR = function(xhr) {
2981 if (xhr) {
2982 try {
2983 var state = xhr.readyState;
2984 xhr.abort();
2985 return state !== XMLHttpRequest.UNSENT;
2986 } catch (x) {
2987 this._debug(x);
2988 }
2989 }
2990 return false;
2991 };
2992
2993 _self.xhrStatus = function(xhr) {
2994 if (xhr) {
2995 try {
2996 return xhr.status;
2997 } catch (x) {
2998 this._debug(x);
2999 }
3000 }
3001 return -1;
3002 };
3003
3004 return _self;
3005};
3006
3007var LongPollingTransport = function LongPollingTransport() {
3008 var _super = new RequestTransport();
3009 var _self = Transport.derive(_super);
3010 // By default, support cross domain
3011 var _supportsCrossDomain = true;
3012
3013 _self.accept = function(version, crossDomain, url) {
3014 return _supportsCrossDomain || !crossDomain;
3015 };
3016
3017 _self.xhrSend = function(packet) {
3018 throw 'Abstract';
3019 };
3020
3021 _self.transportSend = function(envelope, request) {
3022 this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelope);
3023
3024 var self = this;
3025 try {
3026 var sameStack = true;
3027 request.xhr = this.xhrSend({
3028 transport: this,
3029 url: envelope.url,
3030 sync: envelope.sync,
3031 headers: this.getConfiguration().requestHeaders,
3032 body: JSON.stringify(envelope.messages),
3033 onSuccess: function(response) {
3034 self._debug('Transport', self.getType(), 'received response', response);
3035 var success = false;
3036 try {
3037 var received = self.convertToMessages(response);
3038 if (received.length === 0) {
3039 _supportsCrossDomain = false;
3040 self.transportFailure(envelope, request, {
3041 httpCode: 204
3042 });
3043 } else {
3044 success = true;
3045 self.transportSuccess(envelope, request, received);
3046 }
3047 } catch (x) {
3048 self._debug(x);
3049 if (!success) {
3050 _supportsCrossDomain = false;
3051 var failure = {
3052 exception: x
3053 };
3054 failure.httpCode = self.xhrStatus(request.xhr);
3055 self.transportFailure(envelope, request, failure);
3056 }
3057 }
3058 },
3059 onError: function(reason, exception) {
3060 self._debug('Transport', self.getType(), 'received error', reason, exception);
3061 _supportsCrossDomain = false;
3062 var failure = {
3063 reason: reason,
3064 exception: exception
3065 };
3066 failure.httpCode = self.xhrStatus(request.xhr);
3067 if (sameStack) {
3068 // Keep the semantic of calling response callbacks asynchronously after the request
3069 self.setTimeout(function() {
3070 self.transportFailure(envelope, request, failure);
3071 }, 0);
3072 } else {
3073 self.transportFailure(envelope, request, failure);
3074 }
3075 }
3076 });
3077 sameStack = false;
3078 } catch (x) {
3079 _supportsCrossDomain = false;
3080 // Keep the semantic of calling response callbacks asynchronously after the request
3081 self.setTimeout(function() {
3082 self.transportFailure(envelope, request, {
3083 exception: x
3084 });
3085 }, 0);
3086 }
3087 };
3088
3089 _self.reset = function(init) {
3090 _super.reset(init);
3091 _supportsCrossDomain = true;
3092 };
3093
3094 return _self;
3095};
3096
3097/**
3098 * Implements LongPollingTransport using borwser fetch() API
3099 * @access private
3100 * @return {FetchLongPollingTransport}
3101 */
3102function FetchLongPollingTransport() {
3103 var _super = new LongPollingTransport();
3104 var that = Transport.derive(_super);
3105
3106 /**
3107 * Implements transport via fetch() API
3108 * @param {Object} packet
3109 */
3110 that.xhrSend = function (packet) {
3111 FetchLongPollingTransport.fetch(packet.url, {
3112 method: 'post',
3113 body: packet.body,
3114 headers: Object.assign(packet.headers, {
3115 'Content-Type': 'application/json;charset=UTF-8'
3116 })
3117 })
3118 .then(function (response) {
3119 return response.json()
3120 })
3121 .then(packet.onSuccess)
3122 .catch(packet.onError);
3123 };
3124
3125 return that
3126}
3127
3128// Reference global WebSocket
3129FetchLongPollingTransport.fetch = 'Abstract';
3130
3131// Export FetchLongPollingTransport
3132var FetchLongPollingTransport_1 = FetchLongPollingTransport;
3133
3134function WebSocketTransport() {
3135 var _super = new Transport();
3136 var _self = Transport.derive(_super);
3137 var _cometd;
3138 // By default WebSocket is supported
3139 var _webSocketSupported = true;
3140 // Whether we were able to establish a WebSocket connection
3141 var _webSocketConnected = false;
3142 var _stickyReconnect = true;
3143 // The context contains the envelopes that have been sent
3144 // and the timeouts for the messages that have been sent.
3145 var _context = null;
3146 var _connecting = null;
3147 var _connected = false;
3148 var _successCallback = null;
3149
3150 _self.reset = function(init) {
3151 _super.reset(init);
3152 _webSocketSupported = true;
3153 if (init) {
3154 _webSocketConnected = false;
3155 }
3156 _stickyReconnect = true;
3157 _context = null;
3158 _connecting = null;
3159 _connected = false;
3160 };
3161
3162 function _forceClose(context, event) {
3163 if (context) {
3164 this.webSocketClose(context, event.code, event.reason);
3165 // Force immediate failure of pending messages to trigger reconnect.
3166 // This is needed because the server may not reply to our close()
3167 // and therefore the onclose function is never called.
3168 this.onClose(context, event);
3169 }
3170 }
3171
3172 function _sameContext(context) {
3173 return context === _connecting || context === _context;
3174 }
3175
3176 function _storeEnvelope(context, envelope, metaConnect) {
3177 var messageIds = [];
3178 for (var i = 0; i < envelope.messages.length; ++i) {
3179 var message = envelope.messages[i];
3180 if (message.id) {
3181 messageIds.push(message.id);
3182 }
3183 }
3184 context.envelopes[messageIds.join(',')] = [envelope, metaConnect];
3185 this._debug('Transport', this.getType(), 'stored envelope, envelopes', context.envelopes);
3186 }
3187
3188 function _websocketConnect(context) {
3189 // We may have multiple attempts to open a WebSocket
3190 // connection, for example a /meta/connect request that
3191 // may take time, along with a user-triggered publish.
3192 // Early return if we are already connecting.
3193 if (_connecting) {
3194 return;
3195 }
3196
3197 // Mangle the URL, changing the scheme from 'http' to 'ws'.
3198 var url = _cometd.getURL().replace(/^http/, 'ws');
3199 this._debug('Transport', this.getType(), 'connecting to URL', url);
3200
3201 try {
3202 var protocol = _cometd.getConfiguration().protocol;
3203 var WebSocket = WebSocketTransport.WebSocket;
3204 context.webSocket = protocol ? new WebSocket(url, protocol) : new WebSocket(url);
3205 _connecting = context;
3206 } catch (x) {
3207 _webSocketSupported = false;
3208 this._debug('Exception while creating WebSocket object', x);
3209 throw x;
3210 }
3211
3212 // By default use sticky reconnects.
3213 _stickyReconnect = _cometd.getConfiguration().stickyReconnect !== false;
3214
3215 var self = this;
3216 var connectTimeout = _cometd.getConfiguration().connectTimeout;
3217 if (connectTimeout > 0) {
3218 context.connectTimer = self.setTimeout(function() {
3219 _cometd._debug('Transport', self.getType(), 'timed out while connecting to URL', url, ':', connectTimeout, 'ms');
3220 // The connection was not opened, close anyway.
3221 _forceClose.call(self, context, {code: 1000, reason: 'Connect Timeout'});
3222 }, connectTimeout);
3223 }
3224
3225 var onopen = function() {
3226 _cometd._debug('WebSocket onopen', context);
3227 if (context.connectTimer) {
3228 self.clearTimeout(context.connectTimer);
3229 }
3230
3231 if (_sameContext(context)) {
3232 _connecting = null;
3233 _context = context;
3234 _webSocketConnected = true;
3235 self.onOpen(context);
3236 } else {
3237 // We have a valid connection already, close this one.
3238 _cometd._warn('Closing extra WebSocket connection', this, 'active connection', _context);
3239 _forceClose.call(self, context, {code: 1000, reason: 'Extra Connection'});
3240 }
3241 };
3242
3243 // This callback is invoked when the server sends the close frame.
3244 // The close frame for a connection may arrive *after* another
3245 // connection has been opened, so we must make sure that actions
3246 // are performed only if it's the same connection.
3247 var onclose = function(event) {
3248 event = event || {code: 1000};
3249 _cometd._debug('WebSocket onclose', context, event, 'connecting', _connecting, 'current', _context);
3250
3251 if (context.connectTimer) {
3252 self.clearTimeout(context.connectTimer);
3253 }
3254
3255 self.onClose(context, event);
3256 };
3257
3258 var onmessage = function(wsMessage) {
3259 _cometd._debug('WebSocket onmessage', wsMessage, context);
3260 self.onMessage(context, wsMessage);
3261 };
3262
3263 context.webSocket.onopen = onopen;
3264 context.webSocket.onclose = onclose;
3265 context.webSocket.onerror = function() {
3266 // Clients should call onclose(), but if they do not we do it here for safety.
3267 onclose({code: 1000, reason: 'Error'});
3268 };
3269 context.webSocket.onmessage = onmessage;
3270
3271 this._debug('Transport', this.getType(), 'configured callbacks on', context);
3272 }
3273
3274 function _webSocketSend(context, envelope, metaConnect) {
3275 var json = JSON.stringify(envelope.messages);
3276 context.webSocket.send(json);
3277 this._debug('Transport', this.getType(), 'sent', envelope, 'metaConnect =', metaConnect);
3278
3279 // Manage the timeout waiting for the response.
3280 var maxDelay = this.getConfiguration().maxNetworkDelay;
3281 var delay = maxDelay;
3282 if (metaConnect) {
3283 delay += this.getAdvice().timeout;
3284 _connected = true;
3285 }
3286
3287 var self = this;
3288 var messageIds = [];
3289 for (var i = 0; i < envelope.messages.length; ++i) {
3290 (function() {
3291 var message = envelope.messages[i];
3292 if (message.id) {
3293 messageIds.push(message.id);
3294 context.timeouts[message.id] = self.setTimeout(function() {
3295 _cometd._debug('Transport', self.getType(), 'timing out message', message.id, 'after', delay, 'on', context);
3296 _forceClose.call(self, context, {code: 1000, reason: 'Message Timeout'});
3297 }, delay);
3298 }
3299 })();
3300 }
3301
3302 this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for messages', messageIds, 'maxNetworkDelay', maxDelay, ', timeouts:', context.timeouts);
3303 }
3304
3305 _self._notifySuccess = function(fn, messages) {
3306 fn.call(this, messages);
3307 };
3308
3309 _self._notifyFailure = function(fn, context, messages, failure) {
3310 fn.call(this, context, messages, failure);
3311 };
3312
3313 function _send(context, envelope, metaConnect) {
3314 try {
3315 if (context === null) {
3316 context = _connecting || {
3317 envelopes: {},
3318 timeouts: {}
3319 };
3320 _storeEnvelope.call(this, context, envelope, metaConnect);
3321 _websocketConnect.call(this, context);
3322 } else {
3323 _storeEnvelope.call(this, context, envelope, metaConnect);
3324 _webSocketSend.call(this, context, envelope, metaConnect);
3325 }
3326 } catch (x) {
3327 // Keep the semantic of calling response callbacks asynchronously after the request.
3328 var self = this;
3329 self.setTimeout(function() {
3330 _forceClose.call(self, context, {
3331 code: 1000,
3332 reason: 'Exception',
3333 exception: x
3334 });
3335 }, 0);
3336 }
3337 }
3338
3339 _self.onOpen = function(context) {
3340 var envelopes = context.envelopes;
3341 this._debug('Transport', this.getType(), 'opened', context, 'pending messages', envelopes);
3342 for (var key in envelopes) {
3343 if (envelopes.hasOwnProperty(key)) {
3344 var element = envelopes[key];
3345 var envelope = element[0];
3346 var metaConnect = element[1];
3347 // Store the success callback, which is independent from the envelope,
3348 // so that it can be used to notify arrival of messages.
3349 _successCallback = envelope.onSuccess;
3350 _webSocketSend.call(this, context, envelope, metaConnect);
3351 }
3352 }
3353 };
3354
3355 _self.onMessage = function(context, wsMessage) {
3356 this._debug('Transport', this.getType(), 'received websocket message', wsMessage, context);
3357
3358 var close = false;
3359 var messages = this.convertToMessages(wsMessage.data);
3360 var messageIds = [];
3361 for (var i = 0; i < messages.length; ++i) {
3362 var message = messages[i];
3363
3364 // Detect if the message is a response to a request we made.
3365 // If it's a meta message, for sure it's a response; otherwise it's
3366 // a publish message and publish responses don't have the data field.
3367 if (/^\/meta\//.test(message.channel) || message.data === undefined) {
3368 if (message.id) {
3369 messageIds.push(message.id);
3370
3371 var timeout = context.timeouts[message.id];
3372 if (timeout) {
3373 this.clearTimeout(timeout);
3374 delete context.timeouts[message.id];
3375 this._debug('Transport', this.getType(), 'removed timeout for message', message.id, ', timeouts', context.timeouts);
3376 }
3377 }
3378 }
3379
3380 if ('/meta/connect' === message.channel) {
3381 _connected = false;
3382 }
3383 if ('/meta/disconnect' === message.channel && !_connected) {
3384 close = true;
3385 }
3386 }
3387
3388 // Remove the envelope corresponding to the messages.
3389 var removed = false;
3390 var envelopes = context.envelopes;
3391 for (var j = 0; j < messageIds.length; ++j) {
3392 var id = messageIds[j];
3393 for (var key in envelopes) {
3394 if (envelopes.hasOwnProperty(key)) {
3395 var ids = key.split(',');
3396 var index = Utils.inArray(id, ids);
3397 if (index >= 0) {
3398 removed = true;
3399 ids.splice(index, 1);
3400 var envelope = envelopes[key][0];
3401 var metaConnect = envelopes[key][1];
3402 delete envelopes[key];
3403 if (ids.length > 0) {
3404 envelopes[ids.join(',')] = [envelope, metaConnect];
3405 }
3406 break;
3407 }
3408 }
3409 }
3410 }
3411 if (removed) {
3412 this._debug('Transport', this.getType(), 'removed envelope, envelopes', envelopes);
3413 }
3414
3415 this._notifySuccess(_successCallback, messages);
3416
3417 if (close) {
3418 this.webSocketClose(context, 1000, 'Disconnect');
3419 }
3420 };
3421
3422 _self.onClose = function(context, event) {
3423 this._debug('Transport', this.getType(), 'closed', context, event);
3424
3425 if (_sameContext(context)) {
3426 // Remember if we were able to connect.
3427 // This close event could be due to server shutdown,
3428 // and if it restarts we want to try websocket again.
3429 _webSocketSupported = _stickyReconnect && _webSocketConnected;
3430 _connecting = null;
3431 _context = null;
3432 }
3433
3434 var timeouts = context.timeouts;
3435 context.timeouts = {};
3436 for (var id in timeouts) {
3437 if (timeouts.hasOwnProperty(id)) {
3438 this.clearTimeout(timeouts[id]);
3439 }
3440 }
3441
3442 var envelopes = context.envelopes;
3443 context.envelopes = {};
3444 for (var key in envelopes) {
3445 if (envelopes.hasOwnProperty(key)) {
3446 var envelope = envelopes[key][0];
3447 var metaConnect = envelopes[key][1];
3448 if (metaConnect) {
3449 _connected = false;
3450 }
3451 var failure = {
3452 websocketCode: event.code,
3453 reason: event.reason
3454 };
3455 if (event.exception) {
3456 failure.exception = event.exception;
3457 }
3458 this._notifyFailure(envelope.onFailure, context, envelope.messages, failure);
3459 }
3460 }
3461 };
3462
3463 _self.registered = function(type, cometd) {
3464 _super.registered(type, cometd);
3465 _cometd = cometd;
3466 };
3467
3468 _self.accept = function(version, crossDomain, url) {
3469 this._debug('Transport', this.getType(), 'accept, supported:', _webSocketSupported);
3470 // Using !! to return a boolean (and not the WebSocket object).
3471 return _webSocketSupported && !('undefined' === typeof WebSocket) && _cometd.websocketEnabled !== false;
3472 };
3473
3474 _self.send = function(envelope, metaConnect) {
3475 this._debug('Transport', this.getType(), 'sending', envelope, 'metaConnect =', metaConnect);
3476 _send.call(this, _context, envelope, metaConnect);
3477 };
3478
3479 _self.webSocketClose = function(context, code, reason) {
3480 try {
3481 if (context.webSocket) {
3482 context.webSocket.close(code, reason);
3483 }
3484 } catch (x) {
3485 this._debug(x);
3486 }
3487 };
3488
3489 _self.abort = function() {
3490 _super.abort();
3491 _forceClose.call(this, _context, {code: 1000, reason: 'Abort'});
3492 this.reset(true);
3493 };
3494
3495 return _self;
3496}
3497
3498// Reference global WebSocket
3499WebSocketTransport.WebSocket = 'Abstract';
3500
3501// Export WebSocketTransport
3502var WebSocketTransport_1 = WebSocketTransport;
3503
3504// Use node-fetch implementation
3505var fetch_1 = FetchLongPollingTransport_1.fetch = function() {
3506 return fetch.apply(window, arguments);
3507};
3508
3509// Use node-websocket implementation
3510var WebSocket_1 = WebSocketTransport_1.WebSocket = typeof WebSocket === 'undefined' ? null : WebSocket;
3511
3512/**
3513 * Long polling transport layer
3514 */
3515var WEBSOCKET_TRANSPORT = {
3516 type: TransportTypes.WEBSOCKET,
3517 Transport: WebSocketTransport_1
3518};
3519var WEBSOCKET_TRANSPORT_1 = WEBSOCKET_TRANSPORT;
3520
3521/**
3522 * Long polling transport layer
3523 */
3524var LONG_POLLING_TRANSPORT = {
3525 type: TransportTypes.LONG_POLLING,
3526 Transport: FetchLongPollingTransport_1
3527};
3528var LONG_POLLING_TRANSPORT_1 = LONG_POLLING_TRANSPORT;
3529
3530/**
3531 * CometD Transports Layers map
3532 */
3533var ALL = [
3534 WEBSOCKET_TRANSPORT,
3535 LONG_POLLING_TRANSPORT
3536];
3537var ALL_1 = ALL;
3538
3539var Transports$1 = {
3540 fetch: fetch_1,
3541 WebSocket: WebSocket_1,
3542 WEBSOCKET_TRANSPORT: WEBSOCKET_TRANSPORT_1,
3543 LONG_POLLING_TRANSPORT: LONG_POLLING_TRANSPORT_1,
3544 ALL: ALL_1
3545};
3546
3547var CometD = CometD$1;
3548var Transports = Transports$1;
3549
3550/**
3551 * Data aggregation
3552 *
3553 * Provides data aggregation over time and across different items
3554 * User devices push items data on developer-defined categories
3555 * This service automatically aggregates the data
3556 * Raw data is not available for reading, only the generated aggregation result
3557 *
3558 * */
3559/**
3560 * User API for item aggregation
3561 *
3562 * Users can push data and be notified of aggregated data.
3563 * This service does not allow you to read the data. To achieve that kind of behavior, you could configure a callback to store the data.
3564 * @access public
3565 * */
3566var Aggreg = function (_Service) {
3567 inherits(Aggreg, _Service);
3568
3569 function Aggreg() {
3570 classCallCheck(this, Aggreg);
3571 return possibleConstructorReturn(this, (Aggreg.__proto__ || Object.getPrototypeOf(Aggreg)).apply(this, arguments));
3572 }
3573
3574 createClass(Aggreg, [{
3575 key: 'push',
3576
3577 /**
3578 * Pushes some data
3579 *
3580 * Pushes the given data.
3581 * All the items are processed according to the defined rules.
3582 * At least one push for a given item is needed during a time period to trigger processing and calling of the corresponding callback verb/macro.
3583 * */
3584 value: function push(_ref) {
3585 var items = _ref.items,
3586 owner = _ref.owner;
3587 return this.$publish('push', { items: items, owner: owner });
3588 }
3589 }], [{
3590 key: 'DEFAULT_DEPLOYMENT_ID',
3591
3592 /**
3593 * Get default deployment id associated to Aggreg service
3594 * @return {string}
3595 */
3596 get: function get$$1() {
3597 return 'aggreg_0';
3598 }
3599 }]);
3600 return Aggreg;
3601}(Service);
3602/**
3603 * Data stacks
3604 *
3605 * Stacks are a per-user named persistent queue of data
3606 * An administrator creates a stack service
3607 * End-users can push data on an arbitrary number of their own arbitrary named stacks
3608 * */
3609/**
3610 * Data stack user API
3611 *
3612 * Data is stored on a per user basis. However, notifications can be sent to a configurable set of listeners.
3613 * Stack names are arbitrary and do not need to be explicitly initialized.
3614 * @access public
3615 * */
3616var Stack = function (_Service2) {
3617 inherits(Stack, _Service2);
3618
3619 function Stack() {
3620 classCallCheck(this, Stack);
3621 return possibleConstructorReturn(this, (Stack.__proto__ || Object.getPrototypeOf(Stack)).apply(this, arguments));
3622 }
3623
3624 createClass(Stack, [{
3625 key: 'getListeners',
3626
3627 /**
3628 * Lists the listeners
3629 *
3630 * Returns the whole list of listeners for the given stack.
3631 * */
3632 value: function getListeners(_ref2) {
3633 var stack = _ref2.stack,
3634 owner = _ref2.owner;
3635 return this.$publish('getListeners', { stack: stack, owner: owner });
3636 }
3637 /**
3638 * Lists content
3639 *
3640 * Returns a paginated list of contents for the given stack.
3641 * Content is sorted according to the statically configured order.
3642 * */
3643
3644 }, {
3645 key: 'list',
3646 value: function list(_ref3) {
3647 var stack = _ref3.stack,
3648 owner = _ref3.owner,
3649 page = _ref3.page;
3650 return this.$publish('list', { stack: stack, owner: owner, page: page });
3651 }
3652 /**
3653 * Empties a stack
3654 *
3655 * Removes all items from the given stack.
3656 * */
3657
3658 }, {
3659 key: 'purge',
3660 value: function purge(_ref4) {
3661 var stack = _ref4.stack,
3662 owner = _ref4.owner;
3663 return this.$publish('purge', { stack: stack, owner: owner });
3664 }
3665 /**
3666 * Pushes an item
3667 *
3668 * Pushes an item onto the given stack.
3669 * The stack does not need to be created.
3670 * */
3671
3672 }, {
3673 key: 'push',
3674 value: function push(_ref5) {
3675 var stack = _ref5.stack,
3676 data = _ref5.data,
3677 owner = _ref5.owner;
3678 return this.$publish('push', { stack: stack, data: data, owner: owner });
3679 }
3680 /**
3681 * Removes items
3682 *
3683 * Removes the item with the given guid from the given stack.
3684 * */
3685
3686 }, {
3687 key: 'remove',
3688 value: function remove(_ref6) {
3689 var guids = _ref6.guids,
3690 stack = _ref6.stack,
3691 owner = _ref6.owner;
3692 return this.$publish('remove', { guids: guids, stack: stack, owner: owner });
3693 }
3694 /**
3695 * Sets the listeners
3696 *
3697 * Sets the listeners for the given stack.
3698 * */
3699
3700 }, {
3701 key: 'setListeners',
3702 value: function setListeners(_ref7) {
3703 var listeners = _ref7.listeners,
3704 stack = _ref7.stack,
3705 owner = _ref7.owner;
3706 return this.$publish('setListeners', { listeners: listeners, stack: stack, owner: owner });
3707 }
3708 /**
3709 * Updates an item
3710 *
3711 * Updates an existing item of the given stack.
3712 * The item MUST exist prior to the call.
3713 * */
3714
3715 }, {
3716 key: 'update',
3717 value: function update(_ref8) {
3718 var guid = _ref8.guid,
3719 stack = _ref8.stack,
3720 data = _ref8.data,
3721 owner = _ref8.owner;
3722 return this.$publish('update', { guid: guid, stack: stack, data: data, owner: owner });
3723 }
3724 }], [{
3725 key: 'DEFAULT_DEPLOYMENT_ID',
3726
3727 /**
3728 * Get default deployment id associated to Stack service
3729 * @return {string}
3730 */
3731 get: function get$$1() {
3732 return 'stack_0';
3733 }
3734 }]);
3735 return Stack;
3736}(Service);
3737/**
3738 * Echo
3739 *
3740 * Echo
3741 * */
3742/**
3743 * Echo service
3744 *
3745 * Simple echo service, for development purposes.
3746 * @access public
3747 * */
3748var Echo = function (_Service3) {
3749 inherits(Echo, _Service3);
3750
3751 function Echo() {
3752 classCallCheck(this, Echo);
3753 return possibleConstructorReturn(this, (Echo.__proto__ || Object.getPrototypeOf(Echo)).apply(this, arguments));
3754 }
3755
3756 createClass(Echo, [{
3757 key: 'echo',
3758
3759 /**
3760 * Echoes an object
3761 *
3762 * Echoes an object: the server will echo that object on channel 'echo' for the current user.
3763 * */
3764 value: function echo(parameter) {
3765 return this.$publish('echo', parameter);
3766 }
3767 }], [{
3768 key: 'DEFAULT_DEPLOYMENT_ID',
3769
3770 /**
3771 * Get default deployment id associated to Echo service
3772 * @return {string}
3773 */
3774 get: function get$$1() {
3775 return 'echo_0';
3776 }
3777 }]);
3778 return Echo;
3779}(Service);
3780/**
3781 * Game engine
3782 *
3783 * Abstract Game Engine
3784 * Concrete game engines are remote cometd clients or internal macros
3785 * */
3786/**
3787 * User API for games
3788 *
3789 * Users can list, start, join games, and play.
3790 * @access public
3791 * */
3792var Game = function (_Service4) {
3793 inherits(Game, _Service4);
3794
3795 function Game() {
3796 classCallCheck(this, Game);
3797 return possibleConstructorReturn(this, (Game.__proto__ || Object.getPrototypeOf(Game)).apply(this, arguments));
3798 }
3799
3800 createClass(Game, [{
3801 key: 'available',
3802
3803 /**
3804 * Lists game types
3805 *
3806 * Returns the list of game types supported by the server and the currently registered game engines.
3807 * */
3808 value: function available() {
3809 return this.$publish('available', {});
3810 }
3811 /**A user joins a game*/
3812
3813 }, {
3814 key: 'join',
3815 value: function join(_ref9) {
3816 var role = _ref9.role,
3817 gameId = _ref9.gameId,
3818 userId = _ref9.userId,
3819 userName = _ref9.userName;
3820 return this.$publish('join', { role: role, gameId: gameId, userId: userId, userName: userName });
3821 }
3822 /**Organizes a game*/
3823
3824 }, {
3825 key: 'organize',
3826 value: function organize(_ref10) {
3827 var type = _ref10.type,
3828 owner = _ref10.owner,
3829 options = _ref10.options;
3830 return this.$publish('organize', { type: type, owner: owner, options: options });
3831 }
3832 /**Gives some command to the game engine*/
3833
3834 }, {
3835 key: 'play',
3836 value: function play(_ref11) {
3837 var gameId = _ref11.gameId,
3838 userId = _ref11.userId,
3839 data = _ref11.data;
3840 return this.$publish('play', { gameId: gameId, userId: userId, data: data });
3841 }
3842 /**Starts a game*/
3843
3844 }, {
3845 key: 'start',
3846 value: function start(_ref12) {
3847 var gameId = _ref12.gameId;
3848 return this.$publish('start', { gameId: gameId });
3849 }
3850 /**A user cancels joining a game*/
3851
3852 }, {
3853 key: 'unjoin',
3854 value: function unjoin(_ref13) {
3855 var role = _ref13.role,
3856 gameId = _ref13.gameId,
3857 userId = _ref13.userId,
3858 userName = _ref13.userName;
3859 return this.$publish('unjoin', { role: role, gameId: gameId, userId: userId, userName: userName });
3860 }
3861 }], [{
3862 key: 'DEFAULT_DEPLOYMENT_ID',
3863
3864 /**
3865 * Get default deployment id associated to Game service
3866 * @return {string}
3867 */
3868 get: function get$$1() {
3869 return 'game_0';
3870 }
3871 }]);
3872 return Game;
3873}(Service);
3874/**
3875 * Game Engine API
3876 *
3877 * The Game Engine API is for game engine clients, not end-users.
3878 * @access public
3879 * */
3880var GameEngine = function (_Service5) {
3881 inherits(GameEngine, _Service5);
3882
3883 function GameEngine() {
3884 classCallCheck(this, GameEngine);
3885 return possibleConstructorReturn(this, (GameEngine.__proto__ || Object.getPrototypeOf(GameEngine)).apply(this, arguments));
3886 }
3887
3888 createClass(GameEngine, [{
3889 key: 'join_result',
3890
3891 /**
3892 * Notify the result for a join request
3893 *
3894 * A Game Engine notifies the STR of the result of a join request that it received on join_callback
3895 * */
3896 value: function join_result(_ref14) {
3897 var msgId = _ref14.msgId,
3898 payload = _ref14.payload,
3899 error = _ref14.error,
3900 callerId = _ref14.callerId;
3901 return this.$publish('join_result', { msgId: msgId, payload: payload, error: error, callerId: callerId });
3902 }
3903 /**
3904 * Notify the result for an organization request
3905 *
3906 * A Game Engine notifies the STR of the result of an organization request that it received on organize_callback
3907 * */
3908
3909 }, {
3910 key: 'organize_result',
3911 value: function organize_result(_ref15) {
3912 var msgId = _ref15.msgId,
3913 payload = _ref15.payload,
3914 error = _ref15.error,
3915 callerId = _ref15.callerId;
3916 return this.$publish('organize_result', { msgId: msgId, payload: payload, error: error, callerId: callerId });
3917 }
3918 /**
3919 * Registers a game engine
3920 *
3921 * A client registers itself to the STR as a Game Engine.
3922 * The STR may, from now on, dispatch game of the given game type to said client.
3923 * Unregistration is done automatically on logoff.
3924 * */
3925
3926 }, {
3927 key: 'register',
3928 value: function register(_ref16) {
3929 var maxGames = _ref16.maxGames,
3930 gameInfo = _ref16.gameInfo,
3931 location = _ref16.location;
3932 return this.$publish('register', { maxGames: maxGames, gameInfo: gameInfo, location: location });
3933 }
3934 /**
3935 * Notify the result for a start request
3936 *
3937 * A Game Engine notifies the STR of the result of a start request that it received on start_callback
3938 * */
3939
3940 }, {
3941 key: 'start_result',
3942 value: function start_result(_ref17) {
3943 var gameId = _ref17.gameId;
3944 return this.$publish('start_result', { gameId: gameId });
3945 }
3946 /**
3947 * Notify a game event
3948 *
3949 * A Game Engine notifies the STR of some arbitrary game event.
3950 * */
3951
3952 }, {
3953 key: 'state',
3954 value: function state(_ref18) {
3955 var status = _ref18.status,
3956 gameId = _ref18.gameId,
3957 data = _ref18.data;
3958 return this.$publish('state', { status: status, gameId: gameId, data: data });
3959 }
3960 /**
3961 * Notify the result for an unjoin request
3962 *
3963 * A Game Engine notifies the STR of the result of an unjoin request that it received on unjoin_callback
3964 * */
3965
3966 }, {
3967 key: 'unjoin_result',
3968 value: function unjoin_result(_ref19) {
3969 var msgId = _ref19.msgId,
3970 payload = _ref19.payload,
3971 error = _ref19.error,
3972 callerId = _ref19.callerId;
3973 return this.$publish('unjoin_result', { msgId: msgId, payload: payload, error: error, callerId: callerId });
3974 }
3975 }], [{
3976 key: 'DEFAULT_DEPLOYMENT_ID',
3977
3978 /**
3979 * Get default deployment id associated to GameEngine service
3980 * @return {string}
3981 */
3982 get: function get$$1() {
3983 return 'game_0';
3984 }
3985 }]);
3986 return GameEngine;
3987}(Service);
3988/**
3989 * Generic Data Access
3990 *
3991 * Generic Data Access Service : NoSQL storage
3992 * */
3993/**
3994 * GDA User API
3995 *
3996 * User API for Generic Data Access.
3997 * The data are stored on a per-user basis.
3998 * Users can put, get, list their data.
3999 * @access public
4000 * */
4001var Gda = function (_Service6) {
4002 inherits(Gda, _Service6);
4003
4004 function Gda() {
4005 classCallCheck(this, Gda);
4006 return possibleConstructorReturn(this, (Gda.__proto__ || Object.getPrototypeOf(Gda)).apply(this, arguments));
4007 }
4008
4009 createClass(Gda, [{
4010 key: 'get',
4011
4012 /**
4013 * Asks for a data row
4014 *
4015 * Returns a full data row.
4016 * */
4017 value: function get$$1(_ref20) {
4018 var table = _ref20.table,
4019 key = _ref20.key,
4020 owner = _ref20.owner;
4021 return this.$publish('get', { table: table, key: key, owner: owner });
4022 }
4023 /**
4024 * Asks for a data cell
4025 *
4026 * Returns a precise list of cells from a column in a data row.
4027 * */
4028
4029 }, {
4030 key: 'getCells',
4031 value: function getCells(_ref21) {
4032 var table = _ref21.table,
4033 key = _ref21.key,
4034 key2 = _ref21.key2,
4035 owner = _ref21.owner,
4036 column = _ref21.column;
4037 return this.$publish('getCells', { table: table, key: key, key2: key2, owner: owner, column: column });
4038 }
4039 /**
4040 * Increments an integer value
4041 *
4042 * Increments a cell 64-bit signed integer value and returns the result in the data field.
4043 * The increment is atomic : if you concurrently increment 10 times a value by 1, the final result will be the initial value plus 10. The actual individual resulting values seen by the 10 concurrent callers may vary discontinuously, with duplicates : at least one of them will see the final (+10) result.
4044 * */
4045
4046 }, {
4047 key: 'inc',
4048 value: function inc(_ref22) {
4049 var table = _ref22.table,
4050 data = _ref22.data,
4051 key = _ref22.key,
4052 key2 = _ref22.key2,
4053 owner = _ref22.owner,
4054 column = _ref22.column;
4055 return this.$publish('inc', { table: table, data: data, key: key, key2: key2, owner: owner, column: column });
4056 }
4057 /**
4058 * Asks for a list of rows
4059 *
4060 * Returns a paginated list of rows from the given table.
4061 * */
4062
4063 }, {
4064 key: 'list',
4065 value: function list(_ref23) {
4066 var columns = _ref23.columns,
4067 table = _ref23.table,
4068 owner = _ref23.owner,
4069 page = _ref23.page;
4070 return this.$publish('list', { columns: columns, table: table, owner: owner, page: page });
4071 }
4072 /**
4073 * Puts some data into a cell
4074 *
4075 * Creates or replaces the contents of a particular cell.
4076 * */
4077
4078 }, {
4079 key: 'put',
4080 value: function put(_ref24) {
4081 var table = _ref24.table,
4082 data = _ref24.data,
4083 key = _ref24.key,
4084 key2 = _ref24.key2,
4085 owner = _ref24.owner,
4086 column = _ref24.column;
4087 return this.$publish('put', { table: table, data: data, key: key, key2: key2, owner: owner, column: column });
4088 }
4089 /**
4090 * Puts several rows
4091 *
4092 * Creates or replaces the (maybe partial) contents of a collection of rows.
4093 * This method only creates or replaces cells for non-null input values.
4094 * */
4095
4096 }, {
4097 key: 'puts',
4098 value: function puts(_ref25) {
4099 var rows = _ref25.rows,
4100 table = _ref25.table,
4101 owner = _ref25.owner;
4102 return this.$publish('puts', { rows: rows, table: table, owner: owner });
4103 }
4104 /**
4105 * Asks for a range of rows
4106 *
4107 * Returns a paginated range of rows from the given table.
4108 * A range consists of consecutive rows from the start key (inclusive) to the stop key (exclusive).
4109 * You can specify partial keys for the start and stop fields.
4110 * */
4111
4112 }, {
4113 key: 'range',
4114 value: function range(_ref26) {
4115 var columns = _ref26.columns,
4116 start = _ref26.start,
4117 table = _ref26.table,
4118 stop = _ref26.stop,
4119 owner = _ref26.owner,
4120 page = _ref26.page;
4121 return this.$publish('range', { columns: columns, start: start, table: table, stop: stop, owner: owner, page: page });
4122 }
4123 /**
4124 * Removes one cell inside a column of a row
4125 *
4126 * Removes only one cell of the given column of the given row from the given table.
4127 * */
4128
4129 }, {
4130 key: 'removeCell',
4131 value: function removeCell(_ref27) {
4132 var table = _ref27.table,
4133 key = _ref27.key,
4134 key2 = _ref27.key2,
4135 owner = _ref27.owner,
4136 column = _ref27.column;
4137 return this.$publish('removeCell', { table: table, key: key, key2: key2, owner: owner, column: column });
4138 }
4139 /**
4140 * Removes one full column of a row
4141 *
4142 * Removes all cells of the given column of the given row from the given table.
4143 * */
4144
4145 }, {
4146 key: 'removeColumn',
4147 value: function removeColumn(_ref28) {
4148 var table = _ref28.table,
4149 key = _ref28.key,
4150 owner = _ref28.owner,
4151 column = _ref28.column;
4152 return this.$publish('removeColumn', { table: table, key: key, owner: owner, column: column });
4153 }
4154 /**
4155 * Removes a range of rows
4156 *
4157 * Removes the specified columns of the given range of rows from the given table.
4158 * */
4159
4160 }, {
4161 key: 'removeRange',
4162 value: function removeRange(_ref29) {
4163 var columns = _ref29.columns,
4164 start = _ref29.start,
4165 table = _ref29.table,
4166 stop = _ref29.stop,
4167 owner = _ref29.owner;
4168 return this.$publish('removeRange', { columns: columns, start: start, table: table, stop: stop, owner: owner });
4169 }
4170 /**
4171 * Removes one full row
4172 *
4173 * Removes all columns of the given row from the given table.
4174 * */
4175
4176 }, {
4177 key: 'removeRow',
4178 value: function removeRow(_ref30) {
4179 var table = _ref30.table,
4180 key = _ref30.key,
4181 owner = _ref30.owner;
4182 return this.$publish('removeRow', { table: table, key: key, owner: owner });
4183 }
4184 }], [{
4185 key: 'DEFAULT_DEPLOYMENT_ID',
4186
4187 /**
4188 * Get default deployment id associated to Gda service
4189 * @return {string}
4190 */
4191 get: function get$$1() {
4192 return 'gda_0';
4193 }
4194 }]);
4195 return Gda;
4196}(Service);
4197/**
4198 * Groups Management
4199 *
4200 * Groups management for users, grants on resources, remote commands on devices
4201 * This is where you can configure rights for any resource
4202 *
4203 * */
4204/**
4205 * User API for remote control
4206 *
4207 * @access public
4208 * */
4209
4210var Remoting = function (_Service7) {
4211 inherits(Remoting, _Service7);
4212
4213 function Remoting() {
4214 classCallCheck(this, Remoting);
4215 return possibleConstructorReturn(this, (Remoting.__proto__ || Object.getPrototypeOf(Remoting)).apply(this, arguments));
4216 }
4217
4218 createClass(Remoting, [{
4219 key: 'addListener',
4220
4221 /**
4222 * Adds a listener
4223 *
4224 * A user requests notifications from a device owned by anyone who granted him the right authorizations.
4225 * Whenever the device calls 'notify', notifications will be sent to the caller of this verb.
4226 * */
4227 value: function addListener(_ref31) {
4228 var resource = _ref31.resource,
4229 fromResource = _ref31.fromResource,
4230 cmd = _ref31.cmd,
4231 from = _ref31.from,
4232 data = _ref31.data,
4233 owner = _ref31.owner;
4234 return this.$publish('addListener', { resource: resource, fromResource: fromResource, cmd: cmd, from: from, data: data, owner: owner });
4235 }
4236 /**Response to 'getCapabilities'*/
4237
4238 }, {
4239 key: 'capabilities',
4240 value: function capabilities(_ref32) {
4241 var askingResource = _ref32.askingResource,
4242 _capabilities = _ref32.capabilities,
4243 answeringResource = _ref32.answeringResource;
4244 return this.$publish('capabilities', { askingResource: askingResource, capabilities: _capabilities, answeringResource: answeringResource });
4245 }
4246 /**
4247 * Executes a command
4248 *
4249 * A user executes a command on a device owned by anyone who granted him the right authorizations.
4250 * The command is issued on channel 'command'
4251 * */
4252
4253 }, {
4254 key: 'execute',
4255 value: function execute(_ref33) {
4256 var resource = _ref33.resource,
4257 cmd = _ref33.cmd,
4258 data = _ref33.data,
4259 owner = _ref33.owner;
4260 return this.$publish('execute', { resource: resource, cmd: cmd, data: data, owner: owner });
4261 }
4262 /**
4263 * Requests capabilities
4264 *
4265 * A user requests all his devices for the whole list of their capabilities.
4266 * Devices are expected to answer on channel 'capabilities'
4267 * */
4268
4269 }, {
4270 key: 'getCapabilities',
4271 value: function getCapabilities() {
4272 return this.$publish('getCapabilities', {});
4273 }
4274 /**
4275 * Notifies of some event
4276 *
4277 * A device notifies the registered users/devices on this channel.
4278 * The server forwards the notification to said users.
4279 * */
4280
4281 }, {
4282 key: 'notify',
4283 value: function notify(_ref34) {
4284 var resource = _ref34.resource,
4285 fromResource = _ref34.fromResource,
4286 cmd = _ref34.cmd,
4287 from = _ref34.from,
4288 data = _ref34.data,
4289 owner = _ref34.owner;
4290 return this.$publish('notify', { resource: resource, fromResource: fromResource, cmd: cmd, from: from, data: data, owner: owner });
4291 }
4292 /**
4293 * Pings devices
4294 *
4295 * A user requests all devices (of all owners) on which he has authorizations to respond on channel 'pong'
4296 * */
4297
4298 }, {
4299 key: 'ping',
4300 value: function ping(_ref35) {
4301 var action = _ref35.action;
4302 return this.$publish('ping', { action: action });
4303 }
4304 /**Response to ping*/
4305
4306 }, {
4307 key: 'pong',
4308 value: function pong(_ref36) {
4309 var user = _ref36.user,
4310 resource = _ref36.resource,
4311 available = _ref36.available,
4312 uid = _ref36.uid,
4313 owner = _ref36.owner,
4314 action = _ref36.action;
4315 return this.$publish('pong', { user: user, resource: resource, available: available, uid: uid, owner: owner, action: action });
4316 }
4317 /**
4318 * Removes a listener
4319 *
4320 * A user stops requesting notifications from a device owned by anyone who granted him the right authorizations
4321 * */
4322
4323 }, {
4324 key: 'removeListener',
4325 value: function removeListener(_ref37) {
4326 var resource = _ref37.resource,
4327 fromResource = _ref37.fromResource,
4328 cmd = _ref37.cmd,
4329 from = _ref37.from,
4330 data = _ref37.data,
4331 owner = _ref37.owner;
4332 return this.$publish('removeListener', { resource: resource, fromResource: fromResource, cmd: cmd, from: from, data: data, owner: owner });
4333 }
4334 }], [{
4335 key: 'DEFAULT_DEPLOYMENT_ID',
4336
4337 /**
4338 * Get default deployment id associated to Remoting service
4339 * @return {string}
4340 */
4341 get: function get$$1() {
4342 return 'groups_0';
4343 }
4344 }]);
4345 return Remoting;
4346}(Service);
4347var GroupManagement = function (_Service8) {
4348 inherits(GroupManagement, _Service8);
4349
4350 function GroupManagement() {
4351 classCallCheck(this, GroupManagement);
4352 return possibleConstructorReturn(this, (GroupManagement.__proto__ || Object.getPrototypeOf(GroupManagement)).apply(this, arguments));
4353 }
4354
4355 createClass(GroupManagement, [{
4356 key: 'addMe',
4357
4358 /**
4359 * Adds me to a group
4360 *
4361 * Adds me (the caller) to a group.
4362 * This verb exists so that group owners may grant the right to join their groups without granting the right to add other users to those groups.
4363 * The 'user' field is implicitly set to the current user's key.
4364 * */
4365 value: function addMe(_ref38) {
4366 var group = _ref38.group,
4367 owner = _ref38.owner;
4368 return this.$publish('addMe', { group: group, owner: owner });
4369 }
4370 /**
4371 * Adds a user to a group
4372 *
4373 * Adds the given user to the given group.
4374 * Addition may fail if the given group does not already exist.
4375 * */
4376
4377 }, {
4378 key: 'addUser',
4379 value: function addUser(_ref39) {
4380 var user = _ref39.user,
4381 group = _ref39.group,
4382 owner = _ref39.owner;
4383 return this.$publish('addUser', { user: user, group: group, owner: owner });
4384 }
4385 /**Adds users to a group*/
4386
4387 }, {
4388 key: 'addUsers',
4389 value: function addUsers(_ref40) {
4390 var users = _ref40.users,
4391 group = _ref40.group,
4392 owner = _ref40.owner;
4393 return this.$publish('addUsers', { users: users, group: group, owner: owner });
4394 }
4395 /**
4396 * Lists my owned groups, with details
4397 *
4398 * Returns the whole list of groups owned by the current user, with their members
4399 * */
4400
4401 }, {
4402 key: 'allGroups',
4403 value: function allGroups(_ref41) {
4404 var owner = _ref41.owner;
4405 return this.$publish('allGroups', { owner: owner });
4406 }
4407 /**
4408 * Creates a group
4409 *
4410 * Creates a group owned by the current user.
4411 * Group creation may fail if the group already exists.
4412 * */
4413
4414 }, {
4415 key: 'createGroup',
4416 value: function createGroup(_ref42) {
4417 var group = _ref42.group,
4418 groupName = _ref42.groupName,
4419 owner = _ref42.owner;
4420 return this.$publish('createGroup', { group: group, groupName: groupName, owner: owner });
4421 }
4422 /**
4423 * Removes a group
4424 *
4425 * Removes the given group owned by the current user or the given owner.
4426 * Also removes all grants to that group.
4427 * */
4428
4429 }, {
4430 key: 'delGroup',
4431 value: function delGroup(_ref43) {
4432 var group = _ref43.group,
4433 owner = _ref43.owner;
4434 return this.$publish('delGroup', { group: group, owner: owner });
4435 }
4436 /**Removes a user from a group*/
4437
4438 }, {
4439 key: 'delUser',
4440 value: function delUser(_ref44) {
4441 var user = _ref44.user,
4442 group = _ref44.group,
4443 owner = _ref44.owner;
4444 return this.$publish('delUser', { user: user, group: group, owner: owner });
4445 }
4446 /**Removes users from a group*/
4447
4448 }, {
4449 key: 'delUsers',
4450 value: function delUsers(_ref45) {
4451 var users = _ref45.users,
4452 group = _ref45.group,
4453 groupName = _ref45.groupName,
4454 owner = _ref45.owner;
4455 return this.$publish('delUsers', { users: users, group: group, groupName: groupName, owner: owner });
4456 }
4457 /**
4458 * Tests for a group's existence
4459 *
4460 * Returns whether a group exists or not.
4461 * */
4462
4463 }, {
4464 key: 'exists',
4465 value: function exists(_ref46) {
4466 var group = _ref46.group,
4467 owner = _ref46.owner;
4468 return this.$publish('exists', { group: group, owner: owner });
4469 }
4470 /**
4471 * Grants a right to a group
4472 *
4473 * The granting API does not do any check when storing permissions.
4474 * In particular when granting rights on a verb and resource of another API, the existence of said verb and resource is not checked.
4475 * */
4476
4477 }, {
4478 key: 'grant',
4479 value: function grant(_ref47) {
4480 var resource = _ref47.resource,
4481 group = _ref47.group,
4482 owner = _ref47.owner,
4483 action = _ref47.action;
4484 return this.$publish('grant', { resource: resource, group: group, owner: owner, action: action });
4485 }
4486 /**
4487 * Lists the group users
4488 *
4489 * Returns the whole list of users configured inside the given group.
4490 * */
4491
4492 }, {
4493 key: 'groupUsers',
4494 value: function groupUsers(_ref48) {
4495 var group = _ref48.group,
4496 owner = _ref48.owner;
4497 return this.$publish('groupUsers', { group: group, owner: owner });
4498 }
4499 /**
4500 * Lists my owned groups
4501 *
4502 * Returns the whole list of groups owned by the current user
4503 * */
4504
4505 }, {
4506 key: 'groups',
4507 value: function groups(_ref49) {
4508 var owner = _ref49.owner;
4509 return this.$publish('groups', { owner: owner });
4510 }
4511 /**
4512 * Lists rights for a group
4513 *
4514 * This API lists explicitly configured rights.
4515 * Effective rights include configured rights, implicit rights and inherited rights.
4516 * */
4517
4518 }, {
4519 key: 'listGrants',
4520 value: function listGrants(_ref50) {
4521 var group = _ref50.group,
4522 owner = _ref50.owner;
4523 return this.$publish('listGrants', { group: group, owner: owner });
4524 }
4525 /**
4526 * Lists presences for a group
4527 *
4528 * Returns the list of members of the given groups, along with their actual and current presence on the zetapush server.
4529 * The current implementation does not include information about the particular devices users are connected with.
4530 * If a user is connected twice with two different devices, two identical entries will be returned.
4531 * */
4532
4533 }, {
4534 key: 'listPresences',
4535 value: function listPresences(_ref51) {
4536 var group = _ref51.group,
4537 owner = _ref51.owner;
4538 return this.$publish('listPresences', { group: group, owner: owner });
4539 }
4540 /**
4541 * Tests membership
4542 *
4543 * Tests whether I (the caller) am a member of the given group.
4544 * This verb exists so that users can determine if they are part of a group without being granted particular rights.
4545 * The 'user' field is implicitly set to the current user's key.
4546 * */
4547
4548 }, {
4549 key: 'memberOf',
4550 value: function memberOf(_ref52) {
4551 var hardFail = _ref52.hardFail,
4552 group = _ref52.group,
4553 owner = _ref52.owner;
4554 return this.$publish('memberOf', { hardFail: hardFail, group: group, owner: owner });
4555 }
4556 /**
4557 * Grants rights to a group
4558 *
4559 * Grant several rights at once.
4560 * */
4561
4562 }, {
4563 key: 'mgrant',
4564 value: function mgrant(_ref53) {
4565 var resource = _ref53.resource,
4566 actions = _ref53.actions,
4567 group = _ref53.group,
4568 owner = _ref53.owner;
4569 return this.$publish('mgrant', { resource: resource, actions: actions, group: group, owner: owner });
4570 }
4571 /**Revokes rights for a group*/
4572
4573 }, {
4574 key: 'mrevoke',
4575 value: function mrevoke(_ref54) {
4576 var resource = _ref54.resource,
4577 actions = _ref54.actions,
4578 group = _ref54.group,
4579 owner = _ref54.owner;
4580 return this.$publish('mrevoke', { resource: resource, actions: actions, group: group, owner: owner });
4581 }
4582 /**
4583 * Lists the groups I am part of
4584 *
4585 * Returns the whole list of groups the current user is part of.
4586 * Groups may be owned by anyone, including the current user.
4587 * */
4588
4589 }, {
4590 key: 'myGroups',
4591 value: function myGroups(_ref55) {
4592 var owner = _ref55.owner;
4593 return this.$publish('myGroups', { owner: owner });
4594 }
4595 /**Revokes a right for a group*/
4596
4597 }, {
4598 key: 'revoke',
4599 value: function revoke(_ref56) {
4600 var resource = _ref56.resource,
4601 group = _ref56.group,
4602 owner = _ref56.owner,
4603 action = _ref56.action;
4604 return this.$publish('revoke', { resource: resource, group: group, owner: owner, action: action });
4605 }
4606 }], [{
4607 key: 'DEFAULT_DEPLOYMENT_ID',
4608
4609 /**
4610 * Get default deployment id associated to GroupManagement service
4611 * @return {string}
4612 */
4613 get: function get$$1() {
4614 return 'groups_0';
4615 }
4616 }]);
4617 return GroupManagement;
4618}(Service);
4619/**
4620 * HTTP client
4621 *
4622 * Web-service client
4623 * An admin records URL templates that can be called by users
4624 * Calls are not configurable by end-users
4625 * However an admin may leverage the macro service to achieve URL, headers and body configurability
4626 * */
4627/**
4628 * User API for http requests
4629 *
4630 * @access public
4631 * */
4632var Httpclient = function (_Service9) {
4633 inherits(Httpclient, _Service9);
4634
4635 function Httpclient() {
4636 classCallCheck(this, Httpclient);
4637 return possibleConstructorReturn(this, (Httpclient.__proto__ || Object.getPrototypeOf(Httpclient)).apply(this, arguments));
4638 }
4639
4640 createClass(Httpclient, [{
4641 key: 'call',
4642
4643 /**
4644 * Makes a predefined request
4645 *
4646 * Lookups a predefined request by name, and executes it.
4647 * */
4648 value: function call(_ref57) {
4649 var name = _ref57.name,
4650 requestId = _ref57.requestId;
4651 return this.$publish('call', { name: name, requestId: requestId });
4652 }
4653 }], [{
4654 key: 'DEFAULT_DEPLOYMENT_ID',
4655
4656 /**
4657 * Get default deployment id associated to Httpclient service
4658 * @return {string}
4659 */
4660 get: function get$$1() {
4661 return 'httpclient_0';
4662 }
4663 }]);
4664 return Httpclient;
4665}(Service);
4666/**
4667 * Macros
4668 *
4669 * Macro-command service
4670 * An admin defines macro-commands that can sequentially call any number of other api verbs, loop on collections of data, make decisions, etc
4671 *
4672 *
4673 * End-users play them, with contextual parameters
4674 * */
4675/**
4676 * User API for macro debugging
4677 *
4678 * Debugger API for macro.
4679 * These API verbs are not intended for use by most developers.
4680 * @access public
4681 * */
4682
4683var MacroDebug = function (_Service10) {
4684 inherits(MacroDebug, _Service10);
4685
4686 function MacroDebug() {
4687 classCallCheck(this, MacroDebug);
4688 return possibleConstructorReturn(this, (MacroDebug.__proto__ || Object.getPrototypeOf(MacroDebug)).apply(this, arguments));
4689 }
4690
4691 createClass(MacroDebug, [{
4692 key: 'breakpoint',
4693
4694 /**Enables or disables a breakpoint*/
4695 value: function breakpoint(_ref58) {
4696 var _breakpoint = _ref58.breakpoint,
4697 token = _ref58.token,
4698 enabled = _ref58.enabled;
4699 return this.$publish('breakpoint', { breakpoint: _breakpoint, token: token, enabled: enabled });
4700 }
4701 /**Requests some information*/
4702
4703 }, {
4704 key: 'info',
4705 value: function info(_ref59) {
4706 var token = _ref59.token,
4707 path = _ref59.path,
4708 exp = _ref59.exp,
4709 requestId = _ref59.requestId,
4710 frame = _ref59.frame;
4711 return this.$publish('info', { token: token, path: path, exp: exp, requestId: requestId, frame: frame });
4712 }
4713 /**
4714 * Debugs a previously recorded macro
4715 *
4716 * The given breakpoints will be honored, causing a suspension of the execution, resumable via 'resume'.
4717 * Only one debug session can be active at any given time.
4718 * */
4719
4720 }, {
4721 key: 'livedebug',
4722 value: function livedebug(_ref60) {
4723 var parameters = _ref60.parameters,
4724 token = _ref60.token,
4725 breakpoints = _ref60.breakpoints,
4726 hardFail = _ref60.hardFail,
4727 name = _ref60.name,
4728 requestId = _ref60.requestId,
4729 debug = _ref60.debug;
4730 return this.$publish('livedebug', { parameters: parameters, token: token, breakpoints: breakpoints, hardFail: hardFail, name: name, requestId: requestId, debug: debug });
4731 }
4732 /**Resumes a paused macro*/
4733
4734 }, {
4735 key: 'resume',
4736 value: function resume(_ref61) {
4737 var token = _ref61.token,
4738 type = _ref61.type;
4739 return this.$publish('resume', { token: token, type: type });
4740 }
4741 /**Sets a variable value*/
4742
4743 }, {
4744 key: 'variable',
4745 value: function variable(_ref62) {
4746 var token = _ref62.token,
4747 name = _ref62.name,
4748 frame = _ref62.frame,
4749 data = _ref62.data;
4750 return this.$publish('variable', { token: token, name: name, frame: frame, data: data });
4751 }
4752 }], [{
4753 key: 'DEFAULT_DEPLOYMENT_ID',
4754
4755 /**
4756 * Get default deployment id associated to MacroDebug service
4757 * @return {string}
4758 */
4759 get: function get$$1() {
4760 return 'macro_0';
4761 }
4762 }]);
4763 return MacroDebug;
4764}(Service);
4765var Macro = function (_Service11) {
4766 inherits(Macro, _Service11);
4767
4768 function Macro() {
4769 classCallCheck(this, Macro);
4770 return possibleConstructorReturn(this, (Macro.__proto__ || Object.getPrototypeOf(Macro)).apply(this, arguments));
4771 }
4772
4773 createClass(Macro, [{
4774 key: 'call',
4775
4776 /**
4777 * Plays a previously recorded macro
4778 *
4779 * DO NOT use this verb from inside an enclosing macro when you need the result in order to proceed with the enclosing macro.
4780 * You can override the default notification channel when defining the macro.
4781 * */
4782 value: function call(_ref63) {
4783 var parameters = _ref63.parameters,
4784 hardFail = _ref63.hardFail,
4785 name = _ref63.name,
4786 requestId = _ref63.requestId,
4787 debug = _ref63.debug;
4788 return this.$publish('call', { parameters: parameters, hardFail: hardFail, name: name, requestId: requestId, debug: debug });
4789 }
4790 }], [{
4791 key: 'DEFAULT_DEPLOYMENT_ID',
4792
4793 /**
4794 * Get default deployment id associated to Macro service
4795 * @return {string}
4796 */
4797 get: function get$$1() {
4798 return 'macro_0';
4799 }
4800 }]);
4801 return Macro;
4802}(Service);
4803/**
4804 * Mail sender
4805 *
4806 * Sends email through SMTP
4807 * */
4808/**
4809 * Mail service user API
4810 *
4811 * This service is statically configured with an outgoing SMTP server.
4812 * Users call the API here to actually send emails.
4813 * @access public
4814 * */
4815var Sendmail = function (_Service12) {
4816 inherits(Sendmail, _Service12);
4817
4818 function Sendmail() {
4819 classCallCheck(this, Sendmail);
4820 return possibleConstructorReturn(this, (Sendmail.__proto__ || Object.getPrototypeOf(Sendmail)).apply(this, arguments));
4821 }
4822
4823 createClass(Sendmail, null, [{
4824 key: 'DEFAULT_DEPLOYMENT_ID',
4825
4826 /**
4827 * Get default deployment id associated to Sendmail service
4828 * @return {string}
4829 */
4830 get: function get$$1() {
4831 return 'sendmail_0';
4832 }
4833 }]);
4834 return Sendmail;
4835}(Service);
4836/**
4837 * Messaging service
4838 *
4839 * Messaging service
4840 * */
4841/**
4842 * Messaging service
4843 *
4844 * Simple and flexible user-to-user or user-to-group messaging service.
4845 * @access public
4846 * */
4847var Messaging = function (_Service13) {
4848 inherits(Messaging, _Service13);
4849
4850 function Messaging() {
4851 classCallCheck(this, Messaging);
4852 return possibleConstructorReturn(this, (Messaging.__proto__ || Object.getPrototypeOf(Messaging)).apply(this, arguments));
4853 }
4854
4855 createClass(Messaging, [{
4856 key: 'send',
4857
4858 /**
4859 * Sends a message to a target
4860 *
4861 * Sends the given message to the specified target on the given (optional) channel.
4862 * The administratively given default channel name is used when none is provided in the message itself.
4863 * */
4864 value: function send(_ref64) {
4865 var target = _ref64.target,
4866 channel = _ref64.channel,
4867 data = _ref64.data;
4868 return this.$publish('send', { target: target, channel: channel, data: data });
4869 }
4870 }], [{
4871 key: 'DEFAULT_DEPLOYMENT_ID',
4872
4873 /**
4874 * Get default deployment id associated to Messaging service
4875 * @return {string}
4876 */
4877 get: function get$$1() {
4878 return 'messaging_0';
4879 }
4880 }]);
4881 return Messaging;
4882}(Service);
4883/**
4884 * Producer consumer
4885 *
4886 * Producer consumer service
4887 * Users can submit tasks and other users consume them
4888 * */
4889/**
4890 * Producer / consumer real-time API
4891 *
4892 * Task producers submits their tasks.
4893 * The server dispatches the tasks.
4894 * Consumers process them and report completion back to the server.
4895 * Tasks are global to the service (i.e. NOT per user).
4896 * @access public
4897 * */
4898var Queue = function (_Service14) {
4899 inherits(Queue, _Service14);
4900
4901 function Queue() {
4902 classCallCheck(this, Queue);
4903 return possibleConstructorReturn(this, (Queue.__proto__ || Object.getPrototypeOf(Queue)).apply(this, arguments));
4904 }
4905
4906 createClass(Queue, [{
4907 key: 'call',
4908
4909 /**
4910 * Submits a task
4911 *
4912 * Producer API.
4913 * A task producer submits the given task to the server.
4914 * The server will find a tasker with processing capacity and dispatch the task.
4915 * The task result will be returned to the caller.
4916 * When called from inside a macro, the comsumer generated result is available for further use.
4917 * */
4918 value: function call(_ref65) {
4919 var description = _ref65.description,
4920 originBusinessId = _ref65.originBusinessId,
4921 originDeploymentId = _ref65.originDeploymentId,
4922 data = _ref65.data,
4923 owner = _ref65.owner;
4924 return this.$publish('call', { description: description, originBusinessId: originBusinessId, originDeploymentId: originDeploymentId, data: data, owner: owner });
4925 }
4926 /**
4927 * Notifies completion of a task
4928 *
4929 * Consumer API.
4930 * The tasker notifies completion of the given task to the server.
4931 * The tasker can optionally include a result or an error code.
4932 * */
4933
4934 }, {
4935 key: 'done',
4936 value: function done(_ref66) {
4937 var result = _ref66.result,
4938 taskId = _ref66.taskId,
4939 success = _ref66.success;
4940 return this.$publish('done', { result: result, taskId: taskId, success: success });
4941 }
4942 /**
4943 * Registers a consumer
4944 *
4945 * Consumer API.
4946 * Registers the current user resource as an available task consumer.
4947 * Tasks will be then dispatched to that consumer.
4948 * */
4949
4950 }, {
4951 key: 'register',
4952 value: function register(_ref67) {
4953 var capacity = _ref67.capacity;
4954 return this.$publish('register', { capacity: capacity });
4955 }
4956 /**
4957 * Submits a task
4958 *
4959 * Producer API.
4960 * A task producer submits the given task to the server.
4961 * The server will find a tasker with processing capacity and dispatch the task.
4962 * The task result will be ignored : the producer will not receive any notification of any kind, even in case of errors (including capacity exceeded errors).
4963 * This verb will return immediately : you can use this API to asynchronously submit a task.
4964 * */
4965
4966 }, {
4967 key: 'submit',
4968 value: function submit(_ref68) {
4969 var description = _ref68.description,
4970 originBusinessId = _ref68.originBusinessId,
4971 originDeploymentId = _ref68.originDeploymentId,
4972 data = _ref68.data,
4973 owner = _ref68.owner;
4974 return this.$publish('submit', { description: description, originBusinessId: originBusinessId, originDeploymentId: originDeploymentId, data: data, owner: owner });
4975 }
4976 /**
4977 * Unregisters a consumer
4978 *
4979 * Consumer API.
4980 * Unregisters the current user resource as an available task consumer.
4981 * All non finished tasks are returned to the server.
4982 * */
4983
4984 }, {
4985 key: 'unregister',
4986 value: function unregister() {
4987 return this.$publish('unregister', {});
4988 }
4989 }], [{
4990 key: 'DEFAULT_DEPLOYMENT_ID',
4991
4992 /**
4993 * Get default deployment id associated to Queue service
4994 * @return {string}
4995 */
4996 get: function get$$1() {
4997 return 'queue_0';
4998 }
4999 }]);
5000 return Queue;
5001}(Service);
5002/**
5003 * Push Notifications
5004 *
5005 * Native Push Notifications for Android, iOS
5006 *
5007 *
5008 *
5009 * */
5010/**
5011 * Notification User API
5012 *
5013 * User API for notifications.
5014 * For notifications to work properly, it is imperative that the resource name of a device remain constant over time.
5015 * @access public
5016 * */
5017var Notif = function (_Service15) {
5018 inherits(Notif, _Service15);
5019
5020 function Notif() {
5021 classCallCheck(this, Notif);
5022 return possibleConstructorReturn(this, (Notif.__proto__ || Object.getPrototypeOf(Notif)).apply(this, arguments));
5023 }
5024
5025 createClass(Notif, null, [{
5026 key: 'DEFAULT_DEPLOYMENT_ID',
5027
5028 /**
5029 * Get default deployment id associated to Notif service
5030 * @return {string}
5031 */
5032 get: function get$$1() {
5033 return 'notif_0';
5034 }
5035 }]);
5036 return Notif;
5037}(Service);
5038/**
5039 * RDBMS
5040 *
5041 * Relational Database : SQL storage
5042 * */
5043/**
5044 * RDBMS User API
5045 *
5046 * User API for SQL queries.
5047 * Contrary to GDA or Stacks, the data are not stored on a per-user basis.
5048 * Users can store, get, list their data.
5049 * @access public
5050 * */
5051var Rdbms = function (_Service16) {
5052 inherits(Rdbms, _Service16);
5053
5054 function Rdbms() {
5055 classCallCheck(this, Rdbms);
5056 return possibleConstructorReturn(this, (Rdbms.__proto__ || Object.getPrototypeOf(Rdbms)).apply(this, arguments));
5057 }
5058
5059 createClass(Rdbms, null, [{
5060 key: 'DEFAULT_DEPLOYMENT_ID',
5061
5062 /**
5063 * Get default deployment id associated to Rdbms service
5064 * @return {string}
5065 */
5066 get: function get$$1() {
5067 return 'rdbms_0';
5068 }
5069 }]);
5070 return Rdbms;
5071}(Service);
5072/**
5073 * SMS via OVH
5074 *
5075 * SMS sender, to send text messages to mobile phones
5076 * This SMS sending service uses the OVH API
5077 *
5078 * */
5079/**
5080 * SMS service
5081 *
5082 * User API for SMS.
5083 * @access public
5084 * */
5085var Sms_ovh = function (_Service17) {
5086 inherits(Sms_ovh, _Service17);
5087
5088 function Sms_ovh() {
5089 classCallCheck(this, Sms_ovh);
5090 return possibleConstructorReturn(this, (Sms_ovh.__proto__ || Object.getPrototypeOf(Sms_ovh)).apply(this, arguments));
5091 }
5092
5093 createClass(Sms_ovh, null, [{
5094 key: 'DEFAULT_DEPLOYMENT_ID',
5095
5096 /**
5097 * Get default deployment id associated to Sms_ovh service
5098 * @return {string}
5099 */
5100 get: function get$$1() {
5101 return 'sms_ovh_0';
5102 }
5103 }]);
5104 return Sms_ovh;
5105}(Service);
5106/**
5107 * Scheduler
5108 *
5109 * Scheduler service
5110 * End-users can schedule one-time or repetitive tasks using a classical cron syntax (with the year field) or a timestamp (milliseconds from the epoch)
5111 * */
5112/**
5113 * User API for the Scheduler
5114 *
5115 * User endpoints for scheduling : users can schedule, list and delete tasks.
5116 * Tasks are stored on a per-user basis: a task will run with the priviledges of the user who stored it.
5117 * Tasks are run on the server and thus can call api verbs marked as server-only.
5118 * @access public
5119 * */
5120var Cron = function (_Service18) {
5121 inherits(Cron, _Service18);
5122
5123 function Cron() {
5124 classCallCheck(this, Cron);
5125 return possibleConstructorReturn(this, (Cron.__proto__ || Object.getPrototypeOf(Cron)).apply(this, arguments));
5126 }
5127
5128 createClass(Cron, [{
5129 key: 'list',
5130
5131 /**
5132 * List the configured tasks
5133 *
5134 * Returns a paginated list of the asking user's tasks.
5135 * */
5136 value: function list(_ref69) {
5137 var start = _ref69.start,
5138 stop = _ref69.stop,
5139 owner = _ref69.owner,
5140 page = _ref69.page;
5141 return this.$publish('list', { start: start, stop: stop, owner: owner, page: page });
5142 }
5143 }], [{
5144 key: 'DEFAULT_DEPLOYMENT_ID',
5145
5146 /**
5147 * Get default deployment id associated to Cron service
5148 * @return {string}
5149 */
5150 get: function get$$1() {
5151 return 'cron_0';
5152 }
5153 }]);
5154 return Cron;
5155}(Service);
5156/**
5157 * Search engine
5158 *
5159 * ElasticSearch engine, to index and search data
5160 * An admin creates indices
5161 * Users index and search documents
5162 *
5163 * */
5164/**
5165 * ElasticSearch Service
5166 *
5167 * This API is a very thin wrapper around ElasticSearch's API.
5168 * @access public
5169 * */
5170
5171var Search = function (_Service19) {
5172 inherits(Search, _Service19);
5173
5174 function Search() {
5175 classCallCheck(this, Search);
5176 return possibleConstructorReturn(this, (Search.__proto__ || Object.getPrototypeOf(Search)).apply(this, arguments));
5177 }
5178
5179 createClass(Search, [{
5180 key: 'delete',
5181
5182 /**
5183 * Deletes data
5184 *
5185 * Deletes a document from the elasticsearch engine by id.
5186 * */
5187 value: function _delete(_ref70) {
5188 var type = _ref70.type,
5189 id = _ref70.id,
5190 index = _ref70.index;
5191 return this.$publish('delete', { type: type, id: id, index: index });
5192 }
5193 /**
5194 * Gets data
5195 *
5196 * Retrieves a document from the elasticsearch engine by id.
5197 * */
5198
5199 }, {
5200 key: 'get',
5201 value: function get$$1(_ref71) {
5202 var type = _ref71.type,
5203 id = _ref71.id,
5204 index = _ref71.index;
5205 return this.$publish('get', { type: type, id: id, index: index });
5206 }
5207 /**
5208 * Indexes data
5209 *
5210 * Inserts or updates a document into the elasticsearch engine.
5211 * */
5212
5213 }, {
5214 key: 'index',
5215 value: function index(_ref72) {
5216 var type = _ref72.type,
5217 id = _ref72.id,
5218 _index = _ref72.index,
5219 data = _ref72.data;
5220 return this.$publish('index', { type: type, id: id, index: _index, data: data });
5221 }
5222 /**Searches for data*/
5223
5224 }, {
5225 key: 'search',
5226 value: function search(_ref73) {
5227 var indices = _ref73.indices,
5228 query = _ref73.query,
5229 sort = _ref73.sort,
5230 page = _ref73.page,
5231 types = _ref73.types;
5232 return this.$publish('search', { indices: indices, query: query, sort: sort, page: page, types: types });
5233 }
5234 }], [{
5235 key: 'DEFAULT_DEPLOYMENT_ID',
5236
5237 /**
5238 * Get default deployment id associated to Search service
5239 * @return {string}
5240 */
5241 get: function get$$1() {
5242 return 'search_0';
5243 }
5244 }]);
5245 return Search;
5246}(Service);
5247var Template = function (_Service20) {
5248 inherits(Template, _Service20);
5249
5250 function Template() {
5251 classCallCheck(this, Template);
5252 return possibleConstructorReturn(this, (Template.__proto__ || Object.getPrototypeOf(Template)).apply(this, arguments));
5253 }
5254
5255 createClass(Template, [{
5256 key: 'evaluate',
5257
5258 /**
5259 * Evaluates a template
5260 *
5261 * Evaluates the given template and returns the result as a string.
5262 * Templates are parsed the first time they are evaluated. Evaluation may fail early due to a parsing error.
5263 * */
5264 value: function evaluate(_ref74) {
5265 var languageTag = _ref74.languageTag,
5266 name = _ref74.name,
5267 requestId = _ref74.requestId,
5268 data = _ref74.data;
5269 return this.$publish('evaluate', { languageTag: languageTag, name: name, requestId: requestId, data: data });
5270 }
5271 }], [{
5272 key: 'DEFAULT_DEPLOYMENT_ID',
5273
5274 /**
5275 * Get default deployment id associated to Template service
5276 * @return {string}
5277 */
5278 get: function get$$1() {
5279 return 'template_0';
5280 }
5281 }]);
5282 return Template;
5283}(Service);
5284/**
5285 * Triggers
5286 *
5287 * Register callbacks for events and trigger them when needed
5288 *
5289 * */
5290/**
5291 * Trigger service
5292 *
5293 * Register listeners and trigger events.
5294 * @access public
5295 * */
5296var Trigger = function (_Service21) {
5297 inherits(Trigger, _Service21);
5298
5299 function Trigger() {
5300 classCallCheck(this, Trigger);
5301 return possibleConstructorReturn(this, (Trigger.__proto__ || Object.getPrototypeOf(Trigger)).apply(this, arguments));
5302 }
5303
5304 createClass(Trigger, null, [{
5305 key: 'DEFAULT_DEPLOYMENT_ID',
5306
5307 /**
5308 * Get default deployment id associated to Trigger service
5309 * @return {string}
5310 */
5311 get: function get$$1() {
5312 return 'trigger_0';
5313 }
5314 }]);
5315 return Trigger;
5316}(Service);
5317/**
5318 * Upload: S3
5319 *
5320 * Upload service with S3 storage
5321 * */
5322/**
5323 * User API for file management
5324 *
5325 * User API for virtual file management and http file upload
5326 * This API contains all the verbs needed to browse, upload and remove files.
5327 * Files are stored on a per-user basis: each user has his or her own whole virtual filesystem.
5328 * Uploading a file is a 3-step process : request an upload URL, upload via HTTP, notify this service of completion.
5329 * @access public
5330 * */
5331var Zpfs_s3 = function (_Service22) {
5332 inherits(Zpfs_s3, _Service22);
5333
5334 function Zpfs_s3() {
5335 classCallCheck(this, Zpfs_s3);
5336 return possibleConstructorReturn(this, (Zpfs_s3.__proto__ || Object.getPrototypeOf(Zpfs_s3)).apply(this, arguments));
5337 }
5338
5339 createClass(Zpfs_s3, [{
5340 key: 'cp',
5341
5342 /**
5343 * Copies a file
5344 *
5345 * Copies a file or folder (recursively) to a new location.
5346 * May fail if the target location is not empty.
5347 * */
5348 value: function cp(_ref75) {
5349 var oldPath = _ref75.oldPath,
5350 path = _ref75.path,
5351 owner = _ref75.owner;
5352 return this.$publish('cp', { oldPath: oldPath, path: path, owner: owner });
5353 }
5354 /**
5355 * Returns disk usage
5356 *
5357 * Returns an recursively aggregated number of used bytes, starting at the given path.
5358 * */
5359
5360 }, {
5361 key: 'du',
5362 value: function du(_ref76) {
5363 var path = _ref76.path,
5364 owner = _ref76.owner;
5365 return this.$publish('du', { path: path, owner: owner });
5366 }
5367 /**
5368 * Links a file
5369 *
5370 * Links a file or folder to another location.
5371 * May fail if the target location is not empty.
5372 * */
5373
5374 }, {
5375 key: 'link',
5376 value: function link(_ref77) {
5377 var oldPath = _ref77.oldPath,
5378 path = _ref77.path,
5379 owner = _ref77.owner;
5380 return this.$publish('link', { oldPath: oldPath, path: path, owner: owner });
5381 }
5382 /**
5383 * Lists a folder content
5384 *
5385 * Returns a paginated list of the folder's content.
5386 * */
5387
5388 }, {
5389 key: 'ls',
5390 value: function ls(_ref78) {
5391 var folder = _ref78.folder,
5392 owner = _ref78.owner,
5393 page = _ref78.page;
5394 return this.$publish('ls', { folder: folder, owner: owner, page: page });
5395 }
5396 /**
5397 * Creates a folder
5398 *
5399 * Creates a new folder.
5400 * May fail if the target location is not empty.
5401 * */
5402
5403 }, {
5404 key: 'mkdir',
5405 value: function mkdir(_ref79) {
5406 var parents = _ref79.parents,
5407 folder = _ref79.folder,
5408 owner = _ref79.owner;
5409 return this.$publish('mkdir', { parents: parents, folder: folder, owner: owner });
5410 }
5411 /**
5412 * Moves a file
5413 *
5414 * Moves a file or folder (recursively) to a new location.
5415 * May fail if the target location is not empty.
5416 * */
5417
5418 }, {
5419 key: 'mv',
5420 value: function mv(_ref80) {
5421 var oldPath = _ref80.oldPath,
5422 path = _ref80.path,
5423 owner = _ref80.owner;
5424 return this.$publish('mv', { oldPath: oldPath, path: path, owner: owner });
5425 }
5426 /**
5427 * Notifies of upload completion
5428 *
5429 * The client application calls this verb to notify that it's done uploading to the cloud.
5430 * Calling that verb MAY trigger additional events such as thumbnail/metadata creation.
5431 * */
5432
5433 }, {
5434 key: 'newFile',
5435 value: function newFile(_ref81) {
5436 var tags = _ref81.tags,
5437 guid = _ref81.guid,
5438 metadata = _ref81.metadata,
5439 owner = _ref81.owner;
5440 return this.$publish('newFile', { tags: tags, guid: guid, metadata: metadata, owner: owner });
5441 }
5442 /**
5443 * Requests an upload URL
5444 *
5445 * Requests an HTTP upload URL.
5446 * The URL contains temporary credentials (typically valid for a few minutes) and is meant for immediate use.
5447 * */
5448
5449 }, {
5450 key: 'newUploadUrl',
5451 value: function newUploadUrl(_ref82) {
5452 var contentType = _ref82.contentType,
5453 path = _ref82.path,
5454 owner = _ref82.owner;
5455 return this.$publish('newUploadUrl', { contentType: contentType, path: path, owner: owner });
5456 }
5457 /**
5458 * Removes a file
5459 *
5460 * Removes a file or folder (recursively).
5461 * */
5462
5463 }, {
5464 key: 'rm',
5465 value: function rm(_ref83) {
5466 var path = _ref83.path,
5467 owner = _ref83.owner;
5468 return this.$publish('rm', { path: path, owner: owner });
5469 }
5470 /**
5471 * Creates a snapshot in a new folder
5472 *
5473 * Creates a new folder and then copies the given files inside
5474 * */
5475
5476 }, {
5477 key: 'snapshot',
5478 value: function snapshot(_ref84) {
5479 var parents = _ref84.parents,
5480 folder = _ref84.folder,
5481 items = _ref84.items,
5482 flatten = _ref84.flatten,
5483 owner = _ref84.owner;
5484 return this.$publish('snapshot', { parents: parents, folder: folder, items: items, flatten: flatten, owner: owner });
5485 }
5486 /**
5487 * Returns information about a file
5488 *
5489 * Returns information about a single file.
5490 * The entry field will be null if the path does not exist
5491 * */
5492
5493 }, {
5494 key: 'stat',
5495 value: function stat(_ref85) {
5496 var path = _ref85.path,
5497 owner = _ref85.owner;
5498 return this.$publish('stat', { path: path, owner: owner });
5499 }
5500 /**Updates a file's metadata*/
5501
5502 }, {
5503 key: 'updateMeta',
5504 value: function updateMeta(_ref86) {
5505 var path = _ref86.path,
5506 metadataFiles = _ref86.metadataFiles,
5507 metadata = _ref86.metadata,
5508 owner = _ref86.owner;
5509 return this.$publish('updateMeta', { path: path, metadataFiles: metadataFiles, metadata: metadata, owner: owner });
5510 }
5511 }], [{
5512 key: 'DEFAULT_DEPLOYMENT_ID',
5513
5514 /**
5515 * Get default deployment id associated to Zpfs_s3 service
5516 * @return {string}
5517 */
5518 get: function get$$1() {
5519 return 'zpfs_s3_0';
5520 }
5521 }]);
5522 return Zpfs_s3;
5523}(Service);
5524/**
5525 * Upload: local
5526 *
5527 * Upload service with local HDFS storage
5528 * */
5529/**
5530 * User API for local file management
5531 *
5532 * User API for file content manipulation
5533 * @access public
5534 * */
5535var Zpfs_hdfs = function (_Service23) {
5536 inherits(Zpfs_hdfs, _Service23);
5537
5538 function Zpfs_hdfs() {
5539 classCallCheck(this, Zpfs_hdfs);
5540 return possibleConstructorReturn(this, (Zpfs_hdfs.__proto__ || Object.getPrototypeOf(Zpfs_hdfs)).apply(this, arguments));
5541 }
5542
5543 createClass(Zpfs_hdfs, [{
5544 key: 'cp',
5545
5546 /**
5547 * Copies a file
5548 *
5549 * Copies a file or folder (recursively) to a new location.
5550 * May fail if the target location is not empty.
5551 * */
5552 value: function cp(_ref87) {
5553 var oldPath = _ref87.oldPath,
5554 path = _ref87.path,
5555 owner = _ref87.owner;
5556 return this.$publish('cp', { oldPath: oldPath, path: path, owner: owner });
5557 }
5558 /**
5559 * Returns disk usage
5560 *
5561 * Returns an recursively aggregated number of used bytes, starting at the given path.
5562 * */
5563
5564 }, {
5565 key: 'du',
5566 value: function du(_ref88) {
5567 var path = _ref88.path,
5568 owner = _ref88.owner;
5569 return this.$publish('du', { path: path, owner: owner });
5570 }
5571 /**
5572 * Links a file
5573 *
5574 * Links a file or folder to another location.
5575 * May fail if the target location is not empty.
5576 * */
5577
5578 }, {
5579 key: 'link',
5580 value: function link(_ref89) {
5581 var oldPath = _ref89.oldPath,
5582 path = _ref89.path,
5583 owner = _ref89.owner;
5584 return this.$publish('link', { oldPath: oldPath, path: path, owner: owner });
5585 }
5586 /**
5587 * Lists a folder content
5588 *
5589 * Returns a paginated list of the folder's content.
5590 * */
5591
5592 }, {
5593 key: 'ls',
5594 value: function ls(_ref90) {
5595 var folder = _ref90.folder,
5596 owner = _ref90.owner,
5597 page = _ref90.page;
5598 return this.$publish('ls', { folder: folder, owner: owner, page: page });
5599 }
5600 /**
5601 * Creates a folder
5602 *
5603 * Creates a new folder.
5604 * May fail if the target location is not empty.
5605 * */
5606
5607 }, {
5608 key: 'mkdir',
5609 value: function mkdir(_ref91) {
5610 var parents = _ref91.parents,
5611 folder = _ref91.folder,
5612 owner = _ref91.owner;
5613 return this.$publish('mkdir', { parents: parents, folder: folder, owner: owner });
5614 }
5615 /**
5616 * Moves a file
5617 *
5618 * Moves a file or folder (recursively) to a new location.
5619 * May fail if the target location is not empty.
5620 * */
5621
5622 }, {
5623 key: 'mv',
5624 value: function mv(_ref92) {
5625 var oldPath = _ref92.oldPath,
5626 path = _ref92.path,
5627 owner = _ref92.owner;
5628 return this.$publish('mv', { oldPath: oldPath, path: path, owner: owner });
5629 }
5630 /**
5631 * Notifies of upload completion
5632 *
5633 * The client application calls this verb to notify that it's done uploading to the cloud.
5634 * Calling that verb MAY trigger additional events such as thumbnail/metadata creation.
5635 * */
5636
5637 }, {
5638 key: 'newFile',
5639 value: function newFile(_ref93) {
5640 var tags = _ref93.tags,
5641 guid = _ref93.guid,
5642 metadata = _ref93.metadata,
5643 owner = _ref93.owner;
5644 return this.$publish('newFile', { tags: tags, guid: guid, metadata: metadata, owner: owner });
5645 }
5646 /**
5647 * Requests an upload URL
5648 *
5649 * Requests an HTTP upload URL.
5650 * The URL contains temporary credentials (typically valid for a few minutes) and is meant for immediate use.
5651 * */
5652
5653 }, {
5654 key: 'newUploadUrl',
5655 value: function newUploadUrl(_ref94) {
5656 var contentType = _ref94.contentType,
5657 path = _ref94.path,
5658 owner = _ref94.owner;
5659 return this.$publish('newUploadUrl', { contentType: contentType, path: path, owner: owner });
5660 }
5661 /**
5662 * Removes a file
5663 *
5664 * Removes a file or folder (recursively).
5665 * */
5666
5667 }, {
5668 key: 'rm',
5669 value: function rm(_ref95) {
5670 var path = _ref95.path,
5671 owner = _ref95.owner;
5672 return this.$publish('rm', { path: path, owner: owner });
5673 }
5674 /**
5675 * Creates a snapshot in a new folder
5676 *
5677 * Creates a new folder and then copies the given files inside
5678 * */
5679
5680 }, {
5681 key: 'snapshot',
5682 value: function snapshot(_ref96) {
5683 var parents = _ref96.parents,
5684 folder = _ref96.folder,
5685 items = _ref96.items,
5686 flatten = _ref96.flatten,
5687 owner = _ref96.owner;
5688 return this.$publish('snapshot', { parents: parents, folder: folder, items: items, flatten: flatten, owner: owner });
5689 }
5690 /**
5691 * Returns information about a file
5692 *
5693 * Returns information about a single file.
5694 * The entry field will be null if the path does not exist
5695 * */
5696
5697 }, {
5698 key: 'stat',
5699 value: function stat(_ref97) {
5700 var path = _ref97.path,
5701 owner = _ref97.owner;
5702 return this.$publish('stat', { path: path, owner: owner });
5703 }
5704 /**Updates a file's metadata*/
5705
5706 }, {
5707 key: 'updateMeta',
5708 value: function updateMeta(_ref98) {
5709 var path = _ref98.path,
5710 metadataFiles = _ref98.metadataFiles,
5711 metadata = _ref98.metadata,
5712 owner = _ref98.owner;
5713 return this.$publish('updateMeta', { path: path, metadataFiles: metadataFiles, metadata: metadata, owner: owner });
5714 }
5715 }], [{
5716 key: 'DEFAULT_DEPLOYMENT_ID',
5717
5718 /**
5719 * Get default deployment id associated to Zpfs_hdfs service
5720 * @return {string}
5721 */
5722 get: function get$$1() {
5723 return 'zpfs_hdfs_0';
5724 }
5725 }]);
5726 return Zpfs_hdfs;
5727}(Service);
5728/**
5729 * Upload: pseudo-S3
5730 *
5731 * Upload service with pseudo-S3compatible storage
5732 * */
5733/**
5734 * User API for file management
5735 *
5736 * User API for virtual file management and http file upload
5737 * This API contains all the verbs needed to browse, upload and remove files.
5738 * Files are stored on a per-user basis: each user has his or her own whole virtual filesystem.
5739 * Uploading a file is a 3-step process : request an upload URL, upload via HTTP, notify this service of completion.
5740 * @access public
5741 * */
5742var Zpfs_s3compat = function (_Service24) {
5743 inherits(Zpfs_s3compat, _Service24);
5744
5745 function Zpfs_s3compat() {
5746 classCallCheck(this, Zpfs_s3compat);
5747 return possibleConstructorReturn(this, (Zpfs_s3compat.__proto__ || Object.getPrototypeOf(Zpfs_s3compat)).apply(this, arguments));
5748 }
5749
5750 createClass(Zpfs_s3compat, [{
5751 key: 'cp',
5752
5753 /**
5754 * Copies a file
5755 *
5756 * Copies a file or folder (recursively) to a new location.
5757 * May fail if the target location is not empty.
5758 * */
5759 value: function cp(_ref99) {
5760 var oldPath = _ref99.oldPath,
5761 path = _ref99.path,
5762 owner = _ref99.owner;
5763 return this.$publish('cp', { oldPath: oldPath, path: path, owner: owner });
5764 }
5765 /**
5766 * Returns disk usage
5767 *
5768 * Returns an recursively aggregated number of used bytes, starting at the given path.
5769 * */
5770
5771 }, {
5772 key: 'du',
5773 value: function du(_ref100) {
5774 var path = _ref100.path,
5775 owner = _ref100.owner;
5776 return this.$publish('du', { path: path, owner: owner });
5777 }
5778 /**
5779 * Links a file
5780 *
5781 * Links a file or folder to another location.
5782 * May fail if the target location is not empty.
5783 * */
5784
5785 }, {
5786 key: 'link',
5787 value: function link(_ref101) {
5788 var oldPath = _ref101.oldPath,
5789 path = _ref101.path,
5790 owner = _ref101.owner;
5791 return this.$publish('link', { oldPath: oldPath, path: path, owner: owner });
5792 }
5793 /**
5794 * Lists a folder content
5795 *
5796 * Returns a paginated list of the folder's content.
5797 * */
5798
5799 }, {
5800 key: 'ls',
5801 value: function ls(_ref102) {
5802 var folder = _ref102.folder,
5803 owner = _ref102.owner,
5804 page = _ref102.page;
5805 return this.$publish('ls', { folder: folder, owner: owner, page: page });
5806 }
5807 /**
5808 * Creates a folder
5809 *
5810 * Creates a new folder.
5811 * May fail if the target location is not empty.
5812 * */
5813
5814 }, {
5815 key: 'mkdir',
5816 value: function mkdir(_ref103) {
5817 var parents = _ref103.parents,
5818 folder = _ref103.folder,
5819 owner = _ref103.owner;
5820 return this.$publish('mkdir', { parents: parents, folder: folder, owner: owner });
5821 }
5822 /**
5823 * Moves a file
5824 *
5825 * Moves a file or folder (recursively) to a new location.
5826 * May fail if the target location is not empty.
5827 * */
5828
5829 }, {
5830 key: 'mv',
5831 value: function mv(_ref104) {
5832 var oldPath = _ref104.oldPath,
5833 path = _ref104.path,
5834 owner = _ref104.owner;
5835 return this.$publish('mv', { oldPath: oldPath, path: path, owner: owner });
5836 }
5837 /**
5838 * Notifies of upload completion
5839 *
5840 * The client application calls this verb to notify that it's done uploading to the cloud.
5841 * Calling that verb MAY trigger additional events such as thumbnail/metadata creation.
5842 * */
5843
5844 }, {
5845 key: 'newFile',
5846 value: function newFile(_ref105) {
5847 var tags = _ref105.tags,
5848 guid = _ref105.guid,
5849 metadata = _ref105.metadata,
5850 owner = _ref105.owner;
5851 return this.$publish('newFile', { tags: tags, guid: guid, metadata: metadata, owner: owner });
5852 }
5853 /**
5854 * Requests an upload URL
5855 *
5856 * Requests an HTTP upload URL.
5857 * The URL contains temporary credentials (typically valid for a few minutes) and is meant for immediate use.
5858 * */
5859
5860 }, {
5861 key: 'newUploadUrl',
5862 value: function newUploadUrl(_ref106) {
5863 var contentType = _ref106.contentType,
5864 path = _ref106.path,
5865 owner = _ref106.owner;
5866 return this.$publish('newUploadUrl', { contentType: contentType, path: path, owner: owner });
5867 }
5868 /**
5869 * Removes a file
5870 *
5871 * Removes a file or folder (recursively).
5872 * */
5873
5874 }, {
5875 key: 'rm',
5876 value: function rm(_ref107) {
5877 var path = _ref107.path,
5878 owner = _ref107.owner;
5879 return this.$publish('rm', { path: path, owner: owner });
5880 }
5881 /**
5882 * Creates a snapshot in a new folder
5883 *
5884 * Creates a new folder and then copies the given files inside
5885 * */
5886
5887 }, {
5888 key: 'snapshot',
5889 value: function snapshot(_ref108) {
5890 var parents = _ref108.parents,
5891 folder = _ref108.folder,
5892 items = _ref108.items,
5893 flatten = _ref108.flatten,
5894 owner = _ref108.owner;
5895 return this.$publish('snapshot', { parents: parents, folder: folder, items: items, flatten: flatten, owner: owner });
5896 }
5897 /**
5898 * Returns information about a file
5899 *
5900 * Returns information about a single file.
5901 * The entry field will be null if the path does not exist
5902 * */
5903
5904 }, {
5905 key: 'stat',
5906 value: function stat(_ref109) {
5907 var path = _ref109.path,
5908 owner = _ref109.owner;
5909 return this.$publish('stat', { path: path, owner: owner });
5910 }
5911 /**Updates a file's metadata*/
5912
5913 }, {
5914 key: 'updateMeta',
5915 value: function updateMeta(_ref110) {
5916 var path = _ref110.path,
5917 metadataFiles = _ref110.metadataFiles,
5918 metadata = _ref110.metadata,
5919 owner = _ref110.owner;
5920 return this.$publish('updateMeta', { path: path, metadataFiles: metadataFiles, metadata: metadata, owner: owner });
5921 }
5922 }], [{
5923 key: 'DEFAULT_DEPLOYMENT_ID',
5924
5925 /**
5926 * Get default deployment id associated to Zpfs_s3compat service
5927 * @return {string}
5928 */
5929 get: function get$$1() {
5930 return 'zpfs_s3compat_0';
5931 }
5932 }]);
5933 return Zpfs_s3compat;
5934}(Service);
5935/**
5936 * User directory service
5937 *
5938 * User directory service
5939 * */
5940/**
5941 * User API for user information
5942 *
5943 * @access public
5944 * */
5945var Userdir = function (_Service25) {
5946 inherits(Userdir, _Service25);
5947
5948 function Userdir() {
5949 classCallCheck(this, Userdir);
5950 return possibleConstructorReturn(this, (Userdir.__proto__ || Object.getPrototypeOf(Userdir)).apply(this, arguments));
5951 }
5952
5953 createClass(Userdir, [{
5954 key: 'search',
5955
5956 /**Searches for users matching the request*/
5957 value: function search(_ref111) {
5958 var requestId = _ref111.requestId,
5959 query = _ref111.query,
5960 page = _ref111.page;
5961 return this.$publish('search', { requestId: requestId, query: query, page: page });
5962 }
5963 /**Requests public data for the specified users*/
5964
5965 }, {
5966 key: 'userInfo',
5967 value: function userInfo(_ref112) {
5968 var userKeys = _ref112.userKeys;
5969 return this.$publish('userInfo', { userKeys: userKeys });
5970 }
5971 }], [{
5972 key: 'DEFAULT_DEPLOYMENT_ID',
5973
5974 /**
5975 * Get default deployment id associated to Userdir service
5976 * @return {string}
5977 */
5978 get: function get$$1() {
5979 return 'userdir_0';
5980 }
5981 }]);
5982 return Userdir;
5983}(Service);
5984
5985
5986
5987var services = Object.freeze({
5988 Aggreg: Aggreg,
5989 Stack: Stack,
5990 Echo: Echo,
5991 Game: Game,
5992 GameEngine: GameEngine,
5993 Gda: Gda,
5994 Remoting: Remoting,
5995 GroupManagement: GroupManagement,
5996 Httpclient: Httpclient,
5997 MacroDebug: MacroDebug,
5998 Macro: Macro,
5999 Sendmail: Sendmail,
6000 Messaging: Messaging,
6001 Queue: Queue,
6002 Notif: Notif,
6003 Rdbms: Rdbms,
6004 Sms_ovh: Sms_ovh,
6005 Cron: Cron,
6006 Search: Search,
6007 Template: Template,
6008 Trigger: Trigger,
6009 Zpfs_s3: Zpfs_s3,
6010 Zpfs_hdfs: Zpfs_hdfs,
6011 Zpfs_s3compat: Zpfs_s3compat,
6012 Userdir: Userdir
6013});
6014
6015/**
6016 * Match unsecure pattern web
6017 * @type {RegExp}
6018 */
6019var HTTP_PATTERN = /^http:\/\/|^\/\//;
6020
6021/**
6022 * Http protocol
6023 * @type {string}
6024 */
6025var HTTP_PROTOCOL = 'http:';
6026
6027/**
6028 * Https protocol
6029 * @type {string}
6030 */
6031var HTTPS_PROTOCOL = 'https:';
6032
6033/**
6034 * Alpha numeric dictionary
6035 */
6036var DICTIONARY = 'abcdefghijklmnopqrstuvwxyz0123456789';
6037
6038/**
6039 * Default ZetaPush API URL
6040 * @access private
6041 */
6042var API_URL = 'https://api.zpush.io/';
6043
6044/**
6045 * Force ssl based protocol for network echange
6046 * Cross Env (Browser/Node) test
6047 * @access private
6048 * @type boolean
6049 */
6050var FORCE_HTTPS = typeof location === 'undefined' ? false : location.protocol === HTTPS_PROTOCOL;
6051
6052/**
6053 * @access private
6054 * @param {string} apiUrl
6055 * @return {string}
6056 */
6057var normalizeApiUrl = function normalizeApiUrl(apiUrl) {
6058 var last = apiUrl.charAt(apiUrl.length - 1);
6059 var SLASH = '/';
6060 return last === SLASH ? apiUrl : apiUrl + SLASH;
6061};
6062
6063/**
6064 * @access private
6065 * @param {Array<Object>} list
6066 * @return {Object}
6067 */
6068var shuffle = function shuffle(list) {
6069 var index = Math.floor(Math.random() * list.length);
6070 return list[index];
6071};
6072
6073/**
6074 * @access private
6075 * @param {string} url
6076 * @param {boolean} forceHttps
6077 * @return {string}
6078 */
6079var getSecureUrl = function getSecureUrl(url, forceHttps) {
6080 return forceHttps ? url.replace(HTTP_PATTERN, HTTPS_PROTOCOL + '//') : url;
6081};
6082
6083/**
6084 * @access private
6085 * @param {{apiUrl: string, sandboxId: string, forceHttps: boolean, transports: Transports}} parameters
6086 * @return {Promise}
6087 */
6088var getServers = function getServers(_ref) {
6089 var apiUrl = _ref.apiUrl,
6090 sandboxId = _ref.sandboxId,
6091 forceHttps = _ref.forceHttps,
6092 transports = _ref.transports;
6093
6094 var normalizedSecuresApiUrl = normalizeApiUrl(getSecureUrl(apiUrl, forceHttps));
6095 var url = '' + normalizedSecuresApiUrl + sandboxId;
6096 var options = { protocol: forceHttps ? HTTPS_PROTOCOL : HTTP_PROTOCOL };
6097 return transports.fetch(url, options).then(function (response) {
6098 return response.json();
6099 })
6100 // TODO: Replace by a server side implementation when available
6101 .then(function (_ref2) {
6102 var servers = _ref2.servers;
6103 return servers.map(function (server) {
6104 return getSecureUrl(server, forceHttps);
6105 });
6106 });
6107};
6108
6109/**
6110 * @access private
6111 * @param Class Derived
6112 * @param Class Parent
6113 * @return {boolean}
6114 */
6115var isDerivedOf = function isDerivedOf(Derived, Parent) {
6116 var prototype = Object.getPrototypeOf(Derived);
6117 var is = false;
6118 while (!(is || prototype === null)) {
6119 is = prototype === Parent;
6120 prototype = Object.getPrototypeOf(prototype);
6121 }
6122 return is;
6123};
6124
6125/**
6126 * Get random id
6127 * @return {string}
6128 */
6129var uuid = function uuid() {
6130 var entropy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 7;
6131 var dictionary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DICTIONARY;
6132 return Array.from(Array(entropy)).reduce(function (previous) {
6133 var next = dictionary.charAt(Math.floor(Math.random() * dictionary.length));
6134 return '' + previous + next;
6135 }, '');
6136};
6137
6138/**
6139 * CometD Messages enumeration
6140 * @type {Object}
6141 */
6142var Message = {
6143 RECONNECT_HANDSHAKE_VALUE: 'handshake',
6144 RECONNECT_NONE_VALUE: 'none',
6145 RECONNECT_RETRY_VALUE: 'retry'
6146
6147 /**
6148 * Delay to update server url
6149 * @type {integer}
6150 */
6151};var UPDATE_SERVER_URL_DELAY = 250;
6152
6153/**
6154 * Default macro channel
6155 * @type {string}
6156 */
6157var DEFAULT_MACRO_CHANNEL = 'completed';
6158
6159/**
6160 * Provide utilities and abstraction on CometD Transport layer
6161 * @access private
6162 */
6163var ClientHelper = function () {
6164 /**
6165 * Create a new ZetaPush client helper
6166 */
6167 function ClientHelper(_ref) {
6168 var _this = this;
6169
6170 var apiUrl = _ref.apiUrl,
6171 sandboxId = _ref.sandboxId,
6172 _ref$forceHttps = _ref.forceHttps,
6173 forceHttps = _ref$forceHttps === undefined ? false : _ref$forceHttps,
6174 authentication = _ref.authentication,
6175 _ref$resource = _ref.resource,
6176 resource = _ref$resource === undefined ? null : _ref$resource,
6177 _ref$transports = _ref.transports,
6178 transports = _ref$transports === undefined ? Transports : _ref$transports;
6179 classCallCheck(this, ClientHelper);
6180
6181 /**
6182 * @access private
6183 * @type {string}
6184 */
6185 this.sandboxId = sandboxId;
6186 /**
6187 * @access private
6188 * @type {function():AbstractHandshake}
6189 */
6190 this.authentication = authentication;
6191 /**
6192 * @access private
6193 * @type {string}
6194 */
6195 this.resource = resource;
6196 /**
6197 * @access private
6198 * @type {number}
6199 */
6200 this.requestId = 0;
6201 /**
6202 * @access private
6203 * @type {string}
6204 */
6205 this.userId = null;
6206 /**
6207 * @access private
6208 * @type {Object}
6209 */
6210 this.userInfo = null;
6211 /**
6212 * @access private
6213 * @type {string}
6214 */
6215 this.uniqId = uuid();
6216 /**
6217 * @access private
6218 * @type {Promise}
6219 */
6220 this.servers = getServers({ apiUrl: apiUrl, sandboxId: sandboxId, forceHttps: forceHttps, transports: transports }).catch(function (error) {
6221 // Notify error in connection to server step
6222 _this.connectionToServerFail(error);
6223 // Return empty list
6224 return [];
6225 });
6226 /**
6227 * @access private
6228 * @type {Array<Object>}
6229 */
6230 this.connectionListeners = [];
6231 /**
6232 * @access private
6233 * @type {boolean}
6234 */
6235 this.connected = false;
6236 /**
6237 * @access private
6238 * @type {boolean}
6239 */
6240 this.wasConnected = false;
6241 /**
6242 * @access private
6243 * @type {string}
6244 */
6245 this.serverUrl = null;
6246 /**
6247 * @access private
6248 * @type {string}
6249 */
6250 this.sessionId = null;
6251 /**
6252 * @access private
6253 * @type {Array<Object>}
6254 */
6255 this.subscribeQueue = [];
6256 /**
6257 * @access private
6258 * @type {CometD}
6259 */
6260 this.cometd = new CometD();
6261
6262 // Register transports layers
6263 transports.ALL.forEach(function (_ref2) {
6264 var type = _ref2.type,
6265 Transport = _ref2.Transport;
6266
6267 _this.cometd.registerTransport(type, new Transport());
6268 });
6269
6270 // Handle transport exception
6271 this.cometd.onTransportException = function (cometd, transport) {
6272 // Try to find an other available server
6273 // Remove the current one from the _serverList array
6274 _this.updateServerUrl();
6275 };
6276
6277 this.cometd.addListener('/meta/handshake', function (_ref3) {
6278 var ext = _ref3.ext,
6279 successful = _ref3.successful,
6280 advice = _ref3.advice,
6281 error = _ref3.error;
6282
6283 _this.cometd._debug('ClientHelper::/meta/handshake', { ext: ext, successful: successful, advice: advice, error: error });
6284 if (successful) {
6285 var _ext$authentication = ext.authentication,
6286 _authentication = _ext$authentication === undefined ? null : _ext$authentication;
6287
6288 _this.initialized(_authentication);
6289 } else {
6290 _this.handshakeFailure(error);
6291 }
6292 });
6293
6294 this.cometd.addListener('/meta/handshake', function (_ref4) {
6295 var advice = _ref4.advice,
6296 error = _ref4.error,
6297 ext = _ref4.ext,
6298 successful = _ref4.successful;
6299
6300 _this.cometd._debug('ClientHelper::/meta/handshake', { ext: ext, successful: successful, advice: advice, error: error });
6301 // AuthNegotiation
6302 if (!successful) {
6303 if (typeof advice === 'undefined') {
6304 return;
6305 }
6306 if (Message.RECONNECT_NONE_VALUE === advice.reconnect) {
6307 _this.authenticationFailed(error);
6308 } else if (Message.RECONNECT_HANDSHAKE_VALUE === advice.reconnect) {
6309 _this.negotiationFailed(error);
6310 }
6311 }
6312 });
6313
6314 this.cometd.addListener('/meta/connect', function (_ref5) {
6315 var advice = _ref5.advice,
6316 channel = _ref5.channel,
6317 successful = _ref5.successful;
6318
6319 _this.cometd._debug('ClientHelper::/meta/connect', { advice: advice, channel: channel, successful: successful });
6320 // ConnectionListener
6321 if (_this.cometd.isDisconnected()) {
6322 _this.connected = false;
6323 // Notify connection will close
6324 _this.connectionWillClose();
6325 } else {
6326 _this.wasConnected = _this.connected;
6327 _this.connected = successful;
6328 if (!_this.wasConnected && _this.connected) {
6329 _this.cometd.batch(_this, function () {
6330 // Unqueue subscriptions
6331 _this.subscribeQueue.forEach(function (_ref6) {
6332 var prefix = _ref6.prefix,
6333 listener = _ref6.listener,
6334 subscriptions = _ref6.subscriptions;
6335
6336 _this.subscribe(prefix, listener, subscriptions);
6337 });
6338 });
6339 // Notify connection is established
6340 _this.connectionEstablished();
6341 } else if (_this.wasConnected && !_this.connected) {
6342 // Notify connection is broken
6343 _this.connectionBroken();
6344 }
6345 }
6346 });
6347
6348 this.cometd.addListener('/meta/disconnect', function (_ref7) {
6349 var channel = _ref7.channel,
6350 successful = _ref7.successful;
6351
6352 _this.cometd._debug('ClientHelper::/meta/disconnect', { channel: channel, successful: successful });
6353 if (_this.cometd.isDisconnected()) {
6354 _this.connected = false;
6355 // Notify connection is closed
6356 _this.connectionClosed();
6357 }
6358 });
6359 }
6360 /**
6361 * Add a connection listener to handle life cycle connection events
6362 * @param {ConnectionStatusListener} listener
6363 * @return {number} handler
6364 */
6365
6366
6367 createClass(ClientHelper, [{
6368 key: 'addConnectionStatusListener',
6369 value: function addConnectionStatusListener(listener) {
6370 this.connectionListeners.push({
6371 enabled: true,
6372 listener: Object.assign(new ConnectionStatusListener(), listener)
6373 });
6374 return this.connectionListeners.length - 1;
6375 }
6376 /**
6377 * Notify listeners when handshake step succeed
6378 */
6379
6380 }, {
6381 key: 'authenticationFailed',
6382 value: function authenticationFailed(error) {
6383 this.userId = null;
6384 this.userInfo = null;
6385 this.connectionListeners.filter(function (_ref8) {
6386 var enabled = _ref8.enabled;
6387 return enabled;
6388 }).forEach(function (_ref9) {
6389 var listener = _ref9.listener;
6390
6391 listener.onFailedHandshake(error);
6392 });
6393 }
6394 /**
6395 * Connect client using CometD Transport
6396 */
6397
6398 }, {
6399 key: 'connect',
6400 value: function connect() {
6401 var _this2 = this;
6402
6403 this.servers.then(function (servers) {
6404 if (servers.length > 0) {
6405 // Get a random server url
6406 _this2.serverUrl = shuffle(servers);
6407 // Configure CometD
6408 _this2.cometd.configure({
6409 url: _this2.serverUrl + '/strd',
6410 backoffIncrement: 1000,
6411 maxBackoff: 60000,
6412 appendMessageTypeToURL: false
6413 });
6414 // Send handshake fields
6415 _this2.cometd.handshake(_this2.getHandshakeFields());
6416 } else {
6417 // No servers available
6418 _this2.noServerUrlAvailable();
6419 }
6420 });
6421 }
6422 /**
6423 * Notify listeners when connection is broken
6424 */
6425
6426 }, {
6427 key: 'connectionBroken',
6428 value: function connectionBroken() {
6429 this.connectionListeners.filter(function (_ref10) {
6430 var enabled = _ref10.enabled;
6431 return enabled;
6432 }).forEach(function (_ref11) {
6433 var listener = _ref11.listener;
6434
6435 listener.onConnectionBroken();
6436 });
6437 }
6438 /**
6439 * Notify listeners when connection is closed
6440 */
6441
6442 }, {
6443 key: 'connectionClosed',
6444 value: function connectionClosed() {
6445 this.userId = null;
6446 this.userInfo = null;
6447 this.connectionListeners.filter(function (_ref12) {
6448 var enabled = _ref12.enabled;
6449 return enabled;
6450 }).forEach(function (_ref13) {
6451 var listener = _ref13.listener;
6452
6453 listener.onConnectionClosed();
6454 });
6455 }
6456 /**
6457 * Notify listeners when connection is established
6458 */
6459
6460 }, {
6461 key: 'connectionEstablished',
6462 value: function connectionEstablished() {
6463 this.connectionListeners.filter(function (_ref14) {
6464 var enabled = _ref14.enabled;
6465 return enabled;
6466 }).forEach(function (_ref15) {
6467 var listener = _ref15.listener;
6468
6469 listener.onConnectionEstablished();
6470 });
6471 }
6472 /**
6473 * Notify listeners when connection to server fail
6474 */
6475
6476 }, {
6477 key: 'connectionToServerFail',
6478 value: function connectionToServerFail(failure) {
6479 this.connectionListeners.filter(function (_ref16) {
6480 var enabled = _ref16.enabled;
6481 return enabled;
6482 }).forEach(function (_ref17) {
6483 var listener = _ref17.listener;
6484
6485 listener.onConnectionToServerFail(failure);
6486 });
6487 }
6488 /**
6489 * Notify listeners when connection will close
6490 */
6491
6492 }, {
6493 key: 'connectionWillClose',
6494 value: function connectionWillClose() {
6495 this.connectionListeners.filter(function (_ref18) {
6496 var enabled = _ref18.enabled;
6497 return enabled;
6498 }).forEach(function (_ref19) {
6499 var listener = _ref19.listener;
6500
6501 listener.onConnectionWillClose();
6502 });
6503 }
6504 /**
6505 * Create a promise based macro service
6506 * @experimental
6507 * @param {{listener: Object, Type: class, deploymentId: string}} parameters
6508 * @return {Object} service
6509 */
6510
6511 }, {
6512 key: 'createAsyncMacroService',
6513 value: function createAsyncMacroService(_ref20) {
6514 var listener = _ref20.listener,
6515 Type = _ref20.Type,
6516 _ref20$deploymentId = _ref20.deploymentId,
6517 deploymentId = _ref20$deploymentId === undefined ? Type.DEFAULT_DEPLOYMENT_ID : _ref20$deploymentId;
6518
6519 var prefix = '/service/' + this.getSandboxId() + '/' + deploymentId;
6520 var $publish = this.getAsyncMacroPublisher(prefix);
6521 // Create service by publisher
6522 return this.createServiceByPublisher({ listener: listener, prefix: prefix, Type: Type, $publish: $publish });
6523 }
6524 /**
6525 * Create a publish/subscribe service
6526 * @param {{listener: Object, Type: class, deploymentId: string}} parameters
6527 * @return {Object} service
6528 */
6529
6530 }, {
6531 key: 'createService',
6532 value: function createService(_ref21) {
6533 var listener = _ref21.listener,
6534 Type = _ref21.Type,
6535 _ref21$deploymentId = _ref21.deploymentId,
6536 deploymentId = _ref21$deploymentId === undefined ? Type.DEFAULT_DEPLOYMENT_ID : _ref21$deploymentId;
6537
6538 var isMacroType = isDerivedOf(Type, Macro);
6539 var prefix = '/service/' + this.getSandboxId() + '/' + deploymentId;
6540 var $publish = isMacroType ? this.getMacroPublisher(prefix) : this.getServicePublisher(prefix);
6541 // Create service by publisher
6542 return this.createServiceByPublisher({ listener: listener, prefix: prefix, Type: Type, $publish: $publish });
6543 }
6544 /**
6545 * @param {{listener: Object, prefix: string, Type: class, $publish: Function}} parameters
6546 * @return {Object} service
6547 */
6548
6549 }, {
6550 key: 'createServiceByPublisher',
6551 value: function createServiceByPublisher(_ref22) {
6552 var listener = _ref22.listener,
6553 prefix = _ref22.prefix,
6554 Type = _ref22.Type,
6555 $publish = _ref22.$publish;
6556
6557 var service = new Type({ $publish: $publish });
6558 // Store subscription in service instance
6559 service.$subscriptions = this.subscribe(prefix, listener);
6560 return service;
6561 }
6562 /**
6563 * Disconnect CometD client
6564 */
6565
6566 }, {
6567 key: 'disconnect',
6568 value: function disconnect() {
6569 this.cometd.disconnect(true);
6570 }
6571 /**
6572 * Get a publisher for a macro service that return a promise
6573 * @experimental
6574 * @param {string} prefix - Channel prefix
6575 * @return {Function} publisher
6576 */
6577
6578 }, {
6579 key: 'getAsyncMacroPublisher',
6580 value: function getAsyncMacroPublisher(prefix) {
6581 var _this3 = this;
6582
6583 return function (name, parameters) {
6584 var hardFail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6585 var debug = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
6586
6587 var channel = prefix + '/call';
6588 var uniqRequestId = _this3.getUniqRequestId();
6589 var subscriptions = {};
6590 return new Promise(function (resolve, reject) {
6591 var _listener;
6592
6593 var handler = function handler(_ref23) {
6594 var _ref23$data = _ref23.data,
6595 data = _ref23$data === undefined ? {} : _ref23$data;
6596 var _data$result = data.result,
6597 result = _data$result === undefined ? {} : _data$result,
6598 _data$errors = data.errors,
6599 errors = _data$errors === undefined ? [] : _data$errors,
6600 requestId = data.requestId;
6601
6602 if (requestId === uniqRequestId) {
6603 // Handle errors
6604 if (errors.length > 0) {
6605 reject(errors);
6606 } else {
6607 resolve(result);
6608 }
6609 _this3.unsubscribe(subscriptions);
6610 }
6611 };
6612 // Create dynamic listener method
6613 var listener = (_listener = {}, defineProperty(_listener, name, handler), defineProperty(_listener, DEFAULT_MACRO_CHANNEL, handler), _listener);
6614 // Ad-Hoc subscription
6615 _this3.subscribe(prefix, listener, subscriptions);
6616 // Publish message on channel
6617 _this3.publish(channel, {
6618 debug: debug,
6619 hardFail: hardFail,
6620 name: name,
6621 parameters: parameters,
6622 requestId: uniqRequestId
6623 });
6624 });
6625 };
6626 }
6627 /**
6628 * Get client id
6629 * @return {string} clientId
6630 */
6631
6632 }, {
6633 key: 'getClientId',
6634 value: function getClientId() {
6635 return this.cometd.getClientId();
6636 }
6637 /**
6638 * Get CometD handshake parameters
6639 * @return {Object}
6640 */
6641
6642 }, {
6643 key: 'getHandshakeFields',
6644 value: function getHandshakeFields() {
6645 var handshake = this.authentication();
6646 return handshake.getHandshakeFields(this);
6647 }
6648 /**
6649 * Get a publisher for a macro service
6650 * @param {string} prefix - Channel prefix
6651 * @return {Function} publisher
6652 */
6653
6654 }, {
6655 key: 'getMacroPublisher',
6656 value: function getMacroPublisher(prefix) {
6657 var _this4 = this;
6658
6659 return function (name, parameters) {
6660 var hardFail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6661 var debug = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
6662
6663 var channel = prefix + '/call';
6664 var requestId = _this4.getUniqRequestId();
6665 return _this4.publish(channel, {
6666 debug: debug,
6667 hardFail: hardFail,
6668 name: name,
6669 parameters: parameters,
6670 requestId: requestId
6671 });
6672 };
6673 }
6674 /**
6675 * Get queued subscription index
6676 * @return {Object} index
6677 */
6678
6679 }, {
6680 key: 'getQueuedSubscription',
6681 value: function getQueuedSubscription() {
6682 var subscriptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6683
6684 var index = this.subscribeQueue.findIndex(function (element) {
6685 return subscriptions === element.subscriptions;
6686 });
6687 return {
6688 index: index,
6689 queued: index > -1
6690 };
6691 }
6692 /**
6693 * Get resource
6694 * @return {string}
6695 */
6696
6697 }, {
6698 key: 'getResource',
6699 value: function getResource() {
6700 return this.resource;
6701 }
6702 /**
6703 * Get sandbox id
6704 * @return {string}
6705 */
6706
6707 }, {
6708 key: 'getSandboxId',
6709 value: function getSandboxId() {
6710 return this.sandboxId;
6711 }
6712 /**
6713 * Get server urls list
6714 * @return {Promise} servers
6715 */
6716
6717 }, {
6718 key: 'getServers',
6719 value: function getServers$$1() {
6720 return this.servers;
6721 }
6722 /**
6723 * Get a publisher for a service
6724 * @param {string} prefix - Channel prefix
6725 * @return {Function} publisher
6726 */
6727
6728 }, {
6729 key: 'getServicePublisher',
6730 value: function getServicePublisher(prefix) {
6731 var _this5 = this;
6732
6733 return function (method, parameters) {
6734 var channel = prefix + '/' + method;
6735 return _this5.publish(channel, parameters);
6736 };
6737 }
6738 /**
6739 * Get uniq request id
6740 * @return {string}
6741 */
6742
6743 }, {
6744 key: 'getUniqRequestId',
6745 value: function getUniqRequestId() {
6746 return this.getClientId() + ':' + this.uniqId + ':' + ++this.requestId;
6747 }
6748 /**
6749 * Get user id
6750 * @return {string}
6751 */
6752
6753 }, {
6754 key: 'getUserId',
6755 value: function getUserId() {
6756 return this.userId;
6757 }
6758 /**
6759 * Get user info
6760 * @return {Objet}
6761 */
6762
6763 }, {
6764 key: 'getUserInfo',
6765 value: function getUserInfo() {
6766 return this.userInfo;
6767 }
6768 /**
6769 * Manage handshake failure case
6770 */
6771
6772 }, {
6773 key: 'handshakeFailure',
6774 value: function handshakeFailure() {
6775 this.userId = null;
6776 this.userInfo = null;
6777 }
6778 /**
6779 * Notify listeners when connection is established
6780 */
6781
6782 }, {
6783 key: 'initialized',
6784 value: function initialized(authentication) {
6785 if (authentication) {
6786 this.userId = authentication.userId;
6787 this.userInfo = authentication.userInfo;
6788 }
6789 this.connectionListeners.filter(function (_ref24) {
6790 var enabled = _ref24.enabled;
6791 return enabled;
6792 }).forEach(function (_ref25) {
6793 var listener = _ref25.listener;
6794
6795 listener.onSuccessfulHandshake(authentication);
6796 });
6797 }
6798 /**
6799 * Is client connected to ZetaPush
6800 * @return {boolean}
6801 */
6802
6803 }, {
6804 key: 'isConnected',
6805 value: function isConnected() {
6806 return !this.cometd.isDisconnected();
6807 }
6808 /**
6809 * Notify listeners when a message is lost
6810 */
6811
6812 }, {
6813 key: 'messageLost',
6814 value: function messageLost(channel, data) {
6815 this.connectionListeners.filter(function (_ref26) {
6816 var enabled = _ref26.enabled;
6817 return enabled;
6818 }).forEach(function (_ref27) {
6819 var listener = _ref27.listener;
6820
6821 listener.onMessageLost(channel, data);
6822 });
6823 }
6824 /**
6825 * Negociate authentication
6826 * @param {error} error
6827 */
6828
6829 }, {
6830 key: 'negotiationFailed',
6831 value: function negotiationFailed(error) {
6832 this.connectionListeners.filter(function (_ref28) {
6833 var enabled = _ref28.enabled;
6834 return enabled;
6835 }).forEach(function (_ref29) {
6836 var listener = _ref29.listener;
6837
6838 listener.onNegotiationFailed(error);
6839 });
6840 }
6841 /**
6842 * Notify listeners when no server url available
6843 */
6844
6845 }, {
6846 key: 'noServerUrlAvailable',
6847 value: function noServerUrlAvailable() {
6848 this.connectionListeners.filter(function (_ref30) {
6849 var enabled = _ref30.enabled;
6850 return enabled;
6851 }).forEach(function (_ref31) {
6852 var listener = _ref31.listener;
6853
6854 listener.onNoServerUrlAvailable();
6855 });
6856 }
6857 /**
6858 * Wrap CometdD publish method
6859 * @param {String} channel
6860 * @param {Object} parameters
6861 * @return {Object}
6862 */
6863
6864 }, {
6865 key: 'publish',
6866 value: function publish(channel) {
6867 var parameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6868
6869 this.cometd.publish(channel, parameters);
6870 return { channel: channel, parameters: parameters };
6871 }
6872 /**
6873 * Remove a connection status listener
6874 */
6875
6876 }, {
6877 key: 'removeConnectionStatusListener',
6878 value: function removeConnectionStatusListener(handler) {
6879 var listener = this.connectionListeners[handler];
6880 if (listener) {
6881 listener.enabled = false;
6882 }
6883 }
6884 /**
6885 * Set a new authentication methods
6886 * @param {function():AbstractHandshake} authentication
6887 */
6888
6889 }, {
6890 key: 'setAuthentication',
6891 value: function setAuthentication(authentication) {
6892 this.authentication = authentication;
6893 }
6894 /**
6895 * Set logging level for CometD client
6896 * Valid values are the strings 'error', 'warn', 'info' and 'debug', from
6897 * less verbose to more verbose.
6898 * @param {string} level
6899 */
6900
6901 }, {
6902 key: 'setLogLevel',
6903 value: function setLogLevel(level) {
6904 this.cometd.setLogLevel(level);
6905 }
6906 /**
6907 * Subsribe all methods defined in the listener for the given prefixed channel
6908 * @param {string} prefix - Channel prefix
6909 * @param {Object} listener
6910 * @param {Object} subscriptions
6911 * @return {Object} subscriptions
6912 */
6913
6914 }, {
6915 key: 'subscribe',
6916 value: function subscribe(prefix) {
6917 var listener = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6918 var subscriptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
6919
6920 var _getQueuedSubscriptio = this.getQueuedSubscription(subscriptions),
6921 queued = _getQueuedSubscriptio.queued;
6922
6923 if (!queued) {
6924 // Store arguments to renew subscriptions on connection
6925 this.subscribeQueue.push({ prefix: prefix, listener: listener, subscriptions: subscriptions });
6926 }
6927 // Subscribe if user is connected
6928 if (!this.cometd.isDisconnected()) {
6929 for (var method in listener) {
6930 if (listener.hasOwnProperty(method)) {
6931 var channel = prefix + '/' + method;
6932 subscriptions[method] = this.cometd.subscribe(channel, listener[method]);
6933 }
6934 }
6935 }
6936 return subscriptions;
6937 }
6938 /**
6939 * Remove current server url from the server list and shuffle for another one
6940 */
6941
6942 }, {
6943 key: 'updateServerUrl',
6944 value: function updateServerUrl() {
6945 var _this6 = this;
6946
6947 this.servers.then(function (servers) {
6948 var index = servers.indexOf(_this6.serverUrl);
6949 if (index > -1) {
6950 servers.splice(index, 1);
6951 }
6952 if (servers.length === 0) {
6953 // No more server available
6954 _this6.noServerUrlAvailable();
6955 } else {
6956 _this6.serverUrl = shuffle(servers);
6957 _this6.cometd.configure({
6958 url: _this6.serverUrl + '/strd'
6959 });
6960 setTimeout(function () {
6961 _this6.cometd.handshake(_this6.getHandshakeFields());
6962 }, UPDATE_SERVER_URL_DELAY);
6963 }
6964 });
6965 }
6966 /**
6967 * Remove all subscriptions
6968 * @param {Object} subscriptions
6969 */
6970
6971 }, {
6972 key: 'unsubscribe',
6973 value: function unsubscribe() {
6974 var subscriptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6975
6976 // Unsubscribe
6977 for (var method in subscriptions) {
6978 if (subscriptions.hasOwnProperty(method)) {
6979 var subscription = subscriptions[method];
6980 this.cometd.unsubscribe(subscription);
6981 }
6982 }
6983 // Remove subscription from queue
6984
6985 var _getQueuedSubscriptio2 = this.getQueuedSubscription(subscriptions),
6986 index = _getQueuedSubscriptio2.index,
6987 queued = _getQueuedSubscriptio2.queued;
6988
6989 if (queued) {
6990 this.subscribeQueue.splice(index, 1);
6991 }
6992 }
6993 }]);
6994 return ClientHelper;
6995}();
6996
6997/**
6998 * Client config object.
6999 * @typedef {Object} ClientConfig
7000 * @property {string} apiUrl - Api Url
7001 * @property {string} sandboxId - Sandbox id
7002 * @property {boolean} forceHttps - Force end to end HTTPS connection
7003 * @property {function():AbstractHandshake} authentication - Return authentication properties
7004 * @property {string} resource - Client resource id
7005 * @property {Transports} transports - Client transports implementation
7006 */
7007
7008/**
7009 * ZetaPush Client to connect
7010 * @access public
7011 * @example
7012 * // Securized client with token based connection
7013 * const client = new ZetaPush.Client({
7014 * sandboxId: '<YOUR-SANDBOX-ID>',
7015 * authentication() {
7016 * return ZetaPush.Authentication.weak({
7017 * token: null
7018 * })
7019 * }
7020 * })
7021 * @example
7022 * // Client with authentication based connection
7023 * const client = new ZetaPush.Client({
7024 * sandboxId: '<YOUR-SANDBOX-ID>',
7025 * authentication() {
7026 * return ZetaPush.Authentication.simple({
7027 * login: '<USER-LOGIN>',
7028 * password: '<USER-PASSWORD>'
7029 * })
7030 * }
7031 * })
7032 * @example
7033 * // Explicit deploymentId
7034 * const clientSimple = new ZetaPush.Client({
7035 * sandboxId: '<YOUR-SANDBOX-ID>',
7036 * authentication() {
7037 * return ZetaPush.Authentication.simple({
7038 * deploymentId: '<YOUR-SIMPLE-AUTHENTICATION-DEPLOYMENT-ID>',
7039 * login: '<USER-LOGIN>',
7040 * password: '<USER-PASSWORD>'
7041 * })
7042 * }
7043 * })
7044 * const clientWeak = new ZetaPush.Client({
7045 * sandboxId: '<YOUR-SANDBOX-ID>',
7046 * authentication() {
7047 * return ZetaPush.Authentication.weak({
7048 * deploymentId: '<YOUR-WEAK-AUTHENTICATION-DEPLOYMENT-ID>',
7049 * token: '<SESSION-TOKEN>'
7050 * })
7051 * }
7052 * })
7053 */
7054var Client = function () {
7055 /**
7056 * Create a new ZetaPush Client
7057 * @param {ClientConfig} config
7058 */
7059 function Client(_ref) {
7060 var _ref$apiUrl = _ref.apiUrl,
7061 apiUrl = _ref$apiUrl === undefined ? API_URL : _ref$apiUrl,
7062 sandboxId = _ref.sandboxId,
7063 _ref$forceHttps = _ref.forceHttps,
7064 forceHttps = _ref$forceHttps === undefined ? FORCE_HTTPS : _ref$forceHttps,
7065 authentication = _ref.authentication,
7066 resource = _ref.resource,
7067 transports = _ref.transports;
7068 classCallCheck(this, Client);
7069
7070 /**
7071 * @access private
7072 * @type {ClientHelper}
7073 */
7074 this.helper = new ClientHelper({
7075 apiUrl: apiUrl,
7076 sandboxId: sandboxId,
7077 forceHttps: forceHttps,
7078 authentication: authentication,
7079 resource: resource,
7080 transports: transports
7081 });
7082 }
7083 /**
7084 * Add a connection listener to handle life cycle connection events
7085 * @param {ConnectionStatusListener} listener
7086 * @return {number} handler
7087 */
7088
7089
7090 createClass(Client, [{
7091 key: 'addConnectionStatusListener',
7092 value: function addConnectionStatusListener(listener) {
7093 return this.helper.addConnectionStatusListener(listener);
7094 }
7095 /**
7096 * Safely connect client to ZetaPush
7097 */
7098
7099 }, {
7100 key: 'connect',
7101 value: function connect() {
7102 var _this = this;
7103
7104 if (this.isConnected()) {
7105 var handler = this.addConnectionStatusListener({
7106 onConnectionClosed: function onConnectionClosed() {
7107 _this.removeConnectionStatusListener(handler);
7108 _this.helper.connect();
7109 }
7110 });
7111 this.disconnect();
7112 } else {
7113 this.helper.connect();
7114 }
7115 }
7116 /**
7117 * Create a promise based service instance
7118 * @param {{listener: Object, Type: class, deploymentId: string}} parameters
7119 * @return {Object} service
7120 * @example
7121 * const api = client.createAsyncMacroService({
7122 * Type: WelcomeMacro
7123 * })
7124 * api.welcome({
7125 * message: Hello'
7126 * }).then(({ message }) => {
7127 * console.log(message)
7128 * })
7129 */
7130
7131 }, {
7132 key: 'createAsyncMacroService',
7133 value: function createAsyncMacroService(_ref2) {
7134 var deploymentId = _ref2.deploymentId,
7135 listener = _ref2.listener,
7136 Type = _ref2.Type;
7137
7138 return this.helper.createAsyncMacroService({ deploymentId: deploymentId, listener: listener, Type: Type });
7139 }
7140 /**
7141 * Create a publish/subscribe for a service type
7142 * @param {{listener: Object, Type: class, deploymentId: string}} parameters
7143 * @return {Object} service
7144 * @example
7145 * const service = client.createService({
7146 * listener: {
7147 * list(message) {
7148 * console.log('Stack list callback', message)
7149 * },
7150 * push(message) {
7151 * console.log('Stack push callback', message)
7152 * }
7153 * },
7154 * Type: ZetaPush.services.Stack
7155 * })
7156 * service.list({
7157 * stack: '<STACK-ID>'
7158 * })
7159 * @example
7160 * // Explicit deploymentId
7161 * // Authentication provide optional deployment id, according to the following convention `${ServiceType.toLowerCase()_0}`
7162 * const service = client.createService({
7163 * deploymentId: 'stack_0'
7164 * listener: {
7165 * list(message) {
7166 * console.log('Stack list callback', message)
7167 * },
7168 * push(message) {
7169 * console.log('Stack push callback', message)
7170 * }
7171 * },
7172 * Type: ZetaPush.services.Stack
7173 * })
7174 * service.list({
7175 * stack: '<STACK-ID>'
7176 * })
7177 */
7178
7179 }, {
7180 key: 'createService',
7181 value: function createService(_ref3) {
7182 var deploymentId = _ref3.deploymentId,
7183 listener = _ref3.listener,
7184 Type = _ref3.Type;
7185
7186 return this.helper.createService({ deploymentId: deploymentId, listener: listener, Type: Type });
7187 }
7188 /**
7189 * Disonnect client from ZetaPush
7190 */
7191
7192 }, {
7193 key: 'disconnect',
7194 value: function disconnect() {
7195 if (this.isConnected()) {
7196 this.helper.disconnect();
7197 }
7198 }
7199 /**
7200 * Is client connected to ZetaPush
7201 * @return {boolean}
7202 */
7203
7204 }, {
7205 key: 'isConnected',
7206 value: function isConnected() {
7207 return this.helper.isConnected();
7208 }
7209 /**
7210 * Get the client sandbox id
7211 * @return {string}
7212 */
7213
7214 }, {
7215 key: 'getSandboxId',
7216 value: function getSandboxId() {
7217 return this.helper.getSandboxId();
7218 }
7219 /**
7220 * Get the client resource
7221 * @return {string}
7222 */
7223
7224 }, {
7225 key: 'getResource',
7226 value: function getResource() {
7227 return this.helper.getResource();
7228 }
7229 /**
7230 * Get server urls list
7231 * @return {Promise} servers
7232 */
7233
7234 }, {
7235 key: 'getServers',
7236 value: function getServers$$1() {
7237 return this.helper.getServers();
7238 }
7239 /**
7240 * Get the client user id
7241 * @return {string}
7242 */
7243
7244 }, {
7245 key: 'getUserId',
7246 value: function getUserId() {
7247 return this.helper.getUserId();
7248 }
7249 /*
7250 * Get the client user info
7251 * @return {Object}
7252 * @example
7253 * // Create new ZetaPush Client
7254 * const client = new Client({
7255 * sandboxId: '<YOUR-SANDBOX-ID>',
7256 * authentication: () => Authentication.simple({
7257 * login: '<YOUR-USER-LOGIN>',
7258 * password: '<YOUR-USER-PASSWORD>'
7259 * })
7260 * })
7261 * // Add connection establised listener
7262 * client.onConnectionEstablished(() => {
7263 * console.log('onConnectionEstablished')
7264 * const profile = client.getUserInfo()
7265 * console.log('Your profile', profile)
7266 * })
7267 * client.connect()
7268 */
7269
7270 }, {
7271 key: 'getUserInfo',
7272 value: function getUserInfo() {
7273 return this.helper.getUserInfo();
7274 }
7275 /**
7276 * Remove a connection status listener
7277 * @param {number} handler
7278 */
7279
7280 }, {
7281 key: 'removeConnectionStatusListener',
7282 value: function removeConnectionStatusListener(handler) {
7283 return this.helper.removeConnectionStatusListener(handler);
7284 }
7285 /**
7286 * Set a new authentication methods
7287 * @param {function():AbstractHandshake} authentication
7288 */
7289
7290 }, {
7291 key: 'setAuthentication',
7292 value: function setAuthentication(authentication) {
7293 this.helper.setAuthentication(authentication);
7294 }
7295 /**
7296 * Set logging level
7297 * Valid values are the strings 'error', 'warn', 'info' and 'debug', from
7298 * less verbose to more verbose.
7299 * @param {string} level
7300 */
7301
7302 }, {
7303 key: 'setLogLevel',
7304 value: function setLogLevel(level) {
7305 this.helper.setLogLevel(level);
7306 }
7307 /**
7308 * Set new client resource value
7309 * @param {string} resource
7310 */
7311
7312 }, {
7313 key: 'setResource',
7314 value: function setResource(resource) {
7315 this.helper.setResource(resource);
7316 }
7317 /**
7318 * Remove all subscriptions
7319 * @param {Object} service
7320 */
7321
7322 }, {
7323 key: 'unsubscribe',
7324 value: function unsubscribe(service) {
7325 if (!service.$subscriptions) {
7326 throw new TypeError('Missing $subscriptions property in service');
7327 }
7328 return this.helper.unsubscribe(service.$subscriptions);
7329 }
7330 }]);
7331 return Client;
7332}();
7333
7334/**
7335 * Add shorthand connection status method
7336 */
7337Object.getOwnPropertyNames(ConnectionStatusListener.prototype).forEach(function (method) {
7338 // Only implements unsupported methods
7339 if (!Client.prototype.hasOwnProperty(method)) {
7340 Client.prototype[method] = function addListener(listener) {
7341 return this.addConnectionStatusListener(defineProperty({}, method, listener));
7342 };
7343 }
7344});
7345
7346/**
7347 * Provide fallback for DOMStorage
7348 * @access protected
7349 */
7350var MemoryStorage = function () {
7351 function MemoryStorage() {
7352 classCallCheck(this, MemoryStorage);
7353
7354 this._map = new Map();
7355 }
7356
7357 createClass(MemoryStorage, [{
7358 key: 'getItem',
7359 value: function getItem(key) {
7360 return this._map.get(key);
7361 }
7362 }, {
7363 key: 'setItem',
7364 value: function setItem(key, value) {
7365 return this._map.get(key);
7366 }
7367 }, {
7368 key: 'removeItem',
7369 value: function removeItem(key) {
7370 this._map.delete(key);
7371 }
7372 }, {
7373 key: 'clear',
7374 value: function clear() {
7375 this._map = new Map();
7376 }
7377 }, {
7378 key: 'key',
7379 value: function key(n) {
7380 return Array.from(this._map.keys())[n];
7381 }
7382 }, {
7383 key: 'length',
7384 get: function get$$1() {
7385 return this._map.size;
7386 }
7387 }]);
7388 return MemoryStorage;
7389}();
7390
7391/**
7392 * @type {Storage}
7393 * @access protected
7394 */
7395
7396
7397var platformStorage = typeof localStorage === 'undefined' ? new MemoryStorage() : localStorage;
7398
7399/**
7400 * @type {string}
7401 */
7402var ZETAPUSH_SESSION_KEY = 'zetapush.token';
7403
7404/**
7405 * Provide abstraction for token persistence
7406 * @access protected
7407 */
7408var SessionPersistenceStrategy = function () {
7409 /**
7410 * @param {{sandboxId: string, storage: DOMStorage}} parameters
7411 */
7412 function SessionPersistenceStrategy() {
7413 var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
7414 sandboxId = _ref.sandboxId,
7415 _ref$storage = _ref.storage,
7416 storage = _ref$storage === undefined ? platformStorage : _ref$storage;
7417
7418 classCallCheck(this, SessionPersistenceStrategy);
7419
7420 /**
7421 * @access private
7422 * @type {string}
7423 */
7424 this.key = ZETAPUSH_SESSION_KEY + '.' + sandboxId;
7425 /**
7426 * @access private
7427 * @type {DOMStorage}
7428 */
7429 this.storage = storage;
7430 }
7431 /**
7432 * @return {string} session The stored session
7433 */
7434
7435
7436 createClass(SessionPersistenceStrategy, [{
7437 key: 'get',
7438 value: function get$$1() {
7439 var key = this.key,
7440 storage = this.storage;
7441
7442 var json = storage.getItem(key) || '{}';
7443 var session = {};
7444 try {
7445 session = JSON.parse(json);
7446 } catch (e) {}
7447 return session;
7448 }
7449 /**
7450 * @param {Object} session The session to store
7451 */
7452
7453 }, {
7454 key: 'set',
7455 value: function set$$1() {
7456 var session = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
7457 var key = this.key,
7458 storage = this.storage;
7459
7460 var json = JSON.stringify(session);
7461 try {
7462 storage.setItem(key, json);
7463 } catch (e) {}
7464 return session;
7465 }
7466 }]);
7467 return SessionPersistenceStrategy;
7468}();
7469
7470/**
7471 * SmartClient config object.
7472 * @typedef {Object} SmartClientConfig
7473 * @property {string} apiUrl - Api Url
7474 * @property {string} sandboxId - Sandbox id
7475 * @property {boolean} forceHttps - Force end to end HTTPS connection
7476 * @property {string} resource - Client resource id
7477 * @property {Array} transports - Client transports list
7478 */
7479
7480/**
7481 * @access public
7482 * @extends {Client}
7483 * @example
7484 * // Create a new WeakClient
7485 * const client = new ZetaPush.SmartClient({
7486 * sandboxId: '<YOUR-SANDBOX-ID>'
7487 * })
7488 */
7489var SmartClient = function (_Client) {
7490 inherits(SmartClient, _Client);
7491
7492 /**
7493 * Create a new ZetaPush SmartClient
7494 * @param {SmartClientConfig} config
7495 */
7496 function SmartClient(_ref) {
7497 var apiUrl = _ref.apiUrl,
7498 sandboxId = _ref.sandboxId,
7499 forceHttps = _ref.forceHttps,
7500 resource = _ref.resource,
7501 transports = _ref.transports;
7502 classCallCheck(this, SmartClient);
7503
7504 var persistence = new SessionPersistenceStrategy({ sandboxId: sandboxId });
7505
7506 /**
7507 * @return {AbstractHandshakeManager}
7508 */
7509 var authentication = function authentication() {
7510 var session = persistence.get();
7511 var token = session.token;
7512
7513
7514 if (_this.hasCredentials()) {
7515 var _this$getCredentials = _this.getCredentials(),
7516 login = _this$getCredentials.login,
7517 password = _this$getCredentials.password;
7518
7519 _this.setCredentials({});
7520 return Authentication.simple({
7521 login: login,
7522 password: password
7523 });
7524 } else {
7525 if (_this.isStronglyAuthenticated(session)) {
7526 return Authentication.simple({
7527 login: token,
7528 password: null
7529 });
7530 } else {
7531 return Authentication.weak({
7532 token: token
7533 });
7534 }
7535 }
7536 };
7537 // Initialize base client
7538
7539 /**
7540 * @access protected
7541 * @type {SessionPersistenceStrategy}
7542 */
7543 var _this = possibleConstructorReturn(this, (SmartClient.__proto__ || Object.getPrototypeOf(SmartClient)).call(this, {
7544 apiUrl: apiUrl, sandboxId: sandboxId, authentication: authentication, forceHttps: forceHttps, resource: resource, transports: transports
7545 }));
7546
7547 _this.persistence = persistence;
7548 /**
7549 * @access protected
7550 * @type {Object}
7551 */
7552 _this.credentials = {};
7553 /**
7554 * Handle connection lifecycle events
7555 * @access protected
7556 * @type {Object}
7557 */
7558 _this.lifeCycleConnectionHandler = _this.addConnectionStatusListener({
7559 onConnectionClosed: function onConnectionClosed() {
7560 persistence.set({});
7561 },
7562 onSuccessfulHandshake: function onSuccessfulHandshake(session) {
7563 if (session.token) {
7564 persistence.set(session);
7565 }
7566 }
7567 });
7568 // Properly disconnect client to avoir ghost connections
7569 /*
7570 window.addEventListener('beforeunload', () => {
7571 this.removeConnectionStatusListener(this.lifeCycleConnectionHandler)
7572 super.disconnect()
7573 })
7574 */
7575 return _this;
7576 }
7577 /**
7578 * Disconnect client from ZetaPush backend
7579 */
7580
7581
7582 createClass(SmartClient, [{
7583 key: 'disconnect',
7584 value: function disconnect() {
7585 get(SmartClient.prototype.__proto__ || Object.getPrototypeOf(SmartClient.prototype), 'disconnect', this).call(this);
7586 }
7587 /**
7588 * @return {Object}
7589 */
7590
7591 }, {
7592 key: 'getCredentials',
7593 value: function getCredentials() {
7594 return this.credentials;
7595 }
7596 /**
7597 * @return {Object}
7598 */
7599
7600 }, {
7601 key: 'getSession',
7602 value: function getSession() {
7603 return this.persistence.get();
7604 }
7605 /**
7606 * @return {boolean}
7607 */
7608
7609 }, {
7610 key: 'hasCredentials',
7611 value: function hasCredentials() {
7612 var _getCredentials = this.getCredentials(),
7613 login = _getCredentials.login,
7614 password = _getCredentials.password;
7615
7616 return login && password;
7617 }
7618 /**
7619 * @return {boolean}
7620 */
7621
7622 }, {
7623 key: 'isStronglyAuthenticated',
7624 value: function isStronglyAuthenticated() {
7625 var session = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.persistence.get();
7626
7627 return !this.isWeaklyAuthenticated(session) && typeof session.token === 'string';
7628 }
7629 /**
7630 * @return {boolean}
7631 */
7632
7633 }, {
7634 key: 'isWeaklyAuthenticated',
7635 value: function isWeaklyAuthenticated() {
7636 var session = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.persistence.get();
7637
7638 return typeof session.publicToken === 'string';
7639 }
7640 /**
7641 * @param {{login: string, password: string}} parameters
7642 */
7643
7644 }, {
7645 key: 'setCredentials',
7646 value: function setCredentials(_ref2) {
7647 var login = _ref2.login,
7648 password = _ref2.password;
7649
7650 this.credentials = { login: login, password: password };
7651 }
7652 }]);
7653 return SmartClient;
7654}(Client);
7655
7656/**
7657 * WeakClient config object.
7658 * @typedef {Object} WeakClientConfig
7659 * @property {string} apiUrl - Api Url
7660 * @property {string} deploymentId - Authentication deployment id, default value is 'weak_0'
7661 * @property {string} sandboxId - Sandbox id
7662 * @property {boolean} forceHttps - Force end to end HTTPS connection
7663 * @property {string} resource - Client resource id
7664 * @property {Array} transports - Client transports list
7665 */
7666
7667/**
7668 * @access public
7669 * @extends {Client}
7670 * @example
7671 * // Create a new WeakClient
7672 * const client = new ZetaPush.WeakClient({
7673 * sandboxId: '<YOUR-SANDBOX-ID>'
7674 * })
7675 * @example
7676 * // Explicit deploymentId
7677 * // WeakClient provide optional deployment id, according to the following convention `${ServiceType.toLowerCase()_0}`
7678 * // deploymentId default value is weak_0
7679 * const client = new ZetaPush.WeakClient({
7680 * deploymentId: 'weak_0',
7681 * sandboxId: '<YOUR-SANDBOX-ID>'
7682 * })
7683 */
7684var WeakClient = function (_Client) {
7685 inherits(WeakClient, _Client);
7686
7687 /**
7688 * Create a new ZetaPush WeakClient
7689 * @param {WeakClientConfig} config
7690 */
7691 function WeakClient(_ref) {
7692 var apiUrl = _ref.apiUrl,
7693 sandboxId = _ref.sandboxId,
7694 deploymentId = _ref.deploymentId,
7695 forceHttps = _ref.forceHttps,
7696 resource = _ref.resource,
7697 transports = _ref.transports;
7698 classCallCheck(this, WeakClient);
7699
7700 var authentication = function authentication() {
7701 var token = _this.getToken();
7702 var handshake = Authentication.weak({
7703 deploymentId: deploymentId,
7704 token: token
7705 });
7706 return handshake;
7707 };
7708 /**
7709 * Call Client constructor with specific parameters
7710 */
7711
7712 // Handle successful handshake
7713 var _this = possibleConstructorReturn(this, (WeakClient.__proto__ || Object.getPrototypeOf(WeakClient)).call(this, { apiUrl: apiUrl, sandboxId: sandboxId, forceHttps: forceHttps, authentication: authentication, resource: resource, transports: transports }));
7714
7715 var onSuccessfulHandshake = function onSuccessfulHandshake(_ref2) {
7716 var publicToken = _ref2.publicToken,
7717 userId = _ref2.userId,
7718 token = _ref2.token;
7719
7720 if (token) {
7721 _this.strategy.set({ publicToken: publicToken, userId: userId, token: token });
7722 }
7723 };
7724 _this.addConnectionStatusListener({ onSuccessfulHandshake: onSuccessfulHandshake });
7725 /**
7726 * @access private
7727 * @type {SessionPersistenceStrategy}
7728 */
7729 _this.strategy = new SessionPersistenceStrategy({ sandboxId: sandboxId });
7730 return _this;
7731 }
7732 /**
7733 * @return {string} The stored token
7734 */
7735
7736
7737 createClass(WeakClient, [{
7738 key: 'getToken',
7739 value: function getToken() {
7740 var _strategy$get = this.strategy.get(),
7741 token = _strategy$get.token;
7742
7743 return token;
7744 }
7745 }]);
7746 return WeakClient;
7747}(Client);
7748
7749/**
7750 * SDK Version
7751 * @type {string}
7752 */
7753var VERSION = '3.2.2';
7754
7755exports.VERSION = VERSION;
7756exports.Authentication = Authentication;
7757exports.ConnectionStatusListener = ConnectionStatusListener;
7758exports.Client = Client;
7759exports.SmartClient = SmartClient;
7760exports.WeakClient = WeakClient;
7761exports.services = services;
7762
7763Object.defineProperty(exports, '__esModule', { value: true });
7764
7765})));
7766//# sourceMappingURL=zetapush.js.map