CSR Cache & Next.js
The browser cache is used with Core's createCsrCache, and /next's callApiSsrCache is added only when Next.js server Data Cache is needed.
The cache wrapper is also part of commonService.
The callApiClientCache/callApiServerCache code on this page explains only the cache part of the project-wide HTTP adapter. Since the generated service can be configured to import this function, it is clearer to first look at the overall structure of rxjsHttpService.ts/commonService.ts to understand the position and role of each wrapper.
CSR Cache (Client Cache)
createCsrCache<CacheName>()provides callApiCsrCache(callApiFn, serviceArgs, cacheOptions) and removeCsrCache(cacheName).
import {
createCsrCache,
type ServiceArguments,
} from "@byeolnaerim/typed-rx-http";
import type { paths as Paths } from "./@types/ApiTypes";
type CacheNames = "adminList" | "profile";
const csrCache = createCsrCache<CacheNames>();
export const callApiClientCache = <R>(
args: ServiceArguments<Paths, any, any, R>,
cache: {
cacheName: CacheNames;
cacheTime: number;
cacheSize?: number;
},
) => csrCache.callApiCsrCache(
client.callApi,
args as any,
cache as any,
);
csrCache.removeCsrCache("adminList");
csrCache.removeCsrCache("any-prefix");In the server environment, it calls the original callApi without creating a CSR cache map. In the browser, it shares the Observable results of the same cache key using shareReplay.
Next.js Adapter: callApiSsrCache
This is an SSR helper that uses Next.js's next/cache (unstable_cache). If it's a GET request and cacheTime > 0, it uses force-cache + revalidate; otherwise, it executes with no-store.
- You can inject per-request Cookie/Authorization using headersProvider.
- If onServer401 exists at 401, it will be executed.
import type { paths as Paths } from "./@types/ApiTypes";
import { firstValueFrom } from "rxjs";
import {
callApiSsrCache,
redirectToUnauthorizedOnServer401,
} from "@byeolnaerim/typed-rx-http/next";
const apiUrl = process.env.NEXT_PUBLIC_API_URL!;
const headersProvider = async () => {
const { cookies } = await import("next/headers");
const cookieStore = await cookies();
const cookieHeader = cookieStore
.getAll()
.map((c) => `${c.name}=${c.value}`)
.join("; ");
const accessToken = cookieStore.get("accessToken")?.value;
return {
...(cookieHeader ? { Cookie: cookieHeader } : {}),
...(accessToken
? { Authorization: `Bearer ${accessToken}` }
: {}),
};
};
const obs$ = callApiSsrCache<Paths, { ok: true }, "adminList">({
baseUrl: apiUrl,
serviceArguments: { url: "/api/secure", method: "get" },
cacheForService: { cacheName: "adminList", cacheTime: 10_000 },
headersProvider,
onServer401: redirectToUnauthorizedOnServer401,
});
const res = await firstValueFrom(obs$);Do not cache user-specific data.
When bundling browser/server into a single project wrapper
In the shared service, the browser can branch to createCsrCache, and the server can branch to callApiSsrCache. This is a project configuration pattern and not a required structure of Core itself.
commonService.ts
tsconst csrCache = createCsrCache<"memberList" | "profile">();
export const callApiClientCache = (
serviceArguments,
cacheForService,
) => csrCache.callApiCsrCache(
callApi,
serviceArguments,
cacheForService,
);
export const removeCsrCache = csrCache.removeCsrCache;commonService.ts
tsexport const callApiServerCache = (serviceArguments, cacheForService) => {
if (typeof window !== "undefined") {
return callApiClientCache(serviceArguments, cacheForService);
}
return from(
import("@byeolnaerim/typed-rx-http/next"),
).pipe(
mergeMap(({ callApiSsrCache }) =>
callApiSsrCache({
baseUrl: process.env.NEXT_PUBLIC_API_URL || "",
serviceArguments,
cacheForService,
headersProvider,
}),
),
);
};When using the cache wrapper in the auto-generated service, connect this wrapper only to endpoints that need cache functionality, while using the regular callApi for the rest.