mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-15 19:05:28 +02:00
- Added a check to prevent empty values from being processed in the onValueChange handler for Bitbucket, Gitea, GitHub, and GitLab providers. - Removed unnecessary defaultValue prop from Select components to streamline the code. - Updated button styles to remove background color for better consistency across the UI. - Enhanced volume backup selection to display a message when no volumes are found. This update enhances user experience by ensuring that empty selections are handled gracefully and improves the overall visual consistency of the UI components.
374 lines
7.7 KiB
TypeScript
374 lines
7.7 KiB
TypeScript
import { db } from "@dokploy/server/db";
|
|
import {
|
|
type apiCreateEnvironment,
|
|
type apiDuplicateEnvironment,
|
|
environments,
|
|
} from "@dokploy/server/db/schema";
|
|
import { TRPCError } from "@trpc/server";
|
|
import { asc, eq } from "drizzle-orm";
|
|
import type { z } from "zod";
|
|
|
|
export type Environment = typeof environments.$inferSelect;
|
|
|
|
export const createEnvironment = async (
|
|
input: z.infer<typeof apiCreateEnvironment>,
|
|
) => {
|
|
const newEnvironment = await db
|
|
.insert(environments)
|
|
.values({
|
|
...input,
|
|
})
|
|
.returning()
|
|
.then((value) => value[0]);
|
|
|
|
if (!newEnvironment) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "Error creating the environment",
|
|
});
|
|
}
|
|
|
|
return newEnvironment;
|
|
};
|
|
|
|
export const findEnvironmentById = async (environmentId: string) => {
|
|
const environment = await db.query.environments.findFirst({
|
|
where: eq(environments.environmentId, environmentId),
|
|
columns: {
|
|
name: true,
|
|
description: true,
|
|
environmentId: true,
|
|
isDefault: true,
|
|
projectId: true,
|
|
env: true,
|
|
},
|
|
with: {
|
|
applications: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
name: true,
|
|
applicationId: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
icon: true,
|
|
},
|
|
},
|
|
mariadb: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
mariadbId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
mongo: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
mongoId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
mysql: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
mysqlId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
postgres: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
postgresId: true,
|
|
name: true,
|
|
description: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
redis: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
redisId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
compose: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
composeId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
composeStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
libsql: {
|
|
with: {
|
|
server: {
|
|
columns: {
|
|
name: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
},
|
|
columns: {
|
|
libsqlId: true,
|
|
name: true,
|
|
createdAt: true,
|
|
applicationStatus: true,
|
|
description: true,
|
|
serverId: true,
|
|
},
|
|
},
|
|
project: true,
|
|
},
|
|
});
|
|
if (!environment) {
|
|
throw new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: "Environment not found",
|
|
});
|
|
}
|
|
return environment;
|
|
};
|
|
|
|
export const findEnvironmentsByProjectId = async (projectId: string) => {
|
|
const projectEnvironments = await db.query.environments.findMany({
|
|
where: eq(environments.projectId, projectId),
|
|
orderBy: asc(environments.createdAt),
|
|
with: {
|
|
applications: true,
|
|
mariadb: true,
|
|
mongo: true,
|
|
mysql: true,
|
|
postgres: true,
|
|
redis: true,
|
|
compose: true,
|
|
libsql: true,
|
|
project: true,
|
|
},
|
|
columns: {
|
|
name: true,
|
|
description: true,
|
|
environmentId: true,
|
|
isDefault: true,
|
|
},
|
|
});
|
|
return projectEnvironments;
|
|
};
|
|
|
|
const environmentHasServices = (
|
|
env: Awaited<ReturnType<typeof findEnvironmentById>>,
|
|
) => {
|
|
return (
|
|
(env.applications?.length ?? 0) > 0 ||
|
|
(env.compose?.length ?? 0) > 0 ||
|
|
(env.libsql?.length ?? 0) > 0 ||
|
|
(env.mariadb?.length ?? 0) > 0 ||
|
|
(env.mongo?.length ?? 0) > 0 ||
|
|
(env.mysql?.length ?? 0) > 0 ||
|
|
(env.postgres?.length ?? 0) > 0 ||
|
|
(env.redis?.length ?? 0) > 0
|
|
);
|
|
};
|
|
|
|
export const deleteEnvironment = async (environmentId: string) => {
|
|
const currentEnvironment = await findEnvironmentById(environmentId);
|
|
if (currentEnvironment.isDefault) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "You cannot delete the default environment",
|
|
});
|
|
}
|
|
if (environmentHasServices(currentEnvironment)) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message:
|
|
"Cannot delete environment: it has active services. Delete all services first.",
|
|
});
|
|
}
|
|
const deletedEnvironment = await db
|
|
.delete(environments)
|
|
.where(eq(environments.environmentId, environmentId))
|
|
.returning()
|
|
.then((value) => value[0]);
|
|
|
|
return deletedEnvironment;
|
|
};
|
|
|
|
export const updateEnvironmentById = async (
|
|
environmentId: string,
|
|
environmentData: Partial<Environment>,
|
|
) => {
|
|
const result = await db
|
|
.update(environments)
|
|
.set({
|
|
...environmentData,
|
|
})
|
|
.where(eq(environments.environmentId, environmentId))
|
|
.returning()
|
|
.then((res) => res[0]);
|
|
|
|
return result;
|
|
};
|
|
|
|
export const duplicateEnvironment = async (
|
|
input: z.infer<typeof apiDuplicateEnvironment>,
|
|
) => {
|
|
// Find the original environment
|
|
const originalEnvironment = await findEnvironmentById(input.environmentId);
|
|
|
|
// Create a new environment with the provided name and description
|
|
const newEnvironment = await db
|
|
.insert(environments)
|
|
.values({
|
|
name: input.name,
|
|
description: input.description || originalEnvironment.description,
|
|
projectId: originalEnvironment.projectId,
|
|
env: originalEnvironment.env,
|
|
})
|
|
.returning()
|
|
.then((value) => value[0]);
|
|
|
|
if (!newEnvironment) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "Error duplicating the environment",
|
|
});
|
|
}
|
|
|
|
return newEnvironment;
|
|
};
|
|
|
|
interface EnvironmentWithServices {
|
|
applications: { applicationId: string }[];
|
|
compose: { composeId: string }[];
|
|
libsql: { libsqlId: string }[];
|
|
mariadb: { mariadbId: string }[];
|
|
mongo: { mongoId: string }[];
|
|
mysql: { mysqlId: string }[];
|
|
postgres: { postgresId: string }[];
|
|
redis: { redisId: string }[];
|
|
}
|
|
|
|
export const filterEnvironmentServices = <T extends EnvironmentWithServices>(
|
|
environment: T,
|
|
accessedServices: string[],
|
|
): T => ({
|
|
...environment,
|
|
applications: environment.applications.filter((app) =>
|
|
accessedServices.includes(app.applicationId),
|
|
),
|
|
compose: environment.compose.filter((comp) =>
|
|
accessedServices.includes(comp.composeId),
|
|
),
|
|
libsql: environment.libsql.filter((db) =>
|
|
accessedServices.includes(db.libsqlId),
|
|
),
|
|
mariadb: environment.mariadb.filter((db) =>
|
|
accessedServices.includes(db.mariadbId),
|
|
),
|
|
mongo: environment.mongo.filter((db) =>
|
|
accessedServices.includes(db.mongoId),
|
|
),
|
|
mysql: environment.mysql.filter((db) =>
|
|
accessedServices.includes(db.mysqlId),
|
|
),
|
|
postgres: environment.postgres.filter((db) =>
|
|
accessedServices.includes(db.postgresId),
|
|
),
|
|
redis: environment.redis.filter((db) =>
|
|
accessedServices.includes(db.redisId),
|
|
),
|
|
});
|
|
|
|
export const createProductionEnvironment = async (projectId: string) => {
|
|
const newEnvironment = await db
|
|
.insert(environments)
|
|
.values({
|
|
name: "production",
|
|
description: "Production environment",
|
|
projectId,
|
|
isDefault: true,
|
|
})
|
|
.returning()
|
|
.then((value) => value[0]);
|
|
|
|
if (!newEnvironment) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "Error creating the production environment",
|
|
});
|
|
}
|
|
|
|
return newEnvironment;
|
|
};
|