Add PPR error screening to admin pages
This commit is contained in:
parent
1dc267d07c
commit
d06de4d8ea
@ -1,11 +1,11 @@
|
||||
import { authCached } from '@/auth/cache';
|
||||
import { authCachedSafe } from '@/auth/cache';
|
||||
import AdminPhotoMenuClient from './AdminPhotoMenuClient';
|
||||
import { ComponentProps } from 'react';
|
||||
|
||||
export default async function AdminPhotoMenu(
|
||||
props: ComponentProps<typeof AdminPhotoMenuClient>,
|
||||
) {
|
||||
const session = await authCached();
|
||||
const session = await authCachedSafe();
|
||||
return Boolean(session?.user?.email)
|
||||
? <AdminPhotoMenuClient {...props} />
|
||||
: null;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { cache } from 'react';
|
||||
import { auth } from '@/auth';
|
||||
import { screenForPPR } from '@/utility/ppr';
|
||||
|
||||
export const authCached = cache(auth);
|
||||
export const authCachedSafe = cache(() => auth()
|
||||
.catch(e => screenForPPR(e, null, 'auth')));
|
||||
|
||||
@ -27,6 +27,7 @@ import {
|
||||
isUrlFromCloudflareR2,
|
||||
} from './cloudflare-r2';
|
||||
import { PATH_API_PRESIGNED_URL } from '@/site/paths';
|
||||
import { screenForPPR } from '@/utility/ppr';
|
||||
|
||||
export const generateStorageId = () => generateNanoid(16);
|
||||
|
||||
@ -191,13 +192,16 @@ const getStorageUrlsForPrefix = async (prefix = '') => {
|
||||
const urls: StorageListResponse = [];
|
||||
|
||||
if (HAS_VERCEL_BLOB_STORAGE) {
|
||||
urls.push(...await vercelBlobList(prefix));
|
||||
urls.push(...await vercelBlobList(prefix)
|
||||
.catch(e => screenForPPR(e, [], 'vercel blob')));
|
||||
}
|
||||
if (HAS_AWS_S3_STORAGE) {
|
||||
urls.push(...await awsS3List(prefix));
|
||||
urls.push(...await awsS3List(prefix)
|
||||
.catch(e => screenForPPR(e, [], 'aws blob')));
|
||||
}
|
||||
if (HAS_CLOUDFLARE_R2_STORAGE) {
|
||||
urls.push(...await cloudflareR2List(prefix));
|
||||
urls.push(...await cloudflareR2List(prefix)
|
||||
.catch(e => screenForPPR(e, [], 'cloudflare blob')));
|
||||
}
|
||||
|
||||
return urls
|
||||
|
||||
@ -12,6 +12,7 @@ import { parameterize } from '@/utility/string';
|
||||
import { Tags } from '@/tag';
|
||||
import { FilmSimulation, FilmSimulations } from '@/simulation';
|
||||
import { PRIORITY_ORDER_ENABLED } from '@/site/config';
|
||||
import { screenForPPR } from '@/utility/ppr';
|
||||
|
||||
const PHOTO_DEFAULT_LIMIT = 100;
|
||||
|
||||
@ -283,11 +284,8 @@ const safelyQueryPhotos = async <T>(callback: () => Promise<T>): Promise<T> => {
|
||||
try {
|
||||
result = await callback();
|
||||
} catch (e: any) {
|
||||
if (/ppr-caught-error/.test(e.message) && e.sourceError) {
|
||||
// PPR errors, if caught, must be re-thrown in order to
|
||||
// postpone rendering
|
||||
throw e.sourceError;
|
||||
} else if (/relation "photos" does not exist/i.test(e.message)) {
|
||||
screenForPPR(e, undefined, 'neon postgres');
|
||||
if (/relation "photos" does not exist/i.test(e.message)) {
|
||||
console.log('Creating table "photos" because it did not exist');
|
||||
await sqlCreatePhotosTable();
|
||||
result = await callback();
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
pathForTag,
|
||||
} from './paths';
|
||||
import { formatCameraText } from '@/camera';
|
||||
import { authCached } from '@/auth/cache';
|
||||
import { authCachedSafe } from '@/auth/cache';
|
||||
import { getPhotos } from '@/services/vercel-postgres';
|
||||
import { photoQuantityText, titleForPhoto } from '@/photo';
|
||||
import PhotoTiny from '@/photo/PhotoTiny';
|
||||
@ -45,7 +45,7 @@ export default async function CommandK() {
|
||||
getUniqueFilmSimulationsCached().catch(() => []),
|
||||
]);
|
||||
|
||||
const session = await authCached().catch(() => null);
|
||||
const session = await authCachedSafe();
|
||||
|
||||
const isAdminLoggedIn = Boolean(session?.user?.email);
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { authCached } from '@/auth/cache';
|
||||
import { authCachedSafe } from '@/auth/cache';
|
||||
import FooterClient from './FooterClient';
|
||||
|
||||
export default async function Footer() {
|
||||
// Make footer auth resilient to error on first time setup
|
||||
const session = await authCached().catch(() => null);
|
||||
const session = await authCachedSafe();
|
||||
return (
|
||||
<FooterClient userEmail={session?.user?.email} />
|
||||
);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { authCached } from '@/auth/cache';
|
||||
import { authCachedSafe } from '@/auth/cache';
|
||||
import NavClient from './NavClient';
|
||||
|
||||
export default async function Nav() {
|
||||
// Make nav auth resilient to error on first time setup
|
||||
const session = await authCached().catch(() => null);
|
||||
const session = await authCachedSafe();
|
||||
return (
|
||||
<NavClient showAdmin={Boolean(session?.user?.email)} />
|
||||
);
|
||||
|
||||
18
src/utility/ppr.ts
Normal file
18
src/utility/ppr.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export const screenForPPR = <T>(
|
||||
error: any,
|
||||
fallback: T,
|
||||
sourceToLog?: string,
|
||||
): T => {
|
||||
if (/ppr-caught-error/.test(error.message) && error.sourceError) {
|
||||
// PPR errors, if caught, must be re-thrown in order to
|
||||
// postpone rendering
|
||||
console.log(
|
||||
sourceToLog ? `${sourceToLog}: PPR error caught` : 'PPR error caught',
|
||||
error.sourceError,
|
||||
);
|
||||
throw error.sourceError;
|
||||
} else if (sourceToLog) {
|
||||
console.error(sourceToLog, error.sourceError);
|
||||
}
|
||||
return fallback;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user