/**
* Options for creating the request init
* @typedef {Object} CreateDefaultRequestInitOptions
* @property {"POST" | "PUT" | "GET" | "DELETE"} [method="GET"] The HTTP method. One of POST, PUT, GET, DELETE.
* @property {Object.<string, string> | undefined} [headers] an optional object containing key values encoded in the headers of the request. The object should have string keys and string values.
* @property {Object.<string, any> | undefined} [body] an optional object containing key values encoded in the body of the request. The object should have string keys and string values.
* @property {"json" | "text"} [responseType="json"] the type of response expected. Defaults to json.
* @ignore
*/
/**
* Send a request to an API endpoint
* @param {string} url
* @param {CreateDefaultRequestInitOptions} options
* @returns {Promise<any>}
* @ignore
*/
export function request (url, {
responseType = "json",
method = "GET",
...options
} = {}) {
let fetchOptions = {
method,
headers: createJSONEncodedHeaders(options.headers),
body: options.body ? createJSONEncodedBody(options.body) : null,
redirect: "follow",
credentials: "include",
};
return fetch(url, fetchOptions)
.then(getErrorFromResponse)
.then(response => response[responseType]());
}
/**
* Create Headers from an object.
* @ignore
* @param {Object.<string, string> | undefined} headers an object containing key values encoded in the headers.
*/
function createHeadersFromObject(headers) {
let headersToAdd = new Headers();
if (headers !== undefined) {
for (let key of Object.keys(headers)) {
headersToAdd.append(key, headers[key]);
}
}
return headersToAdd;
}
/**
* Convert an object's keys and values into a json string for a json request
* @param {Object} body the object to be url encoded
* @ignore
*/
function createJSONEncodedBody(body) {
return JSON.stringify(body);
}
/**
* Create the default headers used in GET and DELETE requests.
* @param {Object.<string, string> | undefined} headers an object containing key values encoded in the headers.
* @returns {Headers}
* @ignore
*/
function createJSONEncodedHeaders(headers) {
let defaultHeaders = createHeadersFromObject(headers);
defaultHeaders.append("Content-Type", "application/json");
return defaultHeaders;
}
/**
* If the response is ok (status code in range 200-299) returns the response.
* Otherwise the method attempts to parse the response and get an error message
* from the server.
* @ignore
* @param {Response} response a response from the ChatServer
* @returns {Promise<Response>} the untransformed response
*/
export function getErrorFromResponse(response) {
return new Promise((resolve, reject) => {
if (response.ok) {
resolve(response);
}
else {
reject(response);
}
}).catch((responseOrError) => {
if (responseOrError instanceof Response) {
return responseOrError.json().then((errorJSON) => {
console.warn("api error", errorJSON.message);
throw new Error(errorJSON.message);
});
}
throw responseOrError;
});
}
/**
* Normalize an object to an array.
* If the object is an array, it will be returned, otherwise it will be wrapped with an array.
* @param {*} obj
* @returns Array
*/
export function toArray(obj) {
return Array.isArray(obj)? obj : [obj];
}
/**
* Compute the intersection of two iterables and return it as a set.
* @param {Iterable.<*>} arr1
* @param {Iterable.<*>} arr2
*/
export function intersection(arr1, arr2) {
arr1 = new Set(arr1);
arr2 = new Set(arr2);
return new Set([...arr1].filter(x => arr2.has(x)));
}
/**
* Remove duplicate values from an array
* @param {Array} arr The array to operate on.
* @returns {Array} The array with duplicates removed.
*/
export function unique(arr) {
return [...new Set(arr)];
}