mirror of
https://github.com/lux-tel/websites.git
synced 2026-10-30 20:31:36 +00:00
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
import type { FilteredResponseQueryOptions, QueryParams, SanityClient } from 'next-sanity';
|
|
import { isDraftModeEnabled } from './util';
|
|
import { safeTry } from '@session/util-js/try';
|
|
import logger from './logger';
|
|
|
|
/**
|
|
* @see {@link https://nextjs.org/docs/app/api-reference/functions/fetch#optionsnextrevalidate}
|
|
* - `false` - Cache the resource indefinitely. Semantically equivalent to revalidate: Infinity. The HTTP cache may evict older resources over time.
|
|
* - `0` - Prevent the resource from being cached.
|
|
* - `number` - (in seconds) Specify the resource should have a cache lifetime of at most n seconds.
|
|
*/
|
|
export type NextRevalidate = number | false;
|
|
|
|
/**
|
|
* @see {@link https://nextjs.org/docs/app/api-reference/functions/fetch#optionscache}
|
|
*
|
|
* - force-cache (default): Next.js looks for a matching request in its Data Cache.
|
|
* - If there is a match and it is fresh, it will be returned from the cache.
|
|
* - If there is no match or a stale match, Next.js will fetch the resource from the remote server and update the cache with the downloaded resource.
|
|
* - no-store: Next.js fetches the resource from the remote server on every request without looking in the cache, and it will not update the cache with the downloaded resource.
|
|
*
|
|
* The native options from the Web fetch API are also supported @see {@link https://nextjs.org/docs/app/api-reference/functions/fetch#optionscache}
|
|
*/
|
|
export type NextCache =
|
|
| 'default'
|
|
| 'no-store'
|
|
| 'reload'
|
|
| 'no-cache'
|
|
| 'force-cache'
|
|
| 'only-if-cached';
|
|
|
|
export type SanityFetchOptions<QueryString = string> = {
|
|
query: QueryString;
|
|
params?: QueryParams;
|
|
revalidate?: NextRevalidate;
|
|
tags?: Array<string>;
|
|
isClient?: boolean;
|
|
};
|
|
|
|
/**
|
|
* This type fixes the broken `next-sanity` types. Somebody got a little too excited using and
|
|
* relying on global type declarations and this caused a global type conflicts, forcing the `next`
|
|
* and `cache` properties to be ONLY `undefined` as TS couldn't find the `next property in all
|
|
* @see {RequestInit} declarations (it's only in the next.js declaration, not node, web lib, or
|
|
* workers versions).
|
|
*/
|
|
type FixedSanityResponseQueryOptions = Omit<FilteredResponseQueryOptions, 'next' | 'cache'> & {
|
|
cache?: RequestCache;
|
|
next?: {
|
|
cache?: NextCache;
|
|
revalidate?: NextRevalidate;
|
|
tags?: string[];
|
|
};
|
|
};
|
|
|
|
export type SanityFetchGenericOptions = {
|
|
globalOptions: {
|
|
client: SanityClient;
|
|
token?: string;
|
|
disableCaching?: boolean;
|
|
};
|
|
fetchOptions: SanityFetchOptions;
|
|
};
|
|
|
|
export const sanityFetchGeneric = async <R = unknown>({
|
|
globalOptions: { client, token, disableCaching },
|
|
fetchOptions: { query, params = {}, revalidate, tags, isClient },
|
|
}: SanityFetchGenericOptions) =>
|
|
safeTry<R>(
|
|
(async () => {
|
|
const isDraftMode = !isClient && token && isDraftModeEnabled();
|
|
|
|
const perspective = isDraftMode ? 'previewDrafts' : 'published';
|
|
const next = {
|
|
cache: disableCaching ? 'no-store' : 'default',
|
|
revalidate: disableCaching ? 0 : tags?.length ? false : revalidate,
|
|
tags,
|
|
} as const;
|
|
|
|
logger.debug(
|
|
`Fetching ${query} with ${isDraftMode ? '(DRAFT)' : ''} ${JSON.stringify({
|
|
params,
|
|
perspective,
|
|
next,
|
|
})}`
|
|
);
|
|
|
|
const options = {
|
|
token,
|
|
perspective,
|
|
next,
|
|
} satisfies FixedSanityResponseQueryOptions;
|
|
|
|
return client.fetch<R>(
|
|
query,
|
|
params,
|
|
/** @see {FixedSanityResponseQueryOptions} */
|
|
options as unknown as FilteredResponseQueryOptions
|
|
);
|
|
})()
|
|
);
|