Vercel/src/cache/index.ts
2023-10-04 14:22:48 -05:00

185 lines
5.0 KiB
TypeScript

import { revalidateTag, unstable_cache } from 'next/cache';
import {
GetPhotosOptions,
getPhoto,
getPhotos,
getPhotosCount,
getPhotosCountCamera,
getPhotosCountIncludingHidden,
getPhotosCountTag,
getUniqueCameras,
getUniqueTags,
} from '@/services/postgres';
import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo';
import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
import { AuthSession } from 'next-auth';
import { Camera, createCameraKey } from '@/camera';
const TAG_PHOTOS = 'photos';
const TAG_PHOTOS_COUNT = 'photos-count';
const TAG_TAGS = 'tags';
const TAG_CAMERAS = 'cameras';
const TAG_BLOB = 'blob';
// eslint-disable-next-line max-len
const getPhotosCacheTagForKey = (
options: GetPhotosOptions,
key: keyof GetPhotosOptions,
): string | null => {
switch (key) {
// Primitive keys
case 'sortBy':
case 'limit':
case 'offset':
case 'tag':
case 'includeHidden': {
const value = options[key];
return value ? `${key}-${value}` : null;
}
// Date keys
case 'takenBefore':
case 'takenAfterInclusive': {
const value = options[key];
return value ? `${key}-${value.toISOString()}` : null;
}
// Complex keys
case 'camera': {
const value = options[key];
return value ? `${key}-${value.make}-${value.model}` : null;
}
}
};
const getPhotosCacheTags = (options: GetPhotosOptions = {}) => {
const tags: string[] = [];
Object.keys(options).forEach(key => {
const tag = getPhotosCacheTagForKey(options, key as keyof GetPhotosOptions);
if (tag) { tags.push(tag); }
});
return tags;
};
const getPhotoCacheTag = (photoId: string) => `photo-${photoId}`;
const getPhotoTagCountTag = (tag: string) =>
`${TAG_PHOTOS_COUNT}-${TAG_TAGS}-${tag}`;
const getPhotoCameraCountTag = ({ make, model }: Camera) =>
`${TAG_PHOTOS_COUNT}-${TAG_CAMERAS}-${createCameraKey(make, model)}`;
export const revalidatePhotosTag = () =>
revalidateTag(TAG_PHOTOS);
export const revalidateTagsTag = () =>
revalidateTag(TAG_TAGS);
export const revalidateCamerasTag = () =>
revalidateTag(TAG_CAMERAS);
export const revalidateBlobTag = () =>
revalidateTag(TAG_BLOB);
export const revalidatePhotosAndBlobTag = () => {
revalidateTag(TAG_PHOTOS);
revalidateTag(TAG_BLOB);
};
export const revalidateAllTags = () => {
revalidatePhotosTag();
revalidateTagsTag();
revalidateCamerasTag();
revalidateBlobTag();
};
export const getPhotosCached: typeof getPhotos = (...args) =>
unstable_cache(
() => getPhotos(...args),
[TAG_PHOTOS, ...getPhotosCacheTags(...args)], {
tags: [TAG_PHOTOS, ...getPhotosCacheTags(...args)],
}
)().then(parseCachedPhotosDates);
export const getPhotosCountCached: typeof getPhotosCount = (...args) =>
unstable_cache(
() => getPhotosCount(...args),
[TAG_PHOTOS, TAG_PHOTOS_COUNT], {
tags: [TAG_PHOTOS, TAG_PHOTOS_COUNT],
}
)();
export const getPhotosCountTagCached: typeof getPhotosCountTag = (...args) =>
unstable_cache(
() => getPhotosCountTag(...args),
[TAG_PHOTOS, getPhotoTagCountTag(...args)], {
tags: [TAG_PHOTOS, getPhotoTagCountTag(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosCountCameraCached: typeof getPhotosCountCamera = (...args) =>
unstable_cache(
() => getPhotosCountCamera(...args),
[TAG_PHOTOS, getPhotoCameraCountTag(...args)], {
tags: [TAG_PHOTOS, getPhotoCameraCountTag(...args)],
}
)();
export const getPhotosCountIncludingHiddenCached: typeof getPhotosCount =
(...args) =>
unstable_cache(
() => getPhotosCountIncludingHidden(...args),
[TAG_PHOTOS, TAG_PHOTOS_COUNT], {
tags: [TAG_PHOTOS, TAG_PHOTOS_COUNT],
}
)();
export const getPhotoCached: typeof getPhoto = (...args) =>
unstable_cache(
() => getPhoto(...args),
[TAG_PHOTOS, getPhotoCacheTag(...args)], {
tags: [TAG_PHOTOS, getPhotoCacheTag(...args)],
}
)().then(photo => photo ? parseCachedPhotoDates(photo) : undefined);
export const getUniqueTagsCached: typeof getUniqueTags = (...args) =>
unstable_cache(
() => getUniqueTags(...args),
[TAG_PHOTOS, TAG_TAGS], {
tags: [TAG_PHOTOS, TAG_TAGS],
}
)();
export const getUniqueCamerasCached: typeof getUniqueCameras = (...args) =>
unstable_cache(
() => getUniqueCameras(...args),
[TAG_PHOTOS, TAG_CAMERAS], {
tags: [TAG_PHOTOS, TAG_CAMERAS],
}
)();
export const getBlobUploadUrlsCached: typeof getBlobUploadUrls = (...args) =>
unstable_cache(
() => getBlobUploadUrls(...args),
[TAG_BLOB], {
tags: [TAG_BLOB],
}
)();
export const getBlobPhotoUrlsCached: typeof getBlobPhotoUrls = (...args) =>
unstable_cache(
() => getBlobPhotoUrls(...args),
[TAG_BLOB], {
tags: [TAG_BLOB],
}
)();
export const getImageCacheHeadersForAuth = (session: AuthSession | null) => {
return {
'Cache-Control': !session?.user
? 's-maxage=3600, stale-while-revalidate=59'
: 's-maxage=1, stale-while-revalidate=59',
};
};