u
This commit is contained in:
@@ -81,6 +81,62 @@ async function http(path, { method = 'GET', body } = {}) {
|
||||
return json;
|
||||
}
|
||||
|
||||
async function httpMultipart(path, { method = 'POST', formData } = {}) {
|
||||
const url = new URL(path, window.location.origin).href;
|
||||
|
||||
logApi('request', {
|
||||
method,
|
||||
path,
|
||||
url,
|
||||
origin: window.location.origin,
|
||||
credentials: 'include',
|
||||
multipart: true,
|
||||
});
|
||||
|
||||
const res = await fetch(path, {
|
||||
method,
|
||||
credentials: 'include',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const responseHeaders = readableHeaders(res.headers);
|
||||
logApi('response', {
|
||||
method,
|
||||
path,
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
ok: res.ok,
|
||||
responseHeaders,
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
let message = res.statusText;
|
||||
let data;
|
||||
try {
|
||||
data = await res.json();
|
||||
message = data.error || data.message || message;
|
||||
} catch {
|
||||
message = (await res.text().catch(() => message)) || message;
|
||||
}
|
||||
logApi('error-body', { method, path, status: res.status, message, data });
|
||||
const err = new Error(message || `Request failed (${res.status})`);
|
||||
err.status = res.status;
|
||||
err.path = path;
|
||||
err.method = method;
|
||||
err.data = data;
|
||||
throw err;
|
||||
}
|
||||
if (res.status === 204) return null;
|
||||
const json = await res.json();
|
||||
logApi('ok-body', {
|
||||
method,
|
||||
path,
|
||||
keys: json && typeof json === 'object' ? Object.keys(json) : typeof json,
|
||||
hasArticle: Boolean(json?.article),
|
||||
});
|
||||
return json;
|
||||
}
|
||||
|
||||
export const article = {
|
||||
search({ target, filter, offset, maxCount } = {}) {
|
||||
const params = new URLSearchParams({ target });
|
||||
@@ -118,6 +174,21 @@ export const article = {
|
||||
body,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* POST /api/article/:sku/photos — multipart/form-data
|
||||
* Body: file (image/avif, max 1000×1000, prepared client-side), optional sort (default 0)
|
||||
* → 201 { article }
|
||||
*/
|
||||
uploadPhoto(sku, file, { sort = 0 } = {}) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('sort', String(sort));
|
||||
return httpMultipart(`/api/article/${encodeURIComponent(sku)}/photos`, {
|
||||
method: 'POST',
|
||||
formData,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const category = {
|
||||
|
||||
Reference in New Issue
Block a user