mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-10-15 21:31:11 +00:00
184 lines
4.8 KiB
TypeScript
184 lines
4.8 KiB
TypeScript
// No db/schema imports here — client components import this file directly, and dockerode/ssh2 (child_process) would break the browser bundle.
|
|
|
|
export type OverviewServiceType =
|
|
| "application"
|
|
| "postgres"
|
|
| "mysql"
|
|
| "mariadb"
|
|
| "mongo"
|
|
| "redis"
|
|
| "compose"
|
|
| "libsql";
|
|
|
|
export interface OverviewService {
|
|
id: string;
|
|
type: OverviewServiceType;
|
|
name: string;
|
|
appName: string;
|
|
status: string | null;
|
|
createdAt: string;
|
|
serverId: string | null;
|
|
serverName: string | null;
|
|
icon: string | null;
|
|
projectId: string;
|
|
projectName: string;
|
|
environmentId: string;
|
|
environmentName: string;
|
|
lastDeployAt: string | null;
|
|
}
|
|
|
|
export type OverviewSortBy =
|
|
| "name-asc"
|
|
| "name-desc"
|
|
| "type-asc"
|
|
| "type-desc"
|
|
| "createdAt-asc"
|
|
| "createdAt-desc"
|
|
| "lastDeploy-asc"
|
|
| "lastDeploy-desc";
|
|
|
|
export const sortOverviewServices = (
|
|
services: OverviewService[],
|
|
sortBy: OverviewSortBy,
|
|
): OverviewService[] => {
|
|
const [field, direction] = sortBy.split("-") as [string, "asc" | "desc"];
|
|
return [...services].sort((a, b) => {
|
|
if (field === "name") {
|
|
const cmp = a.name.localeCompare(b.name);
|
|
return direction === "asc" ? cmp : -cmp;
|
|
}
|
|
if (field === "type") {
|
|
const cmp = a.type.localeCompare(b.type);
|
|
return direction === "asc" ? cmp : -cmp;
|
|
}
|
|
if (field === "createdAt") {
|
|
const cmp =
|
|
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
return direction === "asc" ? cmp : -cmp;
|
|
}
|
|
// lastDeploy: services without a deploy always sort to the end.
|
|
const aDate = a.lastDeployAt ? new Date(a.lastDeployAt).getTime() : null;
|
|
const bDate = b.lastDeployAt ? new Date(b.lastDeployAt).getTime() : null;
|
|
if (aDate === null && bDate === null) return 0;
|
|
if (aDate === null) return 1;
|
|
if (bDate === null) return -1;
|
|
return direction === "desc" ? bDate - aDate : aDate - bDate;
|
|
});
|
|
};
|
|
|
|
export const DB_ENGINE_ICON_TYPES = new Set([
|
|
"postgres",
|
|
"mariadb",
|
|
"mysql",
|
|
"mongo",
|
|
"redis",
|
|
"libsql",
|
|
]);
|
|
|
|
export const getServiceOverviewIcon = (service: {
|
|
type: OverviewServiceType;
|
|
icon: string | null;
|
|
}):
|
|
| { kind: "db"; engine: string }
|
|
| { kind: "custom"; url: string }
|
|
| { kind: "generic"; type: "application" | "compose" } => {
|
|
if (DB_ENGINE_ICON_TYPES.has(service.type)) {
|
|
return { kind: "db", engine: service.type };
|
|
}
|
|
if (service.icon) {
|
|
return { kind: "custom", url: service.icon };
|
|
}
|
|
return { kind: "generic", type: service.type as "application" | "compose" };
|
|
};
|
|
|
|
export type OverviewBackupKind = "backup" | "volumeBackup";
|
|
|
|
export interface OverviewBackup {
|
|
deploymentId: string;
|
|
kind: OverviewBackupKind;
|
|
status: string | null;
|
|
createdAt: string;
|
|
destinationId: string;
|
|
destinationName: string;
|
|
databaseType: string | null;
|
|
serviceType: string | null;
|
|
backupType: "database" | "compose" | null;
|
|
serviceName: string;
|
|
serviceOwnerId: string | null;
|
|
serviceOwnerType: OverviewServiceType | "web-server";
|
|
serverId: string | null;
|
|
projectId: string | null;
|
|
environmentId: string | null;
|
|
}
|
|
|
|
export type OverviewDomainOwnerType = "application" | "compose";
|
|
|
|
export interface OverviewDomain {
|
|
domainId: string;
|
|
host: string;
|
|
path: string | null;
|
|
port: number | null;
|
|
customEntrypoint: string | null;
|
|
https: boolean;
|
|
certificateType: "letsencrypt" | "none" | "custom";
|
|
createdAt: string;
|
|
enabled: boolean;
|
|
domainType: "application" | "compose" | "preview" | null;
|
|
serviceOwnerId: string;
|
|
serviceOwnerType: OverviewDomainOwnerType;
|
|
serviceName: string;
|
|
projectId: string;
|
|
projectName: string;
|
|
environmentId: string;
|
|
environmentName: string;
|
|
}
|
|
|
|
export type OverviewDomainSortBy =
|
|
| "createdAt-asc"
|
|
| "createdAt-desc"
|
|
| "port-asc"
|
|
| "port-desc";
|
|
|
|
export const sortOverviewDomains = (
|
|
domains: OverviewDomain[],
|
|
sortBy: OverviewDomainSortBy,
|
|
): OverviewDomain[] => {
|
|
const [field, direction] = sortBy.split("-") as [string, "asc" | "desc"];
|
|
return [...domains].sort((a, b) => {
|
|
if (field === "port") {
|
|
// Domains without a port sort to the end regardless of direction.
|
|
const aPort = a.port;
|
|
const bPort = b.port;
|
|
if (aPort === null && bPort === null) return 0;
|
|
if (aPort === null) return 1;
|
|
if (bPort === null) return -1;
|
|
return direction === "asc" ? aPort - bPort : bPort - aPort;
|
|
}
|
|
const cmp =
|
|
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
return direction === "asc" ? cmp : -cmp;
|
|
});
|
|
};
|
|
|
|
export const getBackupOverviewIcon = (
|
|
row: Pick<
|
|
OverviewBackup,
|
|
"databaseType" | "serviceType" | "serviceOwnerType"
|
|
>,
|
|
):
|
|
| { kind: "db"; engine: string }
|
|
| { kind: "generic"; type: "application" | "compose" }
|
|
| { kind: "webServer" } => {
|
|
const engine = row.databaseType ?? row.serviceType;
|
|
if (engine === "web-server") {
|
|
return { kind: "webServer" };
|
|
}
|
|
if (engine && DB_ENGINE_ICON_TYPES.has(engine)) {
|
|
return { kind: "db", engine };
|
|
}
|
|
if (row.serviceOwnerType === "compose") {
|
|
return { kind: "generic", type: "compose" };
|
|
}
|
|
return { kind: "generic", type: "application" };
|
|
};
|