Move all sets to new static generation routine

This commit is contained in:
Sam Becker 2025-03-18 19:14:52 -05:00
parent f0d9ea28b6
commit c4b1e349e1
14 changed files with 131 additions and 83 deletions

View File

@ -13,6 +13,8 @@
"Consolas",
"CredentialsSignin",
"datetime",
"depluralize",
"depluralizes",
"Eterna",
"exif",
"exifr",

View File

@ -1,4 +1,4 @@
import { parameterize } from '@/utility/string';
import { parameterize, depluralize } from '@/utility/string';
describe('String', () => {
it('parameterizes', () => {
@ -10,4 +10,11 @@ describe('String', () => {
expect(parameterize('"person\'s tag"')).toBe('persons-tag');
expect(parameterize('宿宿宿宿')).toBe('宿宿宿宿');
});
it('depluralizes', () => {
expect(depluralize('lenses')).toBe('lens');
expect(depluralize('cameras')).toBe('camera');
expect(depluralize('tags')).toBe('tag');
expect(depluralize('recipes')).toBe('recipe');
expect(depluralize('films')).toBe('film');
});
});

View File

@ -9,20 +9,23 @@ import { FilmSimulation } from '@/simulation';
import { getIBMPlexMono } from '@/app/font';
import { ImageResponse } from 'next/og';
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { getUniqueFilmSimulations } from '@/photo/db/query';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
export let generateStaticParams:
(() => Promise<{ simulation: FilmSimulation }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('films', 'image')) {
generateStaticParams = async () => {
const simulations = await getUniqueFilmSimulations();
return simulations
.map(({ simulation }) => ({ simulation }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'films',
'image',
getUniqueFilmSimulations,
simulations => simulations.map(({ simulation }) => ({ simulation })),
);
}
export async function GET(

View File

@ -7,8 +7,10 @@ import { Metadata } from 'next/types';
import { cache } from 'react';
import { PATH_ROOT } from '@/app/paths';
import { redirect } from 'next/navigation';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
const getPhotosFilmSimulationDataCachedCached =
cache(getPhotosFilmSimulationDataCached);
@ -17,12 +19,13 @@ export let generateStaticParams:
(() => Promise<{ simulation: FilmSimulation }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('films', 'page')) {
generateStaticParams = async () => {
const simulations = await getUniqueFilmSimulations();
return simulations
.map(({ simulation }) => ({ simulation }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'films',
'page',
getUniqueFilmSimulations,
simulations => simulations.map(({ simulation }) => ({ simulation })),
);
}
interface FilmSimulationProps {

View File

@ -9,20 +9,24 @@ import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
import FocalLengthImageResponse from
'@/image-response/FocalLengthImageResponse';
import { formatFocalLength, getFocalLengthFromString } from '@/focal';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { getUniqueFocalLengths } from '@/photo/db/query';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
export let generateStaticParams:
(() => Promise<{ focal: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('focal-lengths', 'image')) {
generateStaticParams = async () => {
const focalLengths= await getUniqueFocalLengths();
return focalLengths
.map(({ focal }) => ({ focal: formatFocalLength(focal)! }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'focal-lengths',
'image',
getUniqueFocalLengths,
focalLengths => focalLengths
.map(({ focal }) => ({ focal: formatFocalLength(focal)! })),
);
}
export async function GET(

View File

@ -7,8 +7,10 @@ import { PATH_ROOT } from '@/app/paths';
import type { Metadata } from 'next';
import { redirect } from 'next/navigation';
import { cache } from 'react';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
const getPhotosFocalDataCachedCached = cache((focal: number) =>
getPhotosFocalLengthDataCached({
@ -20,12 +22,14 @@ export let generateStaticParams:
(() => Promise<{ focal: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('focal-lengths', 'page')) {
generateStaticParams = async () => {
const focalLengths = await getUniqueFocalLengths();
return focalLengths
.map(({ focal }) => ({ focal: focal.toString() }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'focal-lengths',
'page',
getUniqueFocalLengths,
focalLengths => focalLengths
.map(({ focal }) => ({ focal: focal.toString() })),
);
}
interface FocalLengthProps {

View File

@ -6,7 +6,6 @@ import {
import { getIBMPlexMono } from '@/app/font';
import { ImageResponse } from 'next/og';
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { getUniqueLenses } from '@/photo/db/query';
import {
getLensFromParams,
@ -15,17 +14,22 @@ import {
safelyGenerateLensStaticParams,
} from '@/lens';
import LensImageResponse from '@/image-response/LensImageResponse';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
export let generateStaticParams:
(() => Promise<Lens[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('lenses', 'image')) {
generateStaticParams = async () => {
const lenses = await getUniqueLenses();
return safelyGenerateLensStaticParams(lenses)
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'lenses',
'image',
getUniqueLenses,
safelyGenerateLensStaticParams,
);
}
export async function GET(

View File

@ -11,8 +11,10 @@ import {
LensProps,
safelyGenerateLensStaticParams,
} from '@/lens';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
const getPhotosLensDataCachedCached = cache((
make: string | undefined,
@ -27,11 +29,13 @@ export let generateStaticParams:
(() => Promise<Lens[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('lenses', 'page')) {
generateStaticParams = async () => {
const lenses = await getUniqueLenses();
return safelyGenerateLensStaticParams(lenses)
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'lenses',
'page',
getUniqueLenses,
safelyGenerateLensStaticParams,
);
}
export async function generateMetadata({

View File

@ -6,21 +6,24 @@ import {
import { getIBMPlexMono } from '@/app/font';
import { ImageResponse } from 'next/og';
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { getUniqueRecipes } from '@/photo/db/query';
import RecipeImageResponse from '@/image-response/RecipeImageResponse';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
export let generateStaticParams:
(() => Promise<{ recipe: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('recipes', 'image')) {
generateStaticParams = async () => {
const recipes = await getUniqueRecipes();
return recipes
.map(({ recipe }) => ({ recipe }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'recipes',
'image',
getUniqueRecipes,
recipes => recipes.map(({ recipe }) => ({ recipe })),
);
}
export async function GET(

View File

@ -7,8 +7,10 @@ import { cache } from 'react';
import { generateMetaForRecipe } from '@/recipe';
import RecipeOverview from '@/recipe/RecipeOverview';
import { getPhotosRecipeDataCached } from '@/recipe/data';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
const getPhotosRecipeDataCachedCached = cache(getPhotosRecipeDataCached);
@ -16,12 +18,13 @@ export let generateStaticParams:
(() => Promise<{ recipe: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('recipes', 'page')) {
generateStaticParams = async () => {
const recipes = await getUniqueRecipes();
return recipes
.map(({ recipe }) => ({ recipe }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'recipes',
'page',
getUniqueRecipes,
recipes => recipes.map(({ recipe }) => ({ recipe })),
);
}
interface RecipeProps {

View File

@ -7,20 +7,23 @@ import TagImageResponse from '@/image-response/TagImageResponse';
import { getIBMPlexMono } from '@/app/font';
import { ImageResponse } from 'next/og';
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { getUniqueTags } from '@/photo/db/query';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
export let generateStaticParams:
(() => Promise<{ tag: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('tags', 'image')) {
generateStaticParams = async () => {
const tags = await getUniqueTags();
return tags
.map(({ tag }) => ({ tag }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'tags',
'image',
getUniqueTags,
tags => tags.map(({ tag }) => ({ tag })),
);
}
export async function GET(

View File

@ -7,8 +7,10 @@ import { getPhotosTagDataCached } from '@/tag/data';
import type { Metadata } from 'next';
import { redirect } from 'next/navigation';
import { cache } from 'react';
import { shouldGenerateStaticParamsForCategory } from '@/category/server';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import {
shouldGenerateStaticParamsForCategory,
staticallyGenerateCategory,
} from '@/category/server';
const getPhotosTagDataCachedCached = cache((tag: string) =>
getPhotosTagDataCached({ tag, limit: INFINITE_SCROLL_GRID_INITIAL}));
@ -17,12 +19,13 @@ export let generateStaticParams:
(() => Promise<{ tag: string }[]>) | undefined = undefined;
if (shouldGenerateStaticParamsForCategory('tags', 'page')) {
generateStaticParams = async () => {
const tags = await getUniqueTags();
return tags
.map(({ tag }) => ({ tag }))
.slice(0, GENERATE_STATIC_PARAMS_LIMIT);
};
generateStaticParams = () =>
staticallyGenerateCategory(
'tags',
'page',
getUniqueTags,
tags => tags.map(({ tag }) => ({ tag })),
);
}
interface TagProps {

View File

@ -7,7 +7,7 @@ import {
STATICALLY_OPTIMIZED_PHOTO_CATEGORY_OG_IMAGES,
} from '@/app/config';
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
import { pluralize } from '@/utility/string';
import { depluralize, pluralize } from '@/utility/string';
type StaticOutput = 'page' | 'image';
@ -30,9 +30,8 @@ export const staticallyGenerateCategory = async <T, K>(
const data = (await getData()).slice(0, GENERATE_STATIC_PARAMS_LIMIT);
if (IS_BUILDING) {
console.log(
`Statically generating ${key} (${pluralize(data.length, type)})`,
);
const meta = pluralize(data.length, `${depluralize(key)} ${type}`);
console.log(`Statically generating ${meta}`);
}
return formatData(data);

View File

@ -47,6 +47,12 @@ export const pluralize = (
) =>
`${count} ${count === 1 ? singular : plural ?? `${singular}s`}`;
export const depluralize = (string: string) =>
// Handle plurals like "lenses"
/ses$/i.test(string)
? string.replace(/es$/i, '')
: string.replace(/s$/i, '');
export const formatCountDescriptive = (
count: number,
verb = 'found',