172 lines · 3.8 KB · TypeScript
RawDownload
import { db } from "@dokploy/server/db";import {	type apiCreateLibsql,	backups,	buildAppName,	libsql,} from "@dokploy/server/db/schema";import { generatePassword } from "@dokploy/server/templates";import { buildLibsql } from "@dokploy/server/utils/databases/libsql";import {	pullImage,	waitForSwarmServiceConvergence,} from "@dokploy/server/utils/docker/utils";import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";import { TRPCError } from "@trpc/server";import { eq, getTableColumns } from "drizzle-orm";import { quote } from "shell-quote";import type { z } from "zod";import { validUniqueServerAppName } from "./project"; export type Libsql = typeof libsql.$inferSelect; export const createLibsql = async (input: z.infer<typeof apiCreateLibsql>) => {	const appName = buildAppName("libsql", input.appName); 	const valid = await validUniqueServerAppName(input.appName);	if (!valid) {		throw new TRPCError({			code: "CONFLICT",			message: "Service with this 'AppName' already exists",		});	} 	const newLibsql = await db		.insert(libsql)		.values({			...input,			databasePassword: input.databasePassword				? input.databasePassword				: generatePassword(),			appName,		})		.returning()		.then((value) => value[0]); 	if (!newLibsql) {		throw new TRPCError({			code: "BAD_REQUEST",			message: "Error input: Inserting libsql database",		});	} 	return newLibsql;}; // https://github.com/drizzle-team/drizzle-orm/discussions/1483#discussioncomment-7523881export const findLibsqlById = async (libsqlId: string) => {	const result = await db.query.libsql.findFirst({		where: eq(libsql.libsqlId, libsqlId),		with: {			environment: {				with: {					project: true,				},			},			mounts: true,			server: true,			backups: {				with: {					destination: {						columns: {							accessKey: false,							secretAccessKey: false,						},					},					deployments: true,				},			},		},	});	if (!result) {		throw new TRPCError({			code: "NOT_FOUND",			message: "Libsql not found",		});	}	return result;}; export const updateLibsqlById = async (	libsqlId: string,	libsqlData: Partial<Libsql>,) => {	const { appName, ...rest } = libsqlData;	const result = await db		.update(libsql)		.set({			...rest,		})		.where(eq(libsql.libsqlId, libsqlId))		.returning(); 	return result[0];}; export const removeLibsqlById = async (libsqlId: string) => {	const result = await db		.delete(libsql)		.where(eq(libsql.libsqlId, libsqlId))		.returning(); 	return result[0];}; export const findLibsqlByBackupId = async (backupId: string) => {	const result = await db		.select({			...getTableColumns(libsql),		})		.from(libsql)		.innerJoin(backups, eq(libsql.libsqlId, backups.libsqlId))		.where(eq(backups.backupId, backupId))		.limit(1); 	if (!result || !result[0]) {		throw new TRPCError({			code: "NOT_FOUND",			message: "Libsql not found",		});	}	return result[0];}; export const deployLibsql = async (	libsqlId: string,	onData?: (data: any) => void,) => {	const libsql = await findLibsqlById(libsqlId);	try {		await updateLibsqlById(libsqlId, {			applicationStatus: "running",		});		onData?.("Starting libsql deployment...");		if (libsql.serverId) {			await execAsyncRemote(				libsql.serverId,				`docker pull ${quote([libsql.dockerImage])}`,				onData,			);		} else {			await pullImage(libsql.dockerImage, onData);		} 		await buildLibsql(libsql);		await waitForSwarmServiceConvergence(libsql.appName, libsql.serverId);		await updateLibsqlById(libsqlId, {			applicationStatus: "done",		});		onData?.("Deployment completed successfully!");	} catch (error) {		onData?.(`Error: ${error}`);		await updateLibsqlById(libsqlId, {			applicationStatus: "error",		}); 		throw new TRPCError({			code: "INTERNAL_SERVER_ERROR",			message: `Error on deploy libsql${error}`,		});	}	return libsql;};