diff --git a/apps/dokploy/__test__/compose/domain/labels.test.ts b/apps/dokploy/__test__/compose/domain/labels.test.ts new file mode 100644 index 000000000..e2cc7bca4 --- /dev/null +++ b/apps/dokploy/__test__/compose/domain/labels.test.ts @@ -0,0 +1,74 @@ +import type { Domain } from "@/server/api/services/domain"; +import { createDomainLabels } from "@/server/utils/docker/domain"; +import { describe, expect, it } from "vitest"; + +describe("createDomainLabels", () => { + const appName = "test-app"; + const baseDomain: Domain = { + host: "example.com", + port: 8080, + https: false, + uniqueConfigKey: 1, + certificateType: "none", + applicationId: "", + composeId: "", + domainType: "compose", + serviceName: "test-app", + domainId: "", + path: "/", + createdAt: "", + }; + + it("should create basic labels for web entrypoint", async () => { + const labels = await createDomainLabels(appName, baseDomain, "web"); + + expect(labels).toContain( + "traefik.http.routers.test-app-1-web.rule=Host(`example.com`)", + ); + expect(labels).toContain( + "traefik.http.routers.test-app-1-web.entrypoints=web", + ); + expect(labels).toContain( + "traefik.http.services.test-app-1-web.loadbalancer.server.port=8080", + ); + }); + + it("should create labels for websecure entrypoint", async () => { + const labels = await createDomainLabels( + appName, + { ...baseDomain, https: true }, + "websecure", + ); + expect(labels).toContain( + "traefik.http.routers.test-app-1-websecure.rule=Host(`example.com`)", + ); + expect(labels).toContain( + "traefik.http.routers.test-app-1-websecure.entrypoints=websecure", + ); + expect(labels).not.toContain( + "traefik.http.services.test-app-1-websecure.loadbalancer.server.port=8080", + ); + }); + + it("should add redirect middleware for https on web entrypoint", async () => { + const labels = await createDomainLabels( + appName, + { ...baseDomain, https: true }, + "web", + ); + expect(labels).toContain( + "traefik.http.routers.test-app-1-web.middlewares=redirect-to-https@file", + ); + }); + + it("should add Let's Encrypt configuration for websecure with letsencrypt certificate", async () => { + const labels = await createDomainLabels( + appName, + { ...baseDomain, https: true, certificateType: "letsencrypt" }, + "websecure", + ); + expect(labels).toContain( + "traefik.http.routers.test-app-1-websecure.tls.certresolver=letsencrypt", + ); + }); +}); diff --git a/apps/dokploy/__test__/compose/domain/network-root.test.ts b/apps/dokploy/__test__/compose/domain/network-root.test.ts new file mode 100644 index 000000000..ca8b16550 --- /dev/null +++ b/apps/dokploy/__test__/compose/domain/network-root.test.ts @@ -0,0 +1,29 @@ +import { addDokployNetworkToRoot } from "@/server/utils/docker/domain"; +import { describe, expect, it } from "vitest"; + +describe("addDokployNetworkToRoot", () => { + it("should create network object if networks is undefined", () => { + const result = addDokployNetworkToRoot(undefined); + expect(result).toEqual({ "dokploy-network": { external: true } }); + }); + + it("should add network to an empty object", () => { + const result = addDokployNetworkToRoot({}); + expect(result).toEqual({ "dokploy-network": { external: true } }); + }); + + it("should not modify existing network configuration", () => { + const existing = { "dokploy-network": { external: false } }; + const result = addDokployNetworkToRoot(existing); + expect(result).toEqual({ "dokploy-network": { external: true } }); + }); + + it("should add network alongside existing networks", () => { + const existing = { "other-network": { external: true } }; + const result = addDokployNetworkToRoot(existing); + expect(result).toEqual({ + "other-network": { external: true }, + "dokploy-network": { external: true }, + }); + }); +}); diff --git a/apps/dokploy/__test__/compose/domain/network-service.test.ts b/apps/dokploy/__test__/compose/domain/network-service.test.ts new file mode 100644 index 000000000..18faf5645 --- /dev/null +++ b/apps/dokploy/__test__/compose/domain/network-service.test.ts @@ -0,0 +1,24 @@ +import { addDokployNetworkToService } from "@/server/utils/docker/domain"; +import { describe, expect, it } from "vitest"; + +describe("addDokployNetworkToService", () => { + it("should add network to an empty array", () => { + const result = addDokployNetworkToService([]); + expect(result).toEqual(["dokploy-network"]); + }); + + it("should not add duplicate network to an array", () => { + const result = addDokployNetworkToService(["dokploy-network"]); + expect(result).toEqual(["dokploy-network"]); + }); + + it("should add network to an existing array with other networks", () => { + const result = addDokployNetworkToService(["other-network"]); + expect(result).toEqual(["other-network", "dokploy-network"]); + }); + + it("should add network to an object if networks is an object", () => { + const result = addDokployNetworkToService({ "other-network": {} }); + expect(result).toEqual({ "other-network": {}, "dokploy-network": {} }); + }); +}); diff --git a/apps/dokploy/__test__/traefik/traefik.test.ts b/apps/dokploy/__test__/traefik/traefik.test.ts index 5c490f7ce..70dbe5494 100644 --- a/apps/dokploy/__test__/traefik/traefik.test.ts +++ b/apps/dokploy/__test__/traefik/traefik.test.ts @@ -67,6 +67,9 @@ const baseDomain: Domain = { https: false, path: null, port: null, + serviceName: "", + composeId: "", + domainType: "application", uniqueConfigKey: 1, }; diff --git a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx index 71e44f929..ab7db1ef5 100644 --- a/apps/dokploy/components/dashboard/application/domains/add-domain.tsx +++ b/apps/dokploy/components/dashboard/application/domains/add-domain.tsx @@ -27,13 +27,20 @@ import { SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { api } from "@/utils/api"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; -import { domain } from "@/server/db/validations"; +import { domain } from "@/server/db/validations/domain"; import { zodResolver } from "@hookform/resolvers/zod"; +import { Dices } from "lucide-react"; import type z from "zod"; type Domain = z.infer; @@ -60,10 +67,22 @@ export const AddDomain = ({ }, ); + const { data: application } = api.application.one.useQuery( + { + applicationId, + }, + { + enabled: !!applicationId, + }, + ); + const { mutateAsync, isError, error, isLoading } = domainId ? api.domain.update.useMutation() : api.domain.create.useMutation(); + const { mutateAsync: generateDomain, isLoading: isLoadingGenerate } = + api.domain.generateDomain.useMutation(); + const form = useForm({ resolver: zodResolver(domain), }); @@ -142,9 +161,42 @@ export const AddDomain = ({ render={({ field }) => ( Host - - - +
+ + + + + + + + + +

Generate traefik.me domain

+
+
+
+
diff --git a/apps/dokploy/components/dashboard/application/domains/delete-domain.tsx b/apps/dokploy/components/dashboard/application/domains/delete-domain.tsx index 63bd3f305..5933a99a6 100644 --- a/apps/dokploy/components/dashboard/application/domains/delete-domain.tsx +++ b/apps/dokploy/components/dashboard/application/domains/delete-domain.tsx @@ -44,12 +44,19 @@ export const DeleteDomain = ({ domainId }: Props) => { domainId, }) .then((data) => { - utils.domain.byApplicationId.invalidate({ - applicationId: data?.applicationId, - }); - utils.application.readTraefikConfig.invalidate({ - applicationId: data?.applicationId, - }); + if (data?.applicationId) { + utils.domain.byApplicationId.invalidate({ + applicationId: data?.applicationId, + }); + utils.application.readTraefikConfig.invalidate({ + applicationId: data?.applicationId, + }); + } else if (data?.composeId) { + utils.domain.byComposeId.invalidate({ + composeId: data?.composeId, + }); + } + toast.success("Domain delete succesfully"); }) .catch(() => { diff --git a/apps/dokploy/components/dashboard/application/domains/generate-domain.tsx b/apps/dokploy/components/dashboard/application/domains/generate-domain.tsx deleted file mode 100644 index 9ebe8e30c..000000000 --- a/apps/dokploy/components/dashboard/application/domains/generate-domain.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { api } from "@/utils/api"; -import { RefreshCcw } from "lucide-react"; -import Link from "next/link"; -import { GenerateTraefikMe } from "./generate-traefikme"; -import { GenerateWildCard } from "./generate-wildcard"; - -interface Props { - applicationId: string; -} - -export const GenerateDomain = ({ applicationId }: Props) => { - return ( - - - - - - - Generate Domain - - Generate Domains for your applications - - - -
-
    -
  • -
    -
    - 1. Generate TraefikMe Domain -
    -
    - This option generates a free domain provided by{" "} - - TraefikMe - - . We recommend using this for quick domain testing or if you - don't have a domain yet. -
    -
    -
  • - {/*
  • -
    -
    - 2. Use Wildcard Domain -
    -
    - To use this option, you need to set up an 'A' record in your - domain provider. For example, create a record for - *.yourdomain.com. -
    -
    -
  • */} -
-
- - {/* */} -
-
-
-
- ); -}; diff --git a/apps/dokploy/components/dashboard/application/domains/generate-traefikme.tsx b/apps/dokploy/components/dashboard/application/domains/generate-traefikme.tsx deleted file mode 100644 index 3085b3a88..000000000 --- a/apps/dokploy/components/dashboard/application/domains/generate-traefikme.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from "@/components/ui/alert-dialog"; -import { Button } from "@/components/ui/button"; -import { api } from "@/utils/api"; -import { RefreshCcw } from "lucide-react"; -import React from "react"; -import { toast } from "sonner"; - -interface Props { - applicationId: string; -} -export const GenerateTraefikMe = ({ applicationId }: Props) => { - const { mutateAsync, isLoading } = api.domain.generateDomain.useMutation(); - const utils = api.useUtils(); - return ( - - - - - - - - Are you sure to generate a new domain? - - - This will generate a new domain and will be used to access to the - application - - - - Cancel - { - await mutateAsync({ - applicationId, - }) - .then((data) => { - utils.domain.byApplicationId.invalidate({ - applicationId: applicationId, - }); - utils.application.readTraefikConfig.invalidate({ - applicationId: applicationId, - }); - toast.success("Generated Domain succesfully"); - }) - .catch(() => { - toast.error("Error to generate Domain"); - }); - }} - > - Confirm - - - - - ); -}; diff --git a/apps/dokploy/components/dashboard/application/domains/generate-wildcard.tsx b/apps/dokploy/components/dashboard/application/domains/generate-wildcard.tsx deleted file mode 100644 index da4445527..000000000 --- a/apps/dokploy/components/dashboard/application/domains/generate-wildcard.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from "@/components/ui/alert-dialog"; -import { Button } from "@/components/ui/button"; -import { api } from "@/utils/api"; -import { SquareAsterisk } from "lucide-react"; -import React from "react"; -import { toast } from "sonner"; - -interface Props { - applicationId: string; -} -export const GenerateWildCard = ({ applicationId }: Props) => { - const { mutateAsync, isLoading } = api.domain.generateWildcard.useMutation(); - const utils = api.useUtils(); - return ( - - - - - - - - Are you sure to generate a new wildcard domain? - - - This will generate a new domain and will be used to access to the - application - - - - Cancel - { - await mutateAsync({ - applicationId, - }) - .then((data) => { - utils.domain.byApplicationId.invalidate({ - applicationId: applicationId, - }); - utils.application.readTraefikConfig.invalidate({ - applicationId: applicationId, - }); - toast.success("Generated Domain succesfully"); - }) - .catch((e) => { - toast.error(`Error to generate Domain: ${e.message}`); - }); - }} - > - Confirm - - - - - ); -}; diff --git a/apps/dokploy/components/dashboard/application/domains/show-domains.tsx b/apps/dokploy/components/dashboard/application/domains/show-domains.tsx index d7724ce72..46c05f150 100644 --- a/apps/dokploy/components/dashboard/application/domains/show-domains.tsx +++ b/apps/dokploy/components/dashboard/application/domains/show-domains.tsx @@ -12,7 +12,6 @@ import { ExternalLink, GlobeIcon, PenBoxIcon } from "lucide-react"; import Link from "next/link"; import { AddDomain } from "./add-domain"; import { DeleteDomain } from "./delete-domain"; -import { GenerateDomain } from "./generate-domain"; interface Props { applicationId: string; @@ -46,9 +45,6 @@ export const ShowDomains = ({ applicationId }: Props) => { )} - {data && data?.length > 0 && ( - - )} @@ -65,8 +61,6 @@ export const ShowDomains = ({ applicationId }: Props) => { Add Domain - - ) : ( diff --git a/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx b/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx new file mode 100644 index 000000000..a10ce271a --- /dev/null +++ b/apps/dokploy/components/dashboard/compose/domains/add-domain.tsx @@ -0,0 +1,441 @@ +import { AlertBlock } from "@/components/shared/alert-block"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Switch } from "@/components/ui/switch"; +import { api } from "@/utils/api"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; + +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { domainCompose } from "@/server/db/validations/domain"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { DatabaseZap, Dices, RefreshCw } from "lucide-react"; +import type z from "zod"; + +type Domain = z.infer; + +export type CacheType = "fetch" | "cache"; + +interface Props { + composeId: string; + domainId?: string; + children: React.ReactNode; +} + +export const AddDomainCompose = ({ + composeId, + domainId = "", + children, +}: Props) => { + const [isOpen, setIsOpen] = useState(false); + const [cacheType, setCacheType] = useState("cache"); + const utils = api.useUtils(); + const { data, refetch } = api.domain.one.useQuery( + { + domainId, + }, + { + enabled: !!domainId, + }, + ); + + const { data: compose } = api.compose.one.useQuery( + { + composeId, + }, + { + enabled: !!composeId, + }, + ); + + const { + data: services, + isFetching: isLoadingServices, + error: errorServices, + refetch: refetchServices, + } = api.compose.loadServices.useQuery( + { + composeId, + type: cacheType, + }, + { + retry: false, + refetchOnWindowFocus: false, + }, + ); + + const { mutateAsync: generateDomain, isLoading: isLoadingGenerate } = + api.domain.generateDomain.useMutation(); + + const { mutateAsync, isError, error, isLoading } = domainId + ? api.domain.update.useMutation() + : api.domain.create.useMutation(); + + const form = useForm({ + resolver: zodResolver(domainCompose), + }); + + const https = form.watch("https"); + + useEffect(() => { + if (data) { + form.reset({ + ...data, + /* Convert null to undefined */ + path: data?.path || undefined, + port: data?.port || undefined, + serviceName: data?.serviceName || undefined, + }); + } + + if (!domainId) { + form.reset({}); + } + }, [form, form.reset, data, isLoading]); + + const dictionary = { + success: domainId ? "Domain Updated" : "Domain Created", + error: domainId + ? "Error to update the domain" + : "Error to create the domain", + submit: domainId ? "Update" : "Create", + dialogDescription: domainId + ? "In this section you can edit a domain" + : "In this section you can add domains", + }; + + const onSubmit = async (data: Domain) => { + await mutateAsync({ + domainId, + composeId, + domainType: "compose", + ...data, + }) + .then(async () => { + await utils.domain.byComposeId.invalidate({ + composeId, + }); + toast.success(dictionary.success); + if (domainId) { + refetch(); + } + setIsOpen(false); + }) + .catch(() => { + toast.error(dictionary.error); + }); + }; + return ( + + + {children} + + + + Domain + {dictionary.dialogDescription} + + {isError && {error?.message}} + +
+ +
+
+ {errorServices && ( + + {errorServices?.message} + + )} +
+ ( + + Service Name +
+ + + + + + + +

+ Fetch: Will clone the repository and load the + services +

+
+
+
+ + + + + + +

+ Cache: If you previously deployed this + compose, it will read the services from the + last deployment/fetch from the repository +

+
+
+
+
+ + +
+ )} + /> +
+ + ( + + Host +
+ + + + + + + + + +

Generate traefik.me domain

+
+
+
+
+ + +
+ )} + /> + + { + return ( + + Path + + + + + + ); + }} + /> + + { + return ( + + Container Port + + { + field.onChange(Number.parseInt(e.target.value)); + }} + /> + + + + ); + }} + /> + {https && ( + ( + + Certificate + + + + )} + /> + )} + + ( + +
+ HTTPS + + Automatically provision SSL Certificate. + + +
+ + + +
+ )} + /> +
+
+
+ + + + + +
+
+ ); +}; diff --git a/apps/dokploy/components/dashboard/compose/domains/show-domains.tsx b/apps/dokploy/components/dashboard/compose/domains/show-domains.tsx new file mode 100644 index 000000000..01e6f1abc --- /dev/null +++ b/apps/dokploy/components/dashboard/compose/domains/show-domains.tsx @@ -0,0 +1,111 @@ +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { api } from "@/utils/api"; +import { ExternalLink, GlobeIcon, PenBoxIcon } from "lucide-react"; +import Link from "next/link"; +import { DeleteDomain } from "../../application/domains/delete-domain"; +import { AddDomainCompose } from "./add-domain"; + +interface Props { + composeId: string; +} + +export const ShowDomainsCompose = ({ composeId }: Props) => { + const { data } = api.domain.byComposeId.useQuery( + { + composeId, + }, + { + enabled: !!composeId, + }, + ); + + return ( +
+ + +
+ Domains + + Domains are used to access to the application + +
+ +
+ {data && data?.length > 0 && ( + + + + )} +
+
+ + {data?.length === 0 ? ( +
+ + + To access to the application is required to set at least 1 + domain + +
+ + + +
+
+ ) : ( +
+ {data?.map((item) => { + return ( +
+ + + + + + + + +
+ + + + +
+
+ ); + })} +
+ )} +
+
+
+ ); +}; diff --git a/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx b/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx index 035d6c417..bb896e9ac 100644 --- a/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx +++ b/apps/dokploy/components/dashboard/compose/general/compose-file-editor.tsx @@ -72,7 +72,7 @@ export const ComposeFileEditor = ({ composeId }: Props) => { .then(async () => { toast.success("Compose config Updated"); refetch(); - await utils.compose.allServices.invalidate({ + await utils.compose.getConvertedCompose.invalidate({ composeId, }); }) diff --git a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx index 2db4248d5..93a2d7698 100644 --- a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx +++ b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx @@ -5,6 +5,7 @@ import { GitBranch, LockIcon } from "lucide-react"; import Link from "next/link"; import { useState } from "react"; import { ComposeFileEditor } from "../compose-file-editor"; +import { ShowConvertedCompose } from "../show-converted-compose"; import { SaveGitProviderCompose } from "./save-git-provider-compose"; import { SaveGithubProviderCompose } from "./save-github-provider-compose"; @@ -29,7 +30,8 @@ export const ShowProviderFormCompose = ({ composeId }: Props) => { Select the source of your code

-
+
+
diff --git a/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx b/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx new file mode 100644 index 000000000..bb01badc5 --- /dev/null +++ b/apps/dokploy/components/dashboard/compose/general/show-converted-compose.tsx @@ -0,0 +1,87 @@ +import { AlertBlock } from "@/components/shared/alert-block"; +import { CodeEditor } from "@/components/shared/code-editor"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { api } from "@/utils/api"; +import { Puzzle, RefreshCw } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; + +interface Props { + composeId: string; +} + +export const ShowConvertedCompose = ({ composeId }: Props) => { + const [isOpen, setIsOpen] = useState(false); + const { + data: compose, + error, + isError, + refetch, + } = api.compose.getConvertedCompose.useQuery( + { composeId }, + { + retry: false, + }, + ); + + const { mutateAsync, isLoading } = api.compose.fetchSourceType.useMutation(); + + return ( + + + + + + + Converted Compose + + Preview your docker-compose file with added domains. Note: At least + one domain must be specified for this conversion to take effect. + + + {isError && {error?.message}} + +
+ +
+ +
+					
+				
+
+
+ ); +}; diff --git a/apps/dokploy/drizzle/0031_steep_vulture.sql b/apps/dokploy/drizzle/0031_steep_vulture.sql new file mode 100644 index 000000000..eed3d9449 --- /dev/null +++ b/apps/dokploy/drizzle/0031_steep_vulture.sql @@ -0,0 +1,15 @@ +DO $$ BEGIN + CREATE TYPE "public"."domainType" AS ENUM('compose', 'application'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +ALTER TABLE "domain" ALTER COLUMN "applicationId" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "domain" ADD COLUMN "serviceName" text;--> statement-breakpoint +ALTER TABLE "domain" ADD COLUMN "domainType" "domainType" DEFAULT 'application';--> statement-breakpoint +ALTER TABLE "domain" ADD COLUMN "composeId" text;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "domain" ADD CONSTRAINT "domain_composeId_compose_composeId_fk" FOREIGN KEY ("composeId") REFERENCES "public"."compose"("composeId") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/apps/dokploy/drizzle/0032_flashy_shadow_king.sql b/apps/dokploy/drizzle/0032_flashy_shadow_king.sql new file mode 100644 index 000000000..afa5389b5 --- /dev/null +++ b/apps/dokploy/drizzle/0032_flashy_shadow_king.sql @@ -0,0 +1 @@ +ALTER TABLE "domain" ALTER COLUMN "port" SET DEFAULT 3000; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0031_snapshot.json b/apps/dokploy/drizzle/meta/0031_snapshot.json new file mode 100644 index 000000000..3330e3369 --- /dev/null +++ b/apps/dokploy/drizzle/meta/0031_snapshot.json @@ -0,0 +1,3071 @@ +{ + "id": "86b27966-a431-493d-9cbc-2291e280f8f2", + "prevId": "8dc242b9-6fa9-4372-9ecd-86ae90dd7d0d", + "version": "6", + "dialect": "postgresql", + "tables": { + "public.application": { + "name": "application", + "schema": "", + "columns": { + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildArgs": { + "name": "buildArgs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "subtitle": { + "name": "subtitle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildPath": { + "name": "buildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBuildPath": { + "name": "customGitBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerfile": { + "name": "dockerfile", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerContextPath": { + "name": "dockerContextPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dropBuildPath": { + "name": "dropBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "healthCheckSwarm": { + "name": "healthCheckSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "restartPolicySwarm": { + "name": "restartPolicySwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "placementSwarm": { + "name": "placementSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "updateConfigSwarm": { + "name": "updateConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "rollbackConfigSwarm": { + "name": "rollbackConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "modeSwarm": { + "name": "modeSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "labelsSwarm": { + "name": "labelsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "networkSwarm": { + "name": "networkSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "buildType": { + "name": "buildType", + "type": "buildType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'nixpacks'" + }, + "publishDirectory": { + "name": "publishDirectory", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "application_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "application_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "application", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_registryId_registry_registryId_fk": { + "name": "application_registryId_registry_registryId_fk", + "tableFrom": "application", + "tableTo": "registry", + "columnsFrom": [ + "registryId" + ], + "columnsTo": [ + "registryId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_projectId_project_projectId_fk": { + "name": "application_projectId_project_projectId_fk", + "tableFrom": "application", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "application_appName_unique": { + "name": "application_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.postgres": { + "name": "postgres", + "schema": "", + "columns": { + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "postgres_projectId_project_projectId_fk": { + "name": "postgres_projectId_project_projectId_fk", + "tableFrom": "postgres", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "postgres_appName_unique": { + "name": "postgres_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isRegistered": { + "name": "isRegistered", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expirationDate": { + "name": "expirationDate", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "canCreateProjects": { + "name": "canCreateProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToSSHKeys": { + "name": "canAccessToSSHKeys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canCreateServices": { + "name": "canCreateServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteProjects": { + "name": "canDeleteProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteServices": { + "name": "canDeleteServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToDocker": { + "name": "canAccessToDocker", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToAPI": { + "name": "canAccessToAPI", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToTraefikFiles": { + "name": "canAccessToTraefikFiles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "accesedProjects": { + "name": "accesedProjects", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "accesedServices": { + "name": "accesedServices", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_adminId_admin_adminId_fk": { + "name": "user_adminId_admin_adminId_fk", + "tableFrom": "user", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_authId_auth_id_fk": { + "name": "user_authId_auth_id_fk", + "tableFrom": "user", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.admin": { + "name": "admin", + "schema": "", + "columns": { + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "githubAppId": { + "name": "githubAppId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "githubAppName": { + "name": "githubAppName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverIp": { + "name": "serverIp", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubClientId": { + "name": "githubClientId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubClientSecret": { + "name": "githubClientSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubInstallationId": { + "name": "githubInstallationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubPrivateKey": { + "name": "githubPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubWebhookSecret": { + "name": "githubWebhookSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "letsEncryptEmail": { + "name": "letsEncryptEmail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sshPrivateKey": { + "name": "sshPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enableDockerCleanup": { + "name": "enableDockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "admin_authId_auth_id_fk": { + "name": "admin_authId_auth_id_fk", + "tableFrom": "admin", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.auth": { + "name": "auth", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rol": { + "name": "rol", + "type": "Roles", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is2FAEnabled": { + "name": "is2FAEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "auth_email_unique": { + "name": "auth_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "project_adminId_admin_adminId_fk": { + "name": "project_adminId_admin_adminId_fk", + "tableFrom": "project", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.domain": { + "name": "domain", + "schema": "", + "columns": { + "domainId": { + "name": "domainId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "https": { + "name": "https", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 80 + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "domainType": { + "name": "domainType", + "type": "domainType", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'application'" + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + } + }, + "indexes": {}, + "foreignKeys": { + "domain_composeId_compose_composeId_fk": { + "name": "domain_composeId_compose_composeId_fk", + "tableFrom": "domain", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "domain_applicationId_application_applicationId_fk": { + "name": "domain_applicationId_application_applicationId_fk", + "tableFrom": "domain", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mariadb": { + "name": "mariadb", + "schema": "", + "columns": { + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mariadb_projectId_project_projectId_fk": { + "name": "mariadb_projectId_project_projectId_fk", + "tableFrom": "mariadb", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mariadb_appName_unique": { + "name": "mariadb_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mongo": { + "name": "mongo", + "schema": "", + "columns": { + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mongo_projectId_project_projectId_fk": { + "name": "mongo_projectId_project_projectId_fk", + "tableFrom": "mongo", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mongo_appName_unique": { + "name": "mongo_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mysql": { + "name": "mysql", + "schema": "", + "columns": { + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mysql_projectId_project_projectId_fk": { + "name": "mysql_projectId_project_projectId_fk", + "tableFrom": "mysql", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mysql_appName_unique": { + "name": "mysql_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.backup": { + "name": "backup", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "schedule": { + "name": "schedule", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseType": { + "name": "databaseType", + "type": "databaseType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "backup_destinationId_destination_destinationId_fk": { + "name": "backup_destinationId_destination_destinationId_fk", + "tableFrom": "backup", + "tableTo": "destination", + "columnsFrom": [ + "destinationId" + ], + "columnsTo": [ + "destinationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_postgresId_postgres_postgresId_fk": { + "name": "backup_postgresId_postgres_postgresId_fk", + "tableFrom": "backup", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mariadbId_mariadb_mariadbId_fk": { + "name": "backup_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "backup", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mysqlId_mysql_mysqlId_fk": { + "name": "backup_mysqlId_mysql_mysqlId_fk", + "tableFrom": "backup", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mongoId_mongo_mongoId_fk": { + "name": "backup_mongoId_mongo_mongoId_fk", + "tableFrom": "backup", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.destination": { + "name": "destination", + "schema": "", + "columns": { + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessKey": { + "name": "accessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secretAccessKey": { + "name": "secretAccessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bucket": { + "name": "bucket", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "region": { + "name": "region", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "destination_adminId_admin_adminId_fk": { + "name": "destination_adminId_admin_adminId_fk", + "tableFrom": "destination", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "deploymentId": { + "name": "deploymentId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "deploymentStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'running'" + }, + "logPath": { + "name": "logPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_applicationId_application_applicationId_fk": { + "name": "deployment_applicationId_application_applicationId_fk", + "tableFrom": "deployment", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_composeId_compose_composeId_fk": { + "name": "deployment_composeId_compose_composeId_fk", + "tableFrom": "deployment", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mount": { + "name": "mount", + "schema": "", + "columns": { + "mountId": { + "name": "mountId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "mountType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "hostPath": { + "name": "hostPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "volumeName": { + "name": "volumeName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "filePath": { + "name": "filePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serviceType": { + "name": "serviceType", + "type": "serviceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'application'" + }, + "mountPath": { + "name": "mountPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mount_applicationId_application_applicationId_fk": { + "name": "mount_applicationId_application_applicationId_fk", + "tableFrom": "mount", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_postgresId_postgres_postgresId_fk": { + "name": "mount_postgresId_postgres_postgresId_fk", + "tableFrom": "mount", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mariadbId_mariadb_mariadbId_fk": { + "name": "mount_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "mount", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mongoId_mongo_mongoId_fk": { + "name": "mount_mongoId_mongo_mongoId_fk", + "tableFrom": "mount", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mysqlId_mysql_mysqlId_fk": { + "name": "mount_mysqlId_mysql_mysqlId_fk", + "tableFrom": "mount", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_redisId_redis_redisId_fk": { + "name": "mount_redisId_redis_redisId_fk", + "tableFrom": "mount", + "tableTo": "redis", + "columnsFrom": [ + "redisId" + ], + "columnsTo": [ + "redisId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_composeId_compose_composeId_fk": { + "name": "mount_composeId_compose_composeId_fk", + "tableFrom": "mount", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.certificate": { + "name": "certificate", + "schema": "", + "columns": { + "certificateId": { + "name": "certificateId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificateData": { + "name": "certificateData", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "privateKey": { + "name": "privateKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificatePath": { + "name": "certificatePath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "autoRenew": { + "name": "autoRenew", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "certificate_certificatePath_unique": { + "name": "certificate_certificatePath_unique", + "nullsNotDistinct": false, + "columns": [ + "certificatePath" + ] + } + } + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_auth_id_fk": { + "name": "session_user_id_auth_id_fk", + "tableFrom": "session", + "tableTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redirect": { + "name": "redirect", + "schema": "", + "columns": { + "redirectId": { + "name": "redirectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "regex": { + "name": "regex", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "replacement": { + "name": "replacement", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permanent": { + "name": "permanent", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redirect_applicationId_application_applicationId_fk": { + "name": "redirect_applicationId_application_applicationId_fk", + "tableFrom": "redirect", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.security": { + "name": "security", + "schema": "", + "columns": { + "securityId": { + "name": "securityId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "security_applicationId_application_applicationId_fk": { + "name": "security_applicationId_application_applicationId_fk", + "tableFrom": "security", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "security_username_applicationId_unique": { + "name": "security_username_applicationId_unique", + "nullsNotDistinct": false, + "columns": [ + "username", + "applicationId" + ] + } + } + }, + "public.port": { + "name": "port", + "schema": "", + "columns": { + "portId": { + "name": "portId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publishedPort": { + "name": "publishedPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "targetPort": { + "name": "targetPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "protocolType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "port_applicationId_application_applicationId_fk": { + "name": "port_applicationId_application_applicationId_fk", + "tableFrom": "port", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redis": { + "name": "redis", + "schema": "", + "columns": { + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redis_projectId_project_projectId_fk": { + "name": "redis_projectId_project_projectId_fk", + "tableFrom": "redis", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "redis_appName_unique": { + "name": "redis_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.compose": { + "name": "compose", + "schema": "", + "columns": { + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeFile": { + "name": "composeFile", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceTypeCompose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "composeType": { + "name": "composeType", + "type": "composeType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'docker-compose'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "composePath": { + "name": "composePath", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'./docker-compose.yml'" + }, + "composeStatus": { + "name": "composeStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "compose", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_projectId_project_projectId_fk": { + "name": "compose_projectId_project_projectId_fk", + "tableFrom": "compose", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.registry": { + "name": "registry", + "schema": "", + "columns": { + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "registryName": { + "name": "registryName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "imagePrefix": { + "name": "imagePrefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryUrl": { + "name": "registryUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "selfHosted": { + "name": "selfHosted", + "type": "RegistryType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cloud'" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "registry_adminId_admin_adminId_fk": { + "name": "registry_adminId_admin_adminId_fk", + "tableFrom": "registry", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.discord": { + "name": "discord", + "schema": "", + "columns": { + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.email": { + "name": "email", + "schema": "", + "columns": { + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "smtpServer": { + "name": "smtpServer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "smtpPort": { + "name": "smtpPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fromAddress": { + "name": "fromAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "toAddress": { + "name": "toAddress", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.notification": { + "name": "notification", + "schema": "", + "columns": { + "notificationId": { + "name": "notificationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appDeploy": { + "name": "appDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "appBuildError": { + "name": "appBuildError", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "databaseBackup": { + "name": "databaseBackup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dokployRestart": { + "name": "dokployRestart", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dockerCleanup": { + "name": "dockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "notificationType": { + "name": "notificationType", + "type": "notificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "notification_slackId_slack_slackId_fk": { + "name": "notification_slackId_slack_slackId_fk", + "tableFrom": "notification", + "tableTo": "slack", + "columnsFrom": [ + "slackId" + ], + "columnsTo": [ + "slackId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_telegramId_telegram_telegramId_fk": { + "name": "notification_telegramId_telegram_telegramId_fk", + "tableFrom": "notification", + "tableTo": "telegram", + "columnsFrom": [ + "telegramId" + ], + "columnsTo": [ + "telegramId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_discordId_discord_discordId_fk": { + "name": "notification_discordId_discord_discordId_fk", + "tableFrom": "notification", + "tableTo": "discord", + "columnsFrom": [ + "discordId" + ], + "columnsTo": [ + "discordId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_emailId_email_emailId_fk": { + "name": "notification_emailId_email_emailId_fk", + "tableFrom": "notification", + "tableTo": "email", + "columnsFrom": [ + "emailId" + ], + "columnsTo": [ + "emailId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.slack": { + "name": "slack", + "schema": "", + "columns": { + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.telegram": { + "name": "telegram", + "schema": "", + "columns": { + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "botToken": { + "name": "botToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chatId": { + "name": "chatId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.ssh-key": { + "name": "ssh-key", + "schema": "", + "columns": { + "sshKeyId": { + "name": "sshKeyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publicKey": { + "name": "publicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastUsedAt": { + "name": "lastUsedAt", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.buildType": { + "name": "buildType", + "schema": "public", + "values": [ + "dockerfile", + "heroku_buildpacks", + "paketo_buildpacks", + "nixpacks", + "static" + ] + }, + "public.sourceType": { + "name": "sourceType", + "schema": "public", + "values": [ + "docker", + "git", + "github", + "drop" + ] + }, + "public.Roles": { + "name": "Roles", + "schema": "public", + "values": [ + "admin", + "user" + ] + }, + "public.domainType": { + "name": "domainType", + "schema": "public", + "values": [ + "compose", + "application" + ] + }, + "public.databaseType": { + "name": "databaseType", + "schema": "public", + "values": [ + "postgres", + "mariadb", + "mysql", + "mongo" + ] + }, + "public.deploymentStatus": { + "name": "deploymentStatus", + "schema": "public", + "values": [ + "running", + "done", + "error" + ] + }, + "public.mountType": { + "name": "mountType", + "schema": "public", + "values": [ + "bind", + "volume", + "file" + ] + }, + "public.serviceType": { + "name": "serviceType", + "schema": "public", + "values": [ + "application", + "postgres", + "mysql", + "mariadb", + "mongo", + "redis", + "compose" + ] + }, + "public.protocolType": { + "name": "protocolType", + "schema": "public", + "values": [ + "tcp", + "udp" + ] + }, + "public.applicationStatus": { + "name": "applicationStatus", + "schema": "public", + "values": [ + "idle", + "running", + "done", + "error" + ] + }, + "public.certificateType": { + "name": "certificateType", + "schema": "public", + "values": [ + "letsencrypt", + "none" + ] + }, + "public.composeType": { + "name": "composeType", + "schema": "public", + "values": [ + "docker-compose", + "stack" + ] + }, + "public.sourceTypeCompose": { + "name": "sourceTypeCompose", + "schema": "public", + "values": [ + "git", + "github", + "raw" + ] + }, + "public.RegistryType": { + "name": "RegistryType", + "schema": "public", + "values": [ + "selfHosted", + "cloud" + ] + }, + "public.notificationType": { + "name": "notificationType", + "schema": "public", + "values": [ + "slack", + "telegram", + "discord", + "email" + ] + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0032_snapshot.json b/apps/dokploy/drizzle/meta/0032_snapshot.json new file mode 100644 index 000000000..aed881976 --- /dev/null +++ b/apps/dokploy/drizzle/meta/0032_snapshot.json @@ -0,0 +1,3071 @@ +{ + "id": "ce8a8861-2970-4889-ac2e-3cfe60d12736", + "prevId": "86b27966-a431-493d-9cbc-2291e280f8f2", + "version": "6", + "dialect": "postgresql", + "tables": { + "public.application": { + "name": "application", + "schema": "", + "columns": { + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildArgs": { + "name": "buildArgs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "subtitle": { + "name": "subtitle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildPath": { + "name": "buildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBuildPath": { + "name": "customGitBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerfile": { + "name": "dockerfile", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerContextPath": { + "name": "dockerContextPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dropBuildPath": { + "name": "dropBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "healthCheckSwarm": { + "name": "healthCheckSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "restartPolicySwarm": { + "name": "restartPolicySwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "placementSwarm": { + "name": "placementSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "updateConfigSwarm": { + "name": "updateConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "rollbackConfigSwarm": { + "name": "rollbackConfigSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "modeSwarm": { + "name": "modeSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "labelsSwarm": { + "name": "labelsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "networkSwarm": { + "name": "networkSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "buildType": { + "name": "buildType", + "type": "buildType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'nixpacks'" + }, + "publishDirectory": { + "name": "publishDirectory", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "application_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "application_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "application", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_registryId_registry_registryId_fk": { + "name": "application_registryId_registry_registryId_fk", + "tableFrom": "application", + "tableTo": "registry", + "columnsFrom": [ + "registryId" + ], + "columnsTo": [ + "registryId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_projectId_project_projectId_fk": { + "name": "application_projectId_project_projectId_fk", + "tableFrom": "application", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "application_appName_unique": { + "name": "application_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.postgres": { + "name": "postgres", + "schema": "", + "columns": { + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "postgres_projectId_project_projectId_fk": { + "name": "postgres_projectId_project_projectId_fk", + "tableFrom": "postgres", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "postgres_appName_unique": { + "name": "postgres_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isRegistered": { + "name": "isRegistered", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expirationDate": { + "name": "expirationDate", + "type": "timestamp(3)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "canCreateProjects": { + "name": "canCreateProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToSSHKeys": { + "name": "canAccessToSSHKeys", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canCreateServices": { + "name": "canCreateServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteProjects": { + "name": "canDeleteProjects", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteServices": { + "name": "canDeleteServices", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToDocker": { + "name": "canAccessToDocker", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToAPI": { + "name": "canAccessToAPI", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToTraefikFiles": { + "name": "canAccessToTraefikFiles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "accesedProjects": { + "name": "accesedProjects", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "accesedServices": { + "name": "accesedServices", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_adminId_admin_adminId_fk": { + "name": "user_adminId_admin_adminId_fk", + "tableFrom": "user", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_authId_auth_id_fk": { + "name": "user_authId_auth_id_fk", + "tableFrom": "user", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.admin": { + "name": "admin", + "schema": "", + "columns": { + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "githubAppId": { + "name": "githubAppId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "githubAppName": { + "name": "githubAppName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverIp": { + "name": "serverIp", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubClientId": { + "name": "githubClientId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubClientSecret": { + "name": "githubClientSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubInstallationId": { + "name": "githubInstallationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubPrivateKey": { + "name": "githubPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubWebhookSecret": { + "name": "githubWebhookSecret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "letsEncryptEmail": { + "name": "letsEncryptEmail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sshPrivateKey": { + "name": "sshPrivateKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enableDockerCleanup": { + "name": "enableDockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "authId": { + "name": "authId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "admin_authId_auth_id_fk": { + "name": "admin_authId_auth_id_fk", + "tableFrom": "admin", + "tableTo": "auth", + "columnsFrom": [ + "authId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.auth": { + "name": "auth", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rol": { + "name": "rol", + "type": "Roles", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is2FAEnabled": { + "name": "is2FAEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "auth_email_unique": { + "name": "auth_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "project_adminId_admin_adminId_fk": { + "name": "project_adminId_admin_adminId_fk", + "tableFrom": "project", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.domain": { + "name": "domain", + "schema": "", + "columns": { + "domainId": { + "name": "domainId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "host": { + "name": "host", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "https": { + "name": "https", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3000 + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "domainType": { + "name": "domainType", + "type": "domainType", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'application'" + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + } + }, + "indexes": {}, + "foreignKeys": { + "domain_composeId_compose_composeId_fk": { + "name": "domain_composeId_compose_composeId_fk", + "tableFrom": "domain", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "domain_applicationId_application_applicationId_fk": { + "name": "domain_applicationId_application_applicationId_fk", + "tableFrom": "domain", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mariadb": { + "name": "mariadb", + "schema": "", + "columns": { + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mariadb_projectId_project_projectId_fk": { + "name": "mariadb_projectId_project_projectId_fk", + "tableFrom": "mariadb", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mariadb_appName_unique": { + "name": "mariadb_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mongo": { + "name": "mongo", + "schema": "", + "columns": { + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mongo_projectId_project_projectId_fk": { + "name": "mongo_projectId_project_projectId_fk", + "tableFrom": "mongo", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mongo_appName_unique": { + "name": "mongo_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.mysql": { + "name": "mysql", + "schema": "", + "columns": { + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "databaseName": { + "name": "databaseName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseUser": { + "name": "databaseUser", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databasePassword": { + "name": "databasePassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rootPassword": { + "name": "rootPassword", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mysql_projectId_project_projectId_fk": { + "name": "mysql_projectId_project_projectId_fk", + "tableFrom": "mysql", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mysql_appName_unique": { + "name": "mysql_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.backup": { + "name": "backup", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "schedule": { + "name": "schedule", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "database": { + "name": "database", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "databaseType": { + "name": "databaseType", + "type": "databaseType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "backup_destinationId_destination_destinationId_fk": { + "name": "backup_destinationId_destination_destinationId_fk", + "tableFrom": "backup", + "tableTo": "destination", + "columnsFrom": [ + "destinationId" + ], + "columnsTo": [ + "destinationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_postgresId_postgres_postgresId_fk": { + "name": "backup_postgresId_postgres_postgresId_fk", + "tableFrom": "backup", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mariadbId_mariadb_mariadbId_fk": { + "name": "backup_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "backup", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mysqlId_mysql_mysqlId_fk": { + "name": "backup_mysqlId_mysql_mysqlId_fk", + "tableFrom": "backup", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_mongoId_mongo_mongoId_fk": { + "name": "backup_mongoId_mongo_mongoId_fk", + "tableFrom": "backup", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.destination": { + "name": "destination", + "schema": "", + "columns": { + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessKey": { + "name": "accessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secretAccessKey": { + "name": "secretAccessKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "bucket": { + "name": "bucket", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "region": { + "name": "region", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "destination_adminId_admin_adminId_fk": { + "name": "destination_adminId_admin_adminId_fk", + "tableFrom": "destination", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.deployment": { + "name": "deployment", + "schema": "", + "columns": { + "deploymentId": { + "name": "deploymentId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "deploymentStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'running'" + }, + "logPath": { + "name": "logPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "deployment_applicationId_application_applicationId_fk": { + "name": "deployment_applicationId_application_applicationId_fk", + "tableFrom": "deployment", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_composeId_compose_composeId_fk": { + "name": "deployment_composeId_compose_composeId_fk", + "tableFrom": "deployment", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.mount": { + "name": "mount", + "schema": "", + "columns": { + "mountId": { + "name": "mountId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "mountType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "hostPath": { + "name": "hostPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "volumeName": { + "name": "volumeName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "filePath": { + "name": "filePath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serviceType": { + "name": "serviceType", + "type": "serviceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'application'" + }, + "mountPath": { + "name": "mountPath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mariadbId": { + "name": "mariadbId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mongoId": { + "name": "mongoId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mysqlId": { + "name": "mysqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mount_applicationId_application_applicationId_fk": { + "name": "mount_applicationId_application_applicationId_fk", + "tableFrom": "mount", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_postgresId_postgres_postgresId_fk": { + "name": "mount_postgresId_postgres_postgresId_fk", + "tableFrom": "mount", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mariadbId_mariadb_mariadbId_fk": { + "name": "mount_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "mount", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mongoId_mongo_mongoId_fk": { + "name": "mount_mongoId_mongo_mongoId_fk", + "tableFrom": "mount", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_mysqlId_mysql_mysqlId_fk": { + "name": "mount_mysqlId_mysql_mysqlId_fk", + "tableFrom": "mount", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_redisId_redis_redisId_fk": { + "name": "mount_redisId_redis_redisId_fk", + "tableFrom": "mount", + "tableTo": "redis", + "columnsFrom": [ + "redisId" + ], + "columnsTo": [ + "redisId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_composeId_compose_composeId_fk": { + "name": "mount_composeId_compose_composeId_fk", + "tableFrom": "mount", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.certificate": { + "name": "certificate", + "schema": "", + "columns": { + "certificateId": { + "name": "certificateId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificateData": { + "name": "certificateData", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "privateKey": { + "name": "privateKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "certificatePath": { + "name": "certificatePath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "autoRenew": { + "name": "autoRenew", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "certificate_certificatePath_unique": { + "name": "certificate_certificatePath_unique", + "nullsNotDistinct": false, + "columns": [ + "certificatePath" + ] + } + } + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_auth_id_fk": { + "name": "session_user_id_auth_id_fk", + "tableFrom": "session", + "tableTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redirect": { + "name": "redirect", + "schema": "", + "columns": { + "redirectId": { + "name": "redirectId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "regex": { + "name": "regex", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "replacement": { + "name": "replacement", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permanent": { + "name": "permanent", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "uniqueConfigKey": { + "name": "uniqueConfigKey", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redirect_applicationId_application_applicationId_fk": { + "name": "redirect_applicationId_application_applicationId_fk", + "tableFrom": "redirect", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.security": { + "name": "security", + "schema": "", + "columns": { + "securityId": { + "name": "securityId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "security_applicationId_application_applicationId_fk": { + "name": "security_applicationId_application_applicationId_fk", + "tableFrom": "security", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "security_username_applicationId_unique": { + "name": "security_username_applicationId_unique", + "nullsNotDistinct": false, + "columns": [ + "username", + "applicationId" + ] + } + } + }, + "public.port": { + "name": "port", + "schema": "", + "columns": { + "portId": { + "name": "portId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publishedPort": { + "name": "publishedPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "targetPort": { + "name": "targetPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "protocolType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "port_applicationId_application_applicationId_fk": { + "name": "port_applicationId_application_applicationId_fk", + "tableFrom": "port", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.redis": { + "name": "redis", + "schema": "", + "columns": { + "redisId": { + "name": "redisId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "dockerImage": { + "name": "dockerImage", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "redis_projectId_project_projectId_fk": { + "name": "redis_projectId_project_projectId_fk", + "tableFrom": "redis", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "redis_appName_unique": { + "name": "redis_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + } + }, + "public.compose": { + "name": "compose", + "schema": "", + "columns": { + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeFile": { + "name": "composeFile", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sourceType": { + "name": "sourceType", + "type": "sourceTypeCompose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "composeType": { + "name": "composeType", + "type": "composeType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'docker-compose'" + }, + "repository": { + "name": "repository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "customGitUrl": { + "name": "customGitUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitBranch": { + "name": "customGitBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customGitSSHKeyId": { + "name": "customGitSSHKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "composePath": { + "name": "composePath", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'./docker-compose.yml'" + }, + "composeStatus": { + "name": "composeStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk": { + "name": "compose_customGitSSHKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "compose", + "tableTo": "ssh-key", + "columnsFrom": [ + "customGitSSHKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_projectId_project_projectId_fk": { + "name": "compose_projectId_project_projectId_fk", + "tableFrom": "compose", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.registry": { + "name": "registry", + "schema": "", + "columns": { + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "registryName": { + "name": "registryName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "imagePrefix": { + "name": "imagePrefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryUrl": { + "name": "registryUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "selfHosted": { + "name": "selfHosted", + "type": "RegistryType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cloud'" + }, + "adminId": { + "name": "adminId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "registry_adminId_admin_adminId_fk": { + "name": "registry_adminId_admin_adminId_fk", + "tableFrom": "registry", + "tableTo": "admin", + "columnsFrom": [ + "adminId" + ], + "columnsTo": [ + "adminId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.discord": { + "name": "discord", + "schema": "", + "columns": { + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.email": { + "name": "email", + "schema": "", + "columns": { + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "smtpServer": { + "name": "smtpServer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "smtpPort": { + "name": "smtpPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fromAddress": { + "name": "fromAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "toAddress": { + "name": "toAddress", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.notification": { + "name": "notification", + "schema": "", + "columns": { + "notificationId": { + "name": "notificationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appDeploy": { + "name": "appDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "appBuildError": { + "name": "appBuildError", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "databaseBackup": { + "name": "databaseBackup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dokployRestart": { + "name": "dokployRestart", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dockerCleanup": { + "name": "dockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "notificationType": { + "name": "notificationType", + "type": "notificationType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "emailId": { + "name": "emailId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "notification_slackId_slack_slackId_fk": { + "name": "notification_slackId_slack_slackId_fk", + "tableFrom": "notification", + "tableTo": "slack", + "columnsFrom": [ + "slackId" + ], + "columnsTo": [ + "slackId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_telegramId_telegram_telegramId_fk": { + "name": "notification_telegramId_telegram_telegramId_fk", + "tableFrom": "notification", + "tableTo": "telegram", + "columnsFrom": [ + "telegramId" + ], + "columnsTo": [ + "telegramId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_discordId_discord_discordId_fk": { + "name": "notification_discordId_discord_discordId_fk", + "tableFrom": "notification", + "tableTo": "discord", + "columnsFrom": [ + "discordId" + ], + "columnsTo": [ + "discordId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_emailId_email_emailId_fk": { + "name": "notification_emailId_email_emailId_fk", + "tableFrom": "notification", + "tableTo": "email", + "columnsFrom": [ + "emailId" + ], + "columnsTo": [ + "emailId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.slack": { + "name": "slack", + "schema": "", + "columns": { + "slackId": { + "name": "slackId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.telegram": { + "name": "telegram", + "schema": "", + "columns": { + "telegramId": { + "name": "telegramId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "botToken": { + "name": "botToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chatId": { + "name": "chatId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.ssh-key": { + "name": "ssh-key", + "schema": "", + "columns": { + "sshKeyId": { + "name": "sshKeyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publicKey": { + "name": "publicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "lastUsedAt": { + "name": "lastUsedAt", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.buildType": { + "name": "buildType", + "schema": "public", + "values": [ + "dockerfile", + "heroku_buildpacks", + "paketo_buildpacks", + "nixpacks", + "static" + ] + }, + "public.sourceType": { + "name": "sourceType", + "schema": "public", + "values": [ + "docker", + "git", + "github", + "drop" + ] + }, + "public.Roles": { + "name": "Roles", + "schema": "public", + "values": [ + "admin", + "user" + ] + }, + "public.domainType": { + "name": "domainType", + "schema": "public", + "values": [ + "compose", + "application" + ] + }, + "public.databaseType": { + "name": "databaseType", + "schema": "public", + "values": [ + "postgres", + "mariadb", + "mysql", + "mongo" + ] + }, + "public.deploymentStatus": { + "name": "deploymentStatus", + "schema": "public", + "values": [ + "running", + "done", + "error" + ] + }, + "public.mountType": { + "name": "mountType", + "schema": "public", + "values": [ + "bind", + "volume", + "file" + ] + }, + "public.serviceType": { + "name": "serviceType", + "schema": "public", + "values": [ + "application", + "postgres", + "mysql", + "mariadb", + "mongo", + "redis", + "compose" + ] + }, + "public.protocolType": { + "name": "protocolType", + "schema": "public", + "values": [ + "tcp", + "udp" + ] + }, + "public.applicationStatus": { + "name": "applicationStatus", + "schema": "public", + "values": [ + "idle", + "running", + "done", + "error" + ] + }, + "public.certificateType": { + "name": "certificateType", + "schema": "public", + "values": [ + "letsencrypt", + "none" + ] + }, + "public.composeType": { + "name": "composeType", + "schema": "public", + "values": [ + "docker-compose", + "stack" + ] + }, + "public.sourceTypeCompose": { + "name": "sourceTypeCompose", + "schema": "public", + "values": [ + "git", + "github", + "raw" + ] + }, + "public.RegistryType": { + "name": "RegistryType", + "schema": "public", + "values": [ + "selfHosted", + "cloud" + ] + }, + "public.notificationType": { + "name": "notificationType", + "schema": "public", + "values": [ + "slack", + "telegram", + "discord", + "email" + ] + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/_journal.json b/apps/dokploy/drizzle/meta/_journal.json index 89ebb4e71..5cecad09c 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -218,6 +218,20 @@ "when": 1723608499147, "tag": "0030_little_kabuki", "breakpoints": true + }, + { + "idx": 31, + "version": "6", + "when": 1723701656243, + "tag": "0031_steep_vulture", + "breakpoints": true + }, + { + "idx": 32, + "version": "6", + "when": 1723705257806, + "tag": "0032_flashy_shadow_king", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/compose/[composeId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/compose/[composeId].tsx index 22ef75058..225517e56 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/services/compose/[composeId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/compose/[composeId].tsx @@ -2,6 +2,7 @@ import { AddCommandCompose } from "@/components/dashboard/compose/advanced/add-c import { ShowVolumesCompose } from "@/components/dashboard/compose/advanced/show-volumes"; import { DeleteCompose } from "@/components/dashboard/compose/delete-compose"; import { ShowDeploymentsCompose } from "@/components/dashboard/compose/deployments/show-deployments-compose"; +import { ShowDomainsCompose } from "@/components/dashboard/compose/domains/show-domains"; import { ShowEnvironmentCompose } from "@/components/dashboard/compose/enviroment/show"; import { ShowGeneralCompose } from "@/components/dashboard/compose/general/show"; import { ShowDockerLogsCompose } from "@/components/dashboard/compose/logs/show"; @@ -34,6 +35,7 @@ type TabState = | "settings" | "advanced" | "deployments" + | "domains" | "monitoring"; const Service = ( @@ -117,12 +119,13 @@ const Service = ( }} >
- + General Environment Monitoring Logs Deployments + Domains Advanced
@@ -168,6 +171,12 @@ const Service = (
+ + +
+ +
+
diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index 3b8a92f63..d109c2a46 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -3,6 +3,7 @@ import { db } from "@/server/db"; import { apiCreateCompose, apiCreateComposeByTemplate, + apiFetchServices, apiFindCompose, apiRandomizeCompose, apiUpdateCompose, @@ -15,16 +16,18 @@ import { import { myQueue } from "@/server/queues/queueSetup"; import { createCommand } from "@/server/utils/builders/compose"; import { randomizeComposeFile } from "@/server/utils/docker/compose"; +import { addDomainToCompose, cloneCompose } from "@/server/utils/docker/domain"; import { removeComposeDirectory } from "@/server/utils/filesystem/directory"; import { templates } from "@/templates/templates"; import type { TemplatesKeys } from "@/templates/types/templates-data.type"; import { generatePassword, loadTemplateModule, - readComposeFile, + readTemplateComposeFile, } from "@/templates/utils"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; +import { dump } from "js-yaml"; import _ from "lodash"; import { nanoid } from "nanoid"; import { findAdmin } from "../services/admin"; @@ -38,6 +41,7 @@ import { updateCompose, } from "../services/compose"; import { removeDeploymentsByComposeId } from "../services/deployment"; +import { findDomainsByComposeId } from "../services/domain"; import { createMount } from "../services/mount"; import { findProjectById } from "../services/project"; import { addNewService, checkServiceAccess } from "../services/user"; @@ -113,10 +117,25 @@ export const composeRouter = createTRPCRouter({ await cleanQueuesByCompose(input.composeId); }), - allServices: protectedProcedure - .input(apiFindCompose) + loadServices: protectedProcedure + .input(apiFetchServices) .query(async ({ input }) => { - return await loadServices(input.composeId); + return await loadServices(input.composeId, input.type); + }), + fetchSourceType: protectedProcedure + .input(apiFindCompose) + .mutation(async ({ input }) => { + try { + const compose = await findComposeById(input.composeId); + await cloneCompose(compose); + return compose.sourceType; + } catch (err) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error to fetch source type", + cause: err, + }); + } }), randomizeCompose: protectedProcedure @@ -124,6 +143,17 @@ export const composeRouter = createTRPCRouter({ .mutation(async ({ input }) => { return await randomizeComposeFile(input.composeId, input.prefix); }), + getConvertedCompose: protectedProcedure + .input(apiFindCompose) + .query(async ({ input }) => { + const compose = await findComposeById(input.composeId); + const domains = await findDomainsByComposeId(input.composeId); + + const composeFile = await addDomainToCompose(compose, domains); + return dump(composeFile, { + lineWidth: 1000, + }); + }), deploy: protectedProcedure .input(apiFindCompose) @@ -189,7 +219,7 @@ export const composeRouter = createTRPCRouter({ if (ctx.user.rol === "user") { await checkServiceAccess(ctx.user.authId, input.projectId, "create"); } - const composeFile = await readComposeFile(input.id); + const composeFile = await readTemplateComposeFile(input.id); const generate = await loadTemplateModule(input.id as TemplatesKeys); diff --git a/apps/dokploy/server/api/routers/domain.ts b/apps/dokploy/server/api/routers/domain.ts index ec7f13d4f..309dd91ad 100644 --- a/apps/dokploy/server/api/routers/domain.ts +++ b/apps/dokploy/server/api/routers/domain.ts @@ -1,8 +1,12 @@ import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; import { apiCreateDomain, + apiCreateTraefikMeDomain, + apiFindCompose, apiFindDomain, apiFindDomainByApplication, + apiFindDomainByCompose, + apiFindOneApplication, apiUpdateDomain, } from "@/server/db/schema"; import { manageDomain, removeDomain } from "@/server/utils/traefik/domain"; @@ -12,8 +16,8 @@ import { createDomain, findDomainById, findDomainsByApplicationId, - generateDomain, - generateWildcard, + findDomainsByComposeId, + generateTraefikMeDomain, removeDomainById, updateDomainById, } from "../services/domain"; @@ -33,27 +37,30 @@ export const domainRouter = createTRPCRouter({ } }), byApplicationId: protectedProcedure - .input(apiFindDomainByApplication) + .input(apiFindOneApplication) .query(async ({ input }) => { return await findDomainsByApplicationId(input.applicationId); }), + byComposeId: protectedProcedure + .input(apiFindCompose) + .query(async ({ input }) => { + return await findDomainsByComposeId(input.composeId); + }), generateDomain: protectedProcedure - .input(apiFindDomainByApplication) + .input(apiCreateTraefikMeDomain) .mutation(async ({ input }) => { - return generateDomain(input); - }), - generateWildcard: protectedProcedure - .input(apiFindDomainByApplication) - .mutation(async ({ input }) => { - return generateWildcard(input); + return generateTraefikMeDomain(input.appName); }), + update: protectedProcedure .input(apiUpdateDomain) .mutation(async ({ input }) => { const result = await updateDomainById(input.domainId, input); const domain = await findDomainById(input.domainId); - const application = await findApplicationById(domain.applicationId); - await manageDomain(application, domain); + if (domain.applicationId) { + const application = await findApplicationById(domain.applicationId); + await manageDomain(application, domain); + } return result; }), one: protectedProcedure.input(apiFindDomain).query(async ({ input }) => { @@ -64,7 +71,9 @@ export const domainRouter = createTRPCRouter({ .mutation(async ({ input }) => { const domain = await findDomainById(input.domainId); const result = await removeDomainById(input.domainId); - await removeDomain(domain.application.appName, domain.uniqueConfigKey); + if (domain.application) { + await removeDomain(domain.application.appName, domain.uniqueConfigKey); + } return result; }), diff --git a/apps/dokploy/server/api/services/compose.ts b/apps/dokploy/server/api/services/compose.ts index 978c8fb71..bd949bc38 100644 --- a/apps/dokploy/server/api/services/compose.ts +++ b/apps/dokploy/server/api/services/compose.ts @@ -4,6 +4,7 @@ import { db } from "@/server/db"; import { type apiCreateCompose, compose } from "@/server/db/schema"; import { generateAppName } from "@/server/db/schema/utils"; import { buildCompose } from "@/server/utils/builders/compose"; +import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error"; import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success"; @@ -14,7 +15,6 @@ import { createComposeFile } from "@/server/utils/providers/raw"; import { generatePassword } from "@/templates/utils"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; -import { load } from "js-yaml"; import { findAdmin, getDokployUrl } from "./admin"; import { createDeploymentCompose, updateDeploymentStatus } from "./deployment"; import { validUniqueServerAppName } from "./project"; @@ -91,6 +91,7 @@ export const findComposeById = async (composeId: string) => { project: true, deployments: true, mounts: true, + domains: true, }, }); if (!result) { @@ -102,20 +103,27 @@ export const findComposeById = async (composeId: string) => { return result; }; -export const loadServices = async (composeId: string) => { +export const loadServices = async ( + composeId: string, + type: "fetch" | "cache" = "fetch", +) => { const compose = await findComposeById(composeId); - // use js-yaml to parse the docker compose file and then extact the services - const composeFile = compose.composeFile; - const composeData = load(composeFile) as ComposeSpecification; + if (type === "fetch") { + await cloneCompose(compose); + } + const composeData = await loadDockerCompose(compose); if (!composeData?.services) { - return ["All Services"]; + throw new TRPCError({ + code: "NOT_FOUND", + message: "Services not found", + }); } const services = Object.keys(composeData.services); - return [...services, "All Services"]; + return [...services]; }; export const updateCompose = async ( diff --git a/apps/dokploy/server/api/services/domain.ts b/apps/dokploy/server/api/services/domain.ts index b11c0d2ae..53687d28b 100644 --- a/apps/dokploy/server/api/services/domain.ts +++ b/apps/dokploy/server/api/services/domain.ts @@ -15,8 +15,6 @@ export type Domain = typeof domains.$inferSelect; export const createDomain = async (input: typeof apiCreateDomain._type) => { await db.transaction(async (tx) => { - const application = await findApplicationById(input.applicationId); - const domain = await tx .insert(domains) .values({ @@ -32,52 +30,19 @@ export const createDomain = async (input: typeof apiCreateDomain._type) => { }); } - await manageDomain(application, domain); + if (domain.applicationId) { + const application = await findApplicationById(domain.applicationId); + await manageDomain(application, domain); + } }); }; -export const generateDomain = async ( - input: typeof apiFindDomainByApplication._type, -) => { - const application = await findApplicationById(input.applicationId); +export const generateTraefikMeDomain = async (appName: string) => { const admin = await findAdmin(); - const domain = await createDomain({ - applicationId: application.applicationId, - host: generateRandomDomain({ - serverIp: admin.serverIp || "", - projectName: application.appName, - }), - port: 3000, - certificateType: "none", - https: false, - path: "/", + return generateRandomDomain({ + serverIp: admin.serverIp || "", + projectName: appName, }); - - return domain; -}; - -export const generateWildcard = async ( - input: typeof apiFindDomainByApplication._type, -) => { - const application = await findApplicationById(input.applicationId); - const admin = await findAdmin(); - - if (!admin.host) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "We need a host to generate a wildcard domain", - }); - } - const domain = await createDomain({ - applicationId: application.applicationId, - host: generateWildcardDomain(application.appName, admin.host || ""), - port: 3000, - certificateType: "none", - https: false, - path: "/", - }); - - return domain; }; export const generateWildcardDomain = ( @@ -114,6 +79,17 @@ export const findDomainsByApplicationId = async (applicationId: string) => { return domainsArray; }; +export const findDomainsByComposeId = async (composeId: string) => { + const domainsArray = await db.query.domains.findMany({ + where: eq(domains.composeId, composeId), + with: { + compose: true, + }, + }); + + return domainsArray; +}; + export const updateDomainById = async ( domainId: string, domainData: Partial, diff --git a/apps/dokploy/server/db/schema/compose.ts b/apps/dokploy/server/db/schema/compose.ts index 485c51e10..80597d76f 100644 --- a/apps/dokploy/server/db/schema/compose.ts +++ b/apps/dokploy/server/db/schema/compose.ts @@ -1,11 +1,11 @@ import { sshKeys } from "@/server/db/schema/ssh-key"; -import { generatePassword } from "@/templates/utils"; import { relations } from "drizzle-orm"; import { boolean, pgEnum, pgTable, text } from "drizzle-orm/pg-core"; import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; import { z } from "zod"; import { deployments } from "./deployment"; +import { domains } from "./domain"; import { mounts } from "./mount"; import { projects } from "./project"; import { applicationStatus } from "./shared"; @@ -72,6 +72,7 @@ export const composeRelations = relations(compose, ({ one, many }) => ({ fields: [compose.customGitSSHKeyId], references: [sshKeys.sshKeyId], }), + domains: many(domains), })); const createSchema = createInsertSchema(compose, { @@ -106,6 +107,11 @@ export const apiFindCompose = z.object({ composeId: z.string().min(1), }); +export const apiFetchServices = z.object({ + composeId: z.string().min(1), + type: z.enum(["fetch", "cache"]).optional().default("cache"), +}); + export const apiUpdateCompose = createSchema.partial().extend({ composeId: z.string(), composeFile: z.string().optional(), diff --git a/apps/dokploy/server/db/schema/domain.ts b/apps/dokploy/server/db/schema/domain.ts index 48dc05a77..301175fc5 100644 --- a/apps/dokploy/server/db/schema/domain.ts +++ b/apps/dokploy/server/db/schema/domain.ts @@ -1,11 +1,22 @@ -import { domain } from "@/server/db/validations"; +import { domain } from "@/server/db/validations/domain"; import { relations } from "drizzle-orm"; -import { boolean, integer, pgTable, serial, text } from "drizzle-orm/pg-core"; +import { + boolean, + integer, + pgEnum, + pgTable, + serial, + text, +} from "drizzle-orm/pg-core"; import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; +import { z } from "zod"; import { applications } from "./application"; +import { compose } from "./compose"; import { certificateType } from "./shared"; +export const domainType = pgEnum("domainType", ["compose", "application"]); + export const domains = pgTable("domain", { domainId: text("domainId") .notNull() @@ -13,15 +24,21 @@ export const domains = pgTable("domain", { .$defaultFn(() => nanoid()), host: text("host").notNull(), https: boolean("https").notNull().default(false), - port: integer("port").default(80), + port: integer("port").default(3000), path: text("path").default("/"), + serviceName: text("serviceName"), + domainType: domainType("domainType").default("application"), uniqueConfigKey: serial("uniqueConfigKey"), createdAt: text("createdAt") .notNull() .$defaultFn(() => new Date().toISOString()), - applicationId: text("applicationId") - .notNull() - .references(() => applications.applicationId, { onDelete: "cascade" }), + composeId: text("composeId").references(() => compose.composeId, { + onDelete: "cascade", + }), + applicationId: text("applicationId").references( + () => applications.applicationId, + { onDelete: "cascade" }, + ), certificateType: certificateType("certificateType").notNull().default("none"), }); @@ -30,6 +47,10 @@ export const domainsRelations = relations(domains, ({ one }) => ({ fields: [domains.applicationId], references: [applications.applicationId], }), + compose: one(compose, { + fields: [domains.composeId], + references: [compose.composeId], + }), })); const createSchema = createInsertSchema(domains, domain._def.schema.shape); @@ -41,6 +62,9 @@ export const apiCreateDomain = createSchema.pick({ https: true, applicationId: true, certificateType: true, + composeId: true, + serviceName: true, + domainType: true, }); export const apiFindDomain = createSchema @@ -53,6 +77,14 @@ export const apiFindDomainByApplication = createSchema.pick({ applicationId: true, }); +export const apiCreateTraefikMeDomain = createSchema.pick({}).extend({ + appName: z.string().min(1), +}); + +export const apiFindDomainByCompose = createSchema.pick({ + composeId: true, +}); + export const apiUpdateDomain = createSchema .pick({ host: true, @@ -60,5 +92,7 @@ export const apiUpdateDomain = createSchema port: true, https: true, certificateType: true, + serviceName: true, + domainType: true, }) .merge(createSchema.pick({ domainId: true }).required()); diff --git a/apps/dokploy/server/db/validations/domain.ts b/apps/dokploy/server/db/validations/domain.ts new file mode 100644 index 000000000..b09b57b6c --- /dev/null +++ b/apps/dokploy/server/db/validations/domain.ts @@ -0,0 +1,46 @@ +import { z } from "zod"; + +export const domain = z + .object({ + host: z.string().min(1, { message: "Add a hostname" }), + path: z.string().min(1).optional(), + port: z + .number() + .min(1, { message: "Port must be at least 1" }) + .max(65535, { message: "Port must be 65535 or below" }) + .optional(), + https: z.boolean().optional(), + certificateType: z.enum(["letsencrypt", "none"]).optional(), + }) + .superRefine((input, ctx) => { + if (input.https && !input.certificateType) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["certificateType"], + message: "Required", + }); + } + }); + +export const domainCompose = z + .object({ + host: z.string().min(1, { message: "Host is required" }), + path: z.string().min(1).optional(), + port: z + .number() + .min(1, { message: "Port must be at least 1" }) + .max(65535, { message: "Port must be 65535 or below" }) + .optional(), + https: z.boolean().optional(), + certificateType: z.enum(["letsencrypt", "none"]).optional(), + serviceName: z.string().min(1, { message: "Service name is required" }), + }) + .superRefine((input, ctx) => { + if (input.https && !input.certificateType) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["certificateType"], + message: "Required", + }); + } + }); diff --git a/apps/dokploy/server/db/validations/index.ts b/apps/dokploy/server/db/validations/index.ts index 34a425df3..b3cb57852 100644 --- a/apps/dokploy/server/db/validations/index.ts +++ b/apps/dokploy/server/db/validations/index.ts @@ -35,25 +35,3 @@ export const sshKeyUpdate = sshKeyCreate.pick({ export const sshKeyType = z.object({ type: z.enum(["rsa", "ed25519"]).optional(), }); - -export const domain = z - .object({ - host: z.string().min(1, { message: "Add a hostname" }), - path: z.string().min(1).optional(), - port: z - .number() - .min(1, { message: "Port must be at least 1" }) - .max(65535, { message: "Port must be 65535 or below" }) - .optional(), - https: z.boolean().optional(), - certificateType: z.enum(["letsencrypt", "none"]).optional(), - }) - .superRefine((input, ctx) => { - if (input.https && !input.certificateType) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - path: ["certificateType"], - message: "Required", - }); - } - }); diff --git a/apps/dokploy/server/utils/builders/compose.ts b/apps/dokploy/server/utils/builders/compose.ts index 9212cf604..4f72f46d3 100644 --- a/apps/dokploy/server/utils/builders/compose.ts +++ b/apps/dokploy/server/utils/builders/compose.ts @@ -8,20 +8,28 @@ import { dirname, join } from "node:path"; import { COMPOSE_PATH } from "@/server/constants"; import type { InferResultType } from "@/server/types/with"; import boxen from "boxen"; +import { writeDomainsToCompose } from "../docker/domain"; import { prepareEnvironmentVariables } from "../docker/utils"; import { spawnAsync } from "../process/spawnAsync"; export type ComposeNested = InferResultType< "compose", - { project: true; mounts: true } + { project: true; mounts: true; domains: true } >; export const buildCompose = async (compose: ComposeNested, logPath: string) => { const writeStream = createWriteStream(logPath, { flags: "a" }); - const { sourceType, appName, mounts, composeType, env, composePath } = - compose; + const { + sourceType, + appName, + mounts, + composeType, + env, + composePath, + domains, + } = compose; try { const command = createCommand(compose); - + await writeDomainsToCompose(compose, domains); createEnvFile(compose); const logContent = ` diff --git a/apps/dokploy/server/utils/docker/domain.ts b/apps/dokploy/server/utils/docker/domain.ts new file mode 100644 index 000000000..924a9e8e2 --- /dev/null +++ b/apps/dokploy/server/utils/docker/domain.ts @@ -0,0 +1,224 @@ +import fs, { existsSync, readFileSync, writeSync } from "node:fs"; +import { writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import type { Compose } from "@/server/api/services/compose"; +import type { Domain } from "@/server/api/services/domain"; +import { COMPOSE_PATH } from "@/server/constants"; +import { dump, load } from "js-yaml"; +import { cloneGitRawRepository } from "../providers/git"; +import { cloneRawGithubRepository } from "../providers/github"; +import { createComposeFileRaw } from "../providers/raw"; +import type { + ComposeSpecification, + DefinitionsService, + PropertiesNetworks, +} from "./types"; + +export const cloneCompose = async (compose: Compose) => { + if (compose.sourceType === "github") { + await cloneRawGithubRepository(compose); + } else if (compose.sourceType === "git") { + await cloneGitRawRepository(compose); + } else if (compose.sourceType === "raw") { + await createComposeFileRaw(compose); + } +}; + +export const getComposePath = (compose: Compose) => { + const { appName, sourceType, composePath } = compose; + let path = ""; + + if (sourceType === "raw") { + path = "docker-compose.yml"; + } else { + path = composePath; + } + + return join(COMPOSE_PATH, appName, "code", path); +}; + +export const loadDockerCompose = async ( + compose: Compose, +): Promise => { + const path = getComposePath(compose); + + if (existsSync(path)) { + const yamlStr = readFileSync(path, "utf8"); + const parsedConfig = load(yamlStr) as ComposeSpecification; + return parsedConfig; + } + return null; +}; + +export const readComposeFile = async (compose: Compose) => { + const path = getComposePath(compose); + if (existsSync(path)) { + const yamlStr = readFileSync(path, "utf8"); + return yamlStr; + } + return null; +}; + +export const writeDomainsToCompose = async ( + compose: Compose, + domains: Domain[], +) => { + if (!domains.length) { + return; + } + const composeConverted = await addDomainToCompose(compose, domains); + + const path = getComposePath(compose); + const composeString = dump(composeConverted, { lineWidth: 1000 }); + try { + await writeFile(path, composeString, "utf8"); + } catch (error) { + throw error; + } +}; + +export const addDomainToCompose = async ( + compose: Compose, + domains: Domain[], +) => { + const { appName } = compose; + const result = await loadDockerCompose(compose); + + if (!result || domains.length === 0) { + return null; + } + + for (const domain of domains) { + const { serviceName, https } = domain; + if (!serviceName) { + throw new Error("Service name not found"); + } + if (!result?.services?.[serviceName]) { + throw new Error(`The service ${serviceName} not found in the compose`); + } + if (!result.services[serviceName].labels) { + result.services[serviceName].labels = []; + } + + const httpLabels = await createDomainLabels(appName, domain, "web"); + if (https) { + const httpsLabels = await createDomainLabels( + appName, + domain, + "websecure", + ); + httpLabels.push(...httpsLabels); + } + + const labels = result.services[serviceName].labels; + + if (Array.isArray(labels)) { + if (!labels.includes("traefik.enable=true")) { + labels.push("traefik.enable=true"); + } + labels.push(...httpLabels); + } + + // Add the dokploy-network to the service + result.services[serviceName].networks = addDokployNetworkToService( + result.services[serviceName].networks, + ); + } + + // Add dokploy-network to the root of the compose file + result.networks = addDokployNetworkToRoot(result.networks); + + return result; +}; + +export const writeComposeFile = async ( + compose: Compose, + composeSpec: ComposeSpecification, +) => { + const path = getComposePath(compose); + + try { + const composeFile = dump(composeSpec, { + lineWidth: 1000, + }); + fs.writeFileSync(path, composeFile, "utf8"); + } catch (e) { + console.error("Error saving the YAML config file:", e); + } +}; + +export const createDomainLabels = async ( + appName: string, + domain: Domain, + entrypoint: "web" | "websecure", +) => { + const { host, port, https, uniqueConfigKey, certificateType } = domain; + const routerName = `${appName}-${uniqueConfigKey}-${entrypoint}`; + const labels = [ + `traefik.http.routers.${routerName}.rule=Host(\`${host}\`)`, + `traefik.http.routers.${routerName}.entrypoints=${entrypoint}`, + ]; + + if (entrypoint === "web") { + labels.push( + `traefik.http.services.${routerName}.loadbalancer.server.port=${port}`, + ); + } + + if (entrypoint === "web" && https) { + labels.push( + `traefik.http.routers.${routerName}.middlewares=redirect-to-https@file`, + ); + } + + if (entrypoint === "websecure") { + if (certificateType === "letsencrypt") { + labels.push( + `traefik.http.routers.${routerName}.tls.certresolver=letsencrypt`, + ); + } + } + + return labels; +}; + +export const addDokployNetworkToService = ( + networkService: DefinitionsService["networks"], +) => { + let networks = networkService; + const network = "dokploy-network"; + if (!networks) { + networks = []; + } + + if (Array.isArray(networks)) { + if (!networks.includes(network)) { + networks.push(network); + } + } else if (networks && typeof networks === "object") { + if (!(network in networks)) { + networks[network] = {}; + } + } + + return networks; +}; + +export const addDokployNetworkToRoot = ( + networkRoot: PropertiesNetworks | undefined, +) => { + let networks = networkRoot; + const network = "dokploy-network"; + + if (!networks) { + networks = {}; + } + + if (networks[network] || !networks[network]) { + networks[network] = { + external: true, + }; + } + + return networks; +}; diff --git a/apps/dokploy/server/utils/providers/git.ts b/apps/dokploy/server/utils/providers/git.ts index cf3e28aea..bad7e615f 100644 --- a/apps/dokploy/server/utils/providers/git.ts +++ b/apps/dokploy/server/utils/providers/git.ts @@ -139,3 +139,61 @@ const sanitizeRepoPathSSH = (input: string) => { }, }; }; + +export const cloneGitRawRepository = async (entity: { + appName: string; + customGitUrl?: string | null; + customGitBranch?: string | null; + customGitSSHKeyId?: string | null; +}) => { + const { appName, customGitUrl, customGitBranch, customGitSSHKeyId } = entity; + + if (!customGitUrl || !customGitBranch) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error: Repository not found", + }); + } + + const keyPath = path.join(SSH_PATH, `${customGitSSHKeyId}_rsa`); + const basePath = COMPOSE_PATH; + const outputPath = join(basePath, appName, "code"); + const knownHostsPath = path.join(SSH_PATH, "known_hosts"); + + try { + await addHostToKnownHosts(customGitUrl); + await recreateDirectory(outputPath); + + if (customGitSSHKeyId) { + await updateSSHKeyById({ + sshKeyId: customGitSSHKeyId, + lastUsedAt: new Date().toISOString(), + }); + } + + await spawnAsync( + "git", + [ + "clone", + "--branch", + customGitBranch, + "--depth", + "1", + customGitUrl, + outputPath, + "--progress", + ], + (data) => {}, + { + env: { + ...process.env, + ...(customGitSSHKeyId && { + GIT_SSH_COMMAND: `ssh -i ${keyPath} -o UserKnownHostsFile=${knownHostsPath}`, + }), + }, + }, + ); + } catch (error) { + throw error; + } +}; diff --git a/apps/dokploy/server/utils/providers/github.ts b/apps/dokploy/server/utils/providers/github.ts index 06e38e191..a49f2b56e 100644 --- a/apps/dokploy/server/utils/providers/github.ts +++ b/apps/dokploy/server/utils/providers/github.ts @@ -1,6 +1,6 @@ import { createWriteStream } from "node:fs"; import { join } from "node:path"; -import type { Admin } from "@/server/api/services/admin"; +import { type Admin, findAdmin } from "@/server/api/services/admin"; import { APPLICATIONS_PATH, COMPOSE_PATH } from "@/server/constants"; import { createAppAuth } from "@octokit/auth-app"; import { TRPCError } from "@trpc/server"; @@ -128,3 +128,34 @@ export const cloneGithubRepository = async ( writeStream.end(); } }; + +export const cloneRawGithubRepository = async (entity: { + appName: string; + repository?: string | null; + owner?: string | null; + branch?: string | null; +}) => { + const { appName, repository, owner, branch } = entity; + const admin = await findAdmin(); + const basePath = COMPOSE_PATH; + const outputPath = join(basePath, appName, "code"); + const octokit = authGithub(admin); + const token = await getGithubToken(octokit); + const repoclone = `github.com/${owner}/${repository}.git`; + await recreateDirectory(outputPath); + const cloneUrl = `https://oauth2:${token}@${repoclone}`; + try { + await spawnAsync("git", [ + "clone", + "--branch", + branch!, + "--depth", + "1", + cloneUrl, + outputPath, + "--progress", + ]); + } catch (error) { + throw error; + } +}; diff --git a/apps/dokploy/server/utils/providers/raw.ts b/apps/dokploy/server/utils/providers/raw.ts index 63b825a7e..9bf818a30 100644 --- a/apps/dokploy/server/utils/providers/raw.ts +++ b/apps/dokploy/server/utils/providers/raw.ts @@ -26,3 +26,15 @@ export const createComposeFile = async (compose: Compose, logPath: string) => { writeStream.end(); } }; + +export const createComposeFileRaw = async (compose: Compose) => { + const { appName, composeFile } = compose; + const outputPath = join(COMPOSE_PATH, appName, "code"); + const filePath = join(outputPath, "docker-compose.yml"); + try { + await recreateDirectory(outputPath); + await writeFile(filePath, composeFile); + } catch (error) { + throw error; + } +}; diff --git a/apps/dokploy/templates/utils/index.ts b/apps/dokploy/templates/utils/index.ts index 4d194ba94..d2bcae9c5 100644 --- a/apps/dokploy/templates/utils/index.ts +++ b/apps/dokploy/templates/utils/index.ts @@ -57,7 +57,7 @@ export const loadTemplateModule = async ( return generate; }; -export const readComposeFile = async (id: string) => { +export const readTemplateComposeFile = async (id: string) => { const cwd = process.cwd(); const composeFile = await readFile( join(cwd, ".next", "templates", id, "docker-compose.yml"),