Vercel/src/cache/index.ts
2023-11-06 10:05:20 -06:00

276 lines
8.1 KiB
TypeScript

import { revalidatePath, revalidateTag, unstable_cache } from 'next/cache';
import {
GetPhotosOptions,
getPhoto,
getPhotos,
getPhotosCount,
getPhotosCameraCount,
getPhotosCountIncludingHidden,
getPhotosTagCount,
getUniqueCameras,
getUniqueTags,
getPhotosTagDateRange,
getPhotosCameraDateRange,
getUniqueTagsHidden,
getUniqueFilmSimulations,
getPhotosFilmSimulationDateRange,
getPhotosFilmSimulationCount,
} from '@/services/postgres';
import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo';
import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
import type { Session } from 'next-auth';
import { Camera, createCameraKey } from '@/camera';
import { PATHS_ADMIN, PATHS_TO_CACHE } from '@/site/paths';
import { FilmSimulation } from '@/simulation';
const KEY_PHOTOS = 'photos';
const KEY_PHOTOS_COUNT = `${KEY_PHOTOS}-count`;
const KEY_PHOTOS_DATE_RANGE = `${KEY_PHOTOS}-date-range`;
const KEY_TAGS = 'tags';
const KEY_CAMERAS = 'cameras';
const KEY_FILM_SIMULATIONS = 'film-simulations';
const KEY_BLOB = 'blob';
// eslint-disable-next-line max-len
const getPhotosCacheKeyForOption = (
options: GetPhotosOptions,
option: keyof GetPhotosOptions,
): string | null => {
switch (option) {
// Primitive keys
case 'sortBy':
case 'limit':
case 'tag':
case 'simulation':
case 'includeHidden': {
const value = options[option];
return value ? `${option}-${value}` : null;
}
// Date keys
case 'takenBefore':
case 'takenAfterInclusive': {
const value = options[option];
return value ? `${option}-${value.toISOString()}` : null;
}
// Complex keys
case 'camera': {
const value = options[option];
return value ? `${option}-${value.make}-${value.model}` : null;
}
}
};
const getPhotosCacheKeys = (options: GetPhotosOptions = {}) => {
const tags: string[] = [];
Object.keys(options).forEach(key => {
const tag = getPhotosCacheKeyForOption(
options,
key as keyof GetPhotosOptions
);
if (tag) { tags.push(tag); }
});
return tags;
};
const getPhotoCacheKey = (photoId: string) => `photo-${photoId}`;
const getPhotoTagCountKey = (tag: string) =>
`${KEY_PHOTOS_COUNT}-${KEY_TAGS}-${tag}`;
const getPhotoCameraCountKey = (camera: Camera) =>
`${KEY_PHOTOS_COUNT}-${KEY_CAMERAS}-${createCameraKey(camera)}`;
const getPhotoFilmSimulationCountKey = (simulation: FilmSimulation) =>
`${KEY_PHOTOS_COUNT}-${KEY_FILM_SIMULATIONS}-${simulation}`;
const getPhotoTagDateRangeKey = (tag: string) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_TAGS}-${tag}`;
const getPhotoCameraDateRangeKey = (camera: Camera) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_CAMERAS}-${createCameraKey(camera)}`;
const getPhotoFilmSimulationDateRangeKey = (simulation: FilmSimulation) =>
`${KEY_PHOTOS_DATE_RANGE}-${KEY_FILM_SIMULATIONS}-${simulation}`;
export const revalidatePhotosKey = () =>
revalidateTag(KEY_PHOTOS);
export const revalidateTagsKey = () =>
revalidateTag(KEY_TAGS);
export const revalidateCamerasKey = () =>
revalidateTag(KEY_CAMERAS);
export const revalidateFilmSimulationsKey = () =>
revalidateTag(KEY_FILM_SIMULATIONS);
export const revalidateBlobKey = () =>
revalidateTag(KEY_BLOB);
export const revalidatePhotosAndBlobKeys = () => {
revalidatePhotosKey();
revalidateBlobKey();
};
export const revalidateAllKeys = () => {
revalidatePhotosAndBlobKeys();
revalidateTagsKey();
revalidateCamerasKey();
revalidateFilmSimulationsKey();
};
export const revalidateAllKeysAndPaths = () => {
revalidateAllKeys();
PATHS_TO_CACHE.forEach(path => revalidatePath(path));
};
export const revalidateAdminPaths = () => {
PATHS_ADMIN.forEach(path => revalidatePath(path));
};
export const getPhotosCached: typeof getPhotos = (...args) =>
unstable_cache(
() => getPhotos(...args),
[KEY_PHOTOS, ...getPhotosCacheKeys(...args)], {
tags: [KEY_PHOTOS, ...getPhotosCacheKeys(...args)],
}
)().then(parseCachedPhotosDates);
export const getPhotosCountCached: typeof getPhotosCount = (...args) =>
unstable_cache(
() => getPhotosCount(...args),
[KEY_PHOTOS, KEY_PHOTOS_COUNT], {
tags: [KEY_PHOTOS, KEY_PHOTOS_COUNT],
}
)();
export const getPhotosCountIncludingHiddenCached: typeof getPhotosCount =
(...args) =>
unstable_cache(
() => getPhotosCountIncludingHidden(...args),
[KEY_PHOTOS, KEY_PHOTOS_COUNT], {
tags: [KEY_PHOTOS, KEY_PHOTOS_COUNT],
}
)();
export const getPhotosTagCountCached: typeof getPhotosTagCount = (...args) =>
unstable_cache(
() => getPhotosTagCount(...args),
[KEY_PHOTOS, getPhotoTagCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoTagCountKey(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosCameraCountCached: typeof getPhotosCameraCount = (...args) =>
unstable_cache(
() => getPhotosCameraCount(...args),
[KEY_PHOTOS, getPhotoCameraCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCameraCountKey(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosFilmSimulationCountCached: typeof getPhotosFilmSimulationCount = (...args) =>
unstable_cache(
() => getPhotosFilmSimulationCount(...args),
[KEY_PHOTOS, getPhotoFilmSimulationCountKey(...args)], {
tags: [KEY_PHOTOS, getPhotoFilmSimulationCountKey(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosTagDateRangeCached: typeof getPhotosTagDateRange = (...args) =>
unstable_cache(
() => getPhotosTagDateRange(...args),
[KEY_PHOTOS, getPhotoTagDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoTagDateRangeKey(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosCameraDateRangeCached: typeof getPhotosCameraDateRange = (...args) =>
unstable_cache(
() => getPhotosCameraDateRange(...args),
[KEY_PHOTOS, getPhotoCameraDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCameraDateRangeKey(...args)],
}
)();
// eslint-disable-next-line max-len
export const getPhotosFilmSimulationDateRangeCached: typeof getPhotosFilmSimulationDateRange = (...args) =>
unstable_cache(
() => getPhotosFilmSimulationDateRange(...args),
[KEY_PHOTOS, getPhotoFilmSimulationDateRangeKey(...args)], {
tags: [KEY_PHOTOS, getPhotoFilmSimulationDateRangeKey(...args)],
}
)();
export const getPhotoCached: typeof getPhoto = (...args) =>
unstable_cache(
() => getPhoto(...args),
[KEY_PHOTOS, getPhotoCacheKey(...args)], {
tags: [KEY_PHOTOS, getPhotoCacheKey(...args)],
}
)().then(photo => photo ? parseCachedPhotoDates(photo) : undefined);
export const getUniqueTagsCached: typeof getUniqueTags = (...args) =>
unstable_cache(
() => getUniqueTags(...args),
[KEY_PHOTOS, KEY_TAGS], {
tags: [KEY_PHOTOS, KEY_TAGS],
}
)();
// eslint-disable-next-line max-len
export const getUniqueTagsHiddenCached: typeof getUniqueTagsHidden = (...args) =>
unstable_cache(
() => getUniqueTagsHidden(...args),
[KEY_PHOTOS, KEY_TAGS], {
tags: [KEY_PHOTOS, KEY_TAGS],
}
)();
export const getUniqueCamerasCached: typeof getUniqueCameras = (...args) =>
unstable_cache(
() => getUniqueCameras(...args),
[KEY_PHOTOS, KEY_CAMERAS], {
tags: [KEY_PHOTOS, KEY_CAMERAS],
}
)();
// eslint-disable-next-line max-len
export const getUniqueFilmSimulationsCached: typeof getUniqueFilmSimulations = (...args) =>
unstable_cache(
() => getUniqueFilmSimulations(...args),
[KEY_PHOTOS, KEY_FILM_SIMULATIONS], {
tags: [KEY_PHOTOS, KEY_FILM_SIMULATIONS],
}
)();
export const getBlobUploadUrlsCached: typeof getBlobUploadUrls = (...args) =>
unstable_cache(
() => getBlobUploadUrls(...args),
[KEY_BLOB], {
tags: [KEY_BLOB],
}
)();
export const getBlobPhotoUrlsCached: typeof getBlobPhotoUrls = (...args) =>
unstable_cache(
() => getBlobPhotoUrls(...args),
[KEY_BLOB], {
tags: [KEY_BLOB],
}
)();
export const getImageCacheHeadersForAuth = (session: Session | null) => {
return {
'Cache-Control': !session?.user
? 's-maxage=3600, stale-while-revalidate=59'
: 's-maxage=1, stale-while-revalidate=59',
};
};