UNPKG

http-toolkit

Version:

Well-documented toolkit for making elegant HTTP requests with JavaScript

430 lines (363 loc) 18.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.baseOptions = exports.defaultOptions = void 0; var _httpHeaders = require("../models/http-headers"); var _utils = require("../utils"); var _httpMediaTypes = require("../models/http-media-types"); function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var defaultOptions = { numberOfRetries: 0, retryWhen: function retryWhen(response) { return !(0, _utils.isResponseOk)(response); } }; exports.defaultOptions = defaultOptions; var baseOptions = function baseOptions(url, options, baseConfig) { return { /** * Get the currently set url * @returns {string} * @memberOf HttpClientOptions */ getUrl: function getUrl() { return url; }, /** * Get currently set options * @returns {Object} * @memberOf HttpClientOptions */ getOptions: function getOptions() { return options; }, /** * Adds or overwrites header key-value pairs. * @param {Headers|Object} headers - the object to merge with current headers. (if forceExact=true, then it replaces headers instead of merging) * @param {boolean} [forceExact:false] - if true, ignores previously set headers and just uses the provided headers * @returns {HttpClient} a copy of httpClient with new headers * @memberOf HttpClientOptions */ withHeaders: function withHeaders(headers) { var forceExact = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return baseConfig(url, setHeaders(headers, forceExact, options)); }, /** * Adds or overwrites a header. * @param {string} name Header name * @param {string} value Header value * @returns {HttpClient} a copy of httpClient with new headers * @memberOf HttpClientOptions */ withHeader: function withHeader(name, value) { return baseConfig(url, addHeader(name, value, options)); }, /** * Adds or overwrites key-value pairs with current options. * @param {Object} options - the object to merge with current options. (if forceExact=true, then it replaces headers instead of merging) * @param {boolean} [forceExact:false] - if true, ignores previously set headers and just uses the provided headers * @returns {HttpClient} a copy of httpClient with new options * @memberOf HttpClientOptions */ withOptions: function withOptions(options) { var forceExact = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return baseConfig(url, setOptions(options, forceExact, options)); }, /** * Adds or overwrites an option. * @param {string} name Option name * @param {string} value Option value * @returns {HttpClient} a copy of httpClient with new options * @memberOf HttpClientOptions */ withOption: function withOption(name, value) { return baseConfig(url, addOption(name, value, options)); }, /** * Sets Cross-Origin Resource Sharing (CORS) policy * @param {string} cors - policy * @returns {HttpClient} a copy of httpClient with new options * @memberOf HttpClientOptions * @example withCors('no-cors') */ withCors: function withCors() { var cors = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'cors'; return baseConfig(url, setOptions({ cors: cors }, false, options)); }, /** * Sets a new url. **Note** This will also replace any path set earlier. * @param {string} newUrl - The new url to set. * @returns {HttpClient} - a copy of httpClient new full url * @memberOf HttpClientOptions */ withUrl: function withUrl(newUrl) { return baseConfig(newUrl, options); }, /** * Appends a string to the current/base url. * @param {string} path The path to append at the end of base-url * @returns {HttpClient} a copy of httpClient new full url * @memberOf HttpClientOptions */ withPath: function withPath(path) { return baseConfig(url + path, options); }, /** * Sets a value to the Authorization-header. * @param {string} authValue The Authorization value * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ withAuth: function withAuth(authValue) { return baseConfig(url, addHeader(_httpHeaders.HttpHeader.AUTHORIZATION, authValue, options)); }, /** * Sets Authorization-header to "Bearer <token>". * @param {string} token The token value as a string * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ withToken: function withToken(token) { return baseConfig(url, addToken(token, options)); }, /** * Sets Content-Type header * @param {MediaType|string} contentType * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ withContentType: function withContentType(contentType) { return baseConfig(url, addHeader(_httpHeaders.HttpHeader.CONTENT_TYPE, contentType, options)); }, /** * Sets Accept header * @param {MediaType|string} acceptType * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ withAcceptType: function withAcceptType(acceptType) { return baseConfig(url, addHeader(_httpHeaders.HttpHeader.ACCEPT, acceptType, options)); }, /** * Sets application/json to the Accept header * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ acceptJson: function acceptJson() { return baseConfig(url, addHeader(_httpHeaders.HttpHeader.ACCEPT, _httpMediaTypes.MediaType.JSON, options)); }, /** * Sets a body to the client * @param {Object|string} body The body to attach in the request. If it's an object, it will be stringified * @returns {HttpClient} a copy of httpClient with updated body * @memberOf HttpClientOptions */ withBody: function withBody(body) { return baseConfig(url, setBody(body, options)); }, /** * Adds a single key-value pair to the query. If there was no query set previously, adds a leading '?'; else a '&'. * @param {string} key - the query-key to set. * @param {string} value - the query-value to set. * @returns {HttpClient} a copy of httpClient with new query * @memberOf HttpClientOptions * @example myClient.addQuery('foo','bar') */ addQuery: function addQuery(key, value) { return baseConfig(url, addQueryParam(key, value, options)); }, /** * Adds or overwrites the query-params defined as key-value pairs in queryObject. * @param {Object|Array<Object>} queries - the object or array of objects to merge with current queryParams. (if forceExact=true, then it replaces previously set query instead of merging) * @param {boolean} [forceExact:false] - if true, ignores previously set query and just uses the provided queryObject key-values * @returns {HttpClient} a copy of httpClient with new query * @memberOf HttpClientOptions * @example myClient.addQueries([{key: 'value'}, {anotherKey: 'anotherValue'}]) // Guaranteed same order as array * @example myClient.addQueries({key: 'value', anotherKey: 'anotherValue'} // Can't guarantee to be ordered */ addQueries: function addQueries(queries) { var forceExact = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return baseConfig(url, setQueryParams(queries, forceExact, options)); }, /** * Sets the query (it will replace any previously set queries). * @param {string} query - the query to set. * @returns {HttpClient} a copy of httpClient with new query * @memberOf HttpClientOptions * @example myClient.withQuery('foo=bar&hello=world') */ withQuery: function withQuery(query) { return baseConfig(url, _objectSpread({}, options, { query: query.startsWith('?') ? query : "?".concat(query) })); }, /** * Sets a timout in milliseconds. Will abort request and throw ApiError if timeout is reached before response. * @param {number} timeout - Milliseconds to wait for response. Default is unlimited * @returns {HttpClient} a copy of httpClient updated headers * @throws {ApiError} if timeout is reached before response * @memberOf HttpClientOptions */ withTimeout: function withTimeout(timeout) { return baseConfig(url, setOptions({ timeout: timeout }, false, options)); }, /** * Sets the number the request will retry until success. Success is default 2xx status code. If the retryWhen option is set (@see {@link retryWhen}), then the negated predicate provided is considered success. * @param {number} nbrRetries - Number of retries (default is 0) * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions */ withRetries: function withRetries(nbrRetries) { return baseConfig(url, setOptions({ numberOfRetries: nbrRetries }, false, options)); }, /** * Sets the predicate at which the request will retry if true. Default is `retryWhen(response => response.status !== 2xx )` * @param {function} predicate - (response => bool) Check e.g. the status code, *make sure not to use the response stream - use clone()* * @returns {HttpClient} a copy of httpClient updated headers * @memberOf HttpClientOptions * @example myClient.withRetries(5).retryWhen(response => isResponseStatus(response, 200)).getAsync() */ retryWhen: function retryWhen(predicate) { return baseConfig(url, setOptions({ retryWhen: predicate }, false, options)); }, /** * @function addPrefetch * @description Adds a pre-fetch function (function that will execute before each fetch) to the client's prefetch stack. * * *Prefetches are called in the order they are added.* * @param {prefetch} func - Function to be called before requests. Signature: (url, options) * @memberOf HttpClientOptions * @example * addPrefetch((url, options) => console.log(`sending a ${options.method}-request, body is ${options.body}`)) */ addPrefetch: function addPrefetch(func) { return baseConfig(url, _addPrefetch(func, options)); }, /** * @function addPostfetch * @description Adds a post-fetch function (function that will execute after each fetch) to the client's postfetch stack. * * *Postfetches are called in the order they are added* * @param {postfetch} func - Function to be called after requests. Signature: (url, options, response) * @memberOf HttpClientOptions * @example * addPostfetch((url, options, response) => console.log(`sent a ${options.method}-request, response was ${response}`)) */ addPostfetch: function addPostfetch(func) { return baseConfig(url, _addPostfetch(func, options)); } }; }; exports.baseOptions = baseOptions; var _addPostfetch = function _addPostfetch(func, options) { var postfetchStack = _toConsumableArray(options.postfetchStack || []); postfetchStack.push(func); return _objectSpread({}, options, { postfetchStack: postfetchStack }); }; var _addPrefetch = function _addPrefetch(func, options) { var prefetchStack = _toConsumableArray(options.prefetchStack || []); prefetchStack.push(func); return _objectSpread({}, options, { prefetchStack: prefetchStack }); }; var setHeaders = function setHeaders(newHeaders, force) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (force) { return _objectSpread({}, options, { headers: newHeaders }); } var headers = _objectSpread({}, options.headers || {}, {}, newHeaders); return _objectSpread({}, options, { headers: headers }); }; var addHeader = function addHeader(name, value, options) { return setHeaders(_defineProperty({}, name, value), false, options); }; var addAuthorization = function addAuthorization(authValue, options) { return addHeader(_httpHeaders.HttpHeader.AUTHORIZATION, authValue, options); }; var addToken = function addToken(token, options) { return addAuthorization("Bearer ".concat(token), options); }; var setOptions = function setOptions(newOptions, force) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (force) { return newOptions; } return _objectSpread({}, options, {}, newOptions); }; var addOption = function addOption(name, value) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return setOptions(_defineProperty({}, name, value), false, options); }; var setBody = function setBody(body, options) { var bodyString = body; if (typeof body !== 'string') { bodyString = JSON.stringify(body); } return addOption('body', bodyString, options); }; var encodeParam = function encodeParam(key, value) { return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)); }; var addQueryParam = function addQueryParam(key, value) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var query = String(options.query || ''); var param = encodeParam(key, value); query += query.length ? "&".concat(param) : "?".concat(param); return _objectSpread({}, options, { query: query }); }; var setQueryParams = function setQueryParams() { var queries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var force = arguments.length > 1 ? arguments[1] : undefined; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var entries = []; if (Array.isArray(queries)) { queries.forEach(function (q) { var _entries; return (_entries = entries).push.apply(_entries, _toConsumableArray(Object.entries(q))); }); } else { entries = Object.entries(queries); } var _entries$reverse$pop = entries.reverse().pop(), _entries$reverse$pop2 = _slicedToArray(_entries$reverse$pop, 2), firstKey = _entries$reverse$pop2[0], firstValue = _entries$reverse$pop2[1]; var firstParam = encodeParam(firstKey, firstValue); var query = !force && options.query ? "".concat(options.query, "&").concat(firstParam, "&") : "?".concat(firstParam, "&"); query += entries.map(function (entry) { return encodeParam(entry[0], entry[1]); }).join('&'); return _objectSpread({}, options, { query: query }); };