UNPKG

@itslanguage/api

Version:
244 lines (207 loc) 7.23 kB
import "core-js/modules/es.array.iterator"; import "core-js/modules/es.object.assign"; import "core-js/modules/es.promise"; import "core-js/modules/es.regexp.to-string"; import "core-js/modules/es.string.includes"; import "core-js/modules/es.string.replace"; import "core-js/modules/es.string.split"; import "core-js/modules/es.string.starts-with"; import "core-js/modules/es.string.trim"; import "core-js/modules/web.dom-collections.iterator"; import "core-js/modules/web.url"; /** * This file contains the settings and the communication mechanism for the ITSLanguage REST API. * * @module api/communication */ /** * Content-Type HTTP Header key. * @type {string} */ var CONTENT_TYPE = 'Content-Type'; /** * Authorization HTTP Header key. * @type {string} */ var AUTHORIZATION = 'Authorization'; /** * Content-Type HTTP Header value. * @type {string} */ var APPLICATION_JSON = 'application/json'; /** * Link header value. * @type {string} */ var LINK = 'link'; /** * The settings to use for the communication with the ITSLanguage API. */ export var settings = { apiUrl: 'https://api.itslanguage.nl', wsUrl: null, authorizationToken: null }; /** * Update the settings with the `newSettings`. * * @param {Object} newSettings - The settings to inject/update. * * @throws {Error} - When the given `newSettings` is something other than a object. */ export function updateSettings(newSettings) { if (!newSettings || !(newSettings instanceof Object)) { throw new Error('Please, only provide objects as settings.'); } Object.assign(settings, newSettings); } function parseLinkHeader(linkHeader) { var links = linkHeader.split(','); return links.reduce((acc, link) => { var [url, rel] = link.split(';'); url = url.replace(/<(.*)>/, '$1').trim(); rel = rel.replace(/rel="(.*)"/, '$1').trim(); acc[rel] = { url }; return acc; }, {}); } /** * Parse the response of a fetch request. * * Try to parse the given response body as JSON, if it isn't Leave the response as is. * * @param {Response} response - The response to parse. * * @throws {Promise<string>} - When the request wasn't okay and the contents of the response isn't * json. * @throws {Promise<Error>} - When the request wasn't okay and the contents of the response is json. * * @returns {Promise|Response} - The contents of a JSON response or the response itself if the body * is something other than JSON. */ function handleResponse(response) { var responseContentType = response.headers.get(CONTENT_TYPE); var responseLink = response.headers.get(LINK); var parsedLinkHeader = {}; if (responseLink) { parsedLinkHeader = parseLinkHeader(responseLink); } // The ITSLanguage API should return JSON. If t if (responseContentType && responseContentType.includes(APPLICATION_JSON)) { return response.json().then(json => { if (response.ok) { if (responseLink) { return Object.assign({ data: json }, parsedLinkHeader); } return json; } return Promise.reject(json); }); } if (!response.ok) { return Promise.reject(new Error(response.status + ": " + response.statusText)); } return response; } /** * Perform an HTTP request for the given method, url, body, and headers. * * In case the given url is a partial url, meaning it starts with a `/`, the base URL to the * ITSLanguage API is prepended. * * When a Object instance is provided as body, it'll be transformed into JSON. Unless it is either a * `URLSearchParams` or a `FormData` object. Anything else is sent as plain text. * * @param {string} method - The request METHOD ('GET', 'POST', 'PUT', 'DELETE'). * @param {string} url - The location to send the request to. * @param {*} [body] - Anything which needs to be sent somewhere. * @param {Headers} [headers] - Extra headers to send with the request. * * @returns {Promise<Object>} The response of the made request. */ export function request(method, url, body, headers) { var requestHeaders = headers || new Headers(); var requestBody = body; // In case of (any) object-type if (!(body instanceof URLSearchParams || body instanceof FormData) && body instanceof Object) { requestHeaders.set('Content-Type', 'application/json'); requestBody = JSON.stringify(body); } // In case of URLSearchParams if (body instanceof URLSearchParams) { requestHeaders.set('Content-Type', 'application/x-www-form-urlencoded'); requestBody = body.toString(); } // Prepend the url with the set url or use it complete when there was no url set. var requestURL = url; if (url.startsWith('/') || !url) { requestURL = "" + settings.apiUrl + url; } // Gather all the options var requestOptions = { method, headers: requestHeaders, body: requestBody }; // Use fetch to send the request out! return fetch(requestURL, requestOptions).then(handleResponse); } /** * Build a bearer token from the `authorizationToken` in the settings object. * * @throws {Error} When no authorizationToken is set. * * @returns {string} The generated bearer token. */ function getBearerToken() { if (!settings.authorizationToken) { throw new Error('Please authenticate first.'); } return "Bearer " + settings.authorizationToken; } /** * Add an access token to a given URL. * * @param {string} [url=''] - The URL to add an access token to. * @returns {string} An url with the access token appended. */ export function addAccessToken(url) { if (url === void 0) { url = ''; } if (!settings.authorizationToken) { return url; } return "" + url + (url.includes('?') ? '&' : '?') + "access_token=" + encodeURIComponent(settings.authorizationToken); } /** * Perform an HTTP request with the desired method, body, and headers to the given partial * ITSLanguage API URL. * * This request will add the ``Authorization`` header to the request. * * This function only allows to make calls to the ITSLanguage API. * * @param {string} method - The request METHOD ('GET', 'POST', 'PUT', 'DELETE'). * @param {string} url - The location to send the request to. * @param {*} [body] - Anything which needs to be sent somewhere. * @param {Headers} [headers] - Extra headers to send with the request. * * @throws {Promise<string>} - When the given `url` param is not a partial URL, or when there is no * authorisation token available. * * @returns {Promise<Object>} - The response from the ITSLanguage API. */ export function authorisedRequest(method, url, body, headers) { // XXX remove the URL truthy check when all parts of the SDK no longer build // a complete url by themselves using the "private" settings object of their // connection reference. if (url && !url.startsWith('/') && !url.startsWith(settings.apiUrl)) { return Promise.reject(new Error('Only relative ITSLanguage API URLs are allowed.')); } try { var requestHeaders = headers || new Headers(); requestHeaders.set(AUTHORIZATION, getBearerToken()); return request(method, url, body, requestHeaders); } catch (unauthorised) { return Promise.reject(new Error(unauthorised.message)); } }