73 lines
1.6 KiB
TypeScript
73 lines
1.6 KiB
TypeScript
|
|
import type { ListResponse } from './types'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Native fetch wrapper for PocketBase API requests.
|
||
|
|
*/
|
||
|
|
const PB_URL = process.env.NEXT_PUBLIC_PB_URL || 'http://127.0.0.1:8090'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Options for PocketBase collection fetching.
|
||
|
|
*/
|
||
|
|
export type PBFetchOptions = {
|
||
|
|
/**
|
||
|
|
* Sorting criteria (e.g., "-created,order")
|
||
|
|
*/
|
||
|
|
sort?: string
|
||
|
|
/**
|
||
|
|
* Filter query string
|
||
|
|
*/
|
||
|
|
filter?: string
|
||
|
|
/**
|
||
|
|
* Fields to expand (e.g., "stack")
|
||
|
|
*/
|
||
|
|
expand?: string
|
||
|
|
/**
|
||
|
|
* Cache revalidation time in seconds
|
||
|
|
* @default 3600
|
||
|
|
*/
|
||
|
|
revalidate?: number
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch a list of records from a PocketBase collection.
|
||
|
|
*/
|
||
|
|
export async function getCollection<T>(
|
||
|
|
collection: string,
|
||
|
|
options: PBFetchOptions = {}
|
||
|
|
): Promise<ListResponse<T>> {
|
||
|
|
const { sort, filter, expand, revalidate = 3600 } = options
|
||
|
|
|
||
|
|
const params = new URLSearchParams()
|
||
|
|
if (sort) params.set('sort', sort)
|
||
|
|
if (filter) params.set('filter', filter)
|
||
|
|
if (expand) params.set('expand', expand)
|
||
|
|
|
||
|
|
const url = `${PB_URL}/api/collections/${collection}/records?${params.toString()}`
|
||
|
|
|
||
|
|
const res = await fetch(url, {
|
||
|
|
next: { revalidate },
|
||
|
|
})
|
||
|
|
|
||
|
|
if (!res.ok) {
|
||
|
|
throw new Error(`Failed to fetch collection: ${collection}`)
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.json()
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch a single record from a PocketBase collection by ID or filter.
|
||
|
|
*/
|
||
|
|
export async function getFirstRecord<T>(
|
||
|
|
collection: string,
|
||
|
|
options: PBFetchOptions = {}
|
||
|
|
): Promise<T | null> {
|
||
|
|
const data = await getCollection<T>(collection, {
|
||
|
|
...options,
|
||
|
|
// PocketBase convention for "first" or "singleton" patterns
|
||
|
|
filter: options.filter,
|
||
|
|
})
|
||
|
|
|
||
|
|
return data.items[0] || null
|
||
|
|
}
|