Skip to main content
Glama

Storyden

by Southclaws
Mozilla Public License 2.0
227
server.ts2.65 kB
import { cookies } from "next/headers"; import { notFound } from "next/navigation"; import { RequestError, buildRequest, buildResult } from "./common"; // Server side variant of fetcher that includes SSR cookies. type Options = RequestInit & { method: string; }; // Orval fetch generated code is a bit different to SWR fetcher for some reason. type Result<T> = { data: T; status: number; }; export const fetcher = async <T>( url: string, { method, ...opts }: Options, ): Promise<T> => { const { headers: requestHeaders, ...requestInit } = opts; const headers = Object.fromEntries(new Headers(requestHeaders).entries()); const req = buildRequest({ url, headers, method: method as any, data: requestInit.body, // Server side requests are cached a little more aggressively than client // side hydration requests. The downside of this is a user may see a flash // of stale data as the server render loads which will be replaced by the // client side hydration by SWR. However, the second call will most likely // be a 304 if it has been loaded before by the same user already. So, in a // best case, we get a single database read, worst case we get two. The // revalidation period is set to one minute in order to cut down on the // flashes of stale data. However, in reality this doesn't really gain much // as a user landing for the first time will still trigger two DB reads, // and a user returning is quite likely someone who has interacted with a // piece of content and thus will result in a new read at least once. So, // it's not the most efficient approach (ignoring server-side data cache) // but it's the best of a not-so-great situation. This should improve a lot // if Next.js adds support for HTTP Conditional Requests and ETag headers. revalidate: 60, cache: "force-cache", ...requestInit, }); req.headers.set("Cookie", await getCookieHeader()); const response = await fetch(req); try { const result = await buildResult<T>(response); // Orval generated types are incorrect here. For some reason it generates a // struct with a `data` field, but the actual result type is just the data. // However the generated caller passes T as Promise<T> so we need to cast it. return { data: result, status: response.status } as T; } catch (e) { if (e instanceof RequestError && e.status === 404) { notFound(); } throw e; } }; async function getCookieHeader(): Promise<string> { const c = await cookies(); return c .getAll() .map((c) => `${c.name}=${c.value}`) .join("; "); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Southclaws/storyden'

If you have feedback or need assistance with the MCP directory API, please join our Discord server