Spaces:
Running
Running
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants'; | |
export const getModels = async (token: string = '') => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/models`, { | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
let models = res?.data ?? []; | |
models = models | |
.filter((models) => models) | |
// Sort the models | |
.sort((a, b) => { | |
// Check if models have position property | |
const aHasPosition = a.info?.meta?.position !== undefined; | |
const bHasPosition = b.info?.meta?.position !== undefined; | |
// If both a and b have the position property | |
if (aHasPosition && bHasPosition) { | |
return a.info.meta.position - b.info.meta.position; | |
} | |
// If only a has the position property, it should come first | |
if (aHasPosition) return -1; | |
// If only b has the position property, it should come first | |
if (bHasPosition) return 1; | |
// Compare case-insensitively by name for models without position property | |
const lowerA = a.name.toLowerCase(); | |
const lowerB = b.name.toLowerCase(); | |
if (lowerA < lowerB) return -1; | |
if (lowerA > lowerB) return 1; | |
// If same case-insensitively, sort by original strings, | |
// lowercase will come before uppercase due to ASCII values | |
if (a.name < b.name) return -1; | |
if (a.name > b.name) return 1; | |
return 0; // They are equal | |
}); | |
console.log(models); | |
return models; | |
}; | |
type ChatCompletedForm = { | |
model: string; | |
messages: string[]; | |
chat_id: string; | |
session_id: string; | |
}; | |
export const chatCompleted = async (token: string, body: ChatCompletedForm) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/chat/completed`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify(body) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
type ChatActionForm = { | |
model: string; | |
messages: string[]; | |
chat_id: string; | |
}; | |
export const chatAction = async (token: string, action_id: string, body: ChatActionForm) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/chat/actions/${action_id}`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify(body) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getTaskConfig = async (token: string = '') => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/config`, { | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const updateTaskConfig = async (token: string, config: object) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/config/update`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify(config) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const generateTitle = async ( | |
token: string = '', | |
model: string, | |
messages: string[], | |
chat_id?: string | |
) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/title/completions`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
model: model, | |
messages: messages, | |
...(chat_id && { chat_id: chat_id }) | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? 'New Chat'; | |
}; | |
export const generateTags = async ( | |
token: string = '', | |
model: string, | |
messages: string, | |
chat_id?: string | |
) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/tags/completions`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
model: model, | |
messages: messages, | |
...(chat_id && { chat_id: chat_id }) | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
try { | |
// Step 1: Safely extract the response string | |
const response = res?.choices[0]?.message?.content ?? ''; | |
// Step 2: Attempt to fix common JSON format issues like single quotes | |
const sanitizedResponse = response.replace(/['‘’`]/g, '"'); // Convert single quotes to double quotes for valid JSON | |
// Step 3: Find the relevant JSON block within the response | |
const jsonStartIndex = sanitizedResponse.indexOf('{'); | |
const jsonEndIndex = sanitizedResponse.lastIndexOf('}'); | |
// Step 4: Check if we found a valid JSON block (with both `{` and `}`) | |
if (jsonStartIndex !== -1 && jsonEndIndex !== -1) { | |
const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1); | |
// Step 5: Parse the JSON block | |
const parsed = JSON.parse(jsonResponse); | |
// Step 6: If there's a "tags" key, return the tags array; otherwise, return an empty array | |
if (parsed && parsed.tags) { | |
return Array.isArray(parsed.tags) ? parsed.tags : []; | |
} else { | |
return []; | |
} | |
} | |
// If no valid JSON block found, return an empty array | |
return []; | |
} catch (e) { | |
// Catch and safely return empty array on any parsing errors | |
console.error('Failed to parse response: ', e); | |
return []; | |
} | |
}; | |
export const generateEmoji = async ( | |
token: string = '', | |
model: string, | |
prompt: string, | |
chat_id?: string | |
) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/emoji/completions`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
model: model, | |
prompt: prompt, | |
...(chat_id && { chat_id: chat_id }) | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
const response = res?.choices[0]?.message?.content.replace(/["']/g, '') ?? null; | |
if (response) { | |
if (/\p{Extended_Pictographic}/u.test(response)) { | |
return response.match(/\p{Extended_Pictographic}/gu)[0]; | |
} | |
} | |
return null; | |
}; | |
export const generateSearchQuery = async ( | |
token: string = '', | |
model: string, | |
messages: object[], | |
prompt: string | |
) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/query/completions`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
model: model, | |
messages: messages, | |
prompt: prompt | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? prompt; | |
}; | |
export const generateMoACompletion = async ( | |
token: string = '', | |
model: string, | |
prompt: string, | |
responses: string[] | |
) => { | |
const controller = new AbortController(); | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/task/moa/completions`, { | |
signal: controller.signal, | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
model: model, | |
prompt: prompt, | |
responses: responses, | |
stream: true | |
}) | |
}).catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return [res, controller]; | |
}; | |
export const getPipelinesList = async (token: string = '') => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines/list`, { | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
let pipelines = res?.data ?? []; | |
return pipelines; | |
}; | |
export const uploadPipeline = async (token: string, file: File, urlIdx: string) => { | |
let error = null; | |
// Create a new FormData object to handle the file upload | |
const formData = new FormData(); | |
formData.append('file', file); | |
formData.append('urlIdx', urlIdx); | |
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines/upload`, { | |
method: 'POST', | |
headers: { | |
...(token && { authorization: `Bearer ${token}` }) | |
// 'Content-Type': 'multipart/form-data' is not needed as Fetch API will set it automatically | |
}, | |
body: formData | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const downloadPipeline = async (token: string, url: string, urlIdx: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines/add`, { | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify({ | |
url: url, | |
urlIdx: urlIdx | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const deletePipeline = async (token: string, id: string, urlIdx: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines/delete`, { | |
method: 'DELETE', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify({ | |
id: id, | |
urlIdx: urlIdx | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getPipelines = async (token: string, urlIdx?: string) => { | |
let error = null; | |
const searchParams = new URLSearchParams(); | |
if (urlIdx !== undefined) { | |
searchParams.append('urlIdx', urlIdx); | |
} | |
const res = await fetch(`${WEBUI_BASE_URL}/api/pipelines?${searchParams.toString()}`, { | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
let pipelines = res?.data ?? []; | |
return pipelines; | |
}; | |
export const getPipelineValves = async (token: string, pipeline_id: string, urlIdx: string) => { | |
let error = null; | |
const searchParams = new URLSearchParams(); | |
if (urlIdx !== undefined) { | |
searchParams.append('urlIdx', urlIdx); | |
} | |
const res = await fetch( | |
`${WEBUI_BASE_URL}/api/pipelines/${pipeline_id}/valves?${searchParams.toString()}`, | |
{ | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
} | |
) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getPipelineValvesSpec = async (token: string, pipeline_id: string, urlIdx: string) => { | |
let error = null; | |
const searchParams = new URLSearchParams(); | |
if (urlIdx !== undefined) { | |
searchParams.append('urlIdx', urlIdx); | |
} | |
const res = await fetch( | |
`${WEBUI_BASE_URL}/api/pipelines/${pipeline_id}/valves/spec?${searchParams.toString()}`, | |
{ | |
method: 'GET', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
} | |
} | |
) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const updatePipelineValves = async ( | |
token: string = '', | |
pipeline_id: string, | |
valves: object, | |
urlIdx: string | |
) => { | |
let error = null; | |
const searchParams = new URLSearchParams(); | |
if (urlIdx !== undefined) { | |
searchParams.append('urlIdx', urlIdx); | |
} | |
const res = await fetch( | |
`${WEBUI_BASE_URL}/api/pipelines/${pipeline_id}/valves/update?${searchParams.toString()}`, | |
{ | |
method: 'POST', | |
headers: { | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
...(token && { authorization: `Bearer ${token}` }) | |
}, | |
body: JSON.stringify(valves) | |
} | |
) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
if ('detail' in err) { | |
error = err.detail; | |
} else { | |
error = err; | |
} | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getBackendConfig = async () => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/config`, { | |
method: 'GET', | |
credentials: 'include', | |
headers: { | |
'Content-Type': 'application/json' | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getChangelog = async () => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/changelog`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json' | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getVersionUpdates = async () => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/version/updates`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json' | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getModelFilterConfig = async (token: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/config/model/filter`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const updateModelFilterConfig = async ( | |
token: string, | |
enabled: boolean, | |
models: string[] | |
) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/config/model/filter`, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
enabled: enabled, | |
models: models | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getWebhookUrl = async (token: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res.url; | |
}; | |
export const updateWebhookUrl = async (token: string, url: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
url: url | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res.url; | |
}; | |
export const getCommunitySharingEnabledStatus = async (token: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const toggleCommunitySharingEnabledStatus = async (token: string) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing/toggle`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err.detail; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |
export const getModelConfig = async (token: string): Promise<GlobalModelConfig> => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/config/models`, { | |
method: 'GET', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
} | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res.models; | |
}; | |
export interface ModelConfig { | |
id: string; | |
name: string; | |
meta: ModelMeta; | |
base_model_id?: string; | |
params: ModelParams; | |
} | |
export interface ModelMeta { | |
description?: string; | |
capabilities?: object; | |
profile_image_url?: string; | |
} | |
export interface ModelParams {} | |
export type GlobalModelConfig = ModelConfig[]; | |
export const updateModelConfig = async (token: string, config: GlobalModelConfig) => { | |
let error = null; | |
const res = await fetch(`${WEBUI_BASE_URL}/api/config/models`, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${token}` | |
}, | |
body: JSON.stringify({ | |
models: config | |
}) | |
}) | |
.then(async (res) => { | |
if (!res.ok) throw await res.json(); | |
return res.json(); | |
}) | |
.catch((err) => { | |
console.log(err); | |
error = err; | |
return null; | |
}); | |
if (error) { | |
throw error; | |
} | |
return res; | |
}; | |