UNPKG

react-relay

Version:

A framework for building data-driven React applications.

183 lines (158 loc) • 5.86 kB
/** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule RelayDefaultNetworkLayer * @typechecks * */ 'use strict'; var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; var _extends = require('babel-runtime/helpers/extends')['default']; var Promise = require('fbjs/lib/Promise'); var fetch = require('fbjs/lib/fetch'); var fetchWithRetries = require('fbjs/lib/fetchWithRetries'); var RelayDefaultNetworkLayer = (function () { // InitWithRetries function RelayDefaultNetworkLayer(uri, init) { _classCallCheck(this, RelayDefaultNetworkLayer); this._uri = uri; this._init = _extends({}, init); // Bind instance methods to facilitate reuse when creating custom network // layers. var self = this; self.sendMutation = this.sendMutation.bind(this); self.sendQueries = this.sendQueries.bind(this); self.supports = this.supports.bind(this); } /** * Rejects HTTP responses with a status code that is not >= 200 and < 300. * This is done to follow the internal behavior of `fetchWithRetries`. */ RelayDefaultNetworkLayer.prototype.sendMutation = function sendMutation(request) { return this._sendMutation(request).then(function (result) { return result.json(); }).then(function (payload) { if (payload.hasOwnProperty('errors')) { var error = new Error('Server request for mutation `' + request.getDebugName() + '` ' + 'failed for the following reasons:\n\n' + formatRequestErrors(request, payload.errors)); error.source = payload; request.reject(error); } else { request.resolve({ response: payload.data }); } })['catch'](function (error) { return request.reject(error); }); }; RelayDefaultNetworkLayer.prototype.sendQueries = function sendQueries(requests) { var _this = this; return Promise.all(requests.map(function (request) { return _this._sendQuery(request).then(function (result) { return result.json(); }).then(function (payload) { if (payload.hasOwnProperty('errors')) { var error = new Error('Server request for query `' + request.getDebugName() + '` ' + 'failed for the following reasons:\n\n' + formatRequestErrors(request, payload.errors)); error.source = payload; request.reject(error); } else if (!payload.hasOwnProperty('data')) { request.reject(new Error('Server response was missing for query `' + request.getDebugName() + '`.')); } else { request.resolve({ response: payload.data }); } })['catch'](function (error) { return request.reject(error); }); })); }; RelayDefaultNetworkLayer.prototype.supports = function supports() { // Does not support the only defined option, "defer". return false; }; /** * Sends a POST request with optional files. */ RelayDefaultNetworkLayer.prototype._sendMutation = function _sendMutation(request) { var init; var files = request.getFiles(); if (files) { if (!global.FormData) { throw new Error('Uploading files without `FormData` not supported.'); } var formData = new FormData(); formData.append('query', request.getQueryString()); formData.append('variables', JSON.stringify(request.getVariables())); for (var filename in files) { if (files.hasOwnProperty(filename)) { formData.append(filename, files[filename]); } } init = _extends({}, this._init, { body: formData, method: 'POST' }); } else { init = _extends({}, this._init, { body: JSON.stringify({ query: request.getQueryString(), variables: request.getVariables() }), headers: _extends({}, this._init.headers, { 'Content-Type': 'application/json' }), method: 'POST' }); } return fetch(this._uri, init).then(throwOnServerError); }; /** * Sends a POST request and retries if the request fails or times out. */ RelayDefaultNetworkLayer.prototype._sendQuery = function _sendQuery(request) { return fetchWithRetries(this._uri, _extends({}, this._init, { body: JSON.stringify({ query: request.getQueryString(), variables: request.getVariables() }), headers: _extends({}, this._init.headers, { 'Content-Type': 'application/json' }), method: 'POST' })); }; return RelayDefaultNetworkLayer; })(); function throwOnServerError(response) { if (response.status >= 200 && response.status < 300) { return response; } else { throw response; } } /** * Formats an error response from GraphQL server request. */ function formatRequestErrors(request, errors) { var CONTEXT_BEFORE = 20; var CONTEXT_LENGTH = 60; var queryLines = request.getQueryString().split('\n'); return errors.map(function (_ref, ii) { var locations = _ref.locations; var message = _ref.message; var prefix = ii + 1 + '. '; var indent = ' '.repeat(prefix.length); return prefix + message + '\n' + locations.map(function (_ref2) { var column = _ref2.column; var line = _ref2.line; var queryLine = queryLines[line - 1]; var offset = Math.min(column - 1, CONTEXT_BEFORE); return [queryLine.substr(column - 1 - offset, CONTEXT_LENGTH), ' '.repeat(offset) + '^^^'].map(function (messageLine) { return indent + messageLine; }).join('\n'); }).join('\n'); }).join('\n'); } module.exports = RelayDefaultNetworkLayer;