parse
Version:
Parse JavaScript SDK
414 lines • 14.3 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _CoreManager = _interopRequireDefault(require("./CoreManager"));
var _ParseObject = _interopRequireDefault(require("./ParseObject"));
var _LiveQuerySubscription = _interopRequireDefault(require("./LiveQuerySubscription"));
var _promiseUtils = require("./promiseUtils");
var _ParseError = _interopRequireDefault(require("./ParseError"));
var CLIENT_STATE = {
INITIALIZED: 'initialized',
CONNECTING: 'connecting',
CONNECTED: 'connected',
CLOSED: 'closed',
RECONNECTING: 'reconnecting',
DISCONNECTED: 'disconnected'
};
var OP_TYPES = {
CONNECT: 'connect',
SUBSCRIBE: 'subscribe',
UNSUBSCRIBE: 'unsubscribe',
ERROR: 'error'
};
var OP_EVENTS = {
CONNECTED: 'connected',
SUBSCRIBED: 'subscribed',
UNSUBSCRIBED: 'unsubscribed',
ERROR: 'error',
CREATE: 'create',
UPDATE: 'update',
ENTER: 'enter',
LEAVE: 'leave',
DELETE: 'delete'
};
var CLIENT_EMMITER_TYPES = {
CLOSE: 'close',
ERROR: 'error',
OPEN: 'open'
};
var SUBSCRIPTION_EMMITER_TYPES = {
OPEN: 'open',
CLOSE: 'close',
ERROR: 'error',
CREATE: 'create',
UPDATE: 'update',
ENTER: 'enter',
LEAVE: 'leave',
DELETE: 'delete'
};
var generateInterval = function (k) {
return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000;
};
var LiveQueryClient = function () {
function LiveQueryClient(_ref) {
var _this = this;
var applicationId = _ref.applicationId,
serverURL = _ref.serverURL,
javascriptKey = _ref.javascriptKey,
masterKey = _ref.masterKey,
sessionToken = _ref.sessionToken,
installationId = _ref.installationId;
(0, _classCallCheck2.default)(this, LiveQueryClient);
if (!serverURL || serverURL.indexOf('ws') !== 0) {
throw new Error('You need to set a proper Parse LiveQuery server url before using LiveQueryClient');
}
this.reconnectHandle = null;
this.attempts = 1;
this.id = 0;
this.requestId = 1;
this.serverURL = serverURL;
this.applicationId = applicationId;
this.javascriptKey = javascriptKey || undefined;
this.masterKey = masterKey || undefined;
this.sessionToken = sessionToken || undefined;
this.installationId = installationId || undefined;
this.additionalProperties = true;
this.connectPromise = (0, _promiseUtils.resolvingPromise)();
this.subscriptions = new Map();
this.state = CLIENT_STATE.INITIALIZED;
var EventEmitter = _CoreManager.default.getEventEmitter();
this.emitter = new EventEmitter();
this.on = function (eventName, listener) {
return _this.emitter.on(eventName, listener);
};
this.emit = function (eventName) {
var _this$emitter;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return (_this$emitter = _this.emitter).emit.apply(_this$emitter, [eventName].concat(args));
};
this.on('error', function () {});
}
return (0, _createClass2.default)(LiveQueryClient, [{
key: "shouldOpen",
value: function () {
return this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED;
}
}, {
key: "subscribe",
value: function (query, sessionToken) {
var _queryJSON$keys,
_queryJSON$watch,
_this2 = this;
if (!query) {
return;
}
var className = query.className;
var queryJSON = query.toJSON();
var where = queryJSON.where;
var keys = (_queryJSON$keys = queryJSON.keys) == null ? void 0 : _queryJSON$keys.split(',');
var watch = (_queryJSON$watch = queryJSON.watch) == null ? void 0 : _queryJSON$watch.split(',');
var subscribeRequest = {
op: OP_TYPES.SUBSCRIBE,
requestId: this.requestId,
query: {
className: className,
where: where,
keys: keys,
watch: watch
},
sessionToken: undefined
};
if (sessionToken) {
subscribeRequest.sessionToken = sessionToken;
}
var subscription = new _LiveQuerySubscription.default(this.requestId, query, sessionToken);
this.subscriptions.set(this.requestId, subscription);
this.requestId += 1;
this.connectPromise.then(function () {
_this2.socket.send(JSON.stringify(subscribeRequest));
}).catch(function (error) {
subscription.subscribePromise.reject(error);
});
return subscription;
}
}, {
key: "unsubscribe",
value: function () {
var _unsubscribe = (0, _asyncToGenerator2.default)(function* (subscription) {
var _this3 = this;
if (!subscription) {
return;
}
var unsubscribeRequest = {
op: OP_TYPES.UNSUBSCRIBE,
requestId: subscription.id
};
return this.connectPromise.then(function () {
return _this3.socket.send(JSON.stringify(unsubscribeRequest));
}).then(function () {
return subscription.unsubscribePromise;
});
});
function unsubscribe() {
return _unsubscribe.apply(this, arguments);
}
return unsubscribe;
}()
}, {
key: "open",
value: function () {
var _this4 = this;
var WebSocketImplementation = _CoreManager.default.getWebSocketController();
if (!WebSocketImplementation) {
this.emit(CLIENT_EMMITER_TYPES.ERROR, 'Can not find WebSocket implementation');
return;
}
if (this.state !== CLIENT_STATE.RECONNECTING) {
this.state = CLIENT_STATE.CONNECTING;
}
this.socket = new WebSocketImplementation(this.serverURL);
this.socket.closingPromise = (0, _promiseUtils.resolvingPromise)();
this.socket.onopen = function () {
_this4._handleWebSocketOpen();
};
this.socket.onmessage = function (event) {
_this4._handleWebSocketMessage(event);
};
this.socket.onclose = function (event) {
var _this4$socket$closing;
(_this4$socket$closing = _this4.socket.closingPromise) == null ? void 0 : _this4$socket$closing.resolve(event);
_this4._handleWebSocketClose();
};
this.socket.onerror = function (error) {
_this4._handleWebSocketError(error);
};
}
}, {
key: "resubscribe",
value: function () {
var _this5 = this;
this.subscriptions.forEach(function (subscription, requestId) {
var _queryJSON$keys2, _queryJSON$watch2;
var query = subscription.query;
var queryJSON = query.toJSON();
var where = queryJSON.where;
var keys = (_queryJSON$keys2 = queryJSON.keys) == null ? void 0 : _queryJSON$keys2.split(',');
var watch = (_queryJSON$watch2 = queryJSON.watch) == null ? void 0 : _queryJSON$watch2.split(',');
var className = query.className;
var sessionToken = subscription.sessionToken;
var subscribeRequest = {
op: OP_TYPES.SUBSCRIBE,
requestId: requestId,
query: {
className: className,
where: where,
keys: keys,
watch: watch
},
sessionToken: undefined
};
if (sessionToken) {
subscribeRequest.sessionToken = sessionToken;
}
_this5.connectPromise.then(function () {
_this5.socket.send(JSON.stringify(subscribeRequest));
});
});
}
}, {
key: "close",
value: function () {
var _close = (0, _asyncToGenerator2.default)(function* () {
var _this$socket, _this$socket2;
if (this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED) {
return;
}
this.state = CLIENT_STATE.DISCONNECTED;
(_this$socket = this.socket) == null ? void 0 : _this$socket.close();
for (var subscription of this.subscriptions.values()) {
subscription.subscribed = false;
subscription.emit(SUBSCRIPTION_EMMITER_TYPES.CLOSE);
}
this._handleReset();
this.emit(CLIENT_EMMITER_TYPES.CLOSE);
return (_this$socket2 = this.socket) == null ? void 0 : _this$socket2.closingPromise;
});
function close() {
return _close.apply(this, arguments);
}
return close;
}()
}, {
key: "_handleReset",
value: function () {
this.attempts = 1;
this.id = 0;
this.requestId = 1;
this.connectPromise = (0, _promiseUtils.resolvingPromise)();
this.subscriptions = new Map();
}
}, {
key: "_handleWebSocketOpen",
value: function () {
var connectRequest = {
op: OP_TYPES.CONNECT,
applicationId: this.applicationId,
javascriptKey: this.javascriptKey,
masterKey: this.masterKey,
sessionToken: this.sessionToken,
installationId: undefined
};
if (this.additionalProperties) {
connectRequest.installationId = this.installationId;
}
this.socket.send(JSON.stringify(connectRequest));
}
}, {
key: "_handleWebSocketMessage",
value: function (event) {
var data = event.data;
if (typeof data === 'string') {
data = JSON.parse(data);
}
var subscription = null;
if (data.requestId) {
subscription = this.subscriptions.get(data.requestId) || null;
}
var response = {
clientId: data.clientId,
installationId: data.installationId
};
switch (data.op) {
case OP_EVENTS.CONNECTED:
if (this.state === CLIENT_STATE.RECONNECTING) {
this.resubscribe();
}
this.emit(CLIENT_EMMITER_TYPES.OPEN);
this.id = data.clientId;
this.connectPromise.resolve();
this.state = CLIENT_STATE.CONNECTED;
break;
case OP_EVENTS.SUBSCRIBED:
if (subscription) {
this.attempts = 1;
subscription.subscribed = true;
subscription.subscribePromise.resolve();
setTimeout(function () {
return subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response);
}, 200);
}
break;
case OP_EVENTS.ERROR:
{
var parseError = new _ParseError.default(data.code, data.error);
if (!this.id) {
this.connectPromise.reject(parseError);
this.state = CLIENT_STATE.DISCONNECTED;
}
if (data.requestId) {
if (subscription) {
subscription.subscribePromise.reject(parseError);
setTimeout(function () {
return subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error);
}, 200);
}
} else {
this.emit(CLIENT_EMMITER_TYPES.ERROR, data.error);
}
if (data.error === 'Additional properties not allowed') {
this.additionalProperties = false;
}
if (data.reconnect) {
this._handleReconnect();
}
break;
}
case OP_EVENTS.UNSUBSCRIBED:
{
if (subscription) {
this.subscriptions.delete(data.requestId);
subscription.subscribed = false;
subscription.unsubscribePromise.resolve();
}
break;
}
default:
{
if (!subscription) {
break;
}
var override = false;
if (data.original) {
override = true;
delete data.original.__type;
for (var field in data.original) {
if (!(field in data.object)) {
data.object[field] = undefined;
}
}
data.original = _ParseObject.default.fromJSON(data.original, false);
}
delete data.object.__type;
var parseObject = _ParseObject.default.fromJSON(data.object, !(subscription.query && subscription.query._select) ? override : false);
if (data.original) {
subscription.emit(data.op, parseObject, data.original, response);
} else {
subscription.emit(data.op, parseObject, response);
}
var localDatastore = _CoreManager.default.getLocalDatastore();
if (override && localDatastore.isEnabled) {
localDatastore._updateObjectIfPinned(parseObject).then(function () {});
}
}
}
}
}, {
key: "_handleWebSocketClose",
value: function () {
if (this.state === CLIENT_STATE.DISCONNECTED) {
return;
}
this.state = CLIENT_STATE.CLOSED;
this.emit(CLIENT_EMMITER_TYPES.CLOSE);
for (var subscription of this.subscriptions.values()) {
subscription.emit(SUBSCRIPTION_EMMITER_TYPES.CLOSE);
}
this._handleReconnect();
}
}, {
key: "_handleWebSocketError",
value: function (error) {
this.emit(CLIENT_EMMITER_TYPES.ERROR, error);
for (var subscription of this.subscriptions.values()) {
subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, error);
}
this._handleReconnect();
}
}, {
key: "_handleReconnect",
value: function () {
var _this6 = this;
if (this.state === CLIENT_STATE.DISCONNECTED) {
return;
}
this.state = CLIENT_STATE.RECONNECTING;
var time = generateInterval(this.attempts);
if (this.reconnectHandle) {
clearTimeout(this.reconnectHandle);
}
this.reconnectHandle = setTimeout(function () {
_this6.attempts++;
_this6.connectPromise = (0, _promiseUtils.resolvingPromise)();
_this6.open();
}.bind(this), time);
}
}]);
}();
var _default = exports.default = LiveQueryClient;