parse
Version:
Parse JavaScript SDK
317 lines (314 loc) • 11.7 kB
JavaScript
;
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of"));
var _bind = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/bind"));
var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
var _setTimeout2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set-timeout"));
var _uuid = _interopRequireDefault(require("./uuid"));
var _CoreManager = _interopRequireDefault(require("./CoreManager"));
var _ParseError = _interopRequireDefault(require("./ParseError"));
var _promiseUtils = require("./promiseUtils");
var _Xhr = _interopRequireDefault(require("./Xhr.weapp"));
/* global XMLHttpRequest, XDomainRequest */
let XHR = null;
if (typeof XMLHttpRequest !== 'undefined') {
XHR = XMLHttpRequest;
}
XHR = _Xhr.default;
let useXDomainRequest = false;
// @ts-ignore
if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) {
useXDomainRequest = true;
}
function ajaxIE9(method, url, data, _headers, options) {
return new _promise.default((resolve, reject) => {
// @ts-ignore
const xdr = new XDomainRequest();
xdr.onload = function () {
let response;
try {
response = JSON.parse(xdr.responseText);
} catch (e) {
reject(e);
}
if (response) {
resolve({
response
});
}
};
xdr.onerror = xdr.ontimeout = function () {
// Let's fake a real error message.
const fakeResponse = {
responseText: (0, _stringify.default)({
code: _ParseError.default.X_DOMAIN_REQUEST,
error: "IE's XDomainRequest does not supply error info."
})
};
reject(fakeResponse);
};
xdr.onprogress = function () {
if (options && typeof options.progress === 'function') {
options.progress(xdr.responseText);
}
};
xdr.open(method, url);
xdr.send(data);
// @ts-ignore
if (options && typeof options.requestTask === 'function') {
// @ts-ignore
options.requestTask(xdr);
}
});
}
const RESTController = {
ajax(method, url, data, headers, options) {
var _context;
if (useXDomainRequest) {
return ajaxIE9(method, url, data, headers, options);
}
const promise = (0, _promiseUtils.resolvingPromise)();
const isIdempotent = _CoreManager.default.get('IDEMPOTENCY') && (0, _includes.default)(_context = ['POST', 'PUT']).call(_context, method);
const requestId = isIdempotent ? (0, _uuid.default)() : '';
let attempts = 0;
const dispatch = function () {
if (XHR == null) {
throw new Error('Cannot make a request: No definition of XMLHttpRequest was found.');
}
let handled = false;
const xhr = new XHR();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4 || handled || xhr._aborted) {
return;
}
handled = true;
if (xhr.status >= 200 && xhr.status < 300) {
let response;
try {
var _context2, _context3;
response = JSON.parse(xhr.responseText);
const availableHeaders = typeof xhr.getAllResponseHeaders === 'function' ? xhr.getAllResponseHeaders() : '';
headers = {};
if (typeof xhr.getResponseHeader === 'function' && ((_context2 = availableHeaders) == null ? void 0 : (0, _bind.default)(_context3 = Function.call).call(_context3, (0, _indexOf.default)(_context2), _context2))?.('access-control-expose-headers') >= 0) {
const responseHeaders = xhr.getResponseHeader('access-control-expose-headers').split(', ');
(0, _forEach.default)(responseHeaders).call(responseHeaders, header => {
if ((0, _indexOf.default)(availableHeaders).call(availableHeaders, header.toLowerCase()) >= 0) {
headers[header] = xhr.getResponseHeader(header.toLowerCase());
}
});
}
} catch (e) {
promise.reject(e.toString());
}
if (response) {
promise.resolve({
response,
headers,
status: xhr.status,
xhr
});
}
} else if (xhr.status >= 500 || xhr.status === 0) {
// retry on 5XX or node-xmlhttprequest error
if (++attempts < _CoreManager.default.get('REQUEST_ATTEMPT_LIMIT')) {
// Exponentially-growing random delay
const delay = Math.round(Math.random() * 125 * Math.pow(2, attempts));
(0, _setTimeout2.default)(dispatch, delay);
} else if (xhr.status === 0) {
promise.reject('Unable to connect to the Parse API');
} else {
// After the retry limit is reached, fail
promise.reject(xhr);
}
} else {
promise.reject(xhr);
}
};
headers = headers || {};
if (typeof headers['Content-Type'] !== 'string') {
headers['Content-Type'] = 'text/plain'; // Avoid pre-flight
}
if (_CoreManager.default.get('IS_NODE')) {
headers['User-Agent'] = 'Parse/' + _CoreManager.default.get('VERSION') + ' (NodeJS ' + process.versions.node + ')';
}
if (isIdempotent) {
headers['X-Parse-Request-Id'] = requestId;
}
if (_CoreManager.default.get('SERVER_AUTH_TYPE') && _CoreManager.default.get('SERVER_AUTH_TOKEN')) {
headers['Authorization'] = _CoreManager.default.get('SERVER_AUTH_TYPE') + ' ' + _CoreManager.default.get('SERVER_AUTH_TOKEN');
}
const customHeaders = _CoreManager.default.get('REQUEST_HEADERS');
for (const key in customHeaders) {
headers[key] = customHeaders[key];
}
if (options && typeof options.progress === 'function') {
const handleProgress = function (type, event) {
if (event.lengthComputable) {
options.progress(event.loaded / event.total, event.loaded, event.total, {
type
});
} else {
options.progress(null, null, null, {
type
});
}
};
xhr.onprogress = event => {
handleProgress('download', event);
};
if (xhr.upload) {
xhr.upload.onprogress = event => {
handleProgress('upload', event);
};
}
}
xhr.open(method, url, true);
for (const h in headers) {
xhr.setRequestHeader(h, headers[h]);
}
xhr.onabort = function () {
promise.resolve({
response: {
results: []
},
status: 0,
xhr
});
};
xhr.send(data);
// @ts-ignore
if (options && typeof options.requestTask === 'function') {
// @ts-ignore
options.requestTask(xhr);
}
};
dispatch();
return promise;
},
request(method, path, data, options) {
options = options || {};
let url = _CoreManager.default.get('SERVER_URL');
if (url[url.length - 1] !== '/') {
url += '/';
}
url += path;
const payload = {};
if (data && typeof data === 'object') {
for (const k in data) {
payload[k] = data[k];
}
}
// Add context
const context = options.context;
if (context !== undefined) {
payload._context = context;
}
if (method !== 'POST') {
payload._method = method;
method = 'POST';
}
payload._ApplicationId = _CoreManager.default.get('APPLICATION_ID');
const jsKey = _CoreManager.default.get('JAVASCRIPT_KEY');
if (jsKey) {
payload._JavaScriptKey = jsKey;
}
payload._ClientVersion = _CoreManager.default.get('VERSION');
let useMasterKey = options.useMasterKey;
if (typeof useMasterKey === 'undefined') {
useMasterKey = _CoreManager.default.get('USE_MASTER_KEY');
}
if (useMasterKey) {
if (_CoreManager.default.get('MASTER_KEY')) {
delete payload._JavaScriptKey;
payload._MasterKey = _CoreManager.default.get('MASTER_KEY');
} else {
throw new Error('Cannot use the Master Key, it has not been provided.');
}
}
if (options.useMaintenanceKey) {
payload._MaintenanceKey = _CoreManager.default.get('MAINTENANCE_KEY');
}
if (_CoreManager.default.get('FORCE_REVOCABLE_SESSION')) {
payload._RevocableSession = '1';
}
const installationId = options.installationId;
let installationIdPromise;
if (installationId && typeof installationId === 'string') {
installationIdPromise = _promise.default.resolve(installationId);
} else {
const installationController = _CoreManager.default.getInstallationController();
installationIdPromise = installationController.currentInstallationId();
}
return installationIdPromise.then(iid => {
payload._InstallationId = iid;
const userController = _CoreManager.default.getUserController();
if (options && typeof options.sessionToken === 'string') {
return _promise.default.resolve(options.sessionToken);
} else if (userController) {
return userController.currentUserAsync().then(user => {
if (user) {
return _promise.default.resolve(user.getSessionToken());
}
return _promise.default.resolve(null);
});
}
return _promise.default.resolve(null);
}).then(token => {
if (token) {
payload._SessionToken = token;
}
const payloadString = (0, _stringify.default)(payload);
return RESTController.ajax(method, url, payloadString, {}, options).then(_ref => {
let {
response,
status,
headers,
xhr
} = _ref;
if (options.returnStatus) {
return {
...response,
_status: status,
_headers: headers,
_xhr: xhr
};
} else {
return response;
}
});
}).catch(RESTController.handleError);
},
handleError(response) {
// Transform the error into an instance of ParseError by trying to parse
// the error string as JSON
let error;
if (response && response.responseText) {
try {
const errorJSON = JSON.parse(response.responseText);
error = new _ParseError.default(errorJSON.code, errorJSON.error);
} catch (_) {
// If we fail to parse the error text, that's okay.
error = new _ParseError.default(_ParseError.default.INVALID_JSON, 'Received an error with invalid JSON from Parse: ' + response.responseText);
}
} else {
const message = response.message ? response.message : response;
error = new _ParseError.default(_ParseError.default.CONNECTION_FAILED, 'XMLHttpRequest failed: ' + (0, _stringify.default)(message));
}
return _promise.default.reject(error);
},
_setXHR(xhr) {
XHR = xhr;
},
_getXHR() {
return XHR;
}
};
var _default = exports.default = RESTController;