feat: add Strapi API client and data fetching functions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
56
apps/web/src/lib/api.ts
Normal file
56
apps/web/src/lib/api.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type {
|
||||
Game,
|
||||
Documentary,
|
||||
Chapter,
|
||||
StrapiListResponse,
|
||||
StrapiResponse,
|
||||
} from "@afterlife/shared";
|
||||
import { strapiGet } from "./strapi";
|
||||
|
||||
export async function getGames(locale: string): Promise<StrapiListResponse<Game>> {
|
||||
return strapiGet({
|
||||
path: "/games",
|
||||
locale,
|
||||
params: {
|
||||
"populate[coverImage]": "*",
|
||||
"populate[documentary]": "*",
|
||||
"sort": "createdAt:desc",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getGameBySlug(slug: string, locale: string): Promise<StrapiResponse<Game>> {
|
||||
return strapiGet({
|
||||
path: "/games",
|
||||
locale,
|
||||
params: {
|
||||
"filters[slug][$eq]": slug,
|
||||
"populate[coverImage]": "*",
|
||||
"populate[screenshots]": "*",
|
||||
"populate[documentary][populate][chapters][populate]": "*",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getDocumentaryByGameSlug(
|
||||
slug: string,
|
||||
locale: string
|
||||
): Promise<Documentary | null> {
|
||||
const gameRes = await getGameBySlug(slug, locale);
|
||||
const game = Array.isArray(gameRes.data) ? gameRes.data[0] : gameRes.data;
|
||||
return game?.documentary ?? null;
|
||||
}
|
||||
|
||||
export async function getChapter(
|
||||
chapterId: number,
|
||||
locale: string
|
||||
): Promise<StrapiResponse<Chapter>> {
|
||||
return strapiGet({
|
||||
path: `/chapters/${chapterId}`,
|
||||
locale,
|
||||
params: {
|
||||
"populate[audioFile]": "*",
|
||||
"populate[coverImage]": "*",
|
||||
},
|
||||
});
|
||||
}
|
||||
35
apps/web/src/lib/strapi.ts
Normal file
35
apps/web/src/lib/strapi.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
const STRAPI_URL = process.env.STRAPI_URL || "http://localhost:1337";
|
||||
const STRAPI_TOKEN = process.env.STRAPI_API_TOKEN;
|
||||
|
||||
interface FetchOptions {
|
||||
path: string;
|
||||
params?: Record<string, string>;
|
||||
locale?: string;
|
||||
}
|
||||
|
||||
export async function strapiGet<T>({ path, params, locale }: FetchOptions): Promise<T> {
|
||||
const url = new URL(`/api${path}`, STRAPI_URL);
|
||||
|
||||
if (locale) url.searchParams.set("locale", locale);
|
||||
if (params) {
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
url.searchParams.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
const headers: HeadersInit = { "Content-Type": "application/json" };
|
||||
if (STRAPI_TOKEN) {
|
||||
headers.Authorization = `Bearer ${STRAPI_TOKEN}`;
|
||||
}
|
||||
|
||||
const res = await fetch(url.toString(), {
|
||||
headers,
|
||||
next: { revalidate: 60 },
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Strapi error: ${res.status} ${res.statusText}`);
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
Reference in New Issue
Block a user