feat: allow FormData object to be passed in to the API module

Currently, only objects can be passed in, and it is automatically serialized into json and sent via jQuery .ajax().

This PR extends the module so a FormData object can be passed in, and updates the module so it uses Fetch API instead of jQuery.

At this time regular requests continue to use jQuery for backwards compatibility.

Use case: file uploads via API.
isekai-main
Julian Lam 2 years ago
parent a12a9bab7a
commit ed99ea20cb

@ -37,27 +37,60 @@ function call(options, callback) {
}
async function xhr(options, cb) {
// Allow options to be modified by plugins, etc.
({ options } = await fireHook('filter:api.options', { options }));
$.ajax(options)
.done((res) => {
cb(null, (
res &&
res.hasOwnProperty('status') &&
res.hasOwnProperty('response') ? res.response : (res || {})
));
})
.fail((ev) => {
let errMessage;
if (ev.responseJSON) {
errMessage = ev.responseJSON.status && ev.responseJSON.status.message ?
ev.responseJSON.status.message :
ev.responseJSON.error;
}
/**
* N.B. fetch api is only used when payload is a FormData object!
*
* This is because the passed-in options are different between fetch/jQuery .ajax()
* If we updated the code to use only fetch, it would be a breaking change.
*
* Prior to v3.3 there was no support for sending in FormData, so the addition of fetch
* handling is not breaking.
*
* Break this for v4 by making everything use fetch api.
*/
// Adjust options based on payload type
if (options.payload instanceof FormData) {
const url = options.url;
options.body = options.payload;
delete options.payload;
delete options.url;
// Allow options to be modified by plugins, etc.
({ options } = await fireHook('filter:api.fetchOptions', { options }));
await fetch(url, {
...options,
}).then((res) => {
cb(null, res);
}).catch(cb);
} else {
options.data = JSON.stringify(options.payload || {});
options.contentType = 'application/json; charset=utf-8';
delete options.payload;
// Allow options to be modified by plugins, etc.
({ options } = await fireHook('filter:api.options', { options }));
$.ajax(options)
.done((res) => {
cb(null, (
res &&
res.hasOwnProperty('status') &&
res.hasOwnProperty('response') ? res.response : (res || {})
));
})
.fail((ev) => {
let errMessage;
if (ev.responseJSON) {
errMessage = ev.responseJSON.status && ev.responseJSON.status.message ?
ev.responseJSON.status.message :
ev.responseJSON.error;
}
cb(new Error(errMessage || ev.statusText));
});
cb(new Error(errMessage || ev.statusText));
});
}
}
export function get(route, payload, onSuccess) {
@ -77,8 +110,7 @@ export function post(route, payload, onSuccess) {
return call({
url: route,
method: 'post',
data: JSON.stringify(payload || {}),
contentType: 'application/json; charset=utf-8',
payload,
headers: {
'x-csrf-token': config.csrf_token,
},
@ -89,8 +121,7 @@ export function patch(route, payload, onSuccess) {
return call({
url: route,
method: 'patch',
data: JSON.stringify(payload || {}),
contentType: 'application/json; charset=utf-8',
payload,
headers: {
'x-csrf-token': config.csrf_token,
},
@ -101,8 +132,7 @@ export function put(route, payload, onSuccess) {
return call({
url: route,
method: 'put',
data: JSON.stringify(payload || {}),
contentType: 'application/json; charset=utf-8',
payload,
headers: {
'x-csrf-token': config.csrf_token,
},

Loading…
Cancel
Save