parse
Version:
Parse JavaScript SDK
320 lines • 12 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 _uuid = _interopRequireDefault(require("./uuid"));
var _CoreManager = _interopRequireDefault(require("./CoreManager"));
var _ParseError = _interopRequireDefault(require("./ParseError"));
var _promiseUtils = require("./promiseUtils");
var _Xhr = require("./Xhr.weapp");
var useXDomainRequest = false;
if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) {
useXDomainRequest = true;
}
function getPath(base, pathname) {
if (base.endsWith('/')) {
base = base.slice(0, -1);
}
if (!pathname.startsWith('/')) {
pathname = '/' + pathname;
}
return base + pathname;
}
function ajaxIE9(method, url, data, _headers, options) {
return new Promise(function (resolve, reject) {
var xdr = new XDomainRequest();
xdr.onload = function () {
var response;
try {
response = JSON.parse(xdr.responseText);
} catch (e) {
reject(e);
}
if (response) {
resolve({
response: response
});
}
};
xdr.onerror = xdr.ontimeout = function () {
var fakeResponse = {
responseText: JSON.stringify({
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);
if (options && typeof options.requestTask === 'function') {
options.requestTask(xdr);
}
});
}
var RESTController = {
ajax: function () {
var _ajax = (0, _asyncToGenerator2.default)(function* (method, url, data, headers, options) {
if (useXDomainRequest) {
return ajaxIE9(method, url, data, headers, options);
}
if (typeof fetch !== 'function') {
throw new Error('Cannot make a request: Fetch API not found.');
}
var promise = (0, _promiseUtils.resolvingPromise)();
var isIdempotent = _CoreManager.default.get('IDEMPOTENCY') && ['POST', 'PUT'].includes(method);
var requestId = isIdempotent ? (0, _uuid.default)() : '';
var attempts = 0;
var _dispatch = function () {
var _ref = (0, _asyncToGenerator2.default)(function* () {
var controller = new AbortController();
var signal = controller.signal;
headers = headers || {};
if (typeof headers['Content-Type'] !== 'string') {
headers['Content-Type'] = 'text/plain';
}
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;
}
var customHeaders = _CoreManager.default.get('REQUEST_HEADERS');
for (var key in customHeaders) {
headers[key] = customHeaders[key];
}
if (options && typeof options.requestTask === 'function') {
options.requestTask(controller);
}
try {
var fetchOptions = {
method: method,
headers: headers,
signal: signal,
redirect: 'manual'
};
if (data) {
fetchOptions.body = data;
}
var response = yield fetch(url, fetchOptions);
var status = response.status;
if (status >= 200 && status < 300) {
var result;
var responseHeaders = {};
var availableHeaders = response.headers.get('access-control-expose-headers') || '';
availableHeaders.split(', ').forEach(function (header) {
if (header && response.headers.has(header)) {
responseHeaders[header] = response.headers.get(header);
}
});
if (options && typeof options.progress === 'function' && response.body) {
var reader = response.body.getReader();
var length = +response.headers.get('Content-Length') || 0;
if (length === 0) {
options.progress(null, null, null);
result = yield response.json();
} else {
var recieved = 0;
var chunks = [];
while (true) {
var _yield$reader$read = yield reader.read(),
done = _yield$reader$read.done,
value = _yield$reader$read.value;
if (done) {
break;
}
chunks.push(value);
recieved += (value == null ? void 0 : value.length) || 0;
options.progress(recieved / length, recieved, length);
}
var body = new Uint8Array(recieved);
var offset = 0;
for (var chunk of chunks) {
body.set(chunk, offset);
offset += chunk.length;
}
var jsonString = new TextDecoder().decode(body);
result = JSON.parse(jsonString);
}
} else {
result = yield response.json();
}
promise.resolve({
status: status,
response: result,
headers: responseHeaders
});
} else if (status >= 400 && status < 500) {
var error = yield response.json();
promise.reject(error);
} else if ([301, 302, 303, 307, 308].includes(status)) {
var location = response.headers.get('location');
promise.resolve({
status: status,
location: location,
method: status === 303 ? 'GET' : method,
dropBody: status === 303
});
} else if (status >= 500 || status === 0) {
if (++attempts < _CoreManager.default.get('REQUEST_ATTEMPT_LIMIT')) {
var delay = Math.round(Math.random() * 125 * Math.pow(2, attempts));
setTimeout(_dispatch, delay);
} else if (status === 0) {
promise.reject('Unable to connect to the Parse API');
} else {
var _error = yield response.json();
promise.reject(_error);
}
} else {
promise.reject(response);
}
} catch (error) {
var _error$cause;
if (error.name === 'AbortError') {
promise.resolve({
response: {
results: []
},
status: 0
});
} else if (((_error$cause = error.cause) == null ? void 0 : _error$cause.code) === 'ECONNREFUSED') {
promise.reject('Unable to connect to the Parse API');
} else {
promise.reject(error);
}
}
});
return function () {
return _ref.apply(this, arguments);
};
}();
_dispatch();
return promise;
});
function ajax() {
return _ajax.apply(this, arguments);
}
return ajax;
}(),
request: function (method, path, data, options) {
options = options || {};
var url = getPath(_CoreManager.default.get('SERVER_URL'), path);
var payload = {};
if (data && typeof data === 'object') {
for (var k in data) {
payload[k] = data[k];
}
}
var context = options.context;
if (context !== undefined) {
payload._context = context;
}
if (method !== 'POST') {
payload._method = method;
method = 'POST';
}
payload._ApplicationId = _CoreManager.default.get('APPLICATION_ID');
var jsKey = _CoreManager.default.get('JAVASCRIPT_KEY');
if (jsKey) {
payload._JavaScriptKey = jsKey;
}
payload._ClientVersion = _CoreManager.default.get('VERSION');
var 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';
}
var installationId = options.installationId;
var installationIdPromise;
if (installationId && typeof installationId === 'string') {
installationIdPromise = Promise.resolve(installationId);
} else {
var installationController = _CoreManager.default.getInstallationController();
installationIdPromise = installationController.currentInstallationId();
}
return installationIdPromise.then(function (iid) {
payload._InstallationId = iid;
var userController = _CoreManager.default.getUserController();
if (options && typeof options.sessionToken === 'string') {
return Promise.resolve(options.sessionToken);
} else if (userController) {
return userController.currentUserAsync().then(function (user) {
if (user) {
return Promise.resolve(user.getSessionToken());
}
return Promise.resolve(null);
});
}
return Promise.resolve(null);
}).then(function (token) {
if (token) {
payload._SessionToken = token;
}
var payloadString = JSON.stringify(payload);
return RESTController.ajax(method, url, payloadString, {}, options).then(function () {
var _ref2 = (0, _asyncToGenerator2.default)(function* (result) {
if (result.location) {
var newURL = getPath(result.location, path);
var newMethod = result.method;
var newBody = result.dropBody ? undefined : payloadString;
for (var i = 0; i < 5; i += 1) {
var r = yield RESTController.ajax(newMethod, newURL, newBody, {}, options);
if (!r.location) {
result = r;
break;
}
newURL = getPath(r.location, path);
newMethod = r.method;
newBody = r.dropBody ? undefined : payloadString;
}
}
var _result = result,
response = _result.response,
status = _result.status,
headers = _result.headers;
if (options.returnStatus) {
return Object.assign({}, response, {
_status: status,
_headers: headers
});
} else {
return response;
}
});
return function () {
return _ref2.apply(this, arguments);
};
}());
}).catch(RESTController.handleError);
},
handleError: function (errorJSON) {
var error;
if (errorJSON.code || errorJSON.error || errorJSON.message) {
error = new _ParseError.default(errorJSON.code, errorJSON.error || errorJSON.message);
} else {
error = new _ParseError.default(_ParseError.default.CONNECTION_FAILED, 'XMLHttpRequest failed: ' + JSON.stringify(errorJSON));
}
return Promise.reject(error);
}
};
var _default = exports.default = RESTController;