import urlEncoder from 'encodeurl'; /** * Handles fetching. * * This class should not be used directly, but should instead be obtained * from {@link ServiceDescriptor#resourcefulEndpoint} or {@link ServiceDescriptor#businessEndpoint} * * @param {TransportDefaults?} options - The options to use with all fetch requests * @param {string?} encodeUri - Indicate whether to encode request URIs generated. Defaults `false` * * @property {TransportDefaults?} defaults - Stored from the initial 'options' parameter merged with the standard defaults * * @example * import Transport from '@pikselpalette/sequoia-js-client-sdk/lib/transport'; * * const transport = new Transport({method: 'POST'}); * transport.fetchWithDefaults('someurl').then((response) => console.log(response); * */ class Transport { /** * @typedef {Object} TransportDefaults * * Default fetch options to send with all `fetch` requests. * * @see {@link https://github.github.io/fetch/#options} */ constructor(fetchOptions = {}, encodeUri = false) { this.defaults = Object.assign( {}, { method: 'GET', mode: 'cors', headers: { 'Content-Type': 'application/vnd.piksel+json', Accept: 'application/json' } }, fetchOptions ); this.encodeUri = encodeUri; } /** * Encodes the request url if `this.encodeUri` is true. * * @param {string} url - the url to potentially encode */ encodeUrl(url) { if (this.encodeUri === true) { // use encodeUrl dep as it won't double-encode this.encodeUrl = u => urlEncoder(u); return urlEncoder(url); } this.encodeUrl = u => u; return url; } /** * Performs a {@link https://github.github.io/fetch/|fetch} with the default options from {@link Transport} * * @param {string} url - sequoia url * @param {object} options - [fetch options]{@link https://github.github.io/fetch/#options} * * @returns {Promise} */ fetchWithDefaults(url, options = {}) { return fetch( this.encodeUrl(url), Object.assign({}, this.defaults, options) ).then((response) => { if (!response.ok) { return response.json().then( (responseBody) => { const error = new Error(responseBody.message); error.response = response; throw error; }, () => { const error = new Error(response.statusText); error.response = response; throw error; } ); } if (response.status === 204) { return {}; } return response.json(); }); } /** * Performs an HTTP GET request * * @param {string} url - sequoia url * @param {object} options - [fetch options]{@link https://github.github.io/fetch/#options} * * @returns {Promise} */ get(url, options = {}) { return this.fetchWithDefaults(url, options); } /** * Performs an HTTP POST request * * @param {string} url - sequoia url * @param {object} options - [fetch options]{@link https://github.github.io/fetch/#options} * * @returns {Promise} */ post(url, options = {}) { return this.fetchWithDefaults( url, Object.assign({ method: 'POST' }, options) ); } /** * Performs an HTTP PUT request * * @param {string} url - sequoia url * @param {object} options - [fetch options]{@link https://github.github.io/fetch/#options} * * @returns {Promise} */ put(url, options = {}) { return this.fetchWithDefaults( url, Object.assign({ method: 'PUT' }, options) ); } /** * Performs an HTTP DELETE request * * @param {string} url - sequoia url * @param {object} options - [fetch options]{@link https://github.github.io/fetch/#options} * * @returns {Promise} */ destroy(url, options = {}) { return this.fetchWithDefaults( url, Object.assign({ method: 'DELETE' }, options) ); } } export default Transport;