Refactor AI server action code
This commit is contained in:
parent
137b718fb7
commit
fdd392bf25
@ -44,7 +44,7 @@ export const {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const safelyRunServerAdminAction = async <T>(
|
export const safelyRunAdminServerAction = async <T>(
|
||||||
callback: () => T,
|
callback: () => T,
|
||||||
): Promise<T> => {
|
): Promise<T> => {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|||||||
@ -33,10 +33,11 @@ import {
|
|||||||
import { extractExifDataFromBlobPath } from './server';
|
import { extractExifDataFromBlobPath } from './server';
|
||||||
import { TAG_FAVS, isTagFavs } from '@/tag';
|
import { TAG_FAVS, isTagFavs } from '@/tag';
|
||||||
import { convertPhotoToPhotoDbInsert } from '.';
|
import { convertPhotoToPhotoDbInsert } from '.';
|
||||||
import { safelyRunServerAdminAction } from '@/auth';
|
import { safelyRunAdminServerAction } from '@/auth';
|
||||||
|
import { ImageQuery, streamImageQuery } from './ai';
|
||||||
|
|
||||||
export async function createPhotoAction(formData: FormData) {
|
export async function createPhotoAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const photo = convertFormDataToPhotoDbInsert(formData, true);
|
const photo = convertFormDataToPhotoDbInsert(formData, true);
|
||||||
|
|
||||||
const updatedUrl = await convertUploadToPhoto(photo.url, photo.id);
|
const updatedUrl = await convertUploadToPhoto(photo.url, photo.id);
|
||||||
@ -52,7 +53,7 @@ export async function createPhotoAction(formData: FormData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePhotoAction(formData: FormData) {
|
export async function updatePhotoAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const photo = convertFormDataToPhotoDbInsert(formData);
|
const photo = convertFormDataToPhotoDbInsert(formData);
|
||||||
|
|
||||||
await sqlUpdatePhoto(photo);
|
await sqlUpdatePhoto(photo);
|
||||||
@ -67,7 +68,7 @@ export async function toggleFavoritePhotoAction(
|
|||||||
photoId: string,
|
photoId: string,
|
||||||
shouldRedirect?: boolean,
|
shouldRedirect?: boolean,
|
||||||
) {
|
) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const photo = await getPhoto(photoId);
|
const photo = await getPhoto(photoId);
|
||||||
if (photo) {
|
if (photo) {
|
||||||
const { tags } = photo;
|
const { tags } = photo;
|
||||||
@ -88,7 +89,7 @@ export async function deletePhotoAction(
|
|||||||
photoUrl: string,
|
photoUrl: string,
|
||||||
shouldRedirect?: boolean,
|
shouldRedirect?: boolean,
|
||||||
) {
|
) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
await sqlDeletePhoto(photoId).then(() => deleteStorageUrl(photoUrl));
|
await sqlDeletePhoto(photoId).then(() => deleteStorageUrl(photoUrl));
|
||||||
revalidateAllKeysAndPaths();
|
revalidateAllKeysAndPaths();
|
||||||
if (shouldRedirect) {
|
if (shouldRedirect) {
|
||||||
@ -98,7 +99,7 @@ export async function deletePhotoAction(
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function deletePhotoFormAction(formData: FormData) {
|
export async function deletePhotoFormAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () =>
|
return safelyRunAdminServerAction(async () =>
|
||||||
deletePhotoAction(
|
deletePhotoAction(
|
||||||
formData.get('id') as string,
|
formData.get('id') as string,
|
||||||
formData.get('url') as string,
|
formData.get('url') as string,
|
||||||
@ -107,7 +108,7 @@ export async function deletePhotoFormAction(formData: FormData) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function deletePhotoTagGloballyAction(formData: FormData) {
|
export async function deletePhotoTagGloballyAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const tag = formData.get('tag') as string;
|
const tag = formData.get('tag') as string;
|
||||||
|
|
||||||
await sqlDeletePhotoTagGlobally(tag);
|
await sqlDeletePhotoTagGlobally(tag);
|
||||||
@ -118,7 +119,7 @@ export async function deletePhotoTagGloballyAction(formData: FormData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function renamePhotoTagGloballyAction(formData: FormData) {
|
export async function renamePhotoTagGloballyAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const tag = formData.get('tag') as string;
|
const tag = formData.get('tag') as string;
|
||||||
const updatedTag = formData.get('updatedTag') as string;
|
const updatedTag = formData.get('updatedTag') as string;
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ export async function renamePhotoTagGloballyAction(formData: FormData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteBlobPhotoAction(formData: FormData) {
|
export async function deleteBlobPhotoAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
await deleteStorageUrl(formData.get('url') as string);
|
await deleteStorageUrl(formData.get('url') as string);
|
||||||
|
|
||||||
revalidateAdminPaths();
|
revalidateAdminPaths();
|
||||||
@ -146,7 +147,7 @@ export async function deleteBlobPhotoAction(formData: FormData) {
|
|||||||
export async function getExifDataAction(
|
export async function getExifDataAction(
|
||||||
photoFormPrevious: Partial<PhotoFormData>,
|
photoFormPrevious: Partial<PhotoFormData>,
|
||||||
): Promise<Partial<PhotoFormData>> {
|
): Promise<Partial<PhotoFormData>> {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const { url } = photoFormPrevious;
|
const { url } = photoFormPrevious;
|
||||||
if (url) {
|
if (url) {
|
||||||
const { photoFormExif } = await extractExifDataFromBlobPath(url);
|
const { photoFormExif } = await extractExifDataFromBlobPath(url);
|
||||||
@ -159,7 +160,7 @@ export async function getExifDataAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function syncPhotoExifDataAction(formData: FormData) {
|
export async function syncPhotoExifDataAction(formData: FormData) {
|
||||||
return safelyRunServerAdminAction(async () => {
|
return safelyRunAdminServerAction(async () => {
|
||||||
const photoId = formData.get('id') as string;
|
const photoId = formData.get('id') as string;
|
||||||
if (photoId) {
|
if (photoId) {
|
||||||
const photo = await getPhoto(photoId);
|
const photo = await getPhoto(photoId);
|
||||||
@ -179,5 +180,13 @@ export async function syncPhotoExifDataAction(formData: FormData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function syncCacheAction() {
|
export async function syncCacheAction() {
|
||||||
return safelyRunServerAdminAction(revalidateAllKeysAndPaths);
|
return safelyRunAdminServerAction(revalidateAllKeysAndPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function streamImageQueryAction(
|
||||||
|
imageBase64: string,
|
||||||
|
query: ImageQuery,
|
||||||
|
) {
|
||||||
|
return safelyRunAdminServerAction(async () =>
|
||||||
|
streamImageQuery(imageBase64, query));
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/photo/ai.ts
Normal file
13
src/photo/ai.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { streamOpenAiImageQuery } from '@/services/openai';
|
||||||
|
|
||||||
|
export type ImageQuery = 'title' | 'caption' | 'tags' | 'description';
|
||||||
|
|
||||||
|
export const IMAGE_QUERIES: Record<ImageQuery, string> = {
|
||||||
|
title: 'What is the title of this image?',
|
||||||
|
caption: 'What is the caption of this image?',
|
||||||
|
tags: 'Describe this image three or less comma-separated keywords',
|
||||||
|
description: 'Describe this image in detail',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const streamImageQuery = (imageBase64: string, query: ImageQuery) =>
|
||||||
|
streamOpenAiImageQuery(imageBase64, IMAGE_QUERIES[query]);
|
||||||
@ -5,7 +5,10 @@ import { createStreamableValue, render } from 'ai/rsc';
|
|||||||
|
|
||||||
const provider = new OpenAI({ apiKey: process.env.OPENAI_SECRET_KEY });
|
const provider = new OpenAI({ apiKey: process.env.OPENAI_SECRET_KEY });
|
||||||
|
|
||||||
const streamImageQueryRaw = async (imageBase64: string, query: string) => {
|
export const streamOpenAiImageQuery = async (
|
||||||
|
imageBase64: string,
|
||||||
|
query: string,
|
||||||
|
) => {
|
||||||
const stream = createStreamableValue('');
|
const stream = createStreamableValue('');
|
||||||
|
|
||||||
render({
|
render({
|
||||||
@ -36,15 +39,3 @@ const streamImageQueryRaw = async (imageBase64: string, query: string) => {
|
|||||||
|
|
||||||
return stream.value;
|
return stream.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageQuery = 'title' | 'caption' | 'tags' | 'description';
|
|
||||||
|
|
||||||
export const IMAGE_QUERIES: Record<ImageQuery, string> = {
|
|
||||||
title: 'What is the title of this image?',
|
|
||||||
caption: 'What is the caption of this image?',
|
|
||||||
tags: 'Describe this image three or less comma-separated keywords',
|
|
||||||
description: 'Describe this image in detail',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const streamImageQuery = (imageBase64: string, query: ImageQuery) =>
|
|
||||||
streamImageQueryRaw(imageBase64, IMAGE_QUERIES[query]);
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user