pleroma-fe/src/api/helpers.js

146 lines
3.2 KiB
JavaScript
Raw Normal View History

import { snakeCase } from 'lodash'
2026-06-13 03:10:00 +03:00
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
export const paramsString = (params = {}) => {
if (params == null || params === undefined) return ''
if (typeof params !== 'object' || Array.isArray(params)) {
throw new Error('Params are not an object!')
}
const entries = (() => {
if (params instanceof Map) {
return params.entries()
} else {
return Object.entries(params)
}
})()
if (entries.length === 0) return ''
const arrays = []
const nonArrays = []
entries.forEach(([k, v]) => {
if (v == null) return // Drop nulls
if (
(typeof v === 'object' && !Array.isArray(v)) ||
typeof v === 'function'
) {
throw new Error('Param cannot be non-primitive!')
}
if (Array.isArray(v)) {
arrays.push([k, v])
} else {
nonArrays.push([k, v])
}
})
arrays.forEach(([k, array]) => {
array.forEach((v) => {
if (
typeof v === 'object' ||
typeof v === 'function' ||
typeof v === 'undefined'
)
throw new Error('Array param cannot contain non-primitives!')
})
})
return (
'?' +
[
...nonArrays.map(([k, v]) => [snakeCase(k), v]),
// turning [a,[1,2,3]] into [[a[],1],[a[],2],[a[],3]]
...arrays.reduce(
(acc, [k, arrayValue]) => [
...acc,
...arrayValue.map((v) => [snakeCase(k) + '[]', v]),
],
[],
),
]
.map(([k, v]) => `${k}=${window.encodeURIComponent(v)}`)
.join('&')
)
}
export const promisedRequest = async ({
2026-06-13 03:10:00 +03:00
method,
url,
payload,
formData,
credentials,
headers = {},
}) => {
const options = {
method,
credentials: 'same-origin',
headers: {
Accept: 'application/json',
...headers,
},
}
2026-06-13 03:10:00 +03:00
if (!formData) {
options.headers['Content-Type'] = 'application/json'
}
2026-06-13 03:10:00 +03:00
if (formData || payload) {
options.body = formData || JSON.stringify(payload)
}
if (credentials) {
options.headers = {
...options.headers,
...authHeaders(credentials),
}
}
let response = null
try {
response = await fetch(url, options)
const data = await (async () => {
const [contentType] = response.headers
.get('content-type')
.split(';')
.map((x) => x.toLowerCase().trim())
2026-06-22 16:13:30 +03:00
const contentLength = parseInt(response.headers.get('content-length'))
if (contentLength === 0) return null
switch (contentType) {
case 'text/plain':
return await response.text()
case 'application/json':
return await response.json()
default:
return await response.bytes()
}
})()
const { ok, status } = response
if (ok) {
return { response, status, data }
} else {
throw new StatusCodeError(
response.status,
data,
{ url, options },
response,
)
}
} catch (error) {
2026-06-23 18:26:01 +03:00
if (error.name === 'StatusCodeError') throw error
2026-06-22 20:54:34 +03:00
throw new Error(error, { url, options }, response)
}
2026-06-13 03:10:00 +03:00
}
const authHeaders = (accessToken) => {
if (accessToken) {
return { Authorization: `Bearer ${accessToken}` }
} else {
return {}
}
}