import { adminProcedure, createTRPCRouter, protectedProcedure, } from "@/server/api/trpc"; import { db } from "@/server/db"; import { apiCreateDestination, apiFindOneDestination, apiRemoveDestination, apiUpdateDestination, destinations, } from "@/server/db/schema"; import { IS_CLOUD, createDestintation, execAsync, execAsyncRemote, findDestinationById, removeDestinationById, updateDestinationById, } from "@dokploy/server"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; export const destinationRouter = createTRPCRouter({ create: adminProcedure .input(apiCreateDestination) .mutation(async ({ input, ctx }) => { try { return await createDestintation(input, ctx.user.adminId); } catch (error) { throw new TRPCError({ code: "BAD_REQUEST", message: "Error to create the destination", cause: error, }); } }), testConnection: adminProcedure .input(apiCreateDestination) .mutation(async ({ input }) => { const { secretAccessKey, bucket, region, endpoint, accessKey } = input; try { const rcloneFlags = [ // `--s3-provider=Cloudflare`, `--s3-access-key-id=${accessKey}`, `--s3-secret-access-key=${secretAccessKey}`, `--s3-region=${region}`, `--s3-endpoint=${endpoint}`, "--s3-no-check-bucket", "--s3-force-path-style", ]; const rcloneDestination = `:s3:${bucket}`; const rcloneCommand = `rclone ls ${rcloneFlags.join(" ")} "${rcloneDestination}"`; if (IS_CLOUD && !input.serverId) { throw new TRPCError({ code: "NOT_FOUND", message: "Server not found", }); } if (IS_CLOUD) { await execAsyncRemote(input.serverId || "", rcloneCommand); } else { await execAsync(rcloneCommand); } } catch (error) { throw new TRPCError({ code: "BAD_REQUEST", message: error instanceof Error ? error?.message : "Error to connect to bucket", cause: error, }); } }), one: protectedProcedure .input(apiFindOneDestination) .query(async ({ input, ctx }) => { const destination = await findDestinationById(input.destinationId); if (destination.adminId !== ctx.user.adminId) { throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to access this destination", }); } return destination; }), all: protectedProcedure.query(async ({ ctx }) => { return await db.query.destinations.findMany({ where: eq(destinations.adminId, ctx.user.adminId), }); }), remove: adminProcedure .input(apiRemoveDestination) .mutation(async ({ input, ctx }) => { try { const destination = await findDestinationById(input.destinationId); if (destination.adminId !== ctx.user.adminId) { throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to delete this destination", }); } return await removeDestinationById( input.destinationId, ctx.user.adminId, ); } catch (error) { throw error; } }), update: adminProcedure .input(apiUpdateDestination) .mutation(async ({ input, ctx }) => { try { const destination = await findDestinationById(input.destinationId); if (destination.adminId !== ctx.user.adminId) { throw new TRPCError({ code: "UNAUTHORIZED", message: "You are not allowed to update this destination", }); } return await updateDestinationById(input.destinationId, { ...input, adminId: ctx.user.adminId, }); } catch (error) { throw error; } }), });