fix: replace revalidate with cache force-cache for SSG compatibility

This commit is contained in:
Ilia Mashkov
2026-04-23 21:45:40 +03:00
parent 5dbf5e34c2
commit f0fccd55f1
6 changed files with 154 additions and 32 deletions
+26 -23
View File
@@ -1,9 +1,16 @@
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';
const PB_URL =
process.env.NEXT_PUBLIC_PB_URL ||
(process.env.NODE_ENV === 'production'
? (() => {
throw new Error('NEXT_PUBLIC_PB_URL is not set');
})()
: 'http://127.0.0.1:8090');
/**
* Options for PocketBase collection fetching.
@@ -21,46 +28,42 @@ export type PBFetchOptions = {
* 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 { sort, filter, expand } = options;
const params = new URLSearchParams();
if (sort) params.set('sort', sort);
if (filter) params.set('filter', filter);
if (expand) params.set('expand', expand);
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 },
});
/* force-cache deduplicates identical fetches during the static build phase;
* it has no runtime effect in `output: 'export'` mode. */
const res = await fetch(url, { cache: 'force-cache' });
if (!res.ok) {
throw new Error(`Failed to fetch collection: ${collection}`);
throw new Error(`PocketBase ${res.status} ${res.statusText} on collection "${collection}"`);
}
return res.json();
}
/**
* Fetch a single record from a PocketBase collection by ID or filter.
* Fetch the first record matching an optional filter from a PocketBase collection.
*/
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;
const data = await getCollection<T>(collection, options);
return data.items[0] ?? null;
}