mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
Merge branch 'canary' of github.com:imran-vz/dokploy into feat/quick-service-switcher
This commit is contained in:
@@ -99,17 +99,15 @@ const createSchema = createInsertSchema(mounts, {
|
||||
mountPath: z.string().min(1),
|
||||
mountId: z.string().optional(),
|
||||
filePath: z.string().optional(),
|
||||
serviceType: z
|
||||
.enum([
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis",
|
||||
"compose",
|
||||
])
|
||||
.default("application"),
|
||||
serviceType: z.enum([
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis",
|
||||
"compose",
|
||||
]),
|
||||
});
|
||||
|
||||
export type ServiceType = NonNullable<
|
||||
|
||||
@@ -10,7 +10,11 @@ import {
|
||||
type apiCreateDeploymentSchedule,
|
||||
type apiCreateDeploymentServer,
|
||||
type apiCreateDeploymentVolumeBackup,
|
||||
applications,
|
||||
compose,
|
||||
deployments,
|
||||
environments,
|
||||
projects,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { removeDirectoryIfExistsContent } from "@dokploy/server/utils/filesystem/directory";
|
||||
import {
|
||||
@@ -19,7 +23,7 @@ import {
|
||||
} from "@dokploy/server/utils/process/execAsync";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { format } from "date-fns";
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
import { desc, eq, and, inArray, or, sql } from "drizzle-orm";
|
||||
import type { z } from "zod";
|
||||
import {
|
||||
type Application,
|
||||
@@ -38,6 +42,41 @@ import { findScheduleById } from "./schedule";
|
||||
import { findServerById, type Server } from "./server";
|
||||
import { findVolumeBackupById } from "./volume-backups";
|
||||
|
||||
export type ServicePath = { href: string | null; label: string };
|
||||
|
||||
export async function resolveServicePath(
|
||||
orgId: string,
|
||||
data: Record<string, unknown>,
|
||||
): Promise<ServicePath> {
|
||||
try {
|
||||
const applicationId = data?.applicationId as string | undefined;
|
||||
const composeId = data?.composeId as string | undefined;
|
||||
if (applicationId) {
|
||||
const app = await findApplicationById(applicationId);
|
||||
if (app.environment.project.organizationId !== orgId) {
|
||||
return { href: null, label: "Application" };
|
||||
}
|
||||
return {
|
||||
href: `/dashboard/project/${app.environment.project.projectId}/environment/${app.environment.environmentId}/services/application/${app.applicationId}`,
|
||||
label: "Application",
|
||||
};
|
||||
}
|
||||
if (composeId) {
|
||||
const comp = await findComposeById(composeId);
|
||||
if (comp.environment.project.organizationId !== orgId) {
|
||||
return { href: null, label: "Compose" };
|
||||
}
|
||||
return {
|
||||
href: `/dashboard/project/${comp.environment.project.projectId}/environment/${comp.environment.environmentId}/services/compose/${comp.composeId}`,
|
||||
label: "Compose",
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// not found or unauthorized
|
||||
}
|
||||
return { href: null, label: "—" };
|
||||
}
|
||||
|
||||
export type Deployment = typeof deployments.$inferSelect;
|
||||
|
||||
export const findDeploymentById = async (deploymentId: string) => {
|
||||
@@ -738,6 +777,135 @@ export const findAllDeploymentsByComposeId = async (composeId: string) => {
|
||||
return deploymentsList;
|
||||
};
|
||||
|
||||
const centralizedDeploymentsWith = {
|
||||
application: {
|
||||
columns: { applicationId: true, name: true, appName: true },
|
||||
with: {
|
||||
environment: {
|
||||
columns: { environmentId: true, name: true },
|
||||
with: {
|
||||
project: {
|
||||
columns: { projectId: true, name: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
columns: { serverId: true, name: true, serverType: true },
|
||||
},
|
||||
buildServer: {
|
||||
columns: { serverId: true, name: true, serverType: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
compose: {
|
||||
columns: { composeId: true, name: true, appName: true },
|
||||
with: {
|
||||
environment: {
|
||||
columns: { environmentId: true, name: true },
|
||||
with: {
|
||||
project: {
|
||||
columns: { projectId: true, name: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
columns: { serverId: true, name: true, serverType: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
columns: { serverId: true, name: true, serverType: true },
|
||||
},
|
||||
buildServer: {
|
||||
columns: { serverId: true, name: true, serverType: true },
|
||||
},
|
||||
} as const;
|
||||
|
||||
async function getApplicationIdsInOrg(
|
||||
orgId: string,
|
||||
accessedServices: string[] | null,
|
||||
): Promise<string[]> {
|
||||
const rows = await db
|
||||
.select({ applicationId: applications.applicationId })
|
||||
.from(applications)
|
||||
.innerJoin(
|
||||
environments,
|
||||
eq(applications.environmentId, environments.environmentId),
|
||||
)
|
||||
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||
.where(
|
||||
accessedServices !== null
|
||||
? and(
|
||||
eq(projects.organizationId, orgId),
|
||||
inArray(applications.applicationId, accessedServices),
|
||||
)
|
||||
: eq(projects.organizationId, orgId),
|
||||
);
|
||||
return rows.map((r) => r.applicationId);
|
||||
}
|
||||
|
||||
async function getComposeIdsInOrg(
|
||||
orgId: string,
|
||||
accessedServices: string[] | null,
|
||||
): Promise<string[]> {
|
||||
const rows = await db
|
||||
.select({ composeId: compose.composeId })
|
||||
.from(compose)
|
||||
.innerJoin(
|
||||
environments,
|
||||
eq(compose.environmentId, environments.environmentId),
|
||||
)
|
||||
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||
.where(
|
||||
accessedServices !== null
|
||||
? and(
|
||||
eq(projects.organizationId, orgId),
|
||||
inArray(compose.composeId, accessedServices),
|
||||
)
|
||||
: eq(projects.organizationId, orgId),
|
||||
);
|
||||
return rows.map((r) => r.composeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* All deployments for applications and compose in the org.
|
||||
* Pass accessedServices for members (only those services), null for owner/admin.
|
||||
*/
|
||||
export const findAllDeploymentsCentralized = async (
|
||||
orgId: string,
|
||||
accessedServices: string[] | null,
|
||||
) => {
|
||||
if (accessedServices !== null && accessedServices.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const [appIds, compIds] = await Promise.all([
|
||||
getApplicationIdsInOrg(orgId, accessedServices),
|
||||
getComposeIdsInOrg(orgId, accessedServices),
|
||||
]);
|
||||
|
||||
if (appIds.length === 0 && compIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const conditions = [
|
||||
...(appIds.length > 0 ? [inArray(deployments.applicationId, appIds)] : []),
|
||||
...(compIds.length > 0 ? [inArray(deployments.composeId, compIds)] : []),
|
||||
];
|
||||
const whereClause =
|
||||
conditions.length === 0
|
||||
? sql`1 = 0`
|
||||
: conditions.length === 1
|
||||
? conditions[0]
|
||||
: or(...conditions);
|
||||
|
||||
return db.query.deployments.findMany({
|
||||
where: whereClause,
|
||||
orderBy: desc(deployments.createdAt),
|
||||
with: centralizedDeploymentsWith,
|
||||
});
|
||||
};
|
||||
|
||||
export const updateDeployment = async (
|
||||
deploymentId: string,
|
||||
deploymentData: Partial<Deployment>,
|
||||
|
||||
Reference in New Issue
Block a user