mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
chore: remove application delete volume
This commit is contained in:
@@ -1,22 +1,21 @@
|
|||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
@@ -29,158 +28,134 @@ import { toast } from "sonner";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const deleteApplicationSchema = z.object({
|
const deleteApplicationSchema = z.object({
|
||||||
projectName: z.string().min(1, {
|
projectName: z.string().min(1, {
|
||||||
message: "Application name is required",
|
message: "Application name is required",
|
||||||
}),
|
}),
|
||||||
deleteVolumes: z.boolean(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type DeleteApplication = z.infer<typeof deleteApplicationSchema>;
|
type DeleteApplication = z.infer<typeof deleteApplicationSchema>;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DeleteApplication = ({ applicationId }: Props) => {
|
export const DeleteApplication = ({ applicationId }: Props) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const { mutateAsync, isLoading } = api.application.delete.useMutation();
|
const { mutateAsync, isLoading } = api.application.delete.useMutation();
|
||||||
const { data } = api.application.one.useQuery(
|
const { data } = api.application.one.useQuery(
|
||||||
{ applicationId },
|
{ applicationId },
|
||||||
{ enabled: !!applicationId },
|
{ enabled: !!applicationId }
|
||||||
);
|
);
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
const form = useForm<DeleteApplication>({
|
const form = useForm<DeleteApplication>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
projectName: "",
|
projectName: "",
|
||||||
deleteVolumes: false,
|
},
|
||||||
},
|
resolver: zodResolver(deleteApplicationSchema),
|
||||||
resolver: zodResolver(deleteApplicationSchema),
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmit = async (formData: DeleteApplication) => {
|
const onSubmit = async (formData: DeleteApplication) => {
|
||||||
const expectedName = `${data?.name}/${data?.appName}`;
|
const expectedName = `${data?.name}/${data?.appName}`;
|
||||||
if (formData.projectName === expectedName) {
|
if (formData.projectName === expectedName) {
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
applicationId,
|
applicationId,
|
||||||
deleteVolumes: formData.deleteVolumes,
|
})
|
||||||
})
|
.then((data) => {
|
||||||
.then((data) => {
|
push(`/dashboard/project/${data?.projectId}`);
|
||||||
push(`/dashboard/project/${data?.projectId}`);
|
toast.success("Application deleted successfully");
|
||||||
toast.success("Application deleted successfully");
|
setIsOpen(false);
|
||||||
setIsOpen(false);
|
})
|
||||||
})
|
.catch(() => {
|
||||||
.catch(() => {
|
toast.error("Error deleting the application");
|
||||||
toast.error("Error deleting the application");
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
form.setError("projectName", {
|
||||||
form.setError("projectName", {
|
message: "Project name does not match",
|
||||||
message: "Project name does not match",
|
});
|
||||||
});
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="ghost" isLoading={isLoading}>
|
<Button variant="ghost" isLoading={isLoading}>
|
||||||
<TrashIcon className="size-4 text-muted-foreground" />
|
<TrashIcon className="size-4 text-muted-foreground" />
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Are you absolutely sure?</DialogTitle>
|
<DialogTitle>Are you absolutely sure?</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
This action cannot be undone. This will permanently delete the
|
This action cannot be undone. This will permanently delete the
|
||||||
application. If you are sure please enter the application name to
|
application. If you are sure please enter the application name to
|
||||||
delete this application.
|
delete this application.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="grid gap-4">
|
<div className="grid gap-4">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
id="hook-form-delete-application"
|
id="hook-form-delete-application"
|
||||||
className="grid w-full gap-4"
|
className="grid w-full gap-4"
|
||||||
>
|
>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="projectName"
|
name="projectName"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="flex items-center gap-2">
|
<FormLabel className="flex items-center gap-2">
|
||||||
<span>
|
<span>
|
||||||
To confirm, type{" "}
|
To confirm, type{" "}
|
||||||
<Badge
|
<Badge
|
||||||
className="p-2 rounded-md ml-1 mr-1 hover:border-primary hover:text-primary-foreground hover:bg-primary hover:cursor-pointer"
|
className="p-2 rounded-md ml-1 mr-1 hover:border-primary hover:text-primary-foreground hover:bg-primary hover:cursor-pointer"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (data?.name && data?.appName) {
|
if (data?.name && data?.appName) {
|
||||||
navigator.clipboard.writeText(
|
navigator.clipboard.writeText(
|
||||||
`${data.name}/${data.appName}`,
|
`${data.name}/${data.appName}`
|
||||||
);
|
);
|
||||||
toast.success("Copied to clipboard. Be careful!");
|
toast.success("Copied to clipboard. Be careful!");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{data?.name}/{data?.appName}
|
{data?.name}/{data?.appName}
|
||||||
<Copy className="h-4 w-4 ml-1 text-muted-foreground" />
|
<Copy className="h-4 w-4 ml-1 text-muted-foreground" />
|
||||||
</Badge>{" "}
|
</Badge>{" "}
|
||||||
in the box below:
|
in the box below:
|
||||||
</span>
|
</span>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Enter application name to confirm"
|
placeholder="Enter application name to confirm"
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormField
|
</form>
|
||||||
control={form.control}
|
</Form>
|
||||||
name="deleteVolumes"
|
</div>
|
||||||
render={({ field }) => (
|
<DialogFooter>
|
||||||
<FormItem>
|
<Button
|
||||||
<div className="flex items-center">
|
variant="secondary"
|
||||||
<FormControl>
|
onClick={() => {
|
||||||
<Checkbox
|
setIsOpen(false);
|
||||||
checked={field.value}
|
}}
|
||||||
onCheckedChange={field.onChange}
|
>
|
||||||
/>
|
Cancel
|
||||||
</FormControl>
|
</Button>
|
||||||
|
<Button
|
||||||
<FormLabel className="ml-2">
|
isLoading={isLoading}
|
||||||
Delete volumes associated with this compose
|
form="hook-form-delete-application"
|
||||||
</FormLabel>
|
type="submit"
|
||||||
</div>
|
variant="destructive"
|
||||||
<FormMessage />
|
>
|
||||||
</FormItem>
|
Confirm
|
||||||
)}
|
</Button>
|
||||||
/>
|
</DialogFooter>
|
||||||
</form>
|
</DialogContent>
|
||||||
</Form>
|
</Dialog>
|
||||||
</div>
|
);
|
||||||
<DialogFooter>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => {
|
|
||||||
setIsOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
isLoading={isLoading}
|
|
||||||
form="hook-form-delete-application"
|
|
||||||
type="submit"
|
|
||||||
variant="destructive"
|
|
||||||
>
|
|
||||||
Confirm
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
|||||||
import { relations } from "drizzle-orm";
|
import { relations } from "drizzle-orm";
|
||||||
import {
|
import {
|
||||||
boolean,
|
boolean,
|
||||||
integer,
|
integer,
|
||||||
json,
|
json,
|
||||||
pgEnum,
|
pgEnum,
|
||||||
pgTable,
|
pgTable,
|
||||||
text,
|
text,
|
||||||
} from "drizzle-orm/pg-core";
|
} from "drizzle-orm/pg-core";
|
||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
@@ -28,498 +28,493 @@ import { sshKeys } from "./ssh-key";
|
|||||||
import { generateAppName } from "./utils";
|
import { generateAppName } from "./utils";
|
||||||
|
|
||||||
export const sourceType = pgEnum("sourceType", [
|
export const sourceType = pgEnum("sourceType", [
|
||||||
"docker",
|
"docker",
|
||||||
"git",
|
"git",
|
||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"bitbucket",
|
"bitbucket",
|
||||||
"drop",
|
"drop",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const buildType = pgEnum("buildType", [
|
export const buildType = pgEnum("buildType", [
|
||||||
"dockerfile",
|
"dockerfile",
|
||||||
"heroku_buildpacks",
|
"heroku_buildpacks",
|
||||||
"paketo_buildpacks",
|
"paketo_buildpacks",
|
||||||
"nixpacks",
|
"nixpacks",
|
||||||
"static",
|
"static",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// TODO: refactor this types
|
// TODO: refactor this types
|
||||||
export interface HealthCheckSwarm {
|
export interface HealthCheckSwarm {
|
||||||
Test?: string[] | undefined;
|
Test?: string[] | undefined;
|
||||||
Interval?: number | undefined;
|
Interval?: number | undefined;
|
||||||
Timeout?: number | undefined;
|
Timeout?: number | undefined;
|
||||||
StartPeriod?: number | undefined;
|
StartPeriod?: number | undefined;
|
||||||
Retries?: number | undefined;
|
Retries?: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RestartPolicySwarm {
|
export interface RestartPolicySwarm {
|
||||||
Condition?: string | undefined;
|
Condition?: string | undefined;
|
||||||
Delay?: number | undefined;
|
Delay?: number | undefined;
|
||||||
MaxAttempts?: number | undefined;
|
MaxAttempts?: number | undefined;
|
||||||
Window?: number | undefined;
|
Window?: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlacementSwarm {
|
export interface PlacementSwarm {
|
||||||
Constraints?: string[] | undefined;
|
Constraints?: string[] | undefined;
|
||||||
Preferences?: Array<{ Spread: { SpreadDescriptor: string } }> | undefined;
|
Preferences?: Array<{ Spread: { SpreadDescriptor: string } }> | undefined;
|
||||||
MaxReplicas?: number | undefined;
|
MaxReplicas?: number | undefined;
|
||||||
Platforms?:
|
Platforms?:
|
||||||
| Array<{
|
| Array<{
|
||||||
Architecture: string;
|
Architecture: string;
|
||||||
OS: string;
|
OS: string;
|
||||||
}>
|
}>
|
||||||
| undefined;
|
| undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateConfigSwarm {
|
export interface UpdateConfigSwarm {
|
||||||
Parallelism: number;
|
Parallelism: number;
|
||||||
Delay?: number | undefined;
|
Delay?: number | undefined;
|
||||||
FailureAction?: string | undefined;
|
FailureAction?: string | undefined;
|
||||||
Monitor?: number | undefined;
|
Monitor?: number | undefined;
|
||||||
MaxFailureRatio?: number | undefined;
|
MaxFailureRatio?: number | undefined;
|
||||||
Order: string;
|
Order: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServiceModeSwarm {
|
export interface ServiceModeSwarm {
|
||||||
Replicated?: { Replicas?: number | undefined } | undefined;
|
Replicated?: { Replicas?: number | undefined } | undefined;
|
||||||
Global?: {} | undefined;
|
Global?: {} | undefined;
|
||||||
ReplicatedJob?:
|
ReplicatedJob?:
|
||||||
| {
|
| {
|
||||||
MaxConcurrent?: number | undefined;
|
MaxConcurrent?: number | undefined;
|
||||||
TotalCompletions?: number | undefined;
|
TotalCompletions?: number | undefined;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
GlobalJob?: {} | undefined;
|
GlobalJob?: {} | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NetworkSwarm {
|
export interface NetworkSwarm {
|
||||||
Target?: string | undefined;
|
Target?: string | undefined;
|
||||||
Aliases?: string[] | undefined;
|
Aliases?: string[] | undefined;
|
||||||
DriverOpts?: { [key: string]: string } | undefined;
|
DriverOpts?: { [key: string]: string } | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelsSwarm {
|
export interface LabelsSwarm {
|
||||||
[name: string]: string;
|
[name: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const applications = pgTable("application", {
|
export const applications = pgTable("application", {
|
||||||
applicationId: text("applicationId")
|
applicationId: text("applicationId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.primaryKey()
|
.primaryKey()
|
||||||
.$defaultFn(() => nanoid()),
|
.$defaultFn(() => nanoid()),
|
||||||
name: text("name").notNull(),
|
name: text("name").notNull(),
|
||||||
appName: text("appName")
|
appName: text("appName")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => generateAppName("app"))
|
.$defaultFn(() => generateAppName("app"))
|
||||||
.unique(),
|
.unique(),
|
||||||
description: text("description"),
|
description: text("description"),
|
||||||
env: text("env"),
|
env: text("env"),
|
||||||
previewEnv: text("previewEnv"),
|
previewEnv: text("previewEnv"),
|
||||||
previewBuildArgs: text("previewBuildArgs"),
|
previewBuildArgs: text("previewBuildArgs"),
|
||||||
previewWildcard: text("previewWildcard"),
|
previewWildcard: text("previewWildcard"),
|
||||||
previewPort: integer("previewPort").default(3000),
|
previewPort: integer("previewPort").default(3000),
|
||||||
previewHttps: boolean("previewHttps").notNull().default(false),
|
previewHttps: boolean("previewHttps").notNull().default(false),
|
||||||
previewPath: text("previewPath").default("/"),
|
previewPath: text("previewPath").default("/"),
|
||||||
previewCertificateType: certificateType("certificateType")
|
previewCertificateType: certificateType("certificateType")
|
||||||
.notNull()
|
.notNull()
|
||||||
.default("none"),
|
.default("none"),
|
||||||
previewLimit: integer("previewLimit").default(3),
|
previewLimit: integer("previewLimit").default(3),
|
||||||
isPreviewDeploymentsActive: boolean("isPreviewDeploymentsActive").default(
|
isPreviewDeploymentsActive: boolean("isPreviewDeploymentsActive").default(
|
||||||
false,
|
false
|
||||||
),
|
),
|
||||||
buildArgs: text("buildArgs"),
|
buildArgs: text("buildArgs"),
|
||||||
memoryReservation: integer("memoryReservation"),
|
memoryReservation: integer("memoryReservation"),
|
||||||
memoryLimit: integer("memoryLimit"),
|
memoryLimit: integer("memoryLimit"),
|
||||||
cpuReservation: integer("cpuReservation"),
|
cpuReservation: integer("cpuReservation"),
|
||||||
cpuLimit: integer("cpuLimit"),
|
cpuLimit: integer("cpuLimit"),
|
||||||
title: text("title"),
|
title: text("title"),
|
||||||
enabled: boolean("enabled"),
|
enabled: boolean("enabled"),
|
||||||
subtitle: text("subtitle"),
|
subtitle: text("subtitle"),
|
||||||
command: text("command"),
|
command: text("command"),
|
||||||
refreshToken: text("refreshToken").$defaultFn(() => nanoid()),
|
refreshToken: text("refreshToken").$defaultFn(() => nanoid()),
|
||||||
sourceType: sourceType("sourceType").notNull().default("github"),
|
sourceType: sourceType("sourceType").notNull().default("github"),
|
||||||
// Github
|
// Github
|
||||||
repository: text("repository"),
|
repository: text("repository"),
|
||||||
owner: text("owner"),
|
owner: text("owner"),
|
||||||
branch: text("branch"),
|
branch: text("branch"),
|
||||||
buildPath: text("buildPath").default("/"),
|
buildPath: text("buildPath").default("/"),
|
||||||
autoDeploy: boolean("autoDeploy").$defaultFn(() => true),
|
autoDeploy: boolean("autoDeploy").$defaultFn(() => true),
|
||||||
// Gitlab
|
// Gitlab
|
||||||
gitlabProjectId: integer("gitlabProjectId"),
|
gitlabProjectId: integer("gitlabProjectId"),
|
||||||
gitlabRepository: text("gitlabRepository"),
|
gitlabRepository: text("gitlabRepository"),
|
||||||
gitlabOwner: text("gitlabOwner"),
|
gitlabOwner: text("gitlabOwner"),
|
||||||
gitlabBranch: text("gitlabBranch"),
|
gitlabBranch: text("gitlabBranch"),
|
||||||
gitlabBuildPath: text("gitlabBuildPath").default("/"),
|
gitlabBuildPath: text("gitlabBuildPath").default("/"),
|
||||||
gitlabPathNamespace: text("gitlabPathNamespace"),
|
gitlabPathNamespace: text("gitlabPathNamespace"),
|
||||||
// Bitbucket
|
// Bitbucket
|
||||||
bitbucketRepository: text("bitbucketRepository"),
|
bitbucketRepository: text("bitbucketRepository"),
|
||||||
bitbucketOwner: text("bitbucketOwner"),
|
bitbucketOwner: text("bitbucketOwner"),
|
||||||
bitbucketBranch: text("bitbucketBranch"),
|
bitbucketBranch: text("bitbucketBranch"),
|
||||||
bitbucketBuildPath: text("bitbucketBuildPath").default("/"),
|
bitbucketBuildPath: text("bitbucketBuildPath").default("/"),
|
||||||
// Docker
|
// Docker
|
||||||
username: text("username"),
|
username: text("username"),
|
||||||
password: text("password"),
|
password: text("password"),
|
||||||
dockerImage: text("dockerImage"),
|
dockerImage: text("dockerImage"),
|
||||||
registryUrl: text("registryUrl"),
|
registryUrl: text("registryUrl"),
|
||||||
// Git
|
// Git
|
||||||
customGitUrl: text("customGitUrl"),
|
customGitUrl: text("customGitUrl"),
|
||||||
customGitBranch: text("customGitBranch"),
|
customGitBranch: text("customGitBranch"),
|
||||||
customGitBuildPath: text("customGitBuildPath"),
|
customGitBuildPath: text("customGitBuildPath"),
|
||||||
customGitSSHKeyId: text("customGitSSHKeyId").references(
|
customGitSSHKeyId: text("customGitSSHKeyId").references(
|
||||||
() => sshKeys.sshKeyId,
|
() => sshKeys.sshKeyId,
|
||||||
{
|
{
|
||||||
onDelete: "set null",
|
onDelete: "set null",
|
||||||
},
|
}
|
||||||
),
|
),
|
||||||
dockerfile: text("dockerfile"),
|
dockerfile: text("dockerfile"),
|
||||||
dockerContextPath: text("dockerContextPath"),
|
dockerContextPath: text("dockerContextPath"),
|
||||||
dockerBuildStage: text("dockerBuildStage"),
|
dockerBuildStage: text("dockerBuildStage"),
|
||||||
// Drop
|
// Drop
|
||||||
dropBuildPath: text("dropBuildPath"),
|
dropBuildPath: text("dropBuildPath"),
|
||||||
// Docker swarm json
|
// Docker swarm json
|
||||||
healthCheckSwarm: json("healthCheckSwarm").$type<HealthCheckSwarm>(),
|
healthCheckSwarm: json("healthCheckSwarm").$type<HealthCheckSwarm>(),
|
||||||
restartPolicySwarm: json("restartPolicySwarm").$type<RestartPolicySwarm>(),
|
restartPolicySwarm: json("restartPolicySwarm").$type<RestartPolicySwarm>(),
|
||||||
placementSwarm: json("placementSwarm").$type<PlacementSwarm>(),
|
placementSwarm: json("placementSwarm").$type<PlacementSwarm>(),
|
||||||
updateConfigSwarm: json("updateConfigSwarm").$type<UpdateConfigSwarm>(),
|
updateConfigSwarm: json("updateConfigSwarm").$type<UpdateConfigSwarm>(),
|
||||||
rollbackConfigSwarm: json("rollbackConfigSwarm").$type<UpdateConfigSwarm>(),
|
rollbackConfigSwarm: json("rollbackConfigSwarm").$type<UpdateConfigSwarm>(),
|
||||||
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
|
modeSwarm: json("modeSwarm").$type<ServiceModeSwarm>(),
|
||||||
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
|
labelsSwarm: json("labelsSwarm").$type<LabelsSwarm>(),
|
||||||
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
|
networkSwarm: json("networkSwarm").$type<NetworkSwarm[]>(),
|
||||||
//
|
//
|
||||||
replicas: integer("replicas").default(1).notNull(),
|
replicas: integer("replicas").default(1).notNull(),
|
||||||
applicationStatus: applicationStatus("applicationStatus")
|
applicationStatus: applicationStatus("applicationStatus")
|
||||||
.notNull()
|
.notNull()
|
||||||
.default("idle"),
|
.default("idle"),
|
||||||
buildType: buildType("buildType").notNull().default("nixpacks"),
|
buildType: buildType("buildType").notNull().default("nixpacks"),
|
||||||
herokuVersion: text("herokuVersion").default("24"),
|
herokuVersion: text("herokuVersion").default("24"),
|
||||||
publishDirectory: text("publishDirectory"),
|
publishDirectory: text("publishDirectory"),
|
||||||
createdAt: text("createdAt")
|
createdAt: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
registryId: text("registryId").references(() => registry.registryId, {
|
registryId: text("registryId").references(() => registry.registryId, {
|
||||||
onDelete: "set null",
|
onDelete: "set null",
|
||||||
}),
|
}),
|
||||||
projectId: text("projectId")
|
projectId: text("projectId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => projects.projectId, { onDelete: "cascade" }),
|
.references(() => projects.projectId, { onDelete: "cascade" }),
|
||||||
githubId: text("githubId").references(() => github.githubId, {
|
githubId: text("githubId").references(() => github.githubId, {
|
||||||
onDelete: "set null",
|
onDelete: "set null",
|
||||||
}),
|
}),
|
||||||
gitlabId: text("gitlabId").references(() => gitlab.gitlabId, {
|
gitlabId: text("gitlabId").references(() => gitlab.gitlabId, {
|
||||||
onDelete: "set null",
|
onDelete: "set null",
|
||||||
}),
|
}),
|
||||||
bitbucketId: text("bitbucketId").references(() => bitbucket.bitbucketId, {
|
bitbucketId: text("bitbucketId").references(() => bitbucket.bitbucketId, {
|
||||||
onDelete: "set null",
|
onDelete: "set null",
|
||||||
}),
|
}),
|
||||||
serverId: text("serverId").references(() => server.serverId, {
|
serverId: text("serverId").references(() => server.serverId, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const applicationsRelations = relations(
|
export const applicationsRelations = relations(
|
||||||
applications,
|
applications,
|
||||||
({ one, many }) => ({
|
({ one, many }) => ({
|
||||||
project: one(projects, {
|
project: one(projects, {
|
||||||
fields: [applications.projectId],
|
fields: [applications.projectId],
|
||||||
references: [projects.projectId],
|
references: [projects.projectId],
|
||||||
}),
|
}),
|
||||||
deployments: many(deployments),
|
deployments: many(deployments),
|
||||||
customGitSSHKey: one(sshKeys, {
|
customGitSSHKey: one(sshKeys, {
|
||||||
fields: [applications.customGitSSHKeyId],
|
fields: [applications.customGitSSHKeyId],
|
||||||
references: [sshKeys.sshKeyId],
|
references: [sshKeys.sshKeyId],
|
||||||
}),
|
}),
|
||||||
domains: many(domains),
|
domains: many(domains),
|
||||||
mounts: many(mounts),
|
mounts: many(mounts),
|
||||||
redirects: many(redirects),
|
redirects: many(redirects),
|
||||||
security: many(security),
|
security: many(security),
|
||||||
ports: many(ports),
|
ports: many(ports),
|
||||||
registry: one(registry, {
|
registry: one(registry, {
|
||||||
fields: [applications.registryId],
|
fields: [applications.registryId],
|
||||||
references: [registry.registryId],
|
references: [registry.registryId],
|
||||||
}),
|
}),
|
||||||
github: one(github, {
|
github: one(github, {
|
||||||
fields: [applications.githubId],
|
fields: [applications.githubId],
|
||||||
references: [github.githubId],
|
references: [github.githubId],
|
||||||
}),
|
}),
|
||||||
gitlab: one(gitlab, {
|
gitlab: one(gitlab, {
|
||||||
fields: [applications.gitlabId],
|
fields: [applications.gitlabId],
|
||||||
references: [gitlab.gitlabId],
|
references: [gitlab.gitlabId],
|
||||||
}),
|
}),
|
||||||
bitbucket: one(bitbucket, {
|
bitbucket: one(bitbucket, {
|
||||||
fields: [applications.bitbucketId],
|
fields: [applications.bitbucketId],
|
||||||
references: [bitbucket.bitbucketId],
|
references: [bitbucket.bitbucketId],
|
||||||
}),
|
}),
|
||||||
server: one(server, {
|
server: one(server, {
|
||||||
fields: [applications.serverId],
|
fields: [applications.serverId],
|
||||||
references: [server.serverId],
|
references: [server.serverId],
|
||||||
}),
|
}),
|
||||||
previewDeployments: many(previewDeployments),
|
previewDeployments: many(previewDeployments),
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const HealthCheckSwarmSchema = z
|
const HealthCheckSwarmSchema = z
|
||||||
.object({
|
.object({
|
||||||
Test: z.array(z.string()).optional(),
|
Test: z.array(z.string()).optional(),
|
||||||
Interval: z.number().optional(),
|
Interval: z.number().optional(),
|
||||||
Timeout: z.number().optional(),
|
Timeout: z.number().optional(),
|
||||||
StartPeriod: z.number().optional(),
|
StartPeriod: z.number().optional(),
|
||||||
Retries: z.number().optional(),
|
Retries: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const RestartPolicySwarmSchema = z
|
const RestartPolicySwarmSchema = z
|
||||||
.object({
|
.object({
|
||||||
Condition: z.string().optional(),
|
Condition: z.string().optional(),
|
||||||
Delay: z.number().optional(),
|
Delay: z.number().optional(),
|
||||||
MaxAttempts: z.number().optional(),
|
MaxAttempts: z.number().optional(),
|
||||||
Window: z.number().optional(),
|
Window: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const PreferenceSchema = z
|
const PreferenceSchema = z
|
||||||
.object({
|
.object({
|
||||||
Spread: z.object({
|
Spread: z.object({
|
||||||
SpreadDescriptor: z.string(),
|
SpreadDescriptor: z.string(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const PlatformSchema = z
|
const PlatformSchema = z
|
||||||
.object({
|
.object({
|
||||||
Architecture: z.string(),
|
Architecture: z.string(),
|
||||||
OS: z.string(),
|
OS: z.string(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const PlacementSwarmSchema = z
|
const PlacementSwarmSchema = z
|
||||||
.object({
|
.object({
|
||||||
Constraints: z.array(z.string()).optional(),
|
Constraints: z.array(z.string()).optional(),
|
||||||
Preferences: z.array(PreferenceSchema).optional(),
|
Preferences: z.array(PreferenceSchema).optional(),
|
||||||
MaxReplicas: z.number().optional(),
|
MaxReplicas: z.number().optional(),
|
||||||
Platforms: z.array(PlatformSchema).optional(),
|
Platforms: z.array(PlatformSchema).optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const UpdateConfigSwarmSchema = z
|
const UpdateConfigSwarmSchema = z
|
||||||
.object({
|
.object({
|
||||||
Parallelism: z.number(),
|
Parallelism: z.number(),
|
||||||
Delay: z.number().optional(),
|
Delay: z.number().optional(),
|
||||||
FailureAction: z.string().optional(),
|
FailureAction: z.string().optional(),
|
||||||
Monitor: z.number().optional(),
|
Monitor: z.number().optional(),
|
||||||
MaxFailureRatio: z.number().optional(),
|
MaxFailureRatio: z.number().optional(),
|
||||||
Order: z.string(),
|
Order: z.string(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const ReplicatedSchema = z
|
const ReplicatedSchema = z
|
||||||
.object({
|
.object({
|
||||||
Replicas: z.number().optional(),
|
Replicas: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const ReplicatedJobSchema = z
|
const ReplicatedJobSchema = z
|
||||||
.object({
|
.object({
|
||||||
MaxConcurrent: z.number().optional(),
|
MaxConcurrent: z.number().optional(),
|
||||||
TotalCompletions: z.number().optional(),
|
TotalCompletions: z.number().optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const ServiceModeSwarmSchema = z
|
const ServiceModeSwarmSchema = z
|
||||||
.object({
|
.object({
|
||||||
Replicated: ReplicatedSchema.optional(),
|
Replicated: ReplicatedSchema.optional(),
|
||||||
Global: z.object({}).optional(),
|
Global: z.object({}).optional(),
|
||||||
ReplicatedJob: ReplicatedJobSchema.optional(),
|
ReplicatedJob: ReplicatedJobSchema.optional(),
|
||||||
GlobalJob: z.object({}).optional(),
|
GlobalJob: z.object({}).optional(),
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
const NetworkSwarmSchema = z.array(
|
const NetworkSwarmSchema = z.array(
|
||||||
z
|
z
|
||||||
.object({
|
.object({
|
||||||
Target: z.string().optional(),
|
Target: z.string().optional(),
|
||||||
Aliases: z.array(z.string()).optional(),
|
Aliases: z.array(z.string()).optional(),
|
||||||
DriverOpts: z.object({}).optional(),
|
DriverOpts: z.object({}).optional(),
|
||||||
})
|
})
|
||||||
.strict(),
|
.strict()
|
||||||
);
|
);
|
||||||
|
|
||||||
const LabelsSwarmSchema = z.record(z.string());
|
const LabelsSwarmSchema = z.record(z.string());
|
||||||
|
|
||||||
const createSchema = createInsertSchema(applications, {
|
const createSchema = createInsertSchema(applications, {
|
||||||
appName: z.string(),
|
appName: z.string(),
|
||||||
createdAt: z.string(),
|
createdAt: z.string(),
|
||||||
applicationId: z.string(),
|
applicationId: z.string(),
|
||||||
autoDeploy: z.boolean(),
|
autoDeploy: z.boolean(),
|
||||||
env: z.string().optional(),
|
env: z.string().optional(),
|
||||||
buildArgs: z.string().optional(),
|
buildArgs: z.string().optional(),
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
memoryReservation: z.number().optional(),
|
memoryReservation: z.number().optional(),
|
||||||
memoryLimit: z.number().optional(),
|
memoryLimit: z.number().optional(),
|
||||||
cpuReservation: z.number().optional(),
|
cpuReservation: z.number().optional(),
|
||||||
cpuLimit: z.number().optional(),
|
cpuLimit: z.number().optional(),
|
||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
enabled: z.boolean().optional(),
|
enabled: z.boolean().optional(),
|
||||||
subtitle: z.string().optional(),
|
subtitle: z.string().optional(),
|
||||||
dockerImage: z.string().optional(),
|
dockerImage: z.string().optional(),
|
||||||
username: z.string().optional(),
|
username: z.string().optional(),
|
||||||
isPreviewDeploymentsActive: z.boolean().optional(),
|
isPreviewDeploymentsActive: z.boolean().optional(),
|
||||||
password: z.string().optional(),
|
password: z.string().optional(),
|
||||||
registryUrl: z.string().optional(),
|
registryUrl: z.string().optional(),
|
||||||
customGitSSHKeyId: z.string().optional(),
|
customGitSSHKeyId: z.string().optional(),
|
||||||
repository: z.string().optional(),
|
repository: z.string().optional(),
|
||||||
dockerfile: z.string().optional(),
|
dockerfile: z.string().optional(),
|
||||||
branch: z.string().optional(),
|
branch: z.string().optional(),
|
||||||
customGitBranch: z.string().optional(),
|
customGitBranch: z.string().optional(),
|
||||||
customGitBuildPath: z.string().optional(),
|
customGitBuildPath: z.string().optional(),
|
||||||
customGitUrl: z.string().optional(),
|
customGitUrl: z.string().optional(),
|
||||||
buildPath: z.string().optional(),
|
buildPath: z.string().optional(),
|
||||||
projectId: z.string(),
|
projectId: z.string(),
|
||||||
sourceType: z.enum(["github", "docker", "git"]).optional(),
|
sourceType: z.enum(["github", "docker", "git"]).optional(),
|
||||||
applicationStatus: z.enum(["idle", "running", "done", "error"]),
|
applicationStatus: z.enum(["idle", "running", "done", "error"]),
|
||||||
buildType: z.enum([
|
buildType: z.enum([
|
||||||
"dockerfile",
|
"dockerfile",
|
||||||
"heroku_buildpacks",
|
"heroku_buildpacks",
|
||||||
"paketo_buildpacks",
|
"paketo_buildpacks",
|
||||||
"nixpacks",
|
"nixpacks",
|
||||||
"static",
|
"static",
|
||||||
]),
|
]),
|
||||||
herokuVersion: z.string().optional(),
|
herokuVersion: z.string().optional(),
|
||||||
publishDirectory: z.string().optional(),
|
publishDirectory: z.string().optional(),
|
||||||
owner: z.string(),
|
owner: z.string(),
|
||||||
healthCheckSwarm: HealthCheckSwarmSchema.nullable(),
|
healthCheckSwarm: HealthCheckSwarmSchema.nullable(),
|
||||||
restartPolicySwarm: RestartPolicySwarmSchema.nullable(),
|
restartPolicySwarm: RestartPolicySwarmSchema.nullable(),
|
||||||
placementSwarm: PlacementSwarmSchema.nullable(),
|
placementSwarm: PlacementSwarmSchema.nullable(),
|
||||||
updateConfigSwarm: UpdateConfigSwarmSchema.nullable(),
|
updateConfigSwarm: UpdateConfigSwarmSchema.nullable(),
|
||||||
rollbackConfigSwarm: UpdateConfigSwarmSchema.nullable(),
|
rollbackConfigSwarm: UpdateConfigSwarmSchema.nullable(),
|
||||||
modeSwarm: ServiceModeSwarmSchema.nullable(),
|
modeSwarm: ServiceModeSwarmSchema.nullable(),
|
||||||
labelsSwarm: LabelsSwarmSchema.nullable(),
|
labelsSwarm: LabelsSwarmSchema.nullable(),
|
||||||
networkSwarm: NetworkSwarmSchema.nullable(),
|
networkSwarm: NetworkSwarmSchema.nullable(),
|
||||||
previewPort: z.number().optional(),
|
previewPort: z.number().optional(),
|
||||||
previewEnv: z.string().optional(),
|
previewEnv: z.string().optional(),
|
||||||
previewBuildArgs: z.string().optional(),
|
previewBuildArgs: z.string().optional(),
|
||||||
previewWildcard: z.string().optional(),
|
previewWildcard: z.string().optional(),
|
||||||
previewLimit: z.number().optional(),
|
previewLimit: z.number().optional(),
|
||||||
previewHttps: z.boolean().optional(),
|
previewHttps: z.boolean().optional(),
|
||||||
previewPath: z.string().optional(),
|
previewPath: z.string().optional(),
|
||||||
previewCertificateType: z.enum(["letsencrypt", "none"]).optional(),
|
previewCertificateType: z.enum(["letsencrypt", "none"]).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiCreateApplication = createSchema.pick({
|
export const apiCreateApplication = createSchema.pick({
|
||||||
name: true,
|
name: true,
|
||||||
appName: true,
|
appName: true,
|
||||||
description: true,
|
description: true,
|
||||||
projectId: true,
|
projectId: true,
|
||||||
serverId: true,
|
serverId: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiFindOneApplication = createSchema
|
export const apiFindOneApplication = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiReloadApplication = createSchema
|
export const apiReloadApplication = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
appName: true,
|
appName: true,
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiSaveBuildType = createSchema
|
export const apiSaveBuildType = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
buildType: true,
|
buildType: true,
|
||||||
dockerfile: true,
|
dockerfile: true,
|
||||||
dockerContextPath: true,
|
dockerContextPath: true,
|
||||||
dockerBuildStage: true,
|
dockerBuildStage: true,
|
||||||
herokuVersion: true,
|
herokuVersion: true,
|
||||||
})
|
})
|
||||||
.required()
|
.required()
|
||||||
.merge(createSchema.pick({ publishDirectory: true }));
|
.merge(createSchema.pick({ publishDirectory: true }));
|
||||||
|
|
||||||
export const apiSaveGithubProvider = createSchema
|
export const apiSaveGithubProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
repository: true,
|
repository: true,
|
||||||
branch: true,
|
branch: true,
|
||||||
owner: true,
|
owner: true,
|
||||||
buildPath: true,
|
buildPath: true,
|
||||||
githubId: true,
|
githubId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiSaveGitlabProvider = createSchema
|
export const apiSaveGitlabProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
gitlabBranch: true,
|
gitlabBranch: true,
|
||||||
gitlabBuildPath: true,
|
gitlabBuildPath: true,
|
||||||
gitlabOwner: true,
|
gitlabOwner: true,
|
||||||
gitlabRepository: true,
|
gitlabRepository: true,
|
||||||
gitlabId: true,
|
gitlabId: true,
|
||||||
gitlabProjectId: true,
|
gitlabProjectId: true,
|
||||||
gitlabPathNamespace: true,
|
gitlabPathNamespace: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiSaveBitbucketProvider = createSchema
|
export const apiSaveBitbucketProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
bitbucketBranch: true,
|
bitbucketBranch: true,
|
||||||
bitbucketBuildPath: true,
|
bitbucketBuildPath: true,
|
||||||
bitbucketOwner: true,
|
bitbucketOwner: true,
|
||||||
bitbucketRepository: true,
|
bitbucketRepository: true,
|
||||||
bitbucketId: true,
|
bitbucketId: true,
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiSaveDockerProvider = createSchema
|
export const apiSaveDockerProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
dockerImage: true,
|
dockerImage: true,
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
username: true,
|
username: true,
|
||||||
password: true,
|
password: true,
|
||||||
registryUrl: true,
|
registryUrl: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiSaveGitProvider = createSchema
|
export const apiSaveGitProvider = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
customGitBranch: true,
|
customGitBranch: true,
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
customGitBuildPath: true,
|
customGitBuildPath: true,
|
||||||
customGitUrl: true,
|
customGitUrl: true,
|
||||||
})
|
})
|
||||||
.required()
|
.required()
|
||||||
.merge(
|
.merge(
|
||||||
createSchema.pick({
|
createSchema.pick({
|
||||||
customGitSSHKeyId: true,
|
customGitSSHKeyId: true,
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export const apiSaveEnvironmentVariables = createSchema
|
export const apiSaveEnvironmentVariables = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
applicationId: true,
|
applicationId: true,
|
||||||
env: true,
|
env: true,
|
||||||
buildArgs: true,
|
buildArgs: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiFindMonitoringStats = createSchema
|
export const apiFindMonitoringStats = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
appName: true,
|
appName: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiUpdateApplication = createSchema
|
export const apiUpdateApplication = createSchema
|
||||||
.partial()
|
.partial()
|
||||||
.extend({
|
.extend({
|
||||||
applicationId: z.string().min(1),
|
applicationId: z.string().min(1),
|
||||||
})
|
})
|
||||||
.omit({ serverId: true });
|
.omit({ serverId: true });
|
||||||
|
|
||||||
export const apiDeleteApplication = z.object({
|
|
||||||
applicationId: z.string().min(1),
|
|
||||||
deleteVolumes: z.boolean(),
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user