}
+/**
+ * @param {String} method
+ * @param {String} url
+ * @param {Object} events
+ * @return {XMLHttpRequest}
+ */
+export function createXMLHttpRequest(method, url, events = {}) {
+ const csrfToken = document.querySelector('meta[name=token]').getAttribute('content');
+ const req = new XMLHttpRequest();
+
+ for (const [eventName, callback] of Object.entries(events)) {
+ req.addEventListener(eventName, callback.bind(req));
+ }
+
+ req.open(method, url);
+ req.withCredentials = true;
+ req.setRequestHeader('X-CSRF-TOKEN', csrfToken);
+
+ return req;
+}
+
/**
* Create a new HTTP request, setting the required CSRF information
* to communicate with the back-end. Parses & formats the response.
}
export {performDelete as delete};
+
+/**
+ * Parse the response text for an error response to a user
+ * presentable string. Handles a range of errors responses including
+ * validation responses & server response text.
+ * @param {String} text
+ * @returns {String}
+ */
+export function formatErrorResponseText(text) {
+ const data = text.startsWith('{') ? JSON.parse(text) : {message: text};
+ if (!data) {
+ return text;
+ }
+
+ if (data.message || data.error) {
+ return data.message || data.error;
+ }
+
+ const values = Object.values(data);
+ const isValidation = values.every(val => {
+ return Array.isArray(val) || val.every(x => typeof x === 'string');
+ });
+
+ if (isValidation) {
+ return values.flat().join(' ');
+ }
+
+ return text;
+}