mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Simplify and improve pagination
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { ctx, handleError, PagedResponse, userAgent } from './helpers'
|
||||
import { ctx, handleError, PagedResponse, parseHeaderLinks, userAgent } from './helpers'
|
||||
|
||||
export type Params = {
|
||||
method: 'get' | 'post' | 'put' | 'delete'
|
||||
@ -49,29 +49,7 @@ const apiGeneral = async <T = unknown>({
|
||||
? (body as (FormData & { _parts: [][] }) | undefined)?._parts?.length
|
||||
: Object.keys(body).length) && { data: body })
|
||||
})
|
||||
.then(response => {
|
||||
let links: {
|
||||
prev?: { id: string; isOffset: boolean }
|
||||
next?: { id: string; isOffset: boolean }
|
||||
} = {}
|
||||
|
||||
if (response.headers?.link) {
|
||||
const linksParsed = response.headers.link.matchAll(
|
||||
new RegExp('[?&](.*?_id|offset)=(.*?)>; *rel="(.*?)"', 'gi')
|
||||
)
|
||||
for (const link of linksParsed) {
|
||||
switch (link[3]) {
|
||||
case 'prev':
|
||||
links.prev = { id: link[2], isOffset: link[1].includes('offset') }
|
||||
break
|
||||
case 'next':
|
||||
links.next = { id: link[2], isOffset: link[1].includes('offset') }
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve({ body: response.data, links })
|
||||
})
|
||||
.then(response => ({ body: response.data, links: parseHeaderLinks(response.headers.link) }))
|
||||
.catch(handleError())
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import * as Sentry from '@sentry/react-native'
|
||||
import chalk from 'chalk'
|
||||
import Constants from 'expo-constants'
|
||||
import { Platform } from 'react-native'
|
||||
import parse from 'url-parse'
|
||||
|
||||
const userAgent = {
|
||||
'User-Agent': `tooot/${Constants.expoConfig?.version} ${Platform.OS}/${Platform.Version}`
|
||||
@ -64,10 +65,42 @@ const handleError =
|
||||
}
|
||||
}
|
||||
|
||||
export const parseHeaderLinks = (headerLink?: string): PagedResponse['links'] => {
|
||||
if (!headerLink) return undefined
|
||||
|
||||
const links: PagedResponse['links'] = {}
|
||||
|
||||
const linkParsed = [...headerLink.matchAll(/<(\S+?)>; *rel="(next|prev)"/gi)]
|
||||
for (const link of linkParsed) {
|
||||
const queries = parse(link[1], true).query
|
||||
const isOffset = !!queries.offset?.length
|
||||
|
||||
switch (link[2]) {
|
||||
case 'prev':
|
||||
const prevId = isOffset ? queries.offset : queries.min_id
|
||||
if (prevId) links.prev = isOffset ? { offset: prevId } : { min_id: prevId }
|
||||
break
|
||||
case 'next':
|
||||
const nextId = isOffset ? queries.offset : queries.max_id
|
||||
if (nextId) links.next = isOffset ? { offset: nextId } : { max_id: nextId }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (links.prev || links.next) {
|
||||
return links
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
type LinkFormat = { id: string; isOffset: boolean }
|
||||
export type PagedResponse<T = unknown> = {
|
||||
body: T
|
||||
links?: { prev?: LinkFormat; next?: LinkFormat }
|
||||
links?: {
|
||||
prev?: { min_id: string } | { offset: string }
|
||||
next?: { max_id: string } | { offset: string }
|
||||
}
|
||||
}
|
||||
|
||||
export { ctx, handleError, userAgent }
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { getAccountDetails } from '@utils/storage/actions'
|
||||
import axios, { AxiosRequestConfig } from 'axios'
|
||||
import { ctx, handleError, PagedResponse, userAgent } from './helpers'
|
||||
import { ctx, handleError, PagedResponse, parseHeaderLinks, userAgent } from './helpers'
|
||||
|
||||
export type Params = {
|
||||
method: 'get' | 'post' | 'put' | 'delete' | 'patch'
|
||||
@ -57,29 +57,7 @@ const apiInstance = async <T = unknown>({
|
||||
...((body as (FormData & { _parts: [][] }) | undefined)?._parts.length && { data: body }),
|
||||
...extras
|
||||
})
|
||||
.then(response => {
|
||||
let links: {
|
||||
prev?: { id: string; isOffset: boolean }
|
||||
next?: { id: string; isOffset: boolean }
|
||||
} = {}
|
||||
|
||||
if (response.headers?.link) {
|
||||
const linksParsed = response.headers.link.matchAll(
|
||||
new RegExp('[?&](.*?_id|offset)=(.*?)>; *rel="(.*?)"', 'gi')
|
||||
)
|
||||
for (const link of linksParsed) {
|
||||
switch (link[3]) {
|
||||
case 'prev':
|
||||
links.prev = { id: link[2], isOffset: link[1].includes('offset') }
|
||||
break
|
||||
case 'next':
|
||||
links.next = { id: link[2], isOffset: link[1].includes('offset') }
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve({ body: response.data, links })
|
||||
})
|
||||
.then(response => ({ body: response.data, links: parseHeaderLinks(response.headers.link) }))
|
||||
.catch(handleError())
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user