72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import "server-only";
|
|
|
|
import {
|
|
type AnyVariables,
|
|
type TypedDocumentNode,
|
|
cacheExchange,
|
|
createClient,
|
|
fetchExchange,
|
|
stringifyDocument,
|
|
} from "@urql/core";
|
|
import { registerUrql } from "@urql/next/rsc";
|
|
|
|
import { cmsCache, cmsCacheForToday } from "@/lib/cmsCache";
|
|
|
|
const wagtailBaseUrl = process.env.WAGTAIL_BASE_URL;
|
|
if (!wagtailBaseUrl) {
|
|
throw new Error("WAGTAIL_BASE_URL is not set");
|
|
}
|
|
const graphqlEndpoint = `${wagtailBaseUrl.replace(/\/$/, "")}/api/graphql/`;
|
|
|
|
const makeClient = () => {
|
|
return createClient({
|
|
url: graphqlEndpoint,
|
|
exchanges: [cacheExchange, fetchExchange],
|
|
});
|
|
};
|
|
|
|
// Uncached. Only for per-user (search) and token-scoped (preview) queries,
|
|
// together with the `uncached` context; everything else goes through cmsQuery
|
|
export const { getClient } = registerUrql(makeClient);
|
|
|
|
// Throws on GraphQL and network errors, which keeps them out of the cache
|
|
async function runQuery(query: string, variables: AnyVariables) {
|
|
const { data, error } = await getClient().query(query, variables);
|
|
if (error) throw new Error(error.message);
|
|
return data;
|
|
}
|
|
|
|
// The cached functions take the query as text: their arguments are the cache
|
|
// key, and urql adds bookkeeping properties to document objects it has seen
|
|
async function cachedQuery(query: string, variables: AnyVariables) {
|
|
"use cache";
|
|
cmsCache();
|
|
return runQuery(query, variables);
|
|
}
|
|
|
|
async function cachedQueryForToday(query: string, variables: AnyVariables) {
|
|
"use cache";
|
|
cmsCacheForToday();
|
|
return runQuery(query, variables);
|
|
}
|
|
|
|
// Every cacheable CMS read goes through one of the two functions below, so
|
|
// all of them carry the tag the CMS webhook purges
|
|
|
|
// Cached until the content is edited in the CMS
|
|
export function cmsQuery<Data, Variables extends AnyVariables>(
|
|
document: TypedDocumentNode<Data, Variables>,
|
|
variables: Variables
|
|
): Promise<Data | undefined> {
|
|
return cachedQuery(stringifyDocument(document), variables);
|
|
}
|
|
|
|
// For queries where the CMS decides by today's date what to return
|
|
// (futureEvents): also purged at Oslo midnight
|
|
export function cmsQueryForToday<Data, Variables extends AnyVariables>(
|
|
document: TypedDocumentNode<Data, Variables>,
|
|
variables: Variables
|
|
): Promise<Data | undefined> {
|
|
return cachedQueryForToday(stringifyDocument(document), variables);
|
|
}
|