Files
wondif_vue/app/composables/useStrapi.js
2026-05-07 21:04:27 +02:00

133 lines
3.4 KiB
JavaScript

export function useStrapi(endpoint, options = {}) {
const queryString = computed(() => {
const locale = unref(options.locale) ?? "fr-FR"
const sort = unref(options.sort) ?? null
const pageSize = unref(options.pageSize) ?? null
const populate = unref(options.populate) ?? null
const filters = unref(options.filters) ?? null
const query = new URLSearchParams()
query.set("locale", locale)
if (sort) {
query.set("sort[0]", sort)
}
if (typeof pageSize === "number") {
query.set("pagination[pageSize]", String(pageSize))
}
if (populate && typeof populate === "object") {
appendPopulate(query, populate)
}
if (filters && typeof filters === "object") {
appendFilters(query, filters)
}
return query.toString()
})
const fetchAll = computed(() => Boolean(unref(options.fetchAll)))
const asyncDataKey = computed(() => `${endpoint}:${queryString.value}:fetchAll=${fetchAll.value}`)
const { data, pending, error, refresh } = useAsyncData(
asyncDataKey,
async () => {
const baseUrl = `${endpoint}?${queryString.value}`
if (!fetchAll.value) {
return await $fetch(baseUrl)
}
const firstPage = await $fetch(addPageParam(baseUrl, 1))
const pageCount = Number(firstPage?.meta?.pagination?.pageCount || 1)
if (pageCount <= 1) {
return firstPage
}
const otherPages = await Promise.all(
Array.from({ length: pageCount - 1 }, (_, index) => $fetch(addPageParam(baseUrl, index + 2)))
)
return {
...firstPage,
data: [
...(Array.isArray(firstPage?.data) ? firstPage.data : []),
...otherPages.flatMap((page) => (Array.isArray(page?.data) ? page.data : [])),
],
}
},
{
server: true,
watch: [queryString, fetchAll],
}
)
const items = computed(() => {
const raw = data.value?.data
let list = []
if (Array.isArray(raw)) {
list = raw.map(normalizeStrapiItem)
} else if (raw && typeof raw === "object") {
list = [normalizeStrapiItem(raw)]
}
const limit = unref(options.limit)
if (typeof limit === "number") {
list = list.slice(0, Math.max(0, limit))
}
return list
})
return {
items,
pending,
error,
refresh,
}
}
function addPageParam(url, page) {
const separator = url.includes("?") ? "&" : "?"
return `${url}${separator}pagination[page]=${page}`
}
function appendPopulate(query, populate, prefix = "populate") {
Object.entries(populate).forEach(([key, value]) => {
if (value === true) {
query.set(`${prefix}[${key}]`, "true")
return
}
if (value && typeof value === "object") {
appendPopulate(query, value, `${prefix}[${key}][populate]`)
}
})
}
function appendFilters(query, filters, prefix = "filters") {
Object.entries(filters).forEach(([key, value]) => {
if (value === null || value === undefined) return
if (typeof value !== "object") {
query.set(`${prefix}[${key}]`, String(value))
return
}
Object.entries(value).forEach(([k, v]) => {
if (v === null || v === undefined) return
if (typeof v !== "object") {
query.set(`${prefix}[${key}][${k}]`, String(v))
return
}
appendFilters(query, v, `${prefix}[${key}][${k}]`)
})
})
}
function normalizeStrapiItem(item) {
const a = item.attributes || item || {}
return {
id: item.id,
...a,
}
}