Add public /api

This commit is contained in:
Sam Becker 2023-10-07 12:11:47 -05:00
parent 2c7ad19b44
commit bc7c4a35c8
6 changed files with 67 additions and 9 deletions

View File

@ -62,3 +62,4 @@ Installation
1. Set `NEXT_PUBLIC_HIDE_REPO_LINK = 1` to remove footer link to repo
2. Set `NEXT_PUBLIC_PRO_MODE = 1` to enable higher quality image storage
3. Set `NEXT_PUBLIC_PUBLIC_API = 1` to enable a public API available at `/api`

24
src/app/api/route.ts Normal file
View File

@ -0,0 +1,24 @@
import { getPhotosCached } from '@/cache';
import { parsePhotoForApi } from '@/photo';
import {
BASE_URL,
PUBLIC_API_ENABLED,
SITE_TITLE,
} from '@/site/config';
const API_PHOTO_LIMIT = 20;
export async function GET() {
if (PUBLIC_API_ENABLED) {
const photos = await getPhotosCached({ limit: API_PHOTO_LIMIT });
return Response.json({
meta: {
title: SITE_TITLE,
url: BASE_URL,
},
photos: photos.map(parsePhotoForApi),
});
} else {
return Response.json({ message: 'API is disabled' });
}
}

View File

@ -18,7 +18,7 @@ import {
revalidateBlobKey,
revalidatePhotosKey,
} from '@/cache';
import { IS_PRO_MODE } from '@/site/config';
import { PRO_MODE_ENABLED } from '@/site/config';
import { getNextImageUrlForRequest } from '@/utility/image';
import { PATH_ADMIN_PHOTOS, PATH_ADMIN_TAGS } from '@/site/paths';
@ -31,10 +31,10 @@ export async function createPhotoAction(formData: FormData) {
const updatedUrl = await convertUploadToPhoto(
photo.url,
photo.id,
!IS_PRO_MODE
!PRO_MODE_ENABLED
? getNextImageUrlForRequest(photo.url, 3840, 90, requestOrigin)
: undefined,
!IS_PRO_MODE ? 'webp' : undefined,
!PRO_MODE_ENABLED ? 'webp' : undefined,
);
if (updatedUrl) { photo.url = updatedUrl; }

View File

@ -1,4 +1,7 @@
import { ABSOLUTE_PATH_FOR_HOME_IMAGE } from '@/site/paths';
import {
ABSOLUTE_PATH_FOR_HOME_IMAGE,
absolutePathForPhoto,
} from '@/site/paths';
import { formatDateFromPostgresString } from '@/utility/date';
import {
formatAperture,
@ -7,6 +10,7 @@ import {
formatExposureTime,
formatFocalLength,
} from '@/utility/exif';
import { getNextImageUrlForRequest } from '@/utility/image';
import camelcaseKeys from 'camelcase-keys';
import type { Metadata } from 'next';
@ -86,6 +90,21 @@ export const parsePhotoFromDb = (photoDbRaw: PhotoDb): Photo => {
};
};
export const parsePhotoForApi = (photo: Photo) => ({
id: photo.id,
title: photo.title,
url: absolutePathForPhoto(photo),
...photo.make && { make: photo.make },
...photo.model && { model: photo.model },
...photo.tags.length > 0 && { tags: photo.tags },
takenAtNaive: formatDateFromPostgresString(photo.takenAtNaive),
src: {
small: getNextImageUrlForRequest(photo.url, 200),
medium: getNextImageUrlForRequest(photo.url, 640),
large: getNextImageUrlForRequest(photo.url, 1200),
},
});
export const parseCachedPhotoDates = (photo: Photo) => ({
...photo,
takenAt: new Date(photo.takenAt),

View File

@ -26,7 +26,8 @@ export default function SiteChecklistClient({
hasTitle,
hasDomain,
showRepoLink,
isProMode,
isProModeEnabled,
isPublicApiEnabled,
showRefreshButton,
secret,
}: {
@ -37,7 +38,8 @@ export default function SiteChecklistClient({
hasTitle: boolean
hasDomain: boolean
showRepoLink: boolean
isProMode: boolean
isProModeEnabled: boolean
isPublicApiEnabled: boolean
showRefreshButton?: boolean
secret: string
}) {
@ -219,7 +221,7 @@ export default function SiteChecklistClient({
</ChecklistRow>
<ChecklistRow
title="Pro Mode"
status={isProMode}
status={isProModeEnabled}
isPending={isPendingPage}
optional
>
@ -227,6 +229,16 @@ export default function SiteChecklistClient({
higher quality image storage:
{renderEnvVars(['NEXT_PUBLIC_PRO_MODE'])}
</ChecklistRow>
<ChecklistRow
title="Public API"
status={isPublicApiEnabled}
isPending={isPendingPage}
optional
>
Set environment variable to {'"1"'} to enable
a public API available at <code>/api</code>:
{renderEnvVars(['NEXT_PUBLIC_PUBLIC_API'])}
</ChecklistRow>
</Checklist>
{showRefreshButton &&
<div className="py-4 space-y-4">

View File

@ -25,7 +25,8 @@ export const BASE_URL = process.env.NODE_ENV === 'production'
: 'http://localhost:3000';
export const SHOW_REPO_LINK = process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1';
export const IS_PRO_MODE = process.env.NEXT_PUBLIC_PRO_MODE === '1';
export const PRO_MODE_ENABLED = process.env.NEXT_PUBLIC_PRO_MODE === '1';
export const PUBLIC_API_ENABLED = process.env.NEXT_PUBLIC_PUBLIC_API === '1';
export const CONFIG_CHECKLIST_STATUS = {
hasPostgres: (process.env.POSTGRES_HOST ?? '').length > 0,
@ -38,7 +39,8 @@ export const CONFIG_CHECKLIST_STATUS = {
hasTitle: (process.env.NEXT_PUBLIC_SITE_TITLE ?? '').length > 0,
hasDomain: (process.env.NEXT_PUBLIC_SITE_DOMAIN ?? '').length > 0,
showRepoLink: SHOW_REPO_LINK,
isProMode: IS_PRO_MODE,
isProModeEnabled: PRO_MODE_ENABLED,
isPublicApiEnabled: PUBLIC_API_ENABLED,
};
export const IS_CHECKLIST_COMPLETE =