LiveQueryClient.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. "use strict";
  2. var _Reflect$construct = require("@babel/runtime-corejs3/core-js-stable/reflect/construct");
  3. var _sliceInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/slice");
  4. var _Array$from = require("@babel/runtime-corejs3/core-js-stable/array/from");
  5. var _Symbol = require("@babel/runtime-corejs3/core-js-stable/symbol");
  6. var _getIteratorMethod = require("@babel/runtime-corejs3/core-js/get-iterator-method");
  7. var _Array$isArray = require("@babel/runtime-corejs3/core-js-stable/array/is-array");
  8. var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
  9. var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
  10. _Object$defineProperty(exports, "__esModule", {
  11. value: true
  12. });
  13. exports.default = void 0;
  14. var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of"));
  15. var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/map"));
  16. var _keys = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/keys"));
  17. var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
  18. var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
  19. var _values = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/values"));
  20. var _setTimeout2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set-timeout"));
  21. var _bind = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/bind"));
  22. var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof"));
  23. var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));
  24. var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));
  25. var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/assertThisInitialized"));
  26. var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inherits"));
  27. var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/possibleConstructorReturn"));
  28. var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/getPrototypeOf"));
  29. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
  30. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  31. var _EventEmitter2 = _interopRequireDefault(require("./EventEmitter"));
  32. var _ParseObject = _interopRequireDefault(require("./ParseObject"));
  33. var _LiveQuerySubscription = _interopRequireDefault(require("./LiveQuerySubscription"));
  34. var _promiseUtils = require("./promiseUtils");
  35. var _ParseError = _interopRequireDefault(require("./ParseError"));
  36. function _createForOfIteratorHelper(o, allowArrayLike) {
  37. var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"];
  38. if (!it) {
  39. if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
  40. if (it) o = it;
  41. var i = 0;
  42. var F = function () {};
  43. return {
  44. s: F,
  45. n: function () {
  46. if (i >= o.length) return {
  47. done: true
  48. };
  49. return {
  50. done: false,
  51. value: o[i++]
  52. };
  53. },
  54. e: function (_e) {
  55. throw _e;
  56. },
  57. f: F
  58. };
  59. }
  60. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  61. }
  62. var normalCompletion = true,
  63. didErr = false,
  64. err;
  65. return {
  66. s: function () {
  67. it = it.call(o);
  68. },
  69. n: function () {
  70. var step = it.next();
  71. normalCompletion = step.done;
  72. return step;
  73. },
  74. e: function (_e2) {
  75. didErr = true;
  76. err = _e2;
  77. },
  78. f: function () {
  79. try {
  80. if (!normalCompletion && it.return != null) it.return();
  81. } finally {
  82. if (didErr) throw err;
  83. }
  84. }
  85. };
  86. }
  87. function _unsupportedIterableToArray(o, minLen) {
  88. var _context6;
  89. if (!o) return;
  90. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  91. var n = _sliceInstanceProperty(_context6 = Object.prototype.toString.call(o)).call(_context6, 8, -1);
  92. if (n === "Object" && o.constructor) n = o.constructor.name;
  93. if (n === "Map" || n === "Set") return _Array$from(o);
  94. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  95. }
  96. function _arrayLikeToArray(arr, len) {
  97. if (len == null || len > arr.length) len = arr.length;
  98. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  99. return arr2;
  100. }
  101. function _createSuper(Derived) {
  102. var hasNativeReflectConstruct = _isNativeReflectConstruct();
  103. return function () {
  104. var Super = (0, _getPrototypeOf2.default)(Derived),
  105. result;
  106. if (hasNativeReflectConstruct) {
  107. var NewTarget = (0, _getPrototypeOf2.default)(this).constructor;
  108. result = _Reflect$construct(Super, arguments, NewTarget);
  109. } else {
  110. result = Super.apply(this, arguments);
  111. }
  112. return (0, _possibleConstructorReturn2.default)(this, result);
  113. };
  114. }
  115. function _isNativeReflectConstruct() {
  116. if (typeof Reflect === "undefined" || !_Reflect$construct) return false;
  117. if (_Reflect$construct.sham) return false;
  118. if (typeof Proxy === "function") return true;
  119. try {
  120. Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {}));
  121. return true;
  122. } catch (e) {
  123. return false;
  124. }
  125. } /* global WebSocket */
  126. // The LiveQuery client inner state
  127. var CLIENT_STATE = {
  128. INITIALIZED: 'initialized',
  129. CONNECTING: 'connecting',
  130. CONNECTED: 'connected',
  131. CLOSED: 'closed',
  132. RECONNECTING: 'reconnecting',
  133. DISCONNECTED: 'disconnected'
  134. };
  135. // The event type the LiveQuery client should sent to server
  136. var OP_TYPES = {
  137. CONNECT: 'connect',
  138. SUBSCRIBE: 'subscribe',
  139. UNSUBSCRIBE: 'unsubscribe',
  140. ERROR: 'error'
  141. };
  142. // The event we get back from LiveQuery server
  143. var OP_EVENTS = {
  144. CONNECTED: 'connected',
  145. SUBSCRIBED: 'subscribed',
  146. UNSUBSCRIBED: 'unsubscribed',
  147. ERROR: 'error',
  148. CREATE: 'create',
  149. UPDATE: 'update',
  150. ENTER: 'enter',
  151. LEAVE: 'leave',
  152. DELETE: 'delete'
  153. };
  154. // The event the LiveQuery client should emit
  155. var CLIENT_EMMITER_TYPES = {
  156. CLOSE: 'close',
  157. ERROR: 'error',
  158. OPEN: 'open'
  159. };
  160. // The event the LiveQuery subscription should emit
  161. var SUBSCRIPTION_EMMITER_TYPES = {
  162. OPEN: 'open',
  163. CLOSE: 'close',
  164. ERROR: 'error',
  165. CREATE: 'create',
  166. UPDATE: 'update',
  167. ENTER: 'enter',
  168. LEAVE: 'leave',
  169. DELETE: 'delete'
  170. };
  171. var generateInterval = function (k) {
  172. return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000;
  173. };
  174. /**
  175. * Creates a new LiveQueryClient.
  176. * Extends events.EventEmitter
  177. * <a href="https://nodejs.org/api/events.html#events_class_eventemitter">cloud functions</a>.
  178. *
  179. * A wrapper of a standard WebSocket client. We add several useful methods to
  180. * help you connect/disconnect to LiveQueryServer, subscribe/unsubscribe a ParseQuery easily.
  181. *
  182. * javascriptKey and masterKey are used for verifying the LiveQueryClient when it tries
  183. * to connect to the LiveQuery server
  184. *
  185. * We expose three events to help you monitor the status of the LiveQueryClient.
  186. *
  187. * <pre>
  188. * let Parse = require('parse/node');
  189. * let LiveQueryClient = Parse.LiveQueryClient;
  190. * let client = new LiveQueryClient({
  191. * applicationId: '',
  192. * serverURL: '',
  193. * javascriptKey: '',
  194. * masterKey: ''
  195. * });
  196. * </pre>
  197. *
  198. * Open - When we establish the WebSocket connection to the LiveQuery server, you'll get this event.
  199. * <pre>
  200. * client.on('open', () => {
  201. *
  202. * });</pre>
  203. *
  204. * Close - When we lose the WebSocket connection to the LiveQuery server, you'll get this event.
  205. * <pre>
  206. * client.on('close', () => {
  207. *
  208. * });</pre>
  209. *
  210. * Error - When some network error or LiveQuery server error happens, you'll get this event.
  211. * <pre>
  212. * client.on('error', (error) => {
  213. *
  214. * });</pre>
  215. *
  216. * @alias Parse.LiveQueryClient
  217. */
  218. var LiveQueryClient = /*#__PURE__*/function (_EventEmitter) {
  219. (0, _inherits2.default)(LiveQueryClient, _EventEmitter);
  220. var _super = _createSuper(LiveQueryClient);
  221. /**
  222. * @param {object} options
  223. * @param {string} options.applicationId - applicationId of your Parse app
  224. * @param {string} options.serverURL - <b>the URL of your LiveQuery server</b>
  225. * @param {string} options.javascriptKey (optional)
  226. * @param {string} options.masterKey (optional) Your Parse Master Key. (Node.js only!)
  227. * @param {string} options.sessionToken (optional)
  228. * @param {string} options.installationId (optional)
  229. */
  230. function LiveQueryClient(_ref) {
  231. var _this;
  232. var applicationId = _ref.applicationId,
  233. serverURL = _ref.serverURL,
  234. javascriptKey = _ref.javascriptKey,
  235. masterKey = _ref.masterKey,
  236. sessionToken = _ref.sessionToken,
  237. installationId = _ref.installationId;
  238. (0, _classCallCheck2.default)(this, LiveQueryClient);
  239. _this = _super.call(this);
  240. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "attempts", void 0);
  241. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "id", void 0);
  242. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "requestId", void 0);
  243. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "applicationId", void 0);
  244. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "serverURL", void 0);
  245. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "javascriptKey", void 0);
  246. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "masterKey", void 0);
  247. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "sessionToken", void 0);
  248. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "installationId", void 0);
  249. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "additionalProperties", void 0);
  250. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "connectPromise", void 0);
  251. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "subscriptions", void 0);
  252. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "socket", void 0);
  253. (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", void 0);
  254. if (!serverURL || (0, _indexOf.default)(serverURL).call(serverURL, 'ws') !== 0) {
  255. throw new Error('You need to set a proper Parse LiveQuery server url before using LiveQueryClient');
  256. }
  257. _this.reconnectHandle = null;
  258. _this.attempts = 1;
  259. _this.id = 0;
  260. _this.requestId = 1;
  261. _this.serverURL = serverURL;
  262. _this.applicationId = applicationId;
  263. _this.javascriptKey = javascriptKey || undefined;
  264. _this.masterKey = masterKey || undefined;
  265. _this.sessionToken = sessionToken || undefined;
  266. _this.installationId = installationId || undefined;
  267. _this.additionalProperties = true;
  268. _this.connectPromise = (0, _promiseUtils.resolvingPromise)();
  269. _this.subscriptions = new _map.default();
  270. _this.state = CLIENT_STATE.INITIALIZED;
  271. // adding listener so process does not crash
  272. // best practice is for developer to register their own listener
  273. _this.on('error', function () {});
  274. return _this;
  275. }
  276. (0, _createClass2.default)(LiveQueryClient, [{
  277. key: "shouldOpen",
  278. value: function () /*: any*/{
  279. return this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED;
  280. }
  281. /**
  282. * Subscribes to a ParseQuery
  283. *
  284. * If you provide the sessionToken, when the LiveQuery server gets ParseObject's
  285. * updates from parse server, it'll try to check whether the sessionToken fulfills
  286. * the ParseObject's ACL. The LiveQuery server will only send updates to clients whose
  287. * sessionToken is fit for the ParseObject's ACL. You can check the LiveQuery protocol
  288. * <a href="https://github.com/parse-community/parse-server/wiki/Parse-LiveQuery-Protocol-Specification">here</a> for more details. The subscription you get is the same subscription you get
  289. * from our Standard API.
  290. *
  291. * @param {object} query - the ParseQuery you want to subscribe to
  292. * @param {string} sessionToken (optional)
  293. * @returns {LiveQuerySubscription | undefined}
  294. */
  295. }, {
  296. key: "subscribe",
  297. value: function (query /*: Object*/, sessionToken /*: ?string*/) /*: LiveQuerySubscription*/{
  298. var _queryJSON$keys,
  299. _queryJSON$watch,
  300. _this2 = this;
  301. if (!query) {
  302. return;
  303. }
  304. var className = query.className;
  305. var queryJSON = query.toJSON();
  306. var where = queryJSON.where;
  307. var fields = (_queryJSON$keys = (0, _keys.default)(queryJSON)) === null || _queryJSON$keys === void 0 ? void 0 : _queryJSON$keys.split(',');
  308. var watch = (_queryJSON$watch = queryJSON.watch) === null || _queryJSON$watch === void 0 ? void 0 : _queryJSON$watch.split(',');
  309. var subscribeRequest = {
  310. op: OP_TYPES.SUBSCRIBE,
  311. requestId: this.requestId,
  312. query: {
  313. className: className,
  314. where: where,
  315. fields: fields,
  316. watch: watch
  317. }
  318. };
  319. if (sessionToken) {
  320. subscribeRequest.sessionToken = sessionToken;
  321. }
  322. var subscription = new _LiveQuerySubscription.default(this.requestId, query, sessionToken);
  323. this.subscriptions.set(this.requestId, subscription);
  324. this.requestId += 1;
  325. this.connectPromise.then(function () {
  326. _this2.socket.send((0, _stringify.default)(subscribeRequest));
  327. }).catch(function (error) {
  328. subscription.subscribePromise.reject(error);
  329. });
  330. return subscription;
  331. }
  332. /**
  333. * After calling unsubscribe you'll stop receiving events from the subscription object.
  334. *
  335. * @param {object} subscription - subscription you would like to unsubscribe from.
  336. * @returns {Promise | undefined}
  337. */
  338. }, {
  339. key: "unsubscribe",
  340. value: function (subscription /*: Object*/) /*: ?Promise*/{
  341. var _this3 = this;
  342. if (!subscription) {
  343. return;
  344. }
  345. var unsubscribeRequest = {
  346. op: OP_TYPES.UNSUBSCRIBE,
  347. requestId: subscription.id
  348. };
  349. return this.connectPromise.then(function () {
  350. return _this3.socket.send((0, _stringify.default)(unsubscribeRequest));
  351. }).then(function () {
  352. return subscription.unsubscribePromise;
  353. });
  354. }
  355. /**
  356. * After open is called, the LiveQueryClient will try to send a connect request
  357. * to the LiveQuery server.
  358. *
  359. */
  360. }, {
  361. key: "open",
  362. value: function () {
  363. var _this4 = this;
  364. var WebSocketImplementation = _CoreManager.default.getWebSocketController();
  365. if (!WebSocketImplementation) {
  366. this.emit(CLIENT_EMMITER_TYPES.ERROR, 'Can not find WebSocket implementation');
  367. return;
  368. }
  369. if (this.state !== CLIENT_STATE.RECONNECTING) {
  370. this.state = CLIENT_STATE.CONNECTING;
  371. }
  372. this.socket = new WebSocketImplementation(this.serverURL);
  373. this.socket.closingPromise = (0, _promiseUtils.resolvingPromise)();
  374. // Bind WebSocket callbacks
  375. this.socket.onopen = function () {
  376. _this4._handleWebSocketOpen();
  377. };
  378. this.socket.onmessage = function (event) {
  379. _this4._handleWebSocketMessage(event);
  380. };
  381. this.socket.onclose = function (event) {
  382. _this4.socket.closingPromise.resolve(event);
  383. _this4._handleWebSocketClose();
  384. };
  385. this.socket.onerror = function (error) {
  386. _this4._handleWebSocketError(error);
  387. };
  388. }
  389. }, {
  390. key: "resubscribe",
  391. value: function () {
  392. var _context,
  393. _this5 = this;
  394. (0, _forEach.default)(_context = this.subscriptions).call(_context, function (subscription, requestId) {
  395. var query = subscription.query;
  396. var queryJSON = query.toJSON();
  397. var where = queryJSON.where;
  398. var fields = (0, _keys.default)(queryJSON) ? (0, _keys.default)(queryJSON).split(',') : undefined;
  399. var className = query.className;
  400. var sessionToken = subscription.sessionToken;
  401. var subscribeRequest = {
  402. op: OP_TYPES.SUBSCRIBE,
  403. requestId: requestId,
  404. query: {
  405. className: className,
  406. where: where,
  407. fields: fields
  408. }
  409. };
  410. if (sessionToken) {
  411. subscribeRequest.sessionToken = sessionToken;
  412. }
  413. _this5.connectPromise.then(function () {
  414. _this5.socket.send((0, _stringify.default)(subscribeRequest));
  415. });
  416. });
  417. }
  418. /**
  419. * This method will close the WebSocket connection to this LiveQueryClient,
  420. * cancel the auto reconnect and unsubscribe all subscriptions based on it.
  421. *
  422. * @returns {Promise | undefined} CloseEvent {@link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event}
  423. */
  424. }, {
  425. key: "close",
  426. value: function () /*: ?Promise*/{
  427. var _this$socket, _this$socket2, _context2;
  428. if (this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED) {
  429. return;
  430. }
  431. this.state = CLIENT_STATE.DISCONNECTED;
  432. (_this$socket = this.socket) === null || _this$socket === void 0 ? void 0 : _this$socket.close();
  433. // Notify each subscription about the close
  434. var _iterator = _createForOfIteratorHelper((0, _values.default)(_context2 = this.subscriptions).call(_context2)),
  435. _step;
  436. try {
  437. for (_iterator.s(); !(_step = _iterator.n()).done;) {
  438. var subscription = _step.value;
  439. subscription.subscribed = false;
  440. subscription.emit(SUBSCRIPTION_EMMITER_TYPES.CLOSE);
  441. }
  442. } catch (err) {
  443. _iterator.e(err);
  444. } finally {
  445. _iterator.f();
  446. }
  447. this._handleReset();
  448. this.emit(CLIENT_EMMITER_TYPES.CLOSE);
  449. return (_this$socket2 = this.socket) === null || _this$socket2 === void 0 ? void 0 : _this$socket2.closingPromise;
  450. }
  451. // ensure we start with valid state if connect is called again after close
  452. }, {
  453. key: "_handleReset",
  454. value: function () {
  455. this.attempts = 1;
  456. this.id = 0;
  457. this.requestId = 1;
  458. this.connectPromise = (0, _promiseUtils.resolvingPromise)();
  459. this.subscriptions = new _map.default();
  460. }
  461. }, {
  462. key: "_handleWebSocketOpen",
  463. value: function () {
  464. this.attempts = 1;
  465. var connectRequest = {
  466. op: OP_TYPES.CONNECT,
  467. applicationId: this.applicationId,
  468. javascriptKey: this.javascriptKey,
  469. masterKey: this.masterKey,
  470. sessionToken: this.sessionToken
  471. };
  472. if (this.additionalProperties) {
  473. connectRequest.installationId = this.installationId;
  474. }
  475. this.socket.send((0, _stringify.default)(connectRequest));
  476. }
  477. }, {
  478. key: "_handleWebSocketMessage",
  479. value: function (event /*: any*/) {
  480. var data = event.data;
  481. if (typeof data === 'string') {
  482. data = JSON.parse(data);
  483. }
  484. var subscription = null;
  485. if (data.requestId) {
  486. subscription = this.subscriptions.get(data.requestId);
  487. }
  488. var response = {
  489. clientId: data.clientId,
  490. installationId: data.installationId
  491. };
  492. switch (data.op) {
  493. case OP_EVENTS.CONNECTED:
  494. if (this.state === CLIENT_STATE.RECONNECTING) {
  495. this.resubscribe();
  496. }
  497. this.emit(CLIENT_EMMITER_TYPES.OPEN);
  498. this.id = data.clientId;
  499. this.connectPromise.resolve();
  500. this.state = CLIENT_STATE.CONNECTED;
  501. break;
  502. case OP_EVENTS.SUBSCRIBED:
  503. if (subscription) {
  504. subscription.subscribed = true;
  505. subscription.subscribePromise.resolve();
  506. (0, _setTimeout2.default)(function () {
  507. return subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response);
  508. }, 200);
  509. }
  510. break;
  511. case OP_EVENTS.ERROR:
  512. {
  513. var parseError = new _ParseError.default(data.code, data.error);
  514. if (!this.id) {
  515. this.connectPromise.reject(parseError);
  516. this.state = CLIENT_STATE.DISCONNECTED;
  517. }
  518. if (data.requestId) {
  519. if (subscription) {
  520. subscription.subscribePromise.reject(parseError);
  521. (0, _setTimeout2.default)(function () {
  522. return subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error);
  523. }, 200);
  524. }
  525. } else {
  526. this.emit(CLIENT_EMMITER_TYPES.ERROR, data.error);
  527. }
  528. if (data.error === 'Additional properties not allowed') {
  529. this.additionalProperties = false;
  530. }
  531. if (data.reconnect) {
  532. this._handleReconnect();
  533. }
  534. break;
  535. }
  536. case OP_EVENTS.UNSUBSCRIBED:
  537. {
  538. if (subscription) {
  539. this.subscriptions.delete(data.requestId);
  540. subscription.subscribed = false;
  541. subscription.unsubscribePromise.resolve();
  542. }
  543. break;
  544. }
  545. default:
  546. {
  547. // create, update, enter, leave, delete cases
  548. if (!subscription) {
  549. break;
  550. }
  551. var override = false;
  552. if (data.original) {
  553. override = true;
  554. delete data.original.__type;
  555. // Check for removed fields
  556. for (var field in data.original) {
  557. if (!(field in data.object)) {
  558. data.object[field] = undefined;
  559. }
  560. }
  561. data.original = _ParseObject.default.fromJSON(data.original, false);
  562. }
  563. delete data.object.__type;
  564. var parseObject = _ParseObject.default.fromJSON(data.object, !(subscription.query && subscription.query._select) ? override : false);
  565. if (data.original) {
  566. subscription.emit(data.op, parseObject, data.original, response);
  567. } else {
  568. subscription.emit(data.op, parseObject, response);
  569. }
  570. var localDatastore = _CoreManager.default.getLocalDatastore();
  571. if (override && localDatastore.isEnabled) {
  572. localDatastore._updateObjectIfPinned(parseObject).then(function () {});
  573. }
  574. }
  575. }
  576. }
  577. }, {
  578. key: "_handleWebSocketClose",
  579. value: function () {
  580. var _context3;
  581. if (this.state === CLIENT_STATE.DISCONNECTED) {
  582. return;
  583. }
  584. this.state = CLIENT_STATE.CLOSED;
  585. this.emit(CLIENT_EMMITER_TYPES.CLOSE);
  586. // Notify each subscription about the close
  587. var _iterator2 = _createForOfIteratorHelper((0, _values.default)(_context3 = this.subscriptions).call(_context3)),
  588. _step2;
  589. try {
  590. for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
  591. var subscription = _step2.value;
  592. subscription.emit(SUBSCRIPTION_EMMITER_TYPES.CLOSE);
  593. }
  594. } catch (err) {
  595. _iterator2.e(err);
  596. } finally {
  597. _iterator2.f();
  598. }
  599. this._handleReconnect();
  600. }
  601. }, {
  602. key: "_handleWebSocketError",
  603. value: function (error /*: any*/) {
  604. var _context4;
  605. this.emit(CLIENT_EMMITER_TYPES.ERROR, error);
  606. var _iterator3 = _createForOfIteratorHelper((0, _values.default)(_context4 = this.subscriptions).call(_context4)),
  607. _step3;
  608. try {
  609. for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
  610. var subscription = _step3.value;
  611. subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, error);
  612. }
  613. } catch (err) {
  614. _iterator3.e(err);
  615. } finally {
  616. _iterator3.f();
  617. }
  618. this._handleReconnect();
  619. }
  620. }, {
  621. key: "_handleReconnect",
  622. value: function () {
  623. var _context5,
  624. _this6 = this;
  625. // if closed or currently reconnecting we stop attempting to reconnect
  626. if (this.state === CLIENT_STATE.DISCONNECTED) {
  627. return;
  628. }
  629. this.state = CLIENT_STATE.RECONNECTING;
  630. var time = generateInterval(this.attempts);
  631. // handle case when both close/error occur at frequent rates we ensure we do not reconnect unnecessarily.
  632. // we're unable to distinguish different between close/error when we're unable to reconnect therefore
  633. // we try to reconnect in both cases
  634. // server side ws and browser WebSocket behave differently in when close/error get triggered
  635. if (this.reconnectHandle) {
  636. clearTimeout(this.reconnectHandle);
  637. }
  638. this.reconnectHandle = (0, _setTimeout2.default)((0, _bind.default)(_context5 = function () {
  639. _this6.attempts++;
  640. _this6.connectPromise = (0, _promiseUtils.resolvingPromise)();
  641. _this6.open();
  642. }).call(_context5, this), time);
  643. }
  644. }]);
  645. return LiveQueryClient;
  646. }(_EventEmitter2.default);
  647. _CoreManager.default.setWebSocketController(require('./Socket.weapp'));
  648. var _default = LiveQueryClient;
  649. exports.default = _default;