From e68465f9e68433e99006310c6dd81ebb45ffa53d Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 18 Jan 2025 23:07:36 -0600 Subject: [PATCH] refactor: improve error --- .../dashboard/project/ai/step-two.tsx | 25 +- apps/dokploy/server/api/routers/ai.ts | 233 +++++++++--------- 2 files changed, 143 insertions(+), 115 deletions(-) diff --git a/apps/dokploy/components/dashboard/project/ai/step-two.tsx b/apps/dokploy/components/dashboard/project/ai/step-two.tsx index 7d644022..0c039c92 100644 --- a/apps/dokploy/components/dashboard/project/ai/step-two.tsx +++ b/apps/dokploy/components/dashboard/project/ai/step-two.tsx @@ -16,6 +16,7 @@ import { useEffect, useState } from "react"; import ReactMarkdown from "react-markdown"; import { toast } from "sonner"; import type { TemplateInfo } from "./template-generator"; +import { AlertBlock } from "@/components/shared/alert-block"; export interface StepProps { nextStep: () => void; @@ -35,7 +36,8 @@ export const StepTwo = ({ useState(); const [showValues, setShowValues] = useState>({}); - const { mutateAsync, isLoading } = api.ai.suggest.useMutation(); + const { mutateAsync, isLoading, error, isError } = + api.ai.suggest.useMutation(); useEffect(() => { mutateAsync({ @@ -48,7 +50,6 @@ export const StepTwo = ({ setSuggestions(data); }) .catch((error) => { - console.error("Error details:", error); toast.error("Error generating suggestions"); }); }, [templateInfo.userInput]); @@ -75,6 +76,7 @@ export const StepTwo = ({ if (!selectedVariant) return; const updatedEnvVariables = [...selectedVariant.envVariables]; + // @ts-ignore updatedEnvVariables[index] = { ...updatedEnvVariables[index], [field]: value, @@ -151,7 +153,26 @@ export const StepTwo = ({ ], }); }; + if (isError) { + return ( +
+ +

Error

+ + {error?.message || "Error generating suggestions"} + + +
+ ); + } if (isLoading) { return (
diff --git a/apps/dokploy/server/api/routers/ai.ts b/apps/dokploy/server/api/routers/ai.ts index ec4ce16d..b5a91aa7 100644 --- a/apps/dokploy/server/api/routers/ai.ts +++ b/apps/dokploy/server/api/routers/ai.ts @@ -1,145 +1,152 @@ import { slugify } from "@/lib/slug"; import { - adminProcedure, - createTRPCRouter, - protectedProcedure, + adminProcedure, + createTRPCRouter, + protectedProcedure, } from "@/server/api/trpc"; import { generatePassword } from "@/templates/utils"; import { IS_CLOUD } from "@dokploy/server/constants"; import { - apiCreateAi, - apiUpdateAi, - deploySuggestionSchema, + apiCreateAi, + apiUpdateAi, + deploySuggestionSchema, } from "@dokploy/server/db/schema/ai"; import { createDomain } from "@dokploy/server/index"; import { - deleteAiSettings, - getAiSettingById, - getAiSettingsByAdminId, - saveAiSettings, - suggestVariants, + deleteAiSettings, + getAiSettingById, + getAiSettingsByAdminId, + saveAiSettings, + suggestVariants, } from "@dokploy/server/services/ai"; import { createComposeByTemplate } from "@dokploy/server/services/compose"; import { findProjectById } from "@dokploy/server/services/project"; import { - addNewService, - checkServiceAccess, + addNewService, + checkServiceAccess, } from "@dokploy/server/services/user"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; export const aiRouter = createTRPCRouter({ - one: protectedProcedure - .input(z.object({ aiId: z.string() })) - .query(async ({ ctx, input }) => { - const aiSetting = await getAiSettingById(input.aiId); - if (aiSetting.adminId !== ctx.user.adminId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this AI configuration", - }); - } - return aiSetting; - }), - create: adminProcedure.input(apiCreateAi).mutation(async ({ ctx, input }) => { - return await saveAiSettings(ctx.user.adminId, input); - }), + one: protectedProcedure + .input(z.object({ aiId: z.string() })) + .query(async ({ ctx, input }) => { + const aiSetting = await getAiSettingById(input.aiId); + if (aiSetting.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this AI configuration", + }); + } + return aiSetting; + }), + create: adminProcedure.input(apiCreateAi).mutation(async ({ ctx, input }) => { + return await saveAiSettings(ctx.user.adminId, input); + }), - update: protectedProcedure - .input(apiUpdateAi) - .mutation(async ({ ctx, input }) => { - return await saveAiSettings(ctx.user.adminId, input); - }), + update: protectedProcedure + .input(apiUpdateAi) + .mutation(async ({ ctx, input }) => { + return await saveAiSettings(ctx.user.adminId, input); + }), - getAll: adminProcedure.query(async ({ ctx }) => { - return await getAiSettingsByAdminId(ctx.user.adminId); - }), + getAll: adminProcedure.query(async ({ ctx }) => { + return await getAiSettingsByAdminId(ctx.user.adminId); + }), - get: protectedProcedure - .input(z.object({ aiId: z.string() })) - .query(async ({ ctx, input }) => { - const aiSetting = await getAiSettingById(input.aiId); - if (aiSetting.adminId !== ctx.user.authId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this AI configuration", - }); - } - return aiSetting; - }), + get: protectedProcedure + .input(z.object({ aiId: z.string() })) + .query(async ({ ctx, input }) => { + const aiSetting = await getAiSettingById(input.aiId); + if (aiSetting.adminId !== ctx.user.authId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this AI configuration", + }); + } + return aiSetting; + }), - delete: protectedProcedure - .input(z.object({ aiId: z.string() })) - .mutation(async ({ ctx, input }) => { - const aiSetting = await getAiSettingById(input.aiId); - if (aiSetting.adminId !== ctx.user.adminId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this AI configuration", - }); - } - return await deleteAiSettings(input.aiId); - }), + delete: protectedProcedure + .input(z.object({ aiId: z.string() })) + .mutation(async ({ ctx, input }) => { + const aiSetting = await getAiSettingById(input.aiId); + if (aiSetting.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this AI configuration", + }); + } + return await deleteAiSettings(input.aiId); + }), - suggest: protectedProcedure - .input( - z.object({ - aiId: z.string(), - input: z.string(), - serverId: z.string().optional(), - }), - ) - .mutation(async ({ ctx, input }) => { - return await suggestVariants({ - ...input, - adminId: ctx.user.adminId, - }); - }), - deploy: protectedProcedure - .input(deploySuggestionSchema) - .mutation(async ({ ctx, input }) => { - if (ctx.user.rol === "user") { - await checkServiceAccess(ctx.user.adminId, input.projectId, "create"); - } + suggest: protectedProcedure + .input( + z.object({ + aiId: z.string(), + input: z.string(), + serverId: z.string().optional(), + }) + ) + .mutation(async ({ ctx, input }) => { + try { + return await suggestVariants({ + ...input, + adminId: ctx.user.adminId, + }); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: error instanceof Error ? error?.message : `Error: ${error}`, + }); + } + }), + deploy: protectedProcedure + .input(deploySuggestionSchema) + .mutation(async ({ ctx, input }) => { + if (ctx.user.rol === "user") { + await checkServiceAccess(ctx.user.adminId, input.projectId, "create"); + } - if (IS_CLOUD && !input.serverId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You need to use a server to create a compose", - }); - } + if (IS_CLOUD && !input.serverId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You need to use a server to create a compose", + }); + } - const project = await findProjectById(input.projectId); + const project = await findProjectById(input.projectId); - const projectName = slugify(`${project.name} ${input.id}`); + const projectName = slugify(`${project.name} ${input.id}`); - console.log(input); + console.log(input); - const compose = await createComposeByTemplate({ - ...input, - composeFile: input.dockerCompose, - env: input.envVariables, - serverId: input.serverId, - name: input.name, - sourceType: "raw", - appName: `${projectName}-${generatePassword(6)}`, - }); + const compose = await createComposeByTemplate({ + ...input, + composeFile: input.dockerCompose, + env: input.envVariables, + serverId: input.serverId, + name: input.name, + sourceType: "raw", + appName: `${projectName}-${generatePassword(6)}`, + }); - if (input.domains && input.domains?.length > 0) { - for (const domain of input.domains) { - await createDomain({ - ...domain, - domainType: "compose", - certificateType: "none", - composeId: compose.composeId, - }); - } - } + if (input.domains && input.domains?.length > 0) { + for (const domain of input.domains) { + await createDomain({ + ...domain, + domainType: "compose", + certificateType: "none", + composeId: compose.composeId, + }); + } + } - if (ctx.user.rol === "user") { - await addNewService(ctx.user.authId, compose.composeId); - } + if (ctx.user.rol === "user") { + await addNewService(ctx.user.authId, compose.composeId); + } - return null; - }), + return null; + }), });