From 91a385c302ea317652d9c56cff3326009c717d3e Mon Sep 17 00:00:00 2001 From: WalidDevIO Date: Mon, 27 Oct 2025 21:40:50 +0100 Subject: [PATCH 01/25] feat[notifications]: Add dokployBackup notification type support This commit adds support for the dokployBackup notification type across all relevant services and schemas. --- .../notifications/handle-notifications.tsx | 37 + .../drizzle/0119_wakeful_luke_cage.sql | 1 + apps/dokploy/drizzle/meta/0119_snapshot.json | 6686 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + packages/server/src/db/schema/notification.ts | 8 + .../src/emails/emails/dokploy-backup.tsx | 105 + packages/server/src/services/notification.ts | 14 + .../server/src/utils/backups/web-server.ts | 35 +- .../src/utils/notifications/dokploy-backup.ts | 322 + 9 files changed, 7212 insertions(+), 3 deletions(-) create mode 100644 apps/dokploy/drizzle/0119_wakeful_luke_cage.sql create mode 100644 apps/dokploy/drizzle/meta/0119_snapshot.json create mode 100644 packages/server/src/emails/emails/dokploy-backup.tsx create mode 100644 packages/server/src/utils/notifications/dokploy-backup.ts diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index e5fee3a9d..8506446d3 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -44,6 +44,7 @@ const notificationBaseSchema = z.object({ appDeploy: z.boolean().default(false), appBuildError: z.boolean().default(false), databaseBackup: z.boolean().default(false), + dokployBackup: z.boolean().default(false), dokployRestart: z.boolean().default(false), dockerCleanup: z.boolean().default(false), serverThreshold: z.boolean().default(false), @@ -231,6 +232,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, dockerCleanup: notification.dockerCleanup, webhookUrl: notification.slack?.webhookUrl, channel: notification.slack?.channel || "", @@ -244,6 +246,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, botToken: notification.telegram?.botToken, messageThreadId: notification.telegram?.messageThreadId || "", chatId: notification.telegram?.chatId, @@ -258,6 +261,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, webhookUrl: notification.discord?.webhookUrl, decoration: notification.discord?.decoration || undefined, @@ -271,6 +275,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, smtpServer: notification.email?.smtpServer, smtpPort: notification.email?.smtpPort, @@ -288,6 +293,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, appToken: notification.gotify?.appToken, decoration: notification.gotify?.decoration || undefined, @@ -302,6 +308,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, accessToken: notification.ntfy?.accessToken, topic: notification.ntfy?.topic, @@ -317,6 +324,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, webhookUrl: notification.lark?.webhookUrl, name: notification.name, @@ -345,6 +353,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy, dokployRestart, databaseBackup, + dokployBackup, dockerCleanup, serverThreshold, } = data; @@ -355,6 +364,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, webhookUrl: data.webhookUrl, channel: data.channel, name: data.name, @@ -369,6 +379,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, botToken: data.botToken, messageThreadId: data.messageThreadId || "", chatId: data.chatId, @@ -384,6 +395,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, webhookUrl: data.webhookUrl, decoration: data.decoration, name: data.name, @@ -398,6 +410,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, smtpServer: data.smtpServer, smtpPort: data.smtpPort, username: data.username, @@ -416,6 +429,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, serverUrl: data.serverUrl, appToken: data.appToken, priority: data.priority, @@ -431,6 +445,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, serverUrl: data.serverUrl, accessToken: data.accessToken, topic: data.topic, @@ -446,6 +461,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, webhookUrl: data.webhookUrl, name: data.name, dockerCleanup: dockerCleanup, @@ -1130,6 +1146,27 @@ export const HandleNotifications = ({ notificationId }: Props) => { )} /> + ( + +
+ Dokploy Backup + + Trigger the action when a dokploy backup is created. + +
+ + + +
+ )} + /> + { + const previewText = `Dokploy instance backup was ${type === "success" ? "successful ✅" : "failed ❌"}`; + + return ( + + {previewText} + + + + +
+ Dokploy +
+ + Dokploy Instance Backup + + + Hello, + + + Your Dokploy instance backup was{" "} + {type === "success" + ? "successful ✅" + : "failed. Please check the error message below. ❌"} + . + +
+ Details: + + Backup Type: Complete Dokploy Instance + + + Content: /etc/dokploy + PostgreSQL Database + + {backupSize && ( + + Backup Size: {backupSize} + + )} + + Date: {date} + + + Status: {type === "success" ? "Successful" : "Failed"} + +
+ {type === "error" && errorMessage ? ( +
+ Reason: + + {errorMessage || "Error message not provided"} + +
+ ) : null} +
+ +
+ + ); +}; + +export default DokployBackupEmail; \ No newline at end of file diff --git a/packages/server/src/services/notification.ts b/packages/server/src/services/notification.ts index 9eaf812e0..420c269ac 100644 --- a/packages/server/src/services/notification.ts +++ b/packages/server/src/services/notification.ts @@ -57,6 +57,7 @@ export const createSlackNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "slack", @@ -88,6 +89,7 @@ export const updateSlackNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -148,6 +150,7 @@ export const createTelegramNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "telegram", @@ -179,6 +182,7 @@ export const updateTelegramNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -239,6 +243,7 @@ export const createDiscordNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "discord", @@ -270,6 +275,7 @@ export const updateDiscordNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -333,6 +339,7 @@ export const createEmailNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "email", @@ -364,6 +371,7 @@ export const updateEmailNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -429,6 +437,7 @@ export const createGotifyNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "gotify", @@ -459,6 +468,7 @@ export const updateGotifyNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -519,6 +529,7 @@ export const createNtfyNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "ntfy", @@ -549,6 +560,7 @@ export const updateNtfyNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, @@ -637,6 +649,7 @@ export const createLarkNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, notificationType: "lark", @@ -668,6 +681,7 @@ export const updateLarkNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, organizationId: input.organizationId, diff --git a/packages/server/src/utils/backups/web-server.ts b/packages/server/src/utils/backups/web-server.ts index 4d13ae31a..54399da82 100644 --- a/packages/server/src/utils/backups/web-server.ts +++ b/packages/server/src/utils/backups/web-server.ts @@ -1,5 +1,5 @@ import { createWriteStream } from "node:fs"; -import { mkdtemp, rm } from "node:fs/promises"; +import { mkdtemp, rm, stat } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { IS_CLOUD, paths } from "@dokploy/server/constants"; @@ -9,9 +9,19 @@ import { updateDeploymentStatus, } from "@dokploy/server/services/deployment"; import { findDestinationById } from "@dokploy/server/services/destination"; +import { sendDokployBackupNotifications } from "../notifications/dokploy-backup"; import { execAsync } from "../process/execAsync"; import { getS3Credentials, normalizeS3Path } from "./utils"; +function formatBytes(bytes?: number) { + if (bytes === undefined) return "Unknown size"; + if (bytes === 0) return "0 B"; + const sizes = ["B", "KB", "MB", "GB", "TB"]; + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + const value = bytes / Math.pow(1024, i); + return `${value.toFixed(2)} ${sizes[i]} (${bytes} bytes)`; +} + export const runWebServerBackup = async (backup: BackupSchedule) => { if (IS_CLOUD) { return; @@ -23,7 +33,7 @@ export const runWebServerBackup = async (backup: BackupSchedule) => { description: "Web Server Backup", }); const writeStream = createWriteStream(deployment.logPath, { flags: "a" }); - + let computedBackupSize: number | undefined; try { const destination = await findDestinationById(backup.destinationId); const rcloneFlags = getS3Credentials(destination); @@ -79,11 +89,24 @@ export const runWebServerBackup = async (backup: BackupSchedule) => { writeStream.write("Zipped database and filesystem\n"); - const uploadCommand = `rclone copyto ${rcloneFlags.join(" ")} "${tempDir}/${backupFileName}" "${s3Path}"`; + const zipPath = join(tempDir, backupFileName); + try { + const { size } = await stat(zipPath); + computedBackupSize = size; + writeStream.write(`Backup size: ${size} bytes\n`); + } catch { + // If stat fails, keep undefined + } + + const uploadCommand = `rclone copyto ${rcloneFlags.join(" ")} "${zipPath}" "${s3Path}"`; writeStream.write("Running command to upload backup to S3\n"); await execAsync(uploadCommand); writeStream.write("Uploaded backup to S3 ✅\n"); writeStream.end(); + await sendDokployBackupNotifications({ + type: "success", + backupSize: formatBytes(computedBackupSize), + }); await updateDeploymentStatus(deployment.deploymentId, "done"); return true; } finally { @@ -100,6 +123,12 @@ export const runWebServerBackup = async (backup: BackupSchedule) => { error instanceof Error ? error.message : "Unknown error\n", ); writeStream.end(); + await sendDokployBackupNotifications({ + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + backupSize: formatBytes(computedBackupSize), + }); await updateDeploymentStatus(deployment.deploymentId, "error"); throw error; } diff --git a/packages/server/src/utils/notifications/dokploy-backup.ts b/packages/server/src/utils/notifications/dokploy-backup.ts new file mode 100644 index 000000000..707f53839 --- /dev/null +++ b/packages/server/src/utils/notifications/dokploy-backup.ts @@ -0,0 +1,322 @@ +import { db } from "@dokploy/server/db"; +import { notifications } from "@dokploy/server/db/schema"; +import DokployBackupEmail from "@dokploy/server/emails/emails/dokploy-backup"; +import { renderAsync } from "@react-email/components"; +import { format } from "date-fns"; +import { eq } from "drizzle-orm"; +import { + sendDiscordNotification, + sendEmailNotification, + sendLarkNotification, + sendGotifyNotification, + sendNtfyNotification, + sendSlackNotification, + sendTelegramNotification, +} from "./utils"; + +export const sendDokployBackupNotifications = async ({ + type, + errorMessage, + backupSize, +}: { + type: "error" | "success"; + errorMessage?: string; + backupSize?: string; +}) => { + const date = new Date(); + const unixDate = ~~(Number(date) / 1000); + const notificationList = await db.query.notifications.findMany({ + where: eq(notifications.dokployBackup, true), + with: { + email: true, + discord: true, + telegram: true, + slack: true, + gotify: true, + ntfy: true, + lark: true, + }, + }); + + for (const notification of notificationList) { + const { email, discord, telegram, slack, gotify, ntfy, lark } = + notification; + + if (email) { + const template = await renderAsync( + DokployBackupEmail({ + type, + errorMessage, + date: date.toLocaleString(), + backupSize, + }), + ).catch(); + await sendEmailNotification( + email, + "Dokploy instance backup", + template, + ); + } + + if (discord) { + const decorate = (decoration: string, text: string) => + `${discord.decoration ? decoration : ""} ${text}`.trim(); + + await sendDiscordNotification(discord, { + title: + type === "success" + ? decorate(">", "`✅` Dokploy Backup Successful") + : decorate(">", "`❌` Dokploy Backup Failed"), + color: type === "success" ? 0x57f287 : 0xed4245, + fields: [ + { + name: decorate("`📦`", "Backup Type"), + value: "Complete Dokploy Instance", + inline: true, + }, + ...(backupSize + ? [ + { + name: decorate("`💾`", "Backup Size"), + value: backupSize, + inline: true, + }, + ] + : []), + { + name: decorate("`📅`", "Date"), + value: ``, + inline: true, + }, + { + name: decorate("`⌚`", "Time"), + value: ``, + inline: true, + }, + { + name: decorate("`❓`", "Status"), + value: type + .replace("error", "Failed") + .replace("success", "Successful"), + inline: true, + }, + ...(type === "error" && errorMessage + ? [ + { + name: decorate("`⚠️`", "Error Message"), + value: `\`\`\`${errorMessage}\`\`\``, + }, + ] + : []), + ], + timestamp: date.toISOString(), + footer: { + text: "Dokploy Instance Backup Notification", + }, + }); + } + + if (gotify) { + const decorate = (decoration: string, text: string) => + `${gotify.decoration ? decoration : ""} ${text}\n`; + + await sendGotifyNotification( + gotify, + decorate( + type === "success" ? "✅" : "❌", + `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + ), + `${decorate("📦", "Backup Type: Complete Dokploy Instance")}` + + `${backupSize ? decorate("💾", `Backup Size: ${backupSize}`) : ""}` + + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + + `${type === "error" && errorMessage ? decorate("❌", `Error:\n${errorMessage}`) : ""}`, + ); + } + + if (ntfy) { + await sendNtfyNotification( + ntfy, + `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + `${type === "success" ? "white_check_mark" : "x"}`, + "", + `📦Backup Type: Complete Dokploy Instance\n` + + `${backupSize ? `💾Backup Size: ${backupSize}\n` : ""}` + + `🕒Date: ${date.toLocaleString()}\n` + + `${type === "error" && errorMessage ? `❌Error:\n${errorMessage}` : ""}`, + ); + } + + if (telegram) { + const isError = type === "error" && errorMessage; + + const statusEmoji = type === "success" ? "✅" : "❌"; + const typeStatus = type === "success" ? "Successful" : "Failed"; + const errorMsg = isError + ? `\n\nError:\n
${errorMessage}
` + : ""; + const sizeInfo = backupSize ? `\nBackup Size: ${backupSize}` : ""; + + const messageText = `${statusEmoji} Dokploy Backup ${typeStatus}\n\nBackup Type: Complete Dokploy Instance${sizeInfo}\nDate: ${format(date, "PP")}\nTime: ${format(date, "pp")}${isError ? errorMsg : ""}`; + + await sendTelegramNotification(telegram, messageText); + } + + if (slack) { + const { channel } = slack; + await sendSlackNotification(slack, { + channel: channel, + attachments: [ + { + color: type === "success" ? "#00FF00" : "#FF0000", + pretext: + type === "success" + ? ":white_check_mark: *Dokploy Backup Successful*" + : ":x: *Dokploy Backup Failed*", + fields: [ + ...(type === "error" && errorMessage + ? [ + { + title: "Error Message", + value: errorMessage, + short: false, + }, + ] + : []), + { + title: "Backup Type", + value: "Complete Dokploy Instance", + short: true, + }, + ...(backupSize + ? [ + { + title: "Backup Size", + value: backupSize, + short: true, + }, + ] + : []), + { + title: "Time", + value: date.toLocaleString(), + short: true, + }, + { + title: "Status", + value: type === "success" ? "Successful" : "Failed", + short: true, + }, + ], + }, + ], + }); + } + + if (lark) { + const limitCharacter = 800; + const truncatedErrorMessage = + errorMessage && errorMessage.length > limitCharacter + ? errorMessage.substring(0, limitCharacter) + : errorMessage; + + await sendLarkNotification(lark, { + msg_type: "interactive", + card: { + schema: "2.0", + config: { + update_multi: true, + style: { + text_size: { + normal_v2: { + default: "normal", + pc: "normal", + mobile: "heading", + }, + }, + }, + }, + header: { + title: { + tag: "plain_text", + content: + type === "success" + ? "✅ Dokploy Backup Successful" + : "❌ Dokploy Backup Failed", + }, + subtitle: { + tag: "plain_text", + content: "", + }, + template: type === "success" ? "green" : "red", + padding: "12px 12px 12px 12px", + }, + body: { + direction: "vertical", + padding: "12px 12px 12px 12px", + elements: [ + { + tag: "column_set", + columns: [ + { + tag: "column", + width: "weighted", + elements: [ + { + tag: "markdown", + content: `**Backup Type:**\nComplete Dokploy Instance`, + text_align: "left", + text_size: "normal_v2", + }, + { + tag: "markdown", + content: `**Status:**\n${type === "success" ? "Successful" : "Failed"}`, + text_align: "left", + text_size: "normal_v2", + }, + ], + vertical_align: "top", + weight: 1, + }, + { + tag: "column", + width: "weighted", + elements: [ + ...(backupSize + ? [ + { + tag: "markdown", + content: `**Backup Size:**\n${backupSize}`, + text_align: "left", + text_size: "normal_v2", + }, + ] + : []), + { + tag: "markdown", + content: `**Date:**\n${format(date, "PP pp")}`, + text_align: "left", + text_size: "normal_v2", + }, + ], + vertical_align: "top", + weight: 1, + }, + ], + }, + ...(type === "error" && truncatedErrorMessage + ? [ + { + tag: "markdown", + content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``, + text_align: "left", + text_size: "normal_v2", + }, + ] + : []), + ], + }, + }, + }); + } + } +}; \ No newline at end of file From e575e5097965c2bf4432fb38cc0212823ffa9f21 Mon Sep 17 00:00:00 2001 From: faytranevozter Date: Tue, 16 Dec 2025 20:14:31 +0700 Subject: [PATCH 02/25] feat(certificates): enhance certificate handling with common name extraction and chain details --- .../certificates/show-certificates.tsx | 93 +++++++- .../dashboard/settings/certificates/utils.ts | 222 +++++++++++++++++- 2 files changed, 307 insertions(+), 8 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx b/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx index 8356d89c6..da634c873 100644 --- a/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx +++ b/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx @@ -1,4 +1,13 @@ -import { AlertCircle, Link, Loader2, ShieldCheck, Trash2 } from "lucide-react"; +import { + AlertCircle, + ChevronDown, + ChevronRight, + Link, + Loader2, + ShieldCheck, + Trash2, +} from "lucide-react"; +import { useState } from "react"; import { toast } from "sonner"; import { AlertBlock } from "@/components/shared/alert-block"; import { DialogAction } from "@/components/shared/dialog-action"; @@ -12,12 +21,18 @@ import { } from "@/components/ui/card"; import { api } from "@/utils/api"; import { AddCertificate } from "./add-certificate"; -import { getCertificateChainInfo, getExpirationStatus } from "./utils"; +import { + extractLeafCommonName, + getCertificateChainExpirationDetails, + getCertificateChainInfo, + getExpirationStatus, +} from "./utils"; export const ShowCertificates = () => { const { mutateAsync, isLoading: isRemoving } = api.certificates.remove.useMutation(); const { data, isLoading, refetch } = api.certificates.all.useQuery(); + const [expandedChains, setExpandedChains] = useState>(new Set()); return (
@@ -65,6 +80,30 @@ export const ShowCertificates = () => { const chainInfo = getCertificateChainInfo( certificate.certificateData, ); + const commonName = extractLeafCommonName( + certificate.certificateData, + ); + const chainDetails = chainInfo.isChain + ? getCertificateChainExpirationDetails( + certificate.certificateData, + ) + : null; + const isExpanded = expandedChains.has( + certificate.certificateId, + ); + + const toggleChain = () => { + setExpandedChains((prev) => { + const next = new Set(prev); + if (next.has(certificate.certificateId)) { + next.delete(certificate.certificateId); + } else { + next.add(certificate.certificateId); + } + return next; + }); + }; + return (
{ {index + 1}. {certificate.name} + {commonName && ( + + CN: {commonName} + + )} {chainInfo.isChain && ( -
- - - Chain ({chainInfo.count}) - +
+ + {isExpanded && ( +
+ {chainDetails?.map((cert) => ( +
+ + {cert.label} + + {cert.commonName && ( + + CN: {cert.commonName} + + )} + + {cert.message} + +
+ ))} +
+ )}
)}
{ + const certRegex = + /(-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----)/g; + const matches = certData.match(certRegex); + return matches || []; +}; + export const extractExpirationDate = (certData: string): Date | null => { try { // Decode PEM base64 to DER binary @@ -94,8 +102,156 @@ export const extractExpirationDate = (certData: string): Date | null => { } }; +export const extractCommonName = (certData: string): string | null => { + try { + // Decode PEM base64 to DER binary + const b64 = certData.replace(/-----[^-]+-----/g, "").replace(/\s+/g, ""); + const binStr = atob(b64); + const der = new Uint8Array(binStr.length); + for (let i = 0; i < binStr.length; i++) { + der[i] = binStr.charCodeAt(i); + } + + let offset = 0; + + // Helper: read ASN.1 length field + function readLength(pos: number): { length: number; offset: number } { + // biome-ignore lint/style/noParameterAssign: + let len = der[pos++]; + if (len & 0x80) { + const bytes = len & 0x7f; + len = 0; + for (let i = 0; i < bytes; i++) { + // biome-ignore lint/style/noParameterAssign: + len = (len << 8) + der[pos++]; + } + } + return { length: len, offset: pos }; + } + + // Helper: skip a field + function skipField(pos: number): number { + // biome-ignore lint/style/noParameterAssign: + pos++; + const fieldLen = readLength(pos); + return fieldLen.offset + fieldLen.length; + } + + // Skip the outer certificate sequence + if (der[offset++] !== 0x30) throw new Error("Expected sequence"); + ({ offset } = readLength(offset)); + + // Skip tbsCertificate sequence + if (der[offset++] !== 0x30) throw new Error("Expected tbsCertificate"); + ({ offset } = readLength(offset)); + + // Check for optional version field (context-specific tag [0]) + if (der[offset] === 0xa0) { + offset++; + const versionLen = readLength(offset); + offset = versionLen.offset + versionLen.length; + } + + // Skip serialNumber + offset = skipField(offset); + + // Skip signature + offset = skipField(offset); + + // Skip issuer + offset = skipField(offset); + + // Skip validity + offset = skipField(offset); + + // Subject sequence - where we find the CN + if (der[offset++] !== 0x30) throw new Error("Expected subject sequence"); + const subjectLen = readLength(offset); + const subjectEnd = subjectLen.offset + subjectLen.length; + offset = subjectLen.offset; + + // Parse subject RDNs looking for CN (OID 2.5.4.3) + while (offset < subjectEnd) { + if (der[offset++] !== 0x31) continue; // SET + const setLen = readLength(offset); + offset = setLen.offset; + + if (der[offset++] !== 0x30) continue; // SEQUENCE + const seqLen = readLength(offset); + offset = seqLen.offset; + + if (der[offset++] !== 0x06) continue; // OID + const oidLen = readLength(offset); + offset = oidLen.offset; + + // Check if OID is 2.5.4.3 (commonName) + const oid = Array.from(der.slice(offset, offset + oidLen.length)); + offset += oidLen.length; + + // OID 2.5.4.3 in DER: [0x55, 0x04, 0x03] + if ( + oid.length === 3 && + oid[0] === 0x55 && + oid[1] === 0x04 && + oid[2] === 0x03 + ) { + // Next should be the string value + const strType = der[offset++]; + const strLen = readLength(offset); + const cnBytes = der.slice(strLen.offset, strLen.offset + strLen.length); + return new TextDecoder().decode(cnBytes); + } + } + + return null; + } catch (error) { + console.error("Error parsing certificate CN:", error); + return null; + } +}; + +// Extract the Common Name from the first (leaf) certificate in a chain +export const extractLeafCommonName = (certData: string): string | null => { + const certs = splitCertificateChain(certData); + if (certs.length === 0) return null; + return extractCommonName(certs[0]); +}; + +// Extract expiration dates from all certificates in a chain +export const extractAllExpirationDates = ( + certData: string, +): Array<{ + cert: string; + index: number; + expirationDate: Date | null; + commonName: string | null; +}> => { + const certs = splitCertificateChain(certData); + return certs.map((cert, index) => ({ + cert, + index, + expirationDate: extractExpirationDate(cert), + commonName: extractCommonName(cert), + })); +}; + +// Get the earliest expiration date from a certificate chain +export const getEarliestExpirationDate = (certData: string): Date | null => { + const expirationDates = extractAllExpirationDates(certData); + const validDates = expirationDates + .filter((item) => item.expirationDate !== null) + .map((item) => item.expirationDate as Date); + + if (validDates.length === 0) return null; + + return new Date(Math.min(...validDates.map((date) => date.getTime()))); +}; + export const getExpirationStatus = (certData: string) => { - const expirationDate = extractExpirationDate(certData); + const chainInfo = getCertificateChainInfo(certData); + const expirationDate = chainInfo.isChain + ? getEarliestExpirationDate(certData) + : extractExpirationDate(certData); if (!expirationDate) return { @@ -153,3 +309,67 @@ export const getCertificateChainInfo = (certData: string) => { count: 1, }; }; + +// Get detailed expiration information for all certificates in a chain +export const getCertificateChainExpirationDetails = (certData: string) => { + const allExpirations = extractAllExpirationDates(certData); + const now = new Date(); + + return allExpirations.map(({ index, expirationDate, commonName }) => { + if (!expirationDate) { + return { + index, + label: `Certificate ${index + 1}`, + commonName, + status: "unknown" as const, + className: "text-muted-foreground", + message: "Could not determine expiration", + expirationDate: null, + }; + } + + const daysUntilExpiration = Math.ceil( + (expirationDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24), + ); + + let status: "expired" | "warning" | "valid"; + let className: string; + let message: string; + + if (daysUntilExpiration < 0) { + status = "expired"; + className = "text-red-500"; + message = `Expired on ${expirationDate.toLocaleDateString([], { + year: "numeric", + month: "long", + day: "numeric", + })}`; + } else if (daysUntilExpiration <= 30) { + status = "warning"; + className = "text-yellow-500"; + message = `Expires in ${daysUntilExpiration} days`; + } else { + status = "valid"; + className = "text-muted-foreground"; + message = `Expires ${expirationDate.toLocaleDateString([], { + year: "numeric", + month: "long", + day: "numeric", + })}`; + } + + return { + index, + label: + index === 0 + ? `Certificate ${index + 1} (Leaf)` + : `Certificate ${index + 1}`, + commonName, + status, + className, + message, + expirationDate, + daysUntilExpiration, + }; + }); +}; From 8ee374dc6be30d8bb3391ce1ec6d28ed4b356f8a Mon Sep 17 00:00:00 2001 From: impcyber Date: Wed, 25 Mar 2026 00:16:44 +0300 Subject: [PATCH 03/25] Update gitea.ts https://github.com/Dokploy/dokploy/issues/4066 --- packages/server/src/utils/providers/gitea.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utils/providers/gitea.ts b/packages/server/src/utils/providers/gitea.ts index 46dc5381b..20c86a589 100644 --- a/packages/server/src/utils/providers/gitea.ts +++ b/packages/server/src/utils/providers/gitea.ts @@ -170,7 +170,7 @@ export const cloneGiteaRepository = async ({ const repoClone = `${giteaOwner}/${giteaRepository}.git`; const cloneUrl = buildGiteaCloneUrl( - giteaProvider.giteaUrl, + giteaProvider.giteaInternalUrl || giteaProvider.giteaUrl, giteaProvider.accessToken!, giteaOwner!, giteaRepository!, From 815b8136fa0f8e803c43e66ed0002952515d54c3 Mon Sep 17 00:00:00 2001 From: Tam Nguyen Date: Mon, 30 Mar 2026 08:59:14 +1100 Subject: [PATCH 04/25] fix: further typos --- .../compose/network/network-root.test.ts | 2 +- .../compose/network/network-service.test.ts | 212 +++--- ...m.test.ts => service-volumes-from.test.ts} | 0 .../__test__/env/stack-environment.test.ts | 198 ++--- .../advanced/redirects/handle-redirect.tsx | 2 +- ...ow-enviroment.tsx => show-environment.tsx} | 0 .../dashboard/application/logs/show.tsx | 4 +- .../dashboard/compose/logs/show-stack.tsx | 4 +- .../database/backups/restore-backup.tsx | 6 +- .../dashboard/docker/logs/terminal-line.tsx | 2 +- .../docker/show/{colums.tsx => columns.tsx} | 0 .../dashboard/docker/show/show-containers.tsx | 2 +- .../settings/servers/setup-server.tsx | 2 +- .../settings/servers/show-servers.tsx | 4 +- ...scription.tsx => welcome-subscription.tsx} | 2 +- apps/dokploy/components/ui/file-tree.tsx | 12 +- .../pages/api/deploy/[refreshToken].ts | 12 +- .../api/deploy/compose/[refreshToken].ts | 6 +- apps/dokploy/pages/api/stripe/webhook.ts | 12 +- .../services/compose/[composeId].tsx | 2 +- .../services/libsql/[libsqlId].tsx | 2 +- .../services/mariadb/[mariadbId].tsx | 2 +- .../services/mongo/[mongoId].tsx | 2 +- .../services/mysql/[mysqlId].tsx | 2 +- .../services/postgres/[postgresId].tsx | 2 +- .../services/redis/[redisId].tsx | 2 +- .../dokploy/server/api/routers/destination.ts | 4 +- packages/server/src/index.ts | 2 +- packages/server/src/services/deployment.ts | 12 +- packages/server/src/services/destination.ts | 2 +- packages/server/src/services/settings.ts | 4 +- packages/server/src/services/user.ts | 678 +++++++++--------- packages/server/src/setup/setup.ts | 8 +- packages/server/src/utils/builders/compose.ts | 152 ++-- .../server/src/utils/builders/docker-file.ts | 134 ++-- packages/server/src/utils/docker/utils.ts | 2 +- ...l-deployments.ts => cancel-deployments.ts} | 0 37 files changed, 747 insertions(+), 747 deletions(-) rename apps/dokploy/__test__/compose/service/{sevice-volumes-from.test.ts => service-volumes-from.test.ts} (100%) rename apps/dokploy/components/dashboard/application/environment/{show-enviroment.tsx => show-environment.tsx} (100%) rename apps/dokploy/components/dashboard/docker/show/{colums.tsx => columns.tsx} (100%) rename apps/dokploy/components/dashboard/settings/servers/welcome-stripe/{welcome-suscription.tsx => welcome-subscription.tsx} (99%) rename packages/server/src/utils/startup/{cancell-deployments.ts => cancel-deployments.ts} (100%) diff --git a/apps/dokploy/__test__/compose/network/network-root.test.ts b/apps/dokploy/__test__/compose/network/network-root.test.ts index 0d3c841d4..1a6817913 100644 --- a/apps/dokploy/__test__/compose/network/network-root.test.ts +++ b/apps/dokploy/__test__/compose/network/network-root.test.ts @@ -292,7 +292,7 @@ networks: dokploy-network: `; -test("It shoudn't add suffix to dokploy-network", () => { +test("It shouldn't add suffix to dokploy-network", () => { const composeData = parse(composeFile7) as ComposeSpecification; const suffix = generateRandomHash(); diff --git a/apps/dokploy/__test__/compose/network/network-service.test.ts b/apps/dokploy/__test__/compose/network/network-service.test.ts index e07fa1546..91eb5da4e 100644 --- a/apps/dokploy/__test__/compose/network/network-service.test.ts +++ b/apps/dokploy/__test__/compose/network/network-service.test.ts @@ -1,7 +1,7 @@ import type { ComposeSpecification } from "@dokploy/server"; import { - addSuffixToServiceNetworks, - generateRandomHash, + addSuffixToServiceNetworks, + generateRandomHash, } from "@dokploy/server"; import { expect, test } from "vitest"; import { parse } from "yaml"; @@ -23,30 +23,30 @@ services: `; test("Add suffix to networks in services", () => { - const composeData = parse(composeFile) as ComposeSpecification; + const composeData = parse(composeFile) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData?.services?.web?.networks).toContain( - `frontend-${suffix}`, - ); + expect(actualComposeData?.services?.web?.networks).toContain( + `frontend-${suffix}`, + ); - expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${suffix}`, - ); + expect(actualComposeData?.services?.api?.networks).toContain( + `backend-${suffix}`, + ); - const apiNetworks = actualComposeData?.services?.api?.networks; + const apiNetworks = actualComposeData?.services?.api?.networks; - expect(apiNetworks).toBeDefined(); - expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${suffix}`, - ); + expect(apiNetworks).toBeDefined(); + expect(actualComposeData?.services?.api?.networks).toContain( + `backend-${suffix}`, + ); }); // Caso 2: Objeto con aliases @@ -67,29 +67,29 @@ networks: `; test("Add suffix to networks in services with aliases", () => { - const composeData = parse(composeFile2) as ComposeSpecification; + const composeData = parse(composeFile2) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData.services?.api?.networks).toHaveProperty( - `frontend-${suffix}`, - ); + expect(actualComposeData.services?.api?.networks).toHaveProperty( + `frontend-${suffix}`, + ); - const networkConfig = actualComposeData?.services?.api?.networks as { - [key: string]: { aliases?: string[] }; - }; - expect(networkConfig[`frontend-${suffix}`]).toBeDefined(); - expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api"); + const networkConfig = actualComposeData?.services?.api?.networks as { + [key: string]: { aliases?: string[] }; + }; + expect(networkConfig[`frontend-${suffix}`]).toBeDefined(); + expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api"); - expect(actualComposeData.services?.api?.networks).not.toHaveProperty( - "frontend-ash", - ); + expect(actualComposeData.services?.api?.networks).not.toHaveProperty( + "frontend-ash", + ); }); const composeFile3 = ` @@ -107,19 +107,19 @@ networks: `; test("Add suffix to networks in services (Object with simple networks)", () => { - const composeData = parse(composeFile3) as ComposeSpecification; + const composeData = parse(composeFile3) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData.services?.redis?.networks).toHaveProperty( - `backend-${suffix}`, - ); + expect(actualComposeData.services?.redis?.networks).toHaveProperty( + `backend-${suffix}`, + ); }); const composeFileCombined = ` @@ -153,36 +153,36 @@ networks: `; test("Add suffix to networks in services (combined case)", () => { - const composeData = parse(composeFileCombined) as ComposeSpecification; + const composeData = parse(composeFileCombined) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - // Caso 1: ListOfStrings - expect(actualComposeData.services?.web?.networks).toContain( - `frontend-${suffix}`, - ); - expect(actualComposeData.services?.web?.networks).toContain( - `backend-${suffix}`, - ); + // Caso 1: ListOfStrings + expect(actualComposeData.services?.web?.networks).toContain( + `frontend-${suffix}`, + ); + expect(actualComposeData.services?.web?.networks).toContain( + `backend-${suffix}`, + ); - // Caso 2: Objeto con aliases - const apiNetworks = actualComposeData.services?.api?.networks as { - [key: string]: unknown; - }; - expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); - expect(apiNetworks[`frontend-${suffix}`]).toBeDefined(); - expect(apiNetworks).not.toHaveProperty("frontend"); + // Caso 2: Objeto con aliases + const apiNetworks = actualComposeData.services?.api?.networks as { + [key: string]: unknown; + }; + expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); + expect(apiNetworks[`frontend-${suffix}`]).toBeDefined(); + expect(apiNetworks).not.toHaveProperty("frontend"); - // Caso 3: Objeto con redes simples - const redisNetworks = actualComposeData.services?.redis?.networks; - expect(redisNetworks).toHaveProperty(`backend-${suffix}`); - expect(redisNetworks).not.toHaveProperty("backend"); + // Caso 3: Objeto con redes simples + const redisNetworks = actualComposeData.services?.redis?.networks; + expect(redisNetworks).toHaveProperty(`backend-${suffix}`); + expect(redisNetworks).not.toHaveProperty("backend"); }); const composeFile7 = ` @@ -195,19 +195,19 @@ services: - dokploy-network `; -test("It shoudn't add suffix to dokploy-network in services", () => { - const composeData = parse(composeFile7) as ComposeSpecification; +test("It shouldn't add suffix to dokploy-network in services", () => { + const composeData = parse(composeFile7) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const networks = addSuffixToServiceNetworks(composeData.services, suffix); - const service = networks.web; + if (!composeData?.services) { + return; + } + const networks = addSuffixToServiceNetworks(composeData.services, suffix); + const service = networks.web; - expect(service).toBeDefined(); - expect(service?.networks).toContain("dokploy-network"); + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); }); const composeFile8 = ` @@ -241,35 +241,35 @@ services: dokploy-network: aliases: - apid - + `; -test("It shoudn't add suffix to dokploy-network in services multiples cases", () => { - const composeData = parse(composeFile8) as ComposeSpecification; +test("It shouldn't add suffix to dokploy-network in services multiples cases", () => { + const composeData = parse(composeFile8) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const networks = addSuffixToServiceNetworks(composeData.services, suffix); - const service = networks.web; - const api = networks.api; - const redis = networks.redis; - const db = networks.db; + if (!composeData?.services) { + return; + } + const networks = addSuffixToServiceNetworks(composeData.services, suffix); + const service = networks.web; + const api = networks.api; + const redis = networks.redis; + const db = networks.db; - const dbNetworks = db?.networks as { - [key: string]: unknown; - }; + const dbNetworks = db?.networks as { + [key: string]: unknown; + }; - const apiNetworks = api?.networks as { - [key: string]: unknown; - }; + const apiNetworks = api?.networks as { + [key: string]: unknown; + }; - expect(service).toBeDefined(); - expect(service?.networks).toContain("dokploy-network"); + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); - expect(redis?.networks).toHaveProperty("dokploy-network"); - expect(dbNetworks["dokploy-network"]).toBeDefined(); - expect(apiNetworks["dokploy-network"]).toBeDefined(); + expect(redis?.networks).toHaveProperty("dokploy-network"); + expect(dbNetworks["dokploy-network"]).toBeDefined(); + expect(apiNetworks["dokploy-network"]).toBeDefined(); }); diff --git a/apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts b/apps/dokploy/__test__/compose/service/service-volumes-from.test.ts similarity index 100% rename from apps/dokploy/__test__/compose/service/sevice-volumes-from.test.ts rename to apps/dokploy/__test__/compose/service/service-volumes-from.test.ts diff --git a/apps/dokploy/__test__/env/stack-environment.test.ts b/apps/dokploy/__test__/env/stack-environment.test.ts index 13f5adb53..cde7be9db 100644 --- a/apps/dokploy/__test__/env/stack-environment.test.ts +++ b/apps/dokploy/__test__/env/stack-environment.test.ts @@ -1,4 +1,4 @@ -import { getEnviromentVariablesObject } from "@dokploy/server/index"; +import { getEnvironmentVariablesObject } from "@dokploy/server/index"; import { describe, expect, it } from "vitest"; const projectEnv = ` @@ -15,29 +15,29 @@ DATABASE_NAME=dev_database SECRET_KEY=env-secret-123 `; -describe("getEnviromentVariablesObject with environment variables (Stack compose)", () => { - it("resolves environment variables correctly for Stack compose", () => { - const serviceEnv = ` +describe("getEnvironmentVariablesObject with environment variables (Stack compose)", () => { + it("resolves environment variables correctly for Stack compose", () => { + const serviceEnv = ` FOO=\${{environment.NODE_ENV}} BAR=\${{environment.API_URL}} BAZ=test `; - const result = getEnviromentVariablesObject( - serviceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - FOO: "development", - BAR: "https://api.dev.example.com", - BAZ: "test", - }); - }); + expect(result).toEqual({ + FOO: "development", + BAR: "https://api.dev.example.com", + BAZ: "test", + }); + }); - it("resolves both project and environment variables for Stack compose", () => { - const serviceEnv = ` + it("resolves both project and environment variables for Stack compose", () => { + const serviceEnv = ` ENVIRONMENT=\${{project.ENVIRONMENT}} NODE_ENV=\${{environment.NODE_ENV}} API_URL=\${{environment.API_URL}} @@ -45,140 +45,140 @@ DATABASE_URL=\${{project.DATABASE_URL}} SERVICE_PORT=4000 `; - const result = getEnviromentVariablesObject( - serviceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - ENVIRONMENT: "staging", - NODE_ENV: "development", - API_URL: "https://api.dev.example.com", - DATABASE_URL: "postgres://postgres:postgres@localhost:5432/project_db", - SERVICE_PORT: "4000", - }); - }); + expect(result).toEqual({ + ENVIRONMENT: "staging", + NODE_ENV: "development", + API_URL: "https://api.dev.example.com", + DATABASE_URL: "postgres://postgres:postgres@localhost:5432/project_db", + SERVICE_PORT: "4000", + }); + }); - it("handles multiple environment references in single value for Stack compose", () => { - const multiRefEnv = ` + it("handles multiple environment references in single value for Stack compose", () => { + const multiRefEnv = ` HOST=localhost PORT=5432 USERNAME=postgres PASSWORD=secret123 `; - const serviceEnv = ` + const serviceEnv = ` DATABASE_URL=postgresql://\${{environment.USERNAME}}:\${{environment.PASSWORD}}@\${{environment.HOST}}:\${{environment.PORT}}/mydb `; - const result = getEnviromentVariablesObject(serviceEnv, "", multiRefEnv); + const result = getEnvironmentVariablesObject(serviceEnv, "", multiRefEnv); - expect(result).toEqual({ - DATABASE_URL: "postgresql://postgres:secret123@localhost:5432/mydb", - }); - }); + expect(result).toEqual({ + DATABASE_URL: "postgresql://postgres:secret123@localhost:5432/mydb", + }); + }); - it("throws error for undefined environment variables in Stack compose", () => { - const serviceWithUndefined = ` + it("throws error for undefined environment variables in Stack compose", () => { + const serviceWithUndefined = ` UNDEFINED_VAR=\${{environment.UNDEFINED_VAR}} `; - expect(() => - getEnviromentVariablesObject(serviceWithUndefined, "", environmentEnv), - ).toThrow("Invalid environment variable: environment.UNDEFINED_VAR"); - }); + expect(() => + getEnvironmentVariablesObject(serviceWithUndefined, "", environmentEnv), + ).toThrow("Invalid environment variable: environment.UNDEFINED_VAR"); + }); - it("allows service variables to override environment variables in Stack compose", () => { - const serviceOverrideEnv = ` + it("allows service variables to override environment variables in Stack compose", () => { + const serviceOverrideEnv = ` NODE_ENV=production API_URL=\${{environment.API_URL}} `; - const result = getEnviromentVariablesObject( - serviceOverrideEnv, - "", - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceOverrideEnv, + "", + environmentEnv, + ); - expect(result).toEqual({ - NODE_ENV: "production", - API_URL: "https://api.dev.example.com", - }); - }); + expect(result).toEqual({ + NODE_ENV: "production", + API_URL: "https://api.dev.example.com", + }); + }); - it("resolves complex references with project, environment, and service variables for Stack compose", () => { - const complexServiceEnv = ` + it("resolves complex references with project, environment, and service variables for Stack compose", () => { + const complexServiceEnv = ` FULL_DATABASE_URL=\${{project.DATABASE_URL}}/\${{environment.DATABASE_NAME}} API_ENDPOINT=\${{environment.API_URL}}/\${{project.ENVIRONMENT}}/api SERVICE_NAME=my-service COMPLEX_VAR=\${{SERVICE_NAME}}-\${{environment.NODE_ENV}}-\${{project.ENVIRONMENT}} `; - const result = getEnviromentVariablesObject( - complexServiceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + complexServiceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - FULL_DATABASE_URL: - "postgres://postgres:postgres@localhost:5432/project_db/dev_database", - API_ENDPOINT: "https://api.dev.example.com/staging/api", - SERVICE_NAME: "my-service", - COMPLEX_VAR: "my-service-development-staging", - }); - }); + expect(result).toEqual({ + FULL_DATABASE_URL: + "postgres://postgres:postgres@localhost:5432/project_db/dev_database", + API_ENDPOINT: "https://api.dev.example.com/staging/api", + SERVICE_NAME: "my-service", + COMPLEX_VAR: "my-service-development-staging", + }); + }); - it("maintains precedence: service > environment > project in Stack compose", () => { - const conflictingProjectEnv = ` + it("maintains precedence: service > environment > project in Stack compose", () => { + const conflictingProjectEnv = ` NODE_ENV=production-project API_URL=https://project.api.com DATABASE_NAME=project_db `; - const conflictingEnvironmentEnv = ` + const conflictingEnvironmentEnv = ` NODE_ENV=development-environment API_URL=https://environment.api.com DATABASE_NAME=env_db `; - const serviceWithConflicts = ` + const serviceWithConflicts = ` NODE_ENV=service-override PROJECT_ENV=\${{project.NODE_ENV}} ENV_VAR=\${{environment.API_URL}} DB_NAME=\${{environment.DATABASE_NAME}} `; - const result = getEnviromentVariablesObject( - serviceWithConflicts, - conflictingProjectEnv, - conflictingEnvironmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceWithConflicts, + conflictingProjectEnv, + conflictingEnvironmentEnv, + ); - expect(result).toEqual({ - NODE_ENV: "service-override", - PROJECT_ENV: "production-project", - ENV_VAR: "https://environment.api.com", - DB_NAME: "env_db", - }); - }); + expect(result).toEqual({ + NODE_ENV: "service-override", + PROJECT_ENV: "production-project", + ENV_VAR: "https://environment.api.com", + DB_NAME: "env_db", + }); + }); - it("handles empty environment variables in Stack compose", () => { - const serviceWithEmpty = ` + it("handles empty environment variables in Stack compose", () => { + const serviceWithEmpty = ` SERVICE_VAR=test PROJECT_VAR=\${{project.ENVIRONMENT}} `; - const result = getEnviromentVariablesObject( - serviceWithEmpty, - projectEnv, - "", - ); + const result = getEnvironmentVariablesObject( + serviceWithEmpty, + projectEnv, + "", + ); - expect(result).toEqual({ - SERVICE_VAR: "test", - PROJECT_VAR: "staging", - }); - }); + expect(result).toEqual({ + SERVICE_VAR: "test", + PROJECT_VAR: "staging", + }); + }); }); diff --git a/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx b/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx index 172c042f1..603a6d6c8 100644 --- a/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx @@ -149,7 +149,7 @@ export const HandleRedirect = ({ const onDialogToggle = (open: boolean) => { setIsOpen(open); - // commented for the moment because not reseting the form if accidentally closed the dialog can be considered as a feature instead of a bug + // commented for the moment because not resetting the form if accidentally closed the dialog can be considered as a feature instead of a bug // setPresetSelected(""); // form.reset(); }; diff --git a/apps/dokploy/components/dashboard/application/environment/show-enviroment.tsx b/apps/dokploy/components/dashboard/application/environment/show-environment.tsx similarity index 100% rename from apps/dokploy/components/dashboard/application/environment/show-enviroment.tsx rename to apps/dokploy/components/dashboard/application/environment/show-environment.tsx diff --git a/apps/dokploy/components/dashboard/application/logs/show.tsx b/apps/dokploy/components/dashboard/application/logs/show.tsx index cbb6bce09..06b257766 100644 --- a/apps/dokploy/components/dashboard/application/logs/show.tsx +++ b/apps/dokploy/components/dashboard/application/logs/show.tsx @@ -91,7 +91,7 @@ export const ShowDockerLogs = ({ appName, serverId }: Props) => { }, [option, services, containers]); const isLoading = option === "native" ? containersLoading : servicesLoading; - const containersLenght = + const containersLength = option === "native" ? containers?.length : services?.length; return ( @@ -167,7 +167,7 @@ export const ShowDockerLogs = ({ appName, serverId }: Props) => { )} - Containers ({containersLenght}) + Containers ({containersLength}) diff --git a/apps/dokploy/components/dashboard/compose/logs/show-stack.tsx b/apps/dokploy/components/dashboard/compose/logs/show-stack.tsx index 159ab3485..4c3067b15 100644 --- a/apps/dokploy/components/dashboard/compose/logs/show-stack.tsx +++ b/apps/dokploy/components/dashboard/compose/logs/show-stack.tsx @@ -77,7 +77,7 @@ export const ShowDockerLogsStack = ({ appName, serverId }: Props) => { }, [option, services, containers]); const isLoading = option === "native" ? containersLoading : servicesLoading; - const containersLenght = + const containersLength = option === "native" ? containers?.length : services?.length; return ( @@ -152,7 +152,7 @@ export const ShowDockerLogsStack = ({ appName, serverId }: Props) => { )} - Containers ({containersLenght}) + Containers ({containersLength}) diff --git a/apps/dokploy/components/dashboard/database/backups/restore-backup.tsx b/apps/dokploy/components/dashboard/database/backups/restore-backup.tsx index 00647aea7..7b212acb9 100644 --- a/apps/dokploy/components/dashboard/database/backups/restore-backup.tsx +++ b/apps/dokploy/components/dashboard/database/backups/restore-backup.tsx @@ -225,7 +225,7 @@ export const RestoreBackup = ({ resolver: zodResolver(RestoreBackupSchema), }); - const destionationId = form.watch("destinationId"); + const destinationId = form.watch("destinationId"); const currentDatabaseType = form.watch("databaseType"); const metadata = form.watch("metadata"); @@ -240,12 +240,12 @@ export const RestoreBackup = ({ const { data: files = [], isPending } = api.backup.listBackupFiles.useQuery( { - destinationId: destionationId, + destinationId: destinationId, search: debouncedSearchTerm, serverId: serverId ?? "", }, { - enabled: isOpen && !!destionationId, + enabled: isOpen && !!destinationId, }, ); diff --git a/apps/dokploy/components/dashboard/docker/logs/terminal-line.tsx b/apps/dokploy/components/dashboard/docker/logs/terminal-line.tsx index 9d4f47c4a..bed5c6f5d 100644 --- a/apps/dokploy/components/dashboard/docker/logs/terminal-line.tsx +++ b/apps/dokploy/components/dashboard/docker/logs/terminal-line.tsx @@ -103,7 +103,7 @@ export function TerminalLine({ log, noTimestamp, searchTerm }: LogLineProps) { > {" "}
- {/* Icon to expand the log item maybe implement a colapsible later */} + {/* Icon to expand the log item maybe implement a collapsible later */} {/* */} {tooltip(color, rawTimestamp)} {!noTimestamp && ( diff --git a/apps/dokploy/components/dashboard/docker/show/colums.tsx b/apps/dokploy/components/dashboard/docker/show/columns.tsx similarity index 100% rename from apps/dokploy/components/dashboard/docker/show/colums.tsx rename to apps/dokploy/components/dashboard/docker/show/columns.tsx diff --git a/apps/dokploy/components/dashboard/docker/show/show-containers.tsx b/apps/dokploy/components/dashboard/docker/show/show-containers.tsx index 69b0a0da2..8a19566e8 100644 --- a/apps/dokploy/components/dashboard/docker/show/show-containers.tsx +++ b/apps/dokploy/components/dashboard/docker/show/show-containers.tsx @@ -35,7 +35,7 @@ import { TableRow, } from "@/components/ui/table"; import { api, type RouterOutputs } from "@/utils/api"; -import { columns } from "./colums"; +import { columns } from "./columns"; export type Container = NonNullable< RouterOutputs["docker"]["getContainers"] >[0]; diff --git a/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx b/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx index 0d4d3a44f..570955fc8 100644 --- a/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/setup-server.tsx @@ -161,7 +161,7 @@ export const SetupServer = ({ serverId, asButton = false }: Props) => {
  • 1. Add the public SSH Key when you create a server in your - preffered provider (Hostinger, Digital Ocean, Hetzner, + preferred provider (Hostinger, Digital Ocean, Hetzner, etc){" "}
  • 2. Add The SSH Key to Server Manually
  • diff --git a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx index 859098394..7342aafb4 100644 --- a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx @@ -48,7 +48,7 @@ import { ShowMonitoringModal } from "./show-monitoring-modal"; import { ShowSchedulesModal } from "./show-schedules-modal"; import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal"; import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal"; -import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription"; +import { Welcomesubscription } from "./welcome-stripe/welcome-subscription"; export const ShowServers = () => { const router = useRouter(); @@ -63,7 +63,7 @@ export const ShowServers = () => { return (
    - {query?.success && isCloud && } + {query?.success && isCloud && }
    diff --git a/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-suscription.tsx b/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx similarity index 99% rename from apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-suscription.tsx rename to apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx index 004f79f74..295b53516 100644 --- a/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-suscription.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx @@ -51,7 +51,7 @@ export const { useStepper, steps, Scoped } = defineStepper( { id: "complete", title: "Complete", description: "Checkout complete" }, ); -export const WelcomeSuscription = () => { +export const Welcomesubscription = () => { const [showConfetti, setShowConfetti] = useState(false); const stepper = useStepper(); const [isOpen, setIsOpen] = useState(true); diff --git a/apps/dokploy/components/ui/file-tree.tsx b/apps/dokploy/components/ui/file-tree.tsx index e346bf4a6..c1d5dc335 100644 --- a/apps/dokploy/components/ui/file-tree.tsx +++ b/apps/dokploy/components/ui/file-tree.tsx @@ -19,7 +19,7 @@ interface TreeDataItem { type TreeProps = React.HTMLAttributes & { data: TreeDataItem[] | TreeDataItem; - initialSlelectedItemId?: string; + initialSelectedItemId?: string; onSelectChange?: (item: TreeDataItem | undefined) => void; expandAll?: boolean; folderIcon?: LucideIcon; @@ -30,7 +30,7 @@ const Tree = React.forwardRef( ( { data, - initialSlelectedItemId, + initialSelectedItemId, onSelectChange, expandAll, folderIcon, @@ -42,7 +42,7 @@ const Tree = React.forwardRef( ) => { const [selectedItemId, setSelectedItemId] = React.useState< string | undefined - >(initialSlelectedItemId); + >(initialSelectedItemId); const handleSelectChange = React.useCallback( (item: TreeDataItem | undefined) => { @@ -55,7 +55,7 @@ const Tree = React.forwardRef( ); const expandedItemIds = React.useMemo(() => { - if (!initialSlelectedItemId) { + if (!initialSelectedItemId) { return [] as string[]; } @@ -81,9 +81,9 @@ const Tree = React.forwardRef( } } - walkTreeItems(data, initialSlelectedItemId); + walkTreeItems(data, initialSelectedItemId); return ids; - }, [data, initialSlelectedItemId]); + }, [data, initialSelectedItemId]); const { ref: refRoot } = useResizeObserver(); diff --git a/apps/dokploy/pages/api/deploy/[refreshToken].ts b/apps/dokploy/pages/api/deploy/[refreshToken].ts index 14b45f3d7..1c57731a7 100644 --- a/apps/dokploy/pages/api/deploy/[refreshToken].ts +++ b/apps/dokploy/pages/api/deploy/[refreshToken].ts @@ -196,7 +196,7 @@ export default async function handler( return; } - const commitedPaths = await extractCommitedPaths( + const committedPaths = await extractCommittedPaths( req.body, application.bitbucket, application.bitbucketRepositorySlug || @@ -206,7 +206,7 @@ export default async function handler( const shouldDeployPaths = shouldDeploy( application.watchPaths, - commitedPaths, + committedPaths, ); if (!shouldDeployPaths) { @@ -538,7 +538,7 @@ export const getProviderByHeader = (headers: any) => { return null; }; -export const extractCommitedPaths = async ( +export const extractCommittedPaths = async ( body: any, bitbucket: Bitbucket | null, repository: string, @@ -548,7 +548,7 @@ export const extractCommitedPaths = async ( const commitHashes = changes .map((change: any) => change.new?.target?.hash) .filter(Boolean); - const commitedPaths: string[] = []; + const committedPaths: string[] = []; const username = bitbucket?.bitbucketWorkspaceName || bitbucket?.bitbucketUsername || ""; for (const commit of commitHashes) { @@ -559,7 +559,7 @@ export const extractCommitedPaths = async ( }); const data = await response.json(); for (const value of data.values) { - if (value?.new?.path) commitedPaths.push(value.new.path); + if (value?.new?.path) committedPaths.push(value.new.path); } } catch (error) { console.error( @@ -571,5 +571,5 @@ export const extractCommitedPaths = async ( } } - return commitedPaths; + return committedPaths; }; diff --git a/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts b/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts index da3082bb7..c998e83b9 100644 --- a/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts +++ b/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts @@ -8,7 +8,7 @@ import { myQueue } from "@/server/queues/queueSetup"; import { deploy } from "@/server/utils/deploy"; import { extractBranchName, - extractCommitedPaths, + extractCommittedPaths, extractCommitMessage, extractHash, getProviderByHeader, @@ -97,7 +97,7 @@ export default async function handler( return; } - const commitedPaths = await extractCommitedPaths( + const committedPaths = await extractCommittedPaths( req.body, composeResult.bitbucket, composeResult.bitbucketRepositorySlug || @@ -107,7 +107,7 @@ export default async function handler( const shouldDeployPaths = shouldDeploy( composeResult.watchPaths, - commitedPaths, + committedPaths, ); if (!shouldDeployPaths) { diff --git a/apps/dokploy/pages/api/stripe/webhook.ts b/apps/dokploy/pages/api/stripe/webhook.ts index 60468bd2c..deaa5572c 100644 --- a/apps/dokploy/pages/api/stripe/webhook.ts +++ b/apps/dokploy/pages/api/stripe/webhook.ts @@ -174,27 +174,27 @@ export default async function handler( case "invoice.payment_succeeded": { const newInvoice = event.data.object as Stripe.Invoice; - const suscription = await stripe.subscriptions.retrieve( + const subscription = await stripe.subscriptions.retrieve( newInvoice.subscription as string, ); - if (suscription.status !== "active") { + if (subscription.status !== "active") { console.log( - `Skipping invoice.payment_succeeded for subscription ${suscription.id} with status ${suscription.status}`, + `Skipping invoice.payment_succeeded for subscription ${subscription.id} with status ${subscription.status}`, ); break; } const serversQuantity = getSubscriptionServersQuantity( - suscription?.items?.data ?? [], + subscription?.items?.data ?? [], ); await db .update(user) .set({ serversQuantity }) - .where(eq(user.stripeCustomerId, suscription.customer as string)); + .where(eq(user.stripeCustomerId, subscription.customer as string)); const admin = await findUserByStripeCustomerId( - suscription.customer as string, + subscription.customer as string, ); if (!admin) { diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx index 078bf5b6b..781dd7795 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/compose/[composeId].tsx @@ -16,7 +16,7 @@ import { ShowImport } from "@/components/dashboard/application/advanced/import/s import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes"; import { ShowDeployments } from "@/components/dashboard/application/deployments/show-deployments"; import { ShowDomains } from "@/components/dashboard/application/domains/show-domains"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowPatches } from "@/components/dashboard/application/patches/show-patches"; import { ShowSchedules } from "@/components/dashboard/application/schedules/show-schedules"; import { ShowVolumeBackups } from "@/components/dashboard/application/volume-backups/show-volume-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/libsql/[libsqlId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/libsql/[libsqlId].tsx index 6abb53c2b..c9563ebe6 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/libsql/[libsqlId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/libsql/[libsqlId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ShowBackups } from "@/components/dashboard/database/backups/show-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx index 3e3a7d7de..b54804279 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mariadb/[mariadbId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ShowBackups } from "@/components/dashboard/database/backups/show-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx index ea6483499..402718625 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mongo/[mongoId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ShowBackups } from "@/components/dashboard/database/backups/show-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx index ff45c0694..55e1ee6e0 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/mysql/[mysqlId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ShowBackups } from "@/components/dashboard/database/backups/show-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx index 15e91a0bd..f73ce35cb 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/postgres/[postgresId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ShowBackups } from "@/components/dashboard/database/backups/show-backups"; diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx index 05a9e0c91..8847ed891 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId]/environment/[environmentId]/services/redis/[redisId].tsx @@ -10,7 +10,7 @@ import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import superjson from "superjson"; -import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment"; +import { ShowEnvironment } from "@/components/dashboard/application/environment/show-environment"; import { ShowDockerLogs } from "@/components/dashboard/application/logs/show"; import { DeleteService } from "@/components/dashboard/compose/delete-service"; import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring"; diff --git a/apps/dokploy/server/api/routers/destination.ts b/apps/dokploy/server/api/routers/destination.ts index 9f528c16c..cf7395a3f 100644 --- a/apps/dokploy/server/api/routers/destination.ts +++ b/apps/dokploy/server/api/routers/destination.ts @@ -1,5 +1,5 @@ import { - createDestintation, + createDestination, execAsync, execAsyncRemote, findDestinationById, @@ -25,7 +25,7 @@ export const destinationRouter = createTRPCRouter({ .input(apiCreateDestination) .mutation(async ({ input, ctx }) => { try { - const result = await createDestintation( + const result = await createDestination( input, ctx.session.activeOrganizationId, ); diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 22e8872bd..e6fd0ba59 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -121,7 +121,7 @@ export * from "./utils/providers/raw"; export * from "./utils/schedules/index"; export * from "./utils/schedules/utils"; export * from "./utils/servers/remote-docker"; -export * from "./utils/startup/cancell-deployments"; +export * from "./utils/startup/cancel-deployments"; export * from "./utils/tracking/hubspot"; export * from "./utils/traefik/application"; export * from "./utils/traefik/domain"; diff --git a/packages/server/src/services/deployment.ts b/packages/server/src/services/deployment.ts index a9f059465..7b6f0c730 100644 --- a/packages/server/src/services/deployment.ts +++ b/packages/server/src/services/deployment.ts @@ -177,7 +177,7 @@ export const createDeployment = async ( status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) @@ -257,7 +257,7 @@ export const createDeploymentPreview = async ( status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) @@ -334,7 +334,7 @@ echo "Initializing deployment\n" >> ${logFilePath}; status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) @@ -418,7 +418,7 @@ echo "Initializing backup\n" >> ${logFilePath}; status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) @@ -493,7 +493,7 @@ export const createDeploymentSchedule = async ( status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) @@ -578,7 +578,7 @@ export const createDeploymentVolumeBackup = async ( status: "error", logPath: "", description: deployment.description || "", - errorMessage: `An error have occured: ${error instanceof Error ? error.message : error}`, + errorMessage: `An error have occurred: ${error instanceof Error ? error.message : error}`, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(), }) diff --git a/packages/server/src/services/destination.ts b/packages/server/src/services/destination.ts index fa48d0d15..9cbc9afa3 100644 --- a/packages/server/src/services/destination.ts +++ b/packages/server/src/services/destination.ts @@ -9,7 +9,7 @@ import type { z } from "zod"; export type Destination = typeof destinations.$inferSelect; -export const createDestintation = async ( +export const createDestination = async ( input: z.infer, organizationId: string, ) => { diff --git a/packages/server/src/services/settings.ts b/packages/server/src/services/settings.ts index 07aaf690c..ecfb7f6de 100644 --- a/packages/server/src/services/settings.ts +++ b/packages/server/src/services/settings.ts @@ -383,12 +383,12 @@ export const readPorts = async ( const seenPorts = new Set(); for (const key in parsedResult) { if (Object.hasOwn(parsedResult, key)) { - const containerPortMapppings = parsedResult[key]; + const containerPortMappings = parsedResult[key]; const protocol = key.split("/")[1]; const targetPort = Number.parseInt(key.split("/")[0] ?? "0", 10); // Take only the first mapping to avoid duplicates (IPv4 and IPv6) - const firstMapping = containerPortMapppings[0]; + const firstMapping = containerPortMappings[0]; if (firstMapping) { const publishedPort = Number.parseInt(firstMapping.HostPort, 10); const portKey = `${targetPort}-${publishedPort}-${protocol}`; diff --git a/packages/server/src/services/user.ts b/packages/server/src/services/user.ts index 83287a3be..5e66c6f2c 100644 --- a/packages/server/src/services/user.ts +++ b/packages/server/src/services/user.ts @@ -7,452 +7,452 @@ import { auth } from "../lib/auth"; export type User = typeof user.$inferSelect; export const addNewProject = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); + const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedProjects: [...userR.accessedProjects, projectId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + await db + .update(member) + .set({ + accessedProjects: [...userR.accessedProjects, projectId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const addNewEnvironment = async ( - userId: string, - environmentId: string, - organizationId: string, + userId: string, + environmentId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); + const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedEnvironments: [...userR.accessedEnvironments, environmentId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + await db + .update(member) + .set({ + accessedEnvironments: [...userR.accessedEnvironments, environmentId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const addNewService = async ( - userId: string, - serviceId: string, - organizationId: string, + userId: string, + serviceId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedServices: [...userR.accessedServices, serviceId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + const userR = await findMemberById(userId, organizationId); + await db + .update(member) + .set({ + accessedServices: [...userR.accessedServices, serviceId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const canPerformCreationService = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects, canCreateServices } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToProject = accessedProjects.includes(projectId); + const { accessedProjects, canCreateServices } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToProject = accessedProjects.includes(projectId); - if (canCreateServices && haveAccessToProject) { - return true; - } + if (canCreateServices && haveAccessToProject) { + return true; + } - return false; + return false; }; export const canPerformAccessService = async ( - userId: string, - serviceId: string, - organizationId: string, + userId: string, + serviceId: string, + organizationId: string, ) => { - const { accessedServices } = await findMemberById(userId, organizationId); - const haveAccessToService = accessedServices.includes(serviceId); + const { accessedServices } = await findMemberById(userId, organizationId); + const haveAccessToService = accessedServices.includes(serviceId); - if (haveAccessToService) { - return true; - } + if (haveAccessToService) { + return true; + } - return false; + return false; }; -export const canPeformDeleteService = async ( - userId: string, - serviceId: string, - organizationId: string, +export const canPerformDeleteService = async ( + userId: string, + serviceId: string, + organizationId: string, ) => { - const { accessedServices, canDeleteServices } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToService = accessedServices.includes(serviceId); + const { accessedServices, canDeleteServices } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToService = accessedServices.includes(serviceId); - if (canDeleteServices && haveAccessToService) { - return true; - } + if (canDeleteServices && haveAccessToService) { + return true; + } - return false; + return false; }; export const canPerformCreationProject = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canCreateProjects } = await findMemberById(userId, organizationId); + const { canCreateProjects } = await findMemberById(userId, organizationId); - if (canCreateProjects) { - return true; - } + if (canCreateProjects) { + return true; + } - return false; + return false; }; export const canPerformDeleteProject = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canDeleteProjects } = await findMemberById(userId, organizationId); + const { canDeleteProjects } = await findMemberById(userId, organizationId); - if (canDeleteProjects) { - return true; - } + if (canDeleteProjects) { + return true; + } - return false; + return false; }; export const canPerformAccessProject = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects } = await findMemberById(userId, organizationId); + const { accessedProjects } = await findMemberById(userId, organizationId); - const haveAccessToProject = accessedProjects.includes(projectId); + const haveAccessToProject = accessedProjects.includes(projectId); - if (haveAccessToProject) { - return true; - } - return false; + if (haveAccessToProject) { + return true; + } + return false; }; export const canPerformAccessEnvironment = async ( - userId: string, - environmentId: string, - organizationId: string, + userId: string, + environmentId: string, + organizationId: string, ) => { - const { accessedEnvironments } = await findMemberById(userId, organizationId); - const haveAccessToEnvironment = accessedEnvironments.includes(environmentId); + const { accessedEnvironments } = await findMemberById(userId, organizationId); + const haveAccessToEnvironment = accessedEnvironments.includes(environmentId); - if (haveAccessToEnvironment) { - return true; - } + if (haveAccessToEnvironment) { + return true; + } - return false; + return false; }; export const canPerformDeleteEnvironment = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects, canDeleteEnvironments } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToProject = accessedProjects.includes(projectId); + const { accessedProjects, canDeleteEnvironments } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToProject = accessedProjects.includes(projectId); - if (canDeleteEnvironments && haveAccessToProject) { - return true; - } + if (canDeleteEnvironments && haveAccessToProject) { + return true; + } - return false; + return false; }; export const canAccessToTraefikFiles = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canAccessToTraefikFiles } = await findMemberById( - userId, - organizationId, - ); - return canAccessToTraefikFiles; + const { canAccessToTraefikFiles } = await findMemberById( + userId, + organizationId, + ); + return canAccessToTraefikFiles; }; export const checkServiceAccess = async ( - userId: string, - serviceId: string, - organizationId: string, - action = "access" as "access" | "create" | "delete", + userId: string, + serviceId: string, + organizationId: string, + action = "access" as "access" | "create" | "delete", ) => { - let hasPermission = false; - switch (action) { - case "create": - hasPermission = await canPerformCreationService( - userId, - serviceId, - organizationId, - ); - break; - case "access": - hasPermission = await canPerformAccessService( - userId, - serviceId, - organizationId, - ); - break; - case "delete": - hasPermission = await canPeformDeleteService( - userId, - serviceId, - organizationId, - ); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "create": + hasPermission = await canPerformCreationService( + userId, + serviceId, + organizationId, + ); + break; + case "access": + hasPermission = await canPerformAccessService( + userId, + serviceId, + organizationId, + ); + break; + case "delete": + hasPermission = await canPerformDeleteService( + userId, + serviceId, + organizationId, + ); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentAccess = async ( - userId: string, - environmentId: string, - organizationId: string, - action = "access" as const, + userId: string, + environmentId: string, + organizationId: string, + action = "access" as const, ) => { - let hasPermission = false; - switch (action) { - case "access": - hasPermission = await canPerformAccessEnvironment( - userId, - environmentId, - organizationId, - ); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "access": + hasPermission = await canPerformAccessEnvironment( + userId, + environmentId, + organizationId, + ); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentDeletionPermission = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const member = await findMemberById(userId, organizationId); + const member = await findMemberById(userId, organizationId); - if (!member) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "User not found in organization", - }); - } + if (!member) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "User not found in organization", + }); + } - if (member.role === "owner" || member.role === "admin") { - return true; - } + if (member.role === "owner" || member.role === "admin") { + return true; + } - if (!member.canDeleteEnvironments) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have permission to delete environments", - }); - } + if (!member.canDeleteEnvironments) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have permission to delete environments", + }); + } - const hasProjectAccess = member.accessedProjects.includes(projectId); - if (!hasProjectAccess) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this project", - }); - } + const hasProjectAccess = member.accessedProjects.includes(projectId); + if (!hasProjectAccess) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this project", + }); + } - return true; + return true; }; export const checkProjectAccess = async ( - authId: string, - action: "create" | "delete" | "access", - organizationId: string, - projectId?: string, + authId: string, + action: "create" | "delete" | "access", + organizationId: string, + projectId?: string, ) => { - let hasPermission = false; - switch (action) { - case "access": - hasPermission = await canPerformAccessProject( - authId, - projectId as string, - organizationId, - ); - break; - case "create": - hasPermission = await canPerformCreationProject(authId, organizationId); - break; - case "delete": - hasPermission = await canPerformDeleteProject(authId, organizationId); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "access": + hasPermission = await canPerformAccessProject( + authId, + projectId as string, + organizationId, + ); + break; + case "create": + hasPermission = await canPerformCreationProject(authId, organizationId); + break; + case "delete": + hasPermission = await canPerformDeleteProject(authId, organizationId); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentCreationPermission = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - // Get user's member record - const member = await findMemberById(userId, organizationId); + // Get user's member record + const member = await findMemberById(userId, organizationId); - if (!member) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "User not found in organization", - }); - } + if (!member) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "User not found in organization", + }); + } - // Owners and admins can always create environments - if (member.role === "owner" || member.role === "admin") { - return true; - } + // Owners and admins can always create environments + if (member.role === "owner" || member.role === "admin") { + return true; + } - // Check if user has canCreateEnvironments permission - if (!member.canCreateEnvironments) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have permission to create environments", - }); - } + // Check if user has canCreateEnvironments permission + if (!member.canCreateEnvironments) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have permission to create environments", + }); + } - // Check if user has access to the project - const hasProjectAccess = member.accessedProjects.includes(projectId); - if (!hasProjectAccess) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this project", - }); - } + // Check if user has access to the project + const hasProjectAccess = member.accessedProjects.includes(projectId); + if (!hasProjectAccess) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this project", + }); + } - return true; + return true; }; export const findMemberById = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const result = await db.query.member.findFirst({ - where: and( - eq(member.userId, userId), - eq(member.organizationId, organizationId), - ), - with: { - user: true, - }, - }); + const result = await db.query.member.findFirst({ + where: and( + eq(member.userId, userId), + eq(member.organizationId, organizationId), + ), + with: { + user: true, + }, + }); - if (!result) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } - return result; + if (!result) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } + return result; }; export const updateUser = async (userId: string, userData: Partial) => { - // Validate email if it's being updated - if (userData.email !== undefined) { - if (!userData.email || userData.email.trim() === "") { - throw new Error("Email is required and cannot be empty"); - } + // Validate email if it's being updated + if (userData.email !== undefined) { + if (!userData.email || userData.email.trim() === "") { + throw new Error("Email is required and cannot be empty"); + } - // Basic email format validation - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(userData.email)) { - throw new Error("Please enter a valid email address"); - } - } + // Basic email format validation + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(userData.email)) { + throw new Error("Please enter a valid email address"); + } + } - const userResult = await db - .update(user) - .set({ - ...userData, - }) - .where(eq(user.id, userId)) - .returning() - .then((res) => res[0]); + const userResult = await db + .update(user) + .set({ + ...userData, + }) + .where(eq(user.id, userId)) + .returning() + .then((res) => res[0]); - return userResult; + return userResult; }; export const createApiKey = async ( - userId: string, - input: { - name: string; - prefix?: string; - expiresIn?: number; - metadata: { - organizationId: string; - }; - rateLimitEnabled?: boolean; - rateLimitTimeWindow?: number; - rateLimitMax?: number; - remaining?: number; - refillAmount?: number; - refillInterval?: number; - }, + userId: string, + input: { + name: string; + prefix?: string; + expiresIn?: number; + metadata: { + organizationId: string; + }; + rateLimitEnabled?: boolean; + rateLimitTimeWindow?: number; + rateLimitMax?: number; + remaining?: number; + refillAmount?: number; + refillInterval?: number; + }, ) => { - const result = await auth.createApiKey({ - body: { - name: input.name, - expiresIn: input.expiresIn, - prefix: input.prefix, - rateLimitEnabled: input.rateLimitEnabled, - rateLimitTimeWindow: input.rateLimitTimeWindow, - rateLimitMax: input.rateLimitMax, - remaining: input.remaining, - refillAmount: input.refillAmount, - refillInterval: input.refillInterval, - userId, - }, - }); + const result = await auth.createApiKey({ + body: { + name: input.name, + expiresIn: input.expiresIn, + prefix: input.prefix, + rateLimitEnabled: input.rateLimitEnabled, + rateLimitTimeWindow: input.rateLimitTimeWindow, + rateLimitMax: input.rateLimitMax, + remaining: input.remaining, + refillAmount: input.refillAmount, + refillInterval: input.refillInterval, + userId, + }, + }); - if (input.metadata) { - await db - .update(apikey) - .set({ metadata: JSON.stringify(input.metadata) }) - .where(eq(apikey.id, result.id)); - } + if (input.metadata) { + await db + .update(apikey) + .set({ metadata: JSON.stringify(input.metadata) }) + .where(eq(apikey.id, result.id)); + } - return result; + return result; }; diff --git a/packages/server/src/setup/setup.ts b/packages/server/src/setup/setup.ts index 4c01bf6cb..5171063d6 100644 --- a/packages/server/src/setup/setup.ts +++ b/packages/server/src/setup/setup.ts @@ -3,13 +3,13 @@ import { docker } from "../constants"; export const initializeSwarm = async () => { const swarmInitialized = await dockerSwarmInitialized(); if (swarmInitialized) { - console.log("Swarm is already initilized"); + console.log("Swarm is already initialized"); } else { await docker.swarmInit({ AdvertiseAddr: "127.0.0.1", ListenAddr: "0.0.0.0", }); - console.log("Swarm was initilized"); + console.log("Swarm was initialized"); } }; @@ -26,14 +26,14 @@ export const dockerSwarmInitialized = async () => { export const initializeNetwork = async () => { const networkInitialized = await dockerNetworkInitialized(); if (networkInitialized) { - console.log("Network is already initilized"); + console.log("Network is already initialized"); } else { docker.createNetwork({ Attachable: true, Name: "dokploy-network", Driver: "overlay", }); - console.log("Network was initilized"); + console.log("Network was initialized"); } }; diff --git a/packages/server/src/utils/builders/compose.ts b/packages/server/src/utils/builders/compose.ts index ca2b8a6b5..32aecbd4c 100644 --- a/packages/server/src/utils/builders/compose.ts +++ b/packages/server/src/utils/builders/compose.ts @@ -5,26 +5,26 @@ import boxen from "boxen"; import { quote } from "shell-quote"; import { writeDomainsToCompose } from "../docker/domain"; import { - encodeBase64, - getEnviromentVariablesObject, - prepareEnvironmentVariables, + encodeBase64, + getEnvironmentVariablesObject, + prepareEnvironmentVariables, } from "../docker/utils"; export type ComposeNested = InferResultType< - "compose", - { environment: { with: { project: true } }; mounts: true; domains: true } + "compose", + { environment: { with: { project: true } }; mounts: true; domains: true } >; export const getBuildComposeCommand = async (compose: ComposeNested) => { - const { COMPOSE_PATH } = paths(!!compose.serverId); - const { sourceType, appName, mounts, composeType, domains } = compose; - const command = createCommand(compose); - const envCommand = getCreateEnvFileCommand(compose); - const projectPath = join(COMPOSE_PATH, compose.appName, "code"); - const exportEnvCommand = getExportEnvCommand(compose); + const { COMPOSE_PATH } = paths(!!compose.serverId); + const { sourceType, appName, mounts, composeType, domains } = compose; + const command = createCommand(compose); + const envCommand = getCreateEnvFileCommand(compose); + const projectPath = join(COMPOSE_PATH, compose.appName, "code"); + const exportEnvCommand = getExportEnvCommand(compose); - const newCompose = await writeDomainsToCompose(compose, domains); - const logContent = ` + const newCompose = await writeDomainsToCompose(compose, domains); + const logContent = ` App Name: ${appName} Build Compose 🐳 Detected: ${mounts.length} mounts 📂 @@ -32,31 +32,31 @@ Command: docker ${command} Source Type: docker ${sourceType} ✅ Compose Type: ${composeType} ✅`; - const logBox = boxen(logContent, { - padding: { - left: 1, - right: 1, - bottom: 1, - }, - width: 80, - borderStyle: "double", - }); + const logBox = boxen(logContent, { + padding: { + left: 1, + right: 1, + bottom: 1, + }, + width: 80, + borderStyle: "double", + }); - const bashCommand = ` + const bashCommand = ` set -e { echo "${logBox}"; - + ${newCompose} - + ${envCommand} - + cd "${projectPath}"; ${compose.isolatedDeployment ? `docker network inspect ${compose.appName} >/dev/null 2>&1 || docker network create ${compose.composeType === "stack" ? "--driver overlay" : ""} --attachable ${compose.appName}` : ""} env -i PATH="$PATH" ${exportEnvCommand} docker ${command.split(" ").join(" ")} 2>&1 || { echo "Error: ❌ Docker command failed"; exit 1; } ${compose.isolatedDeployment ? `docker network connect ${compose.appName} $(docker ps --filter "name=dokploy-traefik" -q) >/dev/null 2>&1` : ""} - + echo "Docker Compose Deployed: ✅"; } || { echo "Error: ❌ Script execution failed"; @@ -64,81 +64,81 @@ Compose Type: ${composeType} ✅`; } `; - return bashCommand; + return bashCommand; }; const sanitizeCommand = (command: string) => { - const sanitizedCommand = command.trim(); + const sanitizedCommand = command.trim(); - const parts = sanitizedCommand.split(/\s+/); + const parts = sanitizedCommand.split(/\s+/); - const restCommand = parts.map((arg) => arg.replace(/^"(.*)"$/, "$1")); + const restCommand = parts.map((arg) => arg.replace(/^"(.*)"$/, "$1")); - return restCommand.join(" "); + return restCommand.join(" "); }; export const createCommand = (compose: ComposeNested) => { - const { composeType, appName, sourceType } = compose; - if (compose.command) { - return `${sanitizeCommand(compose.command)}`; - } + const { composeType, appName, sourceType } = compose; + if (compose.command) { + return `${sanitizeCommand(compose.command)}`; + } - const path = - sourceType === "raw" ? "docker-compose.yml" : compose.composePath; - let command = ""; + const path = + sourceType === "raw" ? "docker-compose.yml" : compose.composePath; + let command = ""; - if (composeType === "docker-compose") { - command = `compose -p ${appName} -f ${path} up -d --build --remove-orphans`; - } else if (composeType === "stack") { - command = `stack deploy -c ${path} ${appName} --prune --with-registry-auth`; - } + if (composeType === "docker-compose") { + command = `compose -p ${appName} -f ${path} up -d --build --remove-orphans`; + } else if (composeType === "stack") { + command = `stack deploy -c ${path} ${appName} --prune --with-registry-auth`; + } - return command; + return command; }; export const getCreateEnvFileCommand = (compose: ComposeNested) => { - const { COMPOSE_PATH } = paths(!!compose.serverId); - const { env, composePath, appName } = compose; - const composeFilePath = - join(COMPOSE_PATH, appName, "code", composePath) || - join(COMPOSE_PATH, appName, "code", "docker-compose.yml"); + const { COMPOSE_PATH } = paths(!!compose.serverId); + const { env, composePath, appName } = compose; + const composeFilePath = + join(COMPOSE_PATH, appName, "code", composePath) || + join(COMPOSE_PATH, appName, "code", "docker-compose.yml"); - const envFilePath = join(dirname(composeFilePath), ".env"); + const envFilePath = join(dirname(composeFilePath), ".env"); - let envContent = `APP_NAME=${appName}\n`; - envContent += env || ""; - if (!envContent.includes("DOCKER_CONFIG")) { - envContent += "\nDOCKER_CONFIG=/root/.docker"; - } + let envContent = `APP_NAME=${appName}\n`; + envContent += env || ""; + if (!envContent.includes("DOCKER_CONFIG")) { + envContent += "\nDOCKER_CONFIG=/root/.docker"; + } - if (compose.randomize) { - envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`; - } + if (compose.randomize) { + envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`; + } - const envFileContent = prepareEnvironmentVariables( - envContent, - compose.environment.project.env, - compose.environment.env, - ).join("\n"); + const envFileContent = prepareEnvironmentVariables( + envContent, + compose.environment.project.env, + compose.environment.env, + ).join("\n"); - const encodedContent = encodeBase64(envFileContent); - return ` + const encodedContent = encodeBase64(envFileContent); + return ` touch ${envFilePath}; echo "${encodedContent}" | base64 -d > "${envFilePath}"; `; }; const getExportEnvCommand = (compose: ComposeNested) => { - if (compose.composeType !== "stack") return ""; + if (compose.composeType !== "stack") return ""; - const envVars = getEnviromentVariablesObject( - compose.env, - compose.environment.project.env, - compose.environment.env, - ); - const exports = Object.entries(envVars) - .map(([key, value]) => `${key}=${quote([value])}`) - .join(" "); + const envVars = getEnvironmentVariablesObject( + compose.env, + compose.environment.project.env, + compose.environment.env, + ); + const exports = Object.entries(envVars) + .map(([key, value]) => `${key}=${quote([value])}`) + .join(" "); - return exports ? `${exports}` : ""; + return exports ? `${exports}` : ""; }; diff --git a/packages/server/src/utils/builders/docker-file.ts b/packages/server/src/utils/builders/docker-file.ts index ea53a5bff..f2fedf461 100644 --- a/packages/server/src/utils/builders/docker-file.ts +++ b/packages/server/src/utils/builders/docker-file.ts @@ -1,105 +1,105 @@ import { - getEnviromentVariablesObject, - prepareEnvironmentVariablesForShell, + getEnvironmentVariablesObject, + prepareEnvironmentVariablesForShell, } from "@dokploy/server/utils/docker/utils"; import { quote } from "shell-quote"; import { - getBuildAppDirectory, - getDockerContextPath, + getBuildAppDirectory, + getDockerContextPath, } from "../filesystem/directory"; import type { ApplicationNested } from "."; import { createEnvFileCommand } from "./utils"; export const getDockerCommand = (application: ApplicationNested) => { - const { - appName, - env, - publishDirectory, - buildArgs, - buildSecrets, - dockerBuildStage, - cleanCache, - createEnvFile, - } = application; - const dockerFilePath = getBuildAppDirectory(application); + const { + appName, + env, + publishDirectory, + buildArgs, + buildSecrets, + dockerBuildStage, + cleanCache, + createEnvFile, + } = application; + const dockerFilePath = getBuildAppDirectory(application); - try { - const image = `${appName}`; + try { + const image = `${appName}`; - const defaultContextPath = - dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || "."; + const defaultContextPath = + dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || "."; - const dockerContextPath = - getDockerContextPath(application) || defaultContextPath; + const dockerContextPath = + getDockerContextPath(application) || defaultContextPath; - const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."]; + const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."]; - if (dockerBuildStage) { - commandArgs.push("--target", dockerBuildStage); - } + if (dockerBuildStage) { + commandArgs.push("--target", dockerBuildStage); + } - if (cleanCache) { - commandArgs.push("--no-cache"); - } + if (cleanCache) { + commandArgs.push("--no-cache"); + } - const args = prepareEnvironmentVariablesForShell( - buildArgs, - application.environment.project.env, - application.environment.env, - ); + const args = prepareEnvironmentVariablesForShell( + buildArgs, + application.environment.project.env, + application.environment.env, + ); - for (const arg of args) { - commandArgs.push("--build-arg", arg); - } + for (const arg of args) { + commandArgs.push("--build-arg", arg); + } - const secrets = getEnviromentVariablesObject( - buildSecrets, - application.environment.project.env, - application.environment.env, - ); + const secrets = getEnvironmentVariablesObject( + buildSecrets, + application.environment.project.env, + application.environment.env, + ); - const joinedSecrets = Object.entries(secrets) - .map(([key, value]) => `${key}=${quote([value])}`) - .join(" "); + const joinedSecrets = Object.entries(secrets) + .map(([key, value]) => `${key}=${quote([value])}`) + .join(" "); - /* + /* Do not generate an environment file when publishDirectory is specified, as it could be publicly exposed. Also respect the createEnvFile flag. */ - let command = ""; - if (!publishDirectory && createEnvFile) { - command += createEnvFileCommand( - dockerFilePath, - env, - application.environment.project.env, - application.environment.env, - ); - } + let command = ""; + if (!publishDirectory && createEnvFile) { + command += createEnvFileCommand( + dockerFilePath, + env, + application.environment.project.env, + application.environment.env, + ); + } - for (const key in secrets) { - // Although buildx is smart enough to know we may be referring to an environment variable name, - // we still make sure it doesn't fall back to `type=file`. - // See: https://docs.docker.com/reference/cli/docker/buildx/build/#secret - commandArgs.push("--secret", `type=env,id=${key}`); - } + for (const key in secrets) { + // Although buildx is smart enough to know we may be referring to an environment variable name, + // we still make sure it doesn't fall back to `type=file`. + // See: https://docs.docker.com/reference/cli/docker/buildx/build/#secret + commandArgs.push("--secret", `type=env,id=${key}`); + } - command += ` + command += ` echo "Building ${appName}" ; -cd ${dockerContextPath} || { +cd ${dockerContextPath} || { echo "❌ The path ${dockerContextPath} does not exist" ; exit 1; } -${joinedSecrets} docker ${commandArgs.join(" ")} || { +${joinedSecrets} docker ${commandArgs.join(" ")} || { echo "❌ Docker build failed" ; exit 1; } echo "✅ Docker build completed." ; `; - return command; - } catch (error) { - throw error; - } + return command; + } catch (error) { + throw error; + } }; diff --git a/packages/server/src/utils/docker/utils.ts b/packages/server/src/utils/docker/utils.ts index b2c7e5d7b..dd645cd1b 100644 --- a/packages/server/src/utils/docker/utils.ts +++ b/packages/server/src/utils/docker/utils.ts @@ -434,7 +434,7 @@ export const parseEnvironmentKeyValuePair = ( return [key, valueParts.join("=")]; }; -export const getEnviromentVariablesObject = ( +export const getEnvironmentVariablesObject = ( input: string | null, projectEnv?: string | null, environmentEnv?: string | null, diff --git a/packages/server/src/utils/startup/cancell-deployments.ts b/packages/server/src/utils/startup/cancel-deployments.ts similarity index 100% rename from packages/server/src/utils/startup/cancell-deployments.ts rename to packages/server/src/utils/startup/cancel-deployments.ts From 6d17f629425d0c287fc89932a42e4034f8eeae2a Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 22:02:53 +0000 Subject: [PATCH 05/25] [autofix.ci] apply automated fixes --- .../compose/network/network-service.test.ts | 206 +++--- .../__test__/env/stack-environment.test.ts | 194 ++--- packages/server/src/services/user.ts | 676 +++++++++--------- packages/server/src/utils/builders/compose.ts | 144 ++-- .../server/src/utils/builders/docker-file.ts | 130 ++-- 5 files changed, 675 insertions(+), 675 deletions(-) diff --git a/apps/dokploy/__test__/compose/network/network-service.test.ts b/apps/dokploy/__test__/compose/network/network-service.test.ts index 91eb5da4e..073e61615 100644 --- a/apps/dokploy/__test__/compose/network/network-service.test.ts +++ b/apps/dokploy/__test__/compose/network/network-service.test.ts @@ -1,7 +1,7 @@ import type { ComposeSpecification } from "@dokploy/server"; import { - addSuffixToServiceNetworks, - generateRandomHash, + addSuffixToServiceNetworks, + generateRandomHash, } from "@dokploy/server"; import { expect, test } from "vitest"; import { parse } from "yaml"; @@ -23,30 +23,30 @@ services: `; test("Add suffix to networks in services", () => { - const composeData = parse(composeFile) as ComposeSpecification; + const composeData = parse(composeFile) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData?.services?.web?.networks).toContain( - `frontend-${suffix}`, - ); + expect(actualComposeData?.services?.web?.networks).toContain( + `frontend-${suffix}`, + ); - expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${suffix}`, - ); + expect(actualComposeData?.services?.api?.networks).toContain( + `backend-${suffix}`, + ); - const apiNetworks = actualComposeData?.services?.api?.networks; + const apiNetworks = actualComposeData?.services?.api?.networks; - expect(apiNetworks).toBeDefined(); - expect(actualComposeData?.services?.api?.networks).toContain( - `backend-${suffix}`, - ); + expect(apiNetworks).toBeDefined(); + expect(actualComposeData?.services?.api?.networks).toContain( + `backend-${suffix}`, + ); }); // Caso 2: Objeto con aliases @@ -67,29 +67,29 @@ networks: `; test("Add suffix to networks in services with aliases", () => { - const composeData = parse(composeFile2) as ComposeSpecification; + const composeData = parse(composeFile2) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData.services?.api?.networks).toHaveProperty( - `frontend-${suffix}`, - ); + expect(actualComposeData.services?.api?.networks).toHaveProperty( + `frontend-${suffix}`, + ); - const networkConfig = actualComposeData?.services?.api?.networks as { - [key: string]: { aliases?: string[] }; - }; - expect(networkConfig[`frontend-${suffix}`]).toBeDefined(); - expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api"); + const networkConfig = actualComposeData?.services?.api?.networks as { + [key: string]: { aliases?: string[] }; + }; + expect(networkConfig[`frontend-${suffix}`]).toBeDefined(); + expect(networkConfig[`frontend-${suffix}`]?.aliases).toContain("api"); - expect(actualComposeData.services?.api?.networks).not.toHaveProperty( - "frontend-ash", - ); + expect(actualComposeData.services?.api?.networks).not.toHaveProperty( + "frontend-ash", + ); }); const composeFile3 = ` @@ -107,19 +107,19 @@ networks: `; test("Add suffix to networks in services (Object with simple networks)", () => { - const composeData = parse(composeFile3) as ComposeSpecification; + const composeData = parse(composeFile3) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - expect(actualComposeData.services?.redis?.networks).toHaveProperty( - `backend-${suffix}`, - ); + expect(actualComposeData.services?.redis?.networks).toHaveProperty( + `backend-${suffix}`, + ); }); const composeFileCombined = ` @@ -153,36 +153,36 @@ networks: `; test("Add suffix to networks in services (combined case)", () => { - const composeData = parse(composeFileCombined) as ComposeSpecification; + const composeData = parse(composeFileCombined) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const services = addSuffixToServiceNetworks(composeData.services, suffix); - const actualComposeData = { ...composeData, services }; + if (!composeData?.services) { + return; + } + const services = addSuffixToServiceNetworks(composeData.services, suffix); + const actualComposeData = { ...composeData, services }; - // Caso 1: ListOfStrings - expect(actualComposeData.services?.web?.networks).toContain( - `frontend-${suffix}`, - ); - expect(actualComposeData.services?.web?.networks).toContain( - `backend-${suffix}`, - ); + // Caso 1: ListOfStrings + expect(actualComposeData.services?.web?.networks).toContain( + `frontend-${suffix}`, + ); + expect(actualComposeData.services?.web?.networks).toContain( + `backend-${suffix}`, + ); - // Caso 2: Objeto con aliases - const apiNetworks = actualComposeData.services?.api?.networks as { - [key: string]: unknown; - }; - expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); - expect(apiNetworks[`frontend-${suffix}`]).toBeDefined(); - expect(apiNetworks).not.toHaveProperty("frontend"); + // Caso 2: Objeto con aliases + const apiNetworks = actualComposeData.services?.api?.networks as { + [key: string]: unknown; + }; + expect(apiNetworks).toHaveProperty(`frontend-${suffix}`); + expect(apiNetworks[`frontend-${suffix}`]).toBeDefined(); + expect(apiNetworks).not.toHaveProperty("frontend"); - // Caso 3: Objeto con redes simples - const redisNetworks = actualComposeData.services?.redis?.networks; - expect(redisNetworks).toHaveProperty(`backend-${suffix}`); - expect(redisNetworks).not.toHaveProperty("backend"); + // Caso 3: Objeto con redes simples + const redisNetworks = actualComposeData.services?.redis?.networks; + expect(redisNetworks).toHaveProperty(`backend-${suffix}`); + expect(redisNetworks).not.toHaveProperty("backend"); }); const composeFile7 = ` @@ -196,18 +196,18 @@ services: `; test("It shouldn't add suffix to dokploy-network in services", () => { - const composeData = parse(composeFile7) as ComposeSpecification; + const composeData = parse(composeFile7) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const networks = addSuffixToServiceNetworks(composeData.services, suffix); - const service = networks.web; + if (!composeData?.services) { + return; + } + const networks = addSuffixToServiceNetworks(composeData.services, suffix); + const service = networks.web; - expect(service).toBeDefined(); - expect(service?.networks).toContain("dokploy-network"); + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); }); const composeFile8 = ` @@ -245,31 +245,31 @@ services: `; test("It shouldn't add suffix to dokploy-network in services multiples cases", () => { - const composeData = parse(composeFile8) as ComposeSpecification; + const composeData = parse(composeFile8) as ComposeSpecification; - const suffix = generateRandomHash(); + const suffix = generateRandomHash(); - if (!composeData?.services) { - return; - } - const networks = addSuffixToServiceNetworks(composeData.services, suffix); - const service = networks.web; - const api = networks.api; - const redis = networks.redis; - const db = networks.db; + if (!composeData?.services) { + return; + } + const networks = addSuffixToServiceNetworks(composeData.services, suffix); + const service = networks.web; + const api = networks.api; + const redis = networks.redis; + const db = networks.db; - const dbNetworks = db?.networks as { - [key: string]: unknown; - }; + const dbNetworks = db?.networks as { + [key: string]: unknown; + }; - const apiNetworks = api?.networks as { - [key: string]: unknown; - }; + const apiNetworks = api?.networks as { + [key: string]: unknown; + }; - expect(service).toBeDefined(); - expect(service?.networks).toContain("dokploy-network"); + expect(service).toBeDefined(); + expect(service?.networks).toContain("dokploy-network"); - expect(redis?.networks).toHaveProperty("dokploy-network"); - expect(dbNetworks["dokploy-network"]).toBeDefined(); - expect(apiNetworks["dokploy-network"]).toBeDefined(); + expect(redis?.networks).toHaveProperty("dokploy-network"); + expect(dbNetworks["dokploy-network"]).toBeDefined(); + expect(apiNetworks["dokploy-network"]).toBeDefined(); }); diff --git a/apps/dokploy/__test__/env/stack-environment.test.ts b/apps/dokploy/__test__/env/stack-environment.test.ts index cde7be9db..773adf3ed 100644 --- a/apps/dokploy/__test__/env/stack-environment.test.ts +++ b/apps/dokploy/__test__/env/stack-environment.test.ts @@ -16,28 +16,28 @@ SECRET_KEY=env-secret-123 `; describe("getEnvironmentVariablesObject with environment variables (Stack compose)", () => { - it("resolves environment variables correctly for Stack compose", () => { - const serviceEnv = ` + it("resolves environment variables correctly for Stack compose", () => { + const serviceEnv = ` FOO=\${{environment.NODE_ENV}} BAR=\${{environment.API_URL}} BAZ=test `; - const result = getEnvironmentVariablesObject( - serviceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - FOO: "development", - BAR: "https://api.dev.example.com", - BAZ: "test", - }); - }); + expect(result).toEqual({ + FOO: "development", + BAR: "https://api.dev.example.com", + BAZ: "test", + }); + }); - it("resolves both project and environment variables for Stack compose", () => { - const serviceEnv = ` + it("resolves both project and environment variables for Stack compose", () => { + const serviceEnv = ` ENVIRONMENT=\${{project.ENVIRONMENT}} NODE_ENV=\${{environment.NODE_ENV}} API_URL=\${{environment.API_URL}} @@ -45,140 +45,140 @@ DATABASE_URL=\${{project.DATABASE_URL}} SERVICE_PORT=4000 `; - const result = getEnvironmentVariablesObject( - serviceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - ENVIRONMENT: "staging", - NODE_ENV: "development", - API_URL: "https://api.dev.example.com", - DATABASE_URL: "postgres://postgres:postgres@localhost:5432/project_db", - SERVICE_PORT: "4000", - }); - }); + expect(result).toEqual({ + ENVIRONMENT: "staging", + NODE_ENV: "development", + API_URL: "https://api.dev.example.com", + DATABASE_URL: "postgres://postgres:postgres@localhost:5432/project_db", + SERVICE_PORT: "4000", + }); + }); - it("handles multiple environment references in single value for Stack compose", () => { - const multiRefEnv = ` + it("handles multiple environment references in single value for Stack compose", () => { + const multiRefEnv = ` HOST=localhost PORT=5432 USERNAME=postgres PASSWORD=secret123 `; - const serviceEnv = ` + const serviceEnv = ` DATABASE_URL=postgresql://\${{environment.USERNAME}}:\${{environment.PASSWORD}}@\${{environment.HOST}}:\${{environment.PORT}}/mydb `; - const result = getEnvironmentVariablesObject(serviceEnv, "", multiRefEnv); + const result = getEnvironmentVariablesObject(serviceEnv, "", multiRefEnv); - expect(result).toEqual({ - DATABASE_URL: "postgresql://postgres:secret123@localhost:5432/mydb", - }); - }); + expect(result).toEqual({ + DATABASE_URL: "postgresql://postgres:secret123@localhost:5432/mydb", + }); + }); - it("throws error for undefined environment variables in Stack compose", () => { - const serviceWithUndefined = ` + it("throws error for undefined environment variables in Stack compose", () => { + const serviceWithUndefined = ` UNDEFINED_VAR=\${{environment.UNDEFINED_VAR}} `; - expect(() => - getEnvironmentVariablesObject(serviceWithUndefined, "", environmentEnv), - ).toThrow("Invalid environment variable: environment.UNDEFINED_VAR"); - }); + expect(() => + getEnvironmentVariablesObject(serviceWithUndefined, "", environmentEnv), + ).toThrow("Invalid environment variable: environment.UNDEFINED_VAR"); + }); - it("allows service variables to override environment variables in Stack compose", () => { - const serviceOverrideEnv = ` + it("allows service variables to override environment variables in Stack compose", () => { + const serviceOverrideEnv = ` NODE_ENV=production API_URL=\${{environment.API_URL}} `; - const result = getEnvironmentVariablesObject( - serviceOverrideEnv, - "", - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceOverrideEnv, + "", + environmentEnv, + ); - expect(result).toEqual({ - NODE_ENV: "production", - API_URL: "https://api.dev.example.com", - }); - }); + expect(result).toEqual({ + NODE_ENV: "production", + API_URL: "https://api.dev.example.com", + }); + }); - it("resolves complex references with project, environment, and service variables for Stack compose", () => { - const complexServiceEnv = ` + it("resolves complex references with project, environment, and service variables for Stack compose", () => { + const complexServiceEnv = ` FULL_DATABASE_URL=\${{project.DATABASE_URL}}/\${{environment.DATABASE_NAME}} API_ENDPOINT=\${{environment.API_URL}}/\${{project.ENVIRONMENT}}/api SERVICE_NAME=my-service COMPLEX_VAR=\${{SERVICE_NAME}}-\${{environment.NODE_ENV}}-\${{project.ENVIRONMENT}} `; - const result = getEnvironmentVariablesObject( - complexServiceEnv, - projectEnv, - environmentEnv, - ); + const result = getEnvironmentVariablesObject( + complexServiceEnv, + projectEnv, + environmentEnv, + ); - expect(result).toEqual({ - FULL_DATABASE_URL: - "postgres://postgres:postgres@localhost:5432/project_db/dev_database", - API_ENDPOINT: "https://api.dev.example.com/staging/api", - SERVICE_NAME: "my-service", - COMPLEX_VAR: "my-service-development-staging", - }); - }); + expect(result).toEqual({ + FULL_DATABASE_URL: + "postgres://postgres:postgres@localhost:5432/project_db/dev_database", + API_ENDPOINT: "https://api.dev.example.com/staging/api", + SERVICE_NAME: "my-service", + COMPLEX_VAR: "my-service-development-staging", + }); + }); - it("maintains precedence: service > environment > project in Stack compose", () => { - const conflictingProjectEnv = ` + it("maintains precedence: service > environment > project in Stack compose", () => { + const conflictingProjectEnv = ` NODE_ENV=production-project API_URL=https://project.api.com DATABASE_NAME=project_db `; - const conflictingEnvironmentEnv = ` + const conflictingEnvironmentEnv = ` NODE_ENV=development-environment API_URL=https://environment.api.com DATABASE_NAME=env_db `; - const serviceWithConflicts = ` + const serviceWithConflicts = ` NODE_ENV=service-override PROJECT_ENV=\${{project.NODE_ENV}} ENV_VAR=\${{environment.API_URL}} DB_NAME=\${{environment.DATABASE_NAME}} `; - const result = getEnvironmentVariablesObject( - serviceWithConflicts, - conflictingProjectEnv, - conflictingEnvironmentEnv, - ); + const result = getEnvironmentVariablesObject( + serviceWithConflicts, + conflictingProjectEnv, + conflictingEnvironmentEnv, + ); - expect(result).toEqual({ - NODE_ENV: "service-override", - PROJECT_ENV: "production-project", - ENV_VAR: "https://environment.api.com", - DB_NAME: "env_db", - }); - }); + expect(result).toEqual({ + NODE_ENV: "service-override", + PROJECT_ENV: "production-project", + ENV_VAR: "https://environment.api.com", + DB_NAME: "env_db", + }); + }); - it("handles empty environment variables in Stack compose", () => { - const serviceWithEmpty = ` + it("handles empty environment variables in Stack compose", () => { + const serviceWithEmpty = ` SERVICE_VAR=test PROJECT_VAR=\${{project.ENVIRONMENT}} `; - const result = getEnvironmentVariablesObject( - serviceWithEmpty, - projectEnv, - "", - ); + const result = getEnvironmentVariablesObject( + serviceWithEmpty, + projectEnv, + "", + ); - expect(result).toEqual({ - SERVICE_VAR: "test", - PROJECT_VAR: "staging", - }); - }); + expect(result).toEqual({ + SERVICE_VAR: "test", + PROJECT_VAR: "staging", + }); + }); }); diff --git a/packages/server/src/services/user.ts b/packages/server/src/services/user.ts index 5e66c6f2c..ed43f3862 100644 --- a/packages/server/src/services/user.ts +++ b/packages/server/src/services/user.ts @@ -7,452 +7,452 @@ import { auth } from "../lib/auth"; export type User = typeof user.$inferSelect; export const addNewProject = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); + const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedProjects: [...userR.accessedProjects, projectId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + await db + .update(member) + .set({ + accessedProjects: [...userR.accessedProjects, projectId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const addNewEnvironment = async ( - userId: string, - environmentId: string, - organizationId: string, + userId: string, + environmentId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); + const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedEnvironments: [...userR.accessedEnvironments, environmentId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + await db + .update(member) + .set({ + accessedEnvironments: [...userR.accessedEnvironments, environmentId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const addNewService = async ( - userId: string, - serviceId: string, - organizationId: string, + userId: string, + serviceId: string, + organizationId: string, ) => { - const userR = await findMemberById(userId, organizationId); - await db - .update(member) - .set({ - accessedServices: [...userR.accessedServices, serviceId], - }) - .where( - and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), - ); + const userR = await findMemberById(userId, organizationId); + await db + .update(member) + .set({ + accessedServices: [...userR.accessedServices, serviceId], + }) + .where( + and(eq(member.id, userR.id), eq(member.organizationId, organizationId)), + ); }; export const canPerformCreationService = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects, canCreateServices } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToProject = accessedProjects.includes(projectId); + const { accessedProjects, canCreateServices } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToProject = accessedProjects.includes(projectId); - if (canCreateServices && haveAccessToProject) { - return true; - } + if (canCreateServices && haveAccessToProject) { + return true; + } - return false; + return false; }; export const canPerformAccessService = async ( - userId: string, - serviceId: string, - organizationId: string, + userId: string, + serviceId: string, + organizationId: string, ) => { - const { accessedServices } = await findMemberById(userId, organizationId); - const haveAccessToService = accessedServices.includes(serviceId); + const { accessedServices } = await findMemberById(userId, organizationId); + const haveAccessToService = accessedServices.includes(serviceId); - if (haveAccessToService) { - return true; - } + if (haveAccessToService) { + return true; + } - return false; + return false; }; export const canPerformDeleteService = async ( - userId: string, - serviceId: string, - organizationId: string, + userId: string, + serviceId: string, + organizationId: string, ) => { - const { accessedServices, canDeleteServices } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToService = accessedServices.includes(serviceId); + const { accessedServices, canDeleteServices } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToService = accessedServices.includes(serviceId); - if (canDeleteServices && haveAccessToService) { - return true; - } + if (canDeleteServices && haveAccessToService) { + return true; + } - return false; + return false; }; export const canPerformCreationProject = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canCreateProjects } = await findMemberById(userId, organizationId); + const { canCreateProjects } = await findMemberById(userId, organizationId); - if (canCreateProjects) { - return true; - } + if (canCreateProjects) { + return true; + } - return false; + return false; }; export const canPerformDeleteProject = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canDeleteProjects } = await findMemberById(userId, organizationId); + const { canDeleteProjects } = await findMemberById(userId, organizationId); - if (canDeleteProjects) { - return true; - } + if (canDeleteProjects) { + return true; + } - return false; + return false; }; export const canPerformAccessProject = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects } = await findMemberById(userId, organizationId); + const { accessedProjects } = await findMemberById(userId, organizationId); - const haveAccessToProject = accessedProjects.includes(projectId); + const haveAccessToProject = accessedProjects.includes(projectId); - if (haveAccessToProject) { - return true; - } - return false; + if (haveAccessToProject) { + return true; + } + return false; }; export const canPerformAccessEnvironment = async ( - userId: string, - environmentId: string, - organizationId: string, + userId: string, + environmentId: string, + organizationId: string, ) => { - const { accessedEnvironments } = await findMemberById(userId, organizationId); - const haveAccessToEnvironment = accessedEnvironments.includes(environmentId); + const { accessedEnvironments } = await findMemberById(userId, organizationId); + const haveAccessToEnvironment = accessedEnvironments.includes(environmentId); - if (haveAccessToEnvironment) { - return true; - } + if (haveAccessToEnvironment) { + return true; + } - return false; + return false; }; export const canPerformDeleteEnvironment = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const { accessedProjects, canDeleteEnvironments } = await findMemberById( - userId, - organizationId, - ); - const haveAccessToProject = accessedProjects.includes(projectId); + const { accessedProjects, canDeleteEnvironments } = await findMemberById( + userId, + organizationId, + ); + const haveAccessToProject = accessedProjects.includes(projectId); - if (canDeleteEnvironments && haveAccessToProject) { - return true; - } + if (canDeleteEnvironments && haveAccessToProject) { + return true; + } - return false; + return false; }; export const canAccessToTraefikFiles = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const { canAccessToTraefikFiles } = await findMemberById( - userId, - organizationId, - ); - return canAccessToTraefikFiles; + const { canAccessToTraefikFiles } = await findMemberById( + userId, + organizationId, + ); + return canAccessToTraefikFiles; }; export const checkServiceAccess = async ( - userId: string, - serviceId: string, - organizationId: string, - action = "access" as "access" | "create" | "delete", + userId: string, + serviceId: string, + organizationId: string, + action = "access" as "access" | "create" | "delete", ) => { - let hasPermission = false; - switch (action) { - case "create": - hasPermission = await canPerformCreationService( - userId, - serviceId, - organizationId, - ); - break; - case "access": - hasPermission = await canPerformAccessService( - userId, - serviceId, - organizationId, - ); - break; - case "delete": - hasPermission = await canPerformDeleteService( - userId, - serviceId, - organizationId, - ); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "create": + hasPermission = await canPerformCreationService( + userId, + serviceId, + organizationId, + ); + break; + case "access": + hasPermission = await canPerformAccessService( + userId, + serviceId, + organizationId, + ); + break; + case "delete": + hasPermission = await canPerformDeleteService( + userId, + serviceId, + organizationId, + ); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentAccess = async ( - userId: string, - environmentId: string, - organizationId: string, - action = "access" as const, + userId: string, + environmentId: string, + organizationId: string, + action = "access" as const, ) => { - let hasPermission = false; - switch (action) { - case "access": - hasPermission = await canPerformAccessEnvironment( - userId, - environmentId, - organizationId, - ); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "access": + hasPermission = await canPerformAccessEnvironment( + userId, + environmentId, + organizationId, + ); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentDeletionPermission = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - const member = await findMemberById(userId, organizationId); + const member = await findMemberById(userId, organizationId); - if (!member) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "User not found in organization", - }); - } + if (!member) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "User not found in organization", + }); + } - if (member.role === "owner" || member.role === "admin") { - return true; - } + if (member.role === "owner" || member.role === "admin") { + return true; + } - if (!member.canDeleteEnvironments) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have permission to delete environments", - }); - } + if (!member.canDeleteEnvironments) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have permission to delete environments", + }); + } - const hasProjectAccess = member.accessedProjects.includes(projectId); - if (!hasProjectAccess) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this project", - }); - } + const hasProjectAccess = member.accessedProjects.includes(projectId); + if (!hasProjectAccess) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this project", + }); + } - return true; + return true; }; export const checkProjectAccess = async ( - authId: string, - action: "create" | "delete" | "access", - organizationId: string, - projectId?: string, + authId: string, + action: "create" | "delete" | "access", + organizationId: string, + projectId?: string, ) => { - let hasPermission = false; - switch (action) { - case "access": - hasPermission = await canPerformAccessProject( - authId, - projectId as string, - organizationId, - ); - break; - case "create": - hasPermission = await canPerformCreationProject(authId, organizationId); - break; - case "delete": - hasPermission = await canPerformDeleteProject(authId, organizationId); - break; - default: - hasPermission = false; - } - if (!hasPermission) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } + let hasPermission = false; + switch (action) { + case "access": + hasPermission = await canPerformAccessProject( + authId, + projectId as string, + organizationId, + ); + break; + case "create": + hasPermission = await canPerformCreationProject(authId, organizationId); + break; + case "delete": + hasPermission = await canPerformDeleteProject(authId, organizationId); + break; + default: + hasPermission = false; + } + if (!hasPermission) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } }; export const checkEnvironmentCreationPermission = async ( - userId: string, - projectId: string, - organizationId: string, + userId: string, + projectId: string, + organizationId: string, ) => { - // Get user's member record - const member = await findMemberById(userId, organizationId); + // Get user's member record + const member = await findMemberById(userId, organizationId); - if (!member) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "User not found in organization", - }); - } + if (!member) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "User not found in organization", + }); + } - // Owners and admins can always create environments - if (member.role === "owner" || member.role === "admin") { - return true; - } + // Owners and admins can always create environments + if (member.role === "owner" || member.role === "admin") { + return true; + } - // Check if user has canCreateEnvironments permission - if (!member.canCreateEnvironments) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have permission to create environments", - }); - } + // Check if user has canCreateEnvironments permission + if (!member.canCreateEnvironments) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have permission to create environments", + }); + } - // Check if user has access to the project - const hasProjectAccess = member.accessedProjects.includes(projectId); - if (!hasProjectAccess) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You don't have access to this project", - }); - } + // Check if user has access to the project + const hasProjectAccess = member.accessedProjects.includes(projectId); + if (!hasProjectAccess) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this project", + }); + } - return true; + return true; }; export const findMemberById = async ( - userId: string, - organizationId: string, + userId: string, + organizationId: string, ) => { - const result = await db.query.member.findFirst({ - where: and( - eq(member.userId, userId), - eq(member.organizationId, organizationId), - ), - with: { - user: true, - }, - }); + const result = await db.query.member.findFirst({ + where: and( + eq(member.userId, userId), + eq(member.organizationId, organizationId), + ), + with: { + user: true, + }, + }); - if (!result) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Permission denied", - }); - } - return result; + if (!result) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Permission denied", + }); + } + return result; }; export const updateUser = async (userId: string, userData: Partial) => { - // Validate email if it's being updated - if (userData.email !== undefined) { - if (!userData.email || userData.email.trim() === "") { - throw new Error("Email is required and cannot be empty"); - } + // Validate email if it's being updated + if (userData.email !== undefined) { + if (!userData.email || userData.email.trim() === "") { + throw new Error("Email is required and cannot be empty"); + } - // Basic email format validation - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(userData.email)) { - throw new Error("Please enter a valid email address"); - } - } + // Basic email format validation + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(userData.email)) { + throw new Error("Please enter a valid email address"); + } + } - const userResult = await db - .update(user) - .set({ - ...userData, - }) - .where(eq(user.id, userId)) - .returning() - .then((res) => res[0]); + const userResult = await db + .update(user) + .set({ + ...userData, + }) + .where(eq(user.id, userId)) + .returning() + .then((res) => res[0]); - return userResult; + return userResult; }; export const createApiKey = async ( - userId: string, - input: { - name: string; - prefix?: string; - expiresIn?: number; - metadata: { - organizationId: string; - }; - rateLimitEnabled?: boolean; - rateLimitTimeWindow?: number; - rateLimitMax?: number; - remaining?: number; - refillAmount?: number; - refillInterval?: number; - }, + userId: string, + input: { + name: string; + prefix?: string; + expiresIn?: number; + metadata: { + organizationId: string; + }; + rateLimitEnabled?: boolean; + rateLimitTimeWindow?: number; + rateLimitMax?: number; + remaining?: number; + refillAmount?: number; + refillInterval?: number; + }, ) => { - const result = await auth.createApiKey({ - body: { - name: input.name, - expiresIn: input.expiresIn, - prefix: input.prefix, - rateLimitEnabled: input.rateLimitEnabled, - rateLimitTimeWindow: input.rateLimitTimeWindow, - rateLimitMax: input.rateLimitMax, - remaining: input.remaining, - refillAmount: input.refillAmount, - refillInterval: input.refillInterval, - userId, - }, - }); + const result = await auth.createApiKey({ + body: { + name: input.name, + expiresIn: input.expiresIn, + prefix: input.prefix, + rateLimitEnabled: input.rateLimitEnabled, + rateLimitTimeWindow: input.rateLimitTimeWindow, + rateLimitMax: input.rateLimitMax, + remaining: input.remaining, + refillAmount: input.refillAmount, + refillInterval: input.refillInterval, + userId, + }, + }); - if (input.metadata) { - await db - .update(apikey) - .set({ metadata: JSON.stringify(input.metadata) }) - .where(eq(apikey.id, result.id)); - } + if (input.metadata) { + await db + .update(apikey) + .set({ metadata: JSON.stringify(input.metadata) }) + .where(eq(apikey.id, result.id)); + } - return result; + return result; }; diff --git a/packages/server/src/utils/builders/compose.ts b/packages/server/src/utils/builders/compose.ts index 32aecbd4c..316570626 100644 --- a/packages/server/src/utils/builders/compose.ts +++ b/packages/server/src/utils/builders/compose.ts @@ -5,26 +5,26 @@ import boxen from "boxen"; import { quote } from "shell-quote"; import { writeDomainsToCompose } from "../docker/domain"; import { - encodeBase64, - getEnvironmentVariablesObject, - prepareEnvironmentVariables, + encodeBase64, + getEnvironmentVariablesObject, + prepareEnvironmentVariables, } from "../docker/utils"; export type ComposeNested = InferResultType< - "compose", - { environment: { with: { project: true } }; mounts: true; domains: true } + "compose", + { environment: { with: { project: true } }; mounts: true; domains: true } >; export const getBuildComposeCommand = async (compose: ComposeNested) => { - const { COMPOSE_PATH } = paths(!!compose.serverId); - const { sourceType, appName, mounts, composeType, domains } = compose; - const command = createCommand(compose); - const envCommand = getCreateEnvFileCommand(compose); - const projectPath = join(COMPOSE_PATH, compose.appName, "code"); - const exportEnvCommand = getExportEnvCommand(compose); + const { COMPOSE_PATH } = paths(!!compose.serverId); + const { sourceType, appName, mounts, composeType, domains } = compose; + const command = createCommand(compose); + const envCommand = getCreateEnvFileCommand(compose); + const projectPath = join(COMPOSE_PATH, compose.appName, "code"); + const exportEnvCommand = getExportEnvCommand(compose); - const newCompose = await writeDomainsToCompose(compose, domains); - const logContent = ` + const newCompose = await writeDomainsToCompose(compose, domains); + const logContent = ` App Name: ${appName} Build Compose 🐳 Detected: ${mounts.length} mounts 📂 @@ -32,17 +32,17 @@ Command: docker ${command} Source Type: docker ${sourceType} ✅ Compose Type: ${composeType} ✅`; - const logBox = boxen(logContent, { - padding: { - left: 1, - right: 1, - bottom: 1, - }, - width: 80, - borderStyle: "double", - }); + const logBox = boxen(logContent, { + padding: { + left: 1, + right: 1, + bottom: 1, + }, + width: 80, + borderStyle: "double", + }); - const bashCommand = ` + const bashCommand = ` set -e { echo "${logBox}"; @@ -64,81 +64,81 @@ Compose Type: ${composeType} ✅`; } `; - return bashCommand; + return bashCommand; }; const sanitizeCommand = (command: string) => { - const sanitizedCommand = command.trim(); + const sanitizedCommand = command.trim(); - const parts = sanitizedCommand.split(/\s+/); + const parts = sanitizedCommand.split(/\s+/); - const restCommand = parts.map((arg) => arg.replace(/^"(.*)"$/, "$1")); + const restCommand = parts.map((arg) => arg.replace(/^"(.*)"$/, "$1")); - return restCommand.join(" "); + return restCommand.join(" "); }; export const createCommand = (compose: ComposeNested) => { - const { composeType, appName, sourceType } = compose; - if (compose.command) { - return `${sanitizeCommand(compose.command)}`; - } + const { composeType, appName, sourceType } = compose; + if (compose.command) { + return `${sanitizeCommand(compose.command)}`; + } - const path = - sourceType === "raw" ? "docker-compose.yml" : compose.composePath; - let command = ""; + const path = + sourceType === "raw" ? "docker-compose.yml" : compose.composePath; + let command = ""; - if (composeType === "docker-compose") { - command = `compose -p ${appName} -f ${path} up -d --build --remove-orphans`; - } else if (composeType === "stack") { - command = `stack deploy -c ${path} ${appName} --prune --with-registry-auth`; - } + if (composeType === "docker-compose") { + command = `compose -p ${appName} -f ${path} up -d --build --remove-orphans`; + } else if (composeType === "stack") { + command = `stack deploy -c ${path} ${appName} --prune --with-registry-auth`; + } - return command; + return command; }; export const getCreateEnvFileCommand = (compose: ComposeNested) => { - const { COMPOSE_PATH } = paths(!!compose.serverId); - const { env, composePath, appName } = compose; - const composeFilePath = - join(COMPOSE_PATH, appName, "code", composePath) || - join(COMPOSE_PATH, appName, "code", "docker-compose.yml"); + const { COMPOSE_PATH } = paths(!!compose.serverId); + const { env, composePath, appName } = compose; + const composeFilePath = + join(COMPOSE_PATH, appName, "code", composePath) || + join(COMPOSE_PATH, appName, "code", "docker-compose.yml"); - const envFilePath = join(dirname(composeFilePath), ".env"); + const envFilePath = join(dirname(composeFilePath), ".env"); - let envContent = `APP_NAME=${appName}\n`; - envContent += env || ""; - if (!envContent.includes("DOCKER_CONFIG")) { - envContent += "\nDOCKER_CONFIG=/root/.docker"; - } + let envContent = `APP_NAME=${appName}\n`; + envContent += env || ""; + if (!envContent.includes("DOCKER_CONFIG")) { + envContent += "\nDOCKER_CONFIG=/root/.docker"; + } - if (compose.randomize) { - envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`; - } + if (compose.randomize) { + envContent += `\nCOMPOSE_PREFIX=${compose.suffix}`; + } - const envFileContent = prepareEnvironmentVariables( - envContent, - compose.environment.project.env, - compose.environment.env, - ).join("\n"); + const envFileContent = prepareEnvironmentVariables( + envContent, + compose.environment.project.env, + compose.environment.env, + ).join("\n"); - const encodedContent = encodeBase64(envFileContent); - return ` + const encodedContent = encodeBase64(envFileContent); + return ` touch ${envFilePath}; echo "${encodedContent}" | base64 -d > "${envFilePath}"; `; }; const getExportEnvCommand = (compose: ComposeNested) => { - if (compose.composeType !== "stack") return ""; + if (compose.composeType !== "stack") return ""; - const envVars = getEnvironmentVariablesObject( - compose.env, - compose.environment.project.env, - compose.environment.env, - ); - const exports = Object.entries(envVars) - .map(([key, value]) => `${key}=${quote([value])}`) - .join(" "); + const envVars = getEnvironmentVariablesObject( + compose.env, + compose.environment.project.env, + compose.environment.env, + ); + const exports = Object.entries(envVars) + .map(([key, value]) => `${key}=${quote([value])}`) + .join(" "); - return exports ? `${exports}` : ""; + return exports ? `${exports}` : ""; }; diff --git a/packages/server/src/utils/builders/docker-file.ts b/packages/server/src/utils/builders/docker-file.ts index f2fedf461..b20e3f170 100644 --- a/packages/server/src/utils/builders/docker-file.ts +++ b/packages/server/src/utils/builders/docker-file.ts @@ -1,90 +1,90 @@ import { - getEnvironmentVariablesObject, - prepareEnvironmentVariablesForShell, + getEnvironmentVariablesObject, + prepareEnvironmentVariablesForShell, } from "@dokploy/server/utils/docker/utils"; import { quote } from "shell-quote"; import { - getBuildAppDirectory, - getDockerContextPath, + getBuildAppDirectory, + getDockerContextPath, } from "../filesystem/directory"; import type { ApplicationNested } from "."; import { createEnvFileCommand } from "./utils"; export const getDockerCommand = (application: ApplicationNested) => { - const { - appName, - env, - publishDirectory, - buildArgs, - buildSecrets, - dockerBuildStage, - cleanCache, - createEnvFile, - } = application; - const dockerFilePath = getBuildAppDirectory(application); + const { + appName, + env, + publishDirectory, + buildArgs, + buildSecrets, + dockerBuildStage, + cleanCache, + createEnvFile, + } = application; + const dockerFilePath = getBuildAppDirectory(application); - try { - const image = `${appName}`; + try { + const image = `${appName}`; - const defaultContextPath = - dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || "."; + const defaultContextPath = + dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || "."; - const dockerContextPath = - getDockerContextPath(application) || defaultContextPath; + const dockerContextPath = + getDockerContextPath(application) || defaultContextPath; - const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."]; + const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."]; - if (dockerBuildStage) { - commandArgs.push("--target", dockerBuildStage); - } + if (dockerBuildStage) { + commandArgs.push("--target", dockerBuildStage); + } - if (cleanCache) { - commandArgs.push("--no-cache"); - } + if (cleanCache) { + commandArgs.push("--no-cache"); + } - const args = prepareEnvironmentVariablesForShell( - buildArgs, - application.environment.project.env, - application.environment.env, - ); + const args = prepareEnvironmentVariablesForShell( + buildArgs, + application.environment.project.env, + application.environment.env, + ); - for (const arg of args) { - commandArgs.push("--build-arg", arg); - } + for (const arg of args) { + commandArgs.push("--build-arg", arg); + } - const secrets = getEnvironmentVariablesObject( - buildSecrets, - application.environment.project.env, - application.environment.env, - ); + const secrets = getEnvironmentVariablesObject( + buildSecrets, + application.environment.project.env, + application.environment.env, + ); - const joinedSecrets = Object.entries(secrets) - .map(([key, value]) => `${key}=${quote([value])}`) - .join(" "); + const joinedSecrets = Object.entries(secrets) + .map(([key, value]) => `${key}=${quote([value])}`) + .join(" "); - /* + /* Do not generate an environment file when publishDirectory is specified, as it could be publicly exposed. Also respect the createEnvFile flag. */ - let command = ""; - if (!publishDirectory && createEnvFile) { - command += createEnvFileCommand( - dockerFilePath, - env, - application.environment.project.env, - application.environment.env, - ); - } + let command = ""; + if (!publishDirectory && createEnvFile) { + command += createEnvFileCommand( + dockerFilePath, + env, + application.environment.project.env, + application.environment.env, + ); + } - for (const key in secrets) { - // Although buildx is smart enough to know we may be referring to an environment variable name, - // we still make sure it doesn't fall back to `type=file`. - // See: https://docs.docker.com/reference/cli/docker/buildx/build/#secret - commandArgs.push("--secret", `type=env,id=${key}`); - } + for (const key in secrets) { + // Although buildx is smart enough to know we may be referring to an environment variable name, + // we still make sure it doesn't fall back to `type=file`. + // See: https://docs.docker.com/reference/cli/docker/buildx/build/#secret + commandArgs.push("--secret", `type=env,id=${key}`); + } - command += ` + command += ` echo "Building ${appName}" ; cd ${dockerContextPath} || { echo "❌ The path ${dockerContextPath} does not exist" ; @@ -98,8 +98,8 @@ ${joinedSecrets} docker ${commandArgs.join(" ")} || { echo "✅ Docker build completed." ; `; - return command; - } catch (error) { - throw error; - } + return command; + } catch (error) { + throw error; + } }; From 9a1bee5287c9c7f57c6113a6fb15ae6243b8719b Mon Sep 17 00:00:00 2001 From: Tam Nguyen Date: Mon, 30 Mar 2026 09:32:05 +1100 Subject: [PATCH 06/25] fix: more grammar and spelling mistakes --- .../advanced/cluster/show-cluster-settings.tsx | 6 +++--- .../advanced/redirects/handle-redirect.tsx | 6 +++--- .../volume-backups/handle-volume-backups.tsx | 4 ++-- .../free/container/docker-block-chart.tsx | 6 +++--- .../free/container/docker-cpu-chart.tsx | 6 +++--- .../free/container/docker-disk-chart.tsx | 6 +++--- .../free/container/docker-memory-chart.tsx | 6 +++--- .../free/container/docker-network-chart.tsx | 6 +++--- .../show-free-container-monitoring.tsx | 18 +++++++++--------- .../git/gitlab/add-gitlab-provider.tsx | 2 +- .../git/gitlab/edit-gitlab-provider.tsx | 2 +- .../settings/servers/show-servers.tsx | 4 ++-- .../welcome-stripe/welcome-subscription.tsx | 2 +- .../dashboard/settings/users/change-role.tsx | 2 +- .../dashboard/settings/users/show-users.tsx | 2 +- apps/dokploy/components/ui/breadcrumb.tsx | 2 +- .../dokploy/server/api/routers/organization.ts | 4 ++-- apps/dokploy/server/api/trpc.ts | 2 +- 18 files changed, 43 insertions(+), 43 deletions(-) diff --git a/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx b/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx index 02db06345..95f849480 100644 --- a/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/cluster/show-cluster-settings.tsx @@ -40,12 +40,12 @@ interface Props { type: "application" | "mariadb" | "mongo" | "mysql" | "postgres" | "redis"; } -const AddRedirectchema = z.object({ +const AddRedirectSchema = z.object({ replicas: z.number().min(1, "Replicas must be at least 1"), registryId: z.string().optional(), }); -type AddCommand = z.infer; +type AddCommand = z.infer; export const ShowClusterSettings = ({ id, type }: Props) => { const queryMap = { @@ -87,7 +87,7 @@ export const ShowClusterSettings = ({ id, type }: Props) => { : {}), replicas: data?.replicas || 1, }, - resolver: zodResolver(AddRedirectchema), + resolver: zodResolver(AddRedirectSchema), }); useEffect(() => { diff --git a/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx b/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx index 603a6d6c8..683e0ebba 100644 --- a/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/redirects/handle-redirect.tsx @@ -37,13 +37,13 @@ import { Separator } from "@/components/ui/separator"; import { Switch } from "@/components/ui/switch"; import { api } from "@/utils/api"; -const AddRedirectchema = z.object({ +const AddRedirectSchema = z.object({ regex: z.string().min(1, "Regex required"), permanent: z.boolean().default(false), replacement: z.string().min(1, "Replacement required"), }); -type AddRedirect = z.infer; +type AddRedirect = z.infer; // Default presets const redirectPresets = [ @@ -110,7 +110,7 @@ export const HandleRedirect = ({ regex: "", replacement: "", }, - resolver: zodResolver(AddRedirectchema), + resolver: zodResolver(AddRedirectSchema), }); useEffect(() => { diff --git a/apps/dokploy/components/dashboard/application/volume-backups/handle-volume-backups.tsx b/apps/dokploy/components/dashboard/application/volume-backups/handle-volume-backups.tsx index 0d87080d7..f3d60f27f 100644 --- a/apps/dokploy/components/dashboard/application/volume-backups/handle-volume-backups.tsx +++ b/apps/dokploy/components/dashboard/application/volume-backups/handle-volume-backups.tsx @@ -483,7 +483,7 @@ export const HandleVolumeBackups = ({ - Choose the volume to backup, if you dont see the + Choose the volume to backup. If you do not see the volume here, you can type the volume name manually @@ -518,7 +518,7 @@ export const HandleVolumeBackups = ({ - Choose the volume to backup, if you dont see the volume + Choose the volume to backup. If you do not see the volume here, you can type the volume name manually diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx index 718ddafa4..6dc5cd90c 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx @@ -11,11 +11,11 @@ import { import type { DockerStatsJSON } from "./show-free-container-monitoring"; interface Props { - acummulativeData: DockerStatsJSON["block"]; + accumulativeData: DockerStatsJSON["block"]; } -export const DockerBlockChart = ({ acummulativeData }: Props) => { - const transformedData = acummulativeData.map((item, index) => { +export const DockerBlockChart = ({ accumulativeData }: Props) => { + const transformedData = accumulativeData.map((item, index) => { return { time: item.time, name: `Point ${index + 1}`, diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-cpu-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-cpu-chart.tsx index c24a63638..67404268b 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-cpu-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-cpu-chart.tsx @@ -11,11 +11,11 @@ import { import type { DockerStatsJSON } from "./show-free-container-monitoring"; interface Props { - acummulativeData: DockerStatsJSON["cpu"]; + accumulativeData: DockerStatsJSON["cpu"]; } -export const DockerCpuChart = ({ acummulativeData }: Props) => { - const transformedData = acummulativeData.map((item, index) => { +export const DockerCpuChart = ({ accumulativeData }: Props) => { + const transformedData = accumulativeData.map((item, index) => { return { name: `Point ${index + 1}`, time: item.time, diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-disk-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-disk-chart.tsx index 5fe62154c..58cefe6b3 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-disk-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-disk-chart.tsx @@ -11,12 +11,12 @@ import { import type { DockerStatsJSON } from "./show-free-container-monitoring"; interface Props { - acummulativeData: DockerStatsJSON["disk"]; + accumulativeData: DockerStatsJSON["disk"]; diskTotal: number; } -export const DockerDiskChart = ({ acummulativeData, diskTotal }: Props) => { - const transformedData = acummulativeData.map((item, index) => { +export const DockerDiskChart = ({ accumulativeData, diskTotal }: Props) => { + const transformedData = accumulativeData.map((item, index) => { return { time: item.time, name: `Point ${index + 1}`, diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-memory-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-memory-chart.tsx index 34a3913a7..226623fa2 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-memory-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-memory-chart.tsx @@ -12,15 +12,15 @@ import type { DockerStatsJSON } from "./show-free-container-monitoring"; import { convertMemoryToBytes } from "./show-free-container-monitoring"; interface Props { - acummulativeData: DockerStatsJSON["memory"]; + accumulativeData: DockerStatsJSON["memory"]; memoryLimitGB: number; } export const DockerMemoryChart = ({ - acummulativeData, + accumulativeData, memoryLimitGB, }: Props) => { - const transformedData = acummulativeData.map((item, index) => { + const transformedData = accumulativeData.map((item, index) => { return { time: item.time, name: `Point ${index + 1}`, diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx index 5e2414cea..8dafcb465 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx @@ -11,11 +11,11 @@ import { import type { DockerStatsJSON } from "./show-free-container-monitoring"; interface Props { - acummulativeData: DockerStatsJSON["network"]; + accumulativeData: DockerStatsJSON["network"]; } -export const DockerNetworkChart = ({ acummulativeData }: Props) => { - const transformedData = acummulativeData.map((item, index) => { +export const DockerNetworkChart = ({ accumulativeData }: Props) => { + const transformedData = accumulativeData.map((item, index) => { return { time: item.time, name: `Point ${index + 1}`, diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx index 42bb361bb..6e572c224 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx @@ -124,7 +124,7 @@ export const ContainerFreeMonitoring = ({ refetchOnWindowFocus: false, }, ); - const [acummulativeData, setAcummulativeData] = useState({ + const [accumulativeData, setAccumulativeData] = useState({ cpu: [], memory: [], block: [], @@ -136,7 +136,7 @@ export const ContainerFreeMonitoring = ({ useEffect(() => { setCurrentData(defaultData); - setAcummulativeData({ + setAccumulativeData({ cpu: [], memory: [], block: [], @@ -155,7 +155,7 @@ export const ContainerFreeMonitoring = ({ network: data.network[data.network.length - 1] ?? currentData.network, disk: data.disk[data.disk.length - 1] ?? currentData.disk, }); - setAcummulativeData({ + setAccumulativeData({ block: data?.block || [], cpu: data?.cpu || [], disk: data?.disk || [], @@ -184,7 +184,7 @@ export const ContainerFreeMonitoring = ({ setCurrentData(data); const MAX_DATA_POINTS = 300; - setAcummulativeData((prevData) => ({ + setAccumulativeData((prevData) => ({ cpu: [...prevData.cpu, data.cpu].slice(-MAX_DATA_POINTS), memory: [...prevData.memory, data.memory].slice(-MAX_DATA_POINTS), block: [...prevData.block, data.block].slice(-MAX_DATA_POINTS), @@ -228,7 +228,7 @@ export const ContainerFreeMonitoring = ({ )} className="w-[100%]" /> - +
    @@ -252,7 +252,7 @@ export const ContainerFreeMonitoring = ({ className="w-[100%]" />
    @@ -294,7 +294,7 @@ export const ContainerFreeMonitoring = ({ {`Read: ${currentData.block.value.readMb} / Write: ${currentData.block.value.writeMb} `} - +
@@ -307,7 +307,7 @@ export const ContainerFreeMonitoring = ({ {`In MB: ${currentData.network.value.inputMb} / Out MB: ${currentData.network.value.outputMb} `} - +
diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx index 7c637f5ef..863d5d0f1 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx @@ -283,7 +283,7 @@ export const AddGitlabProvider = () => { diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx index e48df084b..73c3b4523 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx @@ -192,7 +192,7 @@ export const EditGitlabProvider = ({ gitlabId }: Props) => { diff --git a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx index 7342aafb4..1326c554a 100644 --- a/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/show-servers.tsx @@ -48,7 +48,7 @@ import { ShowMonitoringModal } from "./show-monitoring-modal"; import { ShowSchedulesModal } from "./show-schedules-modal"; import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal"; import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal"; -import { Welcomesubscription } from "./welcome-stripe/welcome-subscription"; +import { WelcomeSubscription } from "./welcome-stripe/welcome-subscription"; export const ShowServers = () => { const router = useRouter(); @@ -63,7 +63,7 @@ export const ShowServers = () => { return (
- {query?.success && isCloud && } + {query?.success && isCloud && }
diff --git a/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx b/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx index 295b53516..91dce72b9 100644 --- a/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/welcome-stripe/welcome-subscription.tsx @@ -51,7 +51,7 @@ export const { useStepper, steps, Scoped } = defineStepper( { id: "complete", title: "Complete", description: "Checkout complete" }, ); -export const Welcomesubscription = () => { +export const WelcomeSubscription = () => { const [showConfetti, setShowConfetti] = useState(false); const stepper = useStepper(); const [isOpen, setIsOpen] = useState(true); diff --git a/apps/dokploy/components/dashboard/settings/users/change-role.tsx b/apps/dokploy/components/dashboard/settings/users/change-role.tsx index 2178284b1..dfa35a28d 100644 --- a/apps/dokploy/components/dashboard/settings/users/change-role.tsx +++ b/apps/dokploy/components/dashboard/settings/users/change-role.tsx @@ -153,7 +153,7 @@ export const ChangeRole = ({ memberId, currentRole, userEmail }: Props) => { )}
- Note: Owner role is intransferible. + Note: Owner role is nontransferable. diff --git a/apps/dokploy/components/dashboard/settings/users/show-users.tsx b/apps/dokploy/components/dashboard/settings/users/show-users.tsx index 75aa839f9..23356dcd4 100644 --- a/apps/dokploy/components/dashboard/settings/users/show-users.tsx +++ b/apps/dokploy/components/dashboard/settings/users/show-users.tsx @@ -122,7 +122,7 @@ export const ShowUsers = () => { // Can change role based on hierarchy: // - Owner: Can change anyone's role (except themselves and other owners) // - Admin: Can only change member/custom roles (not other admins or owners) - // - Owner role is intransferible + // - Owner role is nontransferable const canChangeRole = member.role !== "owner" && member.user.id !== session?.user?.id && diff --git a/apps/dokploy/components/ui/breadcrumb.tsx b/apps/dokploy/components/ui/breadcrumb.tsx index a189f6fa1..8bf95ea32 100644 --- a/apps/dokploy/components/ui/breadcrumb.tsx +++ b/apps/dokploy/components/ui/breadcrumb.tsx @@ -101,7 +101,7 @@ const BreadcrumbEllipsis = ({ More ); -BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"; +BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis"; export { Breadcrumb, diff --git a/apps/dokploy/server/api/routers/organization.ts b/apps/dokploy/server/api/routers/organization.ts index 2f7d45287..47d0fc75f 100644 --- a/apps/dokploy/server/api/routers/organization.ts +++ b/apps/dokploy/server/api/routers/organization.ts @@ -409,11 +409,11 @@ export const organizationRouter = createTRPCRouter({ }); } - // Owner role is intransferible - cannot change to or from owner + // Owner role is nontransferable - cannot change to or from owner if (target.role === "owner" || input.role === "owner") { throw new TRPCError({ code: "FORBIDDEN", - message: "The owner role is intransferible", + message: "The owner role is nontransferable", }); } diff --git a/apps/dokploy/server/api/trpc.ts b/apps/dokploy/server/api/trpc.ts index 486640349..d0b43e76f 100644 --- a/apps/dokploy/server/api/trpc.ts +++ b/apps/dokploy/server/api/trpc.ts @@ -106,7 +106,7 @@ export const createTRPCContext = async (opts: CreateNextContextOptions) => { * 2. INITIALIZATION * * This is where the tRPC API is initialized, connecting the context and transformer. We also parse - * ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation + * ZodErrors so that you get type safety on the frontend if your procedure fails due to validation * errors on the backend. */ From f83ab2923d399b725a07f5ca755e3bbd33ddc300 Mon Sep 17 00:00:00 2001 From: Tam Nguyen Date: Mon, 30 Mar 2026 09:33:38 +1100 Subject: [PATCH 07/25] stlye: format and lint --- .../permissions/enterprise-only-resources.test.ts | 2 +- .../application/deployments/show-deployments.tsx | 2 +- .../components/dashboard/application/patches/index.ts | 2 +- .../components/dashboard/deployments/show-queue-table.tsx | 2 +- .../settings/destination/handle-destinations.tsx | 8 ++++---- .../settings/notifications/handle-notifications.tsx | 2 +- apps/dokploy/lib/auth-client.ts | 2 +- apps/dokploy/pages/api/deploy/compose/[refreshToken].ts | 2 +- apps/dokploy/pages/dashboard/settings/users.tsx | 4 ++-- apps/dokploy/server/api/routers/ai.ts | 2 +- apps/dokploy/server/api/routers/backup.ts | 2 +- apps/dokploy/server/api/routers/certificate.ts | 2 +- apps/dokploy/server/api/routers/compose.ts | 4 ++-- apps/dokploy/server/api/routers/git-provider.ts | 2 +- apps/dokploy/server/api/routers/mongo.ts | 7 ++++--- apps/dokploy/server/api/routers/mysql.ts | 4 ++-- apps/dokploy/server/api/routers/organization.ts | 2 +- apps/dokploy/server/api/routers/postgres.ts | 7 ++++--- apps/dokploy/server/api/routers/redis.ts | 7 ++++--- apps/dokploy/server/api/routers/registry.ts | 2 +- apps/dokploy/server/api/routers/schedule.ts | 2 +- apps/dokploy/server/api/routers/server.ts | 2 +- apps/dokploy/server/api/routers/ssh-key.ts | 2 +- apps/dokploy/server/api/utils/audit.ts | 2 +- packages/server/auth-schema2.ts | 6 +++--- packages/server/src/db/schema/index.ts | 2 +- packages/server/src/db/schema/volume-backups.ts | 2 +- packages/server/src/services/deployment.ts | 2 +- packages/server/src/services/proprietary/audit-log.ts | 2 +- packages/server/src/utils/providers/github.ts | 2 +- packages/server/src/utils/providers/gitlab.ts | 2 +- 31 files changed, 48 insertions(+), 45 deletions(-) diff --git a/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts b/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts index 3138085e3..bb6f5f18b 100644 --- a/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts +++ b/apps/dokploy/__test__/permissions/enterprise-only-resources.test.ts @@ -1,8 +1,8 @@ -import { describe, it, expect } from "vitest"; import { enterpriseOnlyResources, statements, } from "@dokploy/server/lib/access-control"; +import { describe, expect, it } from "vitest"; const FREE_TIER_RESOURCES = [ "organization", diff --git a/apps/dokploy/components/dashboard/application/deployments/show-deployments.tsx b/apps/dokploy/components/dashboard/application/deployments/show-deployments.tsx index 3cecef1ec..ccf2564b0 100644 --- a/apps/dokploy/components/dashboard/application/deployments/show-deployments.tsx +++ b/apps/dokploy/components/dashboard/application/deployments/show-deployments.tsx @@ -1,3 +1,4 @@ +import copy from "copy-to-clipboard"; import { ChevronDown, ChevronUp, @@ -11,7 +12,6 @@ import { } from "lucide-react"; import React, { useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; -import copy from "copy-to-clipboard"; import { AlertBlock } from "@/components/shared/alert-block"; import { DateTooltip } from "@/components/shared/date-tooltip"; import { DialogAction } from "@/components/shared/dialog-action"; diff --git a/apps/dokploy/components/dashboard/application/patches/index.ts b/apps/dokploy/components/dashboard/application/patches/index.ts index 1854bd3e5..053e644b7 100644 --- a/apps/dokploy/components/dashboard/application/patches/index.ts +++ b/apps/dokploy/components/dashboard/application/patches/index.ts @@ -1,2 +1,2 @@ -export * from "./show-patches"; export * from "./patch-editor"; +export * from "./show-patches"; diff --git a/apps/dokploy/components/dashboard/deployments/show-queue-table.tsx b/apps/dokploy/components/dashboard/deployments/show-queue-table.tsx index e46b33a6a..22b132f16 100644 --- a/apps/dokploy/components/dashboard/deployments/show-queue-table.tsx +++ b/apps/dokploy/components/dashboard/deployments/show-queue-table.tsx @@ -1,8 +1,8 @@ "use client"; import type { inferRouterOutputs } from "@trpc/server"; -import Link from "next/link"; import { ArrowRight, ListTodo, Loader2, XCircle } from "lucide-react"; +import Link from "next/link"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { diff --git a/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx b/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx index 25a3a1048..e7ecf92b2 100644 --- a/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx +++ b/apps/dokploy/components/dashboard/settings/destination/handle-destinations.tsx @@ -1,3 +1,7 @@ +import { + ADDITIONAL_FLAG_ERROR, + ADDITIONAL_FLAG_REGEX, +} from "@dokploy/server/db/validations/destination"; import { standardSchemaResolver as zodResolver } from "@hookform/resolvers/standard-schema"; import { PenBoxIcon, PlusIcon, Trash2 } from "lucide-react"; import { useEffect, useState } from "react"; @@ -35,10 +39,6 @@ import { } from "@/components/ui/select"; import { cn } from "@/lib/utils"; import { api } from "@/utils/api"; -import { - ADDITIONAL_FLAG_ERROR, - ADDITIONAL_FLAG_REGEX, -} from "@dokploy/server/db/validations/destination"; import { S3_PROVIDERS } from "./constants"; const addDestination = z.object({ diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index 28d762c1c..0617aa68d 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -12,9 +12,9 @@ import { toast } from "sonner"; import { z } from "zod"; import { DiscordIcon, - MattermostIcon, GotifyIcon, LarkIcon, + MattermostIcon, NtfyIcon, PushoverIcon, ResendIcon, diff --git a/apps/dokploy/lib/auth-client.ts b/apps/dokploy/lib/auth-client.ts index 6d786cc11..864ba1f68 100644 --- a/apps/dokploy/lib/auth-client.ts +++ b/apps/dokploy/lib/auth-client.ts @@ -1,5 +1,5 @@ -import { ssoClient } from "@better-auth/sso/client"; import { apiKeyClient } from "@better-auth/api-key/client"; +import { ssoClient } from "@better-auth/sso/client"; import { adminClient, inferAdditionalFields, diff --git a/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts b/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts index c998e83b9..640a2531d 100644 --- a/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts +++ b/apps/dokploy/pages/api/deploy/compose/[refreshToken].ts @@ -8,8 +8,8 @@ import { myQueue } from "@/server/queues/queueSetup"; import { deploy } from "@/server/utils/deploy"; import { extractBranchName, - extractCommittedPaths, extractCommitMessage, + extractCommittedPaths, extractHash, getProviderByHeader, } from "../[refreshToken]"; diff --git a/apps/dokploy/pages/dashboard/settings/users.tsx b/apps/dokploy/pages/dashboard/settings/users.tsx index 43c014279..a3bd953d1 100644 --- a/apps/dokploy/pages/dashboard/settings/users.tsx +++ b/apps/dokploy/pages/dashboard/settings/users.tsx @@ -3,10 +3,10 @@ import { createServerSideHelpers } from "@trpc/react-query/server"; import type { GetServerSidePropsContext } from "next"; import type { ReactElement } from "react"; import superjson from "superjson"; -import { DashboardLayout } from "@/components/layouts/dashboard-layout"; -import { ManageCustomRoles } from "@/components/proprietary/roles/manage-custom-roles"; import { ShowInvitations } from "@/components/dashboard/settings/users/show-invitations"; import { ShowUsers } from "@/components/dashboard/settings/users/show-users"; +import { DashboardLayout } from "@/components/layouts/dashboard-layout"; +import { ManageCustomRoles } from "@/components/proprietary/roles/manage-custom-roles"; import { appRouter } from "@/server/api/root"; import { api } from "@/utils/api"; diff --git a/apps/dokploy/server/api/routers/ai.ts b/apps/dokploy/server/api/routers/ai.ts index b46fcf99a..a4527497d 100644 --- a/apps/dokploy/server/api/routers/ai.ts +++ b/apps/dokploy/server/api/routers/ai.ts @@ -17,11 +17,11 @@ import { suggestVariants, } from "@dokploy/server/services/ai"; import { createComposeByTemplate } from "@dokploy/server/services/compose"; -import { findProjectById } from "@dokploy/server/services/project"; import { addNewService, checkServiceAccess, } from "@dokploy/server/services/permission"; +import { findProjectById } from "@dokploy/server/services/project"; import { getProviderHeaders, getProviderName, diff --git a/apps/dokploy/server/api/routers/backup.ts b/apps/dokploy/server/api/routers/backup.ts index 6d358f631..ad3b40622 100644 --- a/apps/dokploy/server/api/routers/backup.ts +++ b/apps/dokploy/server/api/routers/backup.ts @@ -28,6 +28,7 @@ import { updateBackupById, } from "@dokploy/server"; import { findDestinationById } from "@dokploy/server/services/destination"; +import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission"; import { runComposeBackup } from "@dokploy/server/utils/backups/compose"; import { getS3Credentials, @@ -53,7 +54,6 @@ import { protectedProcedure, withPermission, } from "@/server/api/trpc"; -import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission"; import { audit } from "@/server/api/utils/audit"; import { apiCreateBackup, diff --git a/apps/dokploy/server/api/routers/certificate.ts b/apps/dokploy/server/api/routers/certificate.ts index 0ebd33e7f..e506a846b 100644 --- a/apps/dokploy/server/api/routers/certificate.ts +++ b/apps/dokploy/server/api/routers/certificate.ts @@ -7,8 +7,8 @@ import { import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, withPermission } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiCreateCertificate, apiFindCertificate, diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index 0d3782eab..6e272a6cc 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -31,13 +31,13 @@ import { updateCompose, updateDeploymentStatus, } from "@dokploy/server"; +import { db } from "@dokploy/server/db"; import { addNewService, checkServiceAccess, checkServicePermissionAndAccess, findMemberByUserId, } from "@dokploy/server/services/permission"; -import { db } from "@dokploy/server/db"; import { type CompleteTemplate, fetchTemplateFiles, @@ -75,8 +75,8 @@ import { } from "@/server/queues/queueSetup"; import { cancelDeployment, deploy } from "@/server/utils/deploy"; import { generatePassword } from "@/templates/utils"; -import { audit } from "../utils/audit"; import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; +import { audit } from "../utils/audit"; export const composeRouter = createTRPCRouter({ create: protectedProcedure diff --git a/apps/dokploy/server/api/routers/git-provider.ts b/apps/dokploy/server/api/routers/git-provider.ts index b0aa8627d..0b186ae9a 100644 --- a/apps/dokploy/server/api/routers/git-provider.ts +++ b/apps/dokploy/server/api/routers/git-provider.ts @@ -2,12 +2,12 @@ import { findGitProviderById, removeGitProvider } from "@dokploy/server"; import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { and, desc, eq } from "drizzle-orm"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure, withPermission, } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiRemoveGitProvider, gitProvider } from "@/server/db/schema"; export const gitProviderRouter = createTRPCRouter({ diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts index a64535e24..37d8c23f6 100644 --- a/apps/dokploy/server/api/routers/mongo.ts +++ b/apps/dokploy/server/api/routers/mongo.ts @@ -17,18 +17,18 @@ import { stopServiceRemote, updateMongoById, } from "@dokploy/server"; +import { db } from "@dokploy/server/db"; import { addNewService, checkServiceAccess, checkServicePermissionAndAccess, findMemberByUserId, } from "@dokploy/server/services/permission"; -import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { and, desc, eq, ilike, or, sql } from "drizzle-orm"; import { z } from "zod"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiChangeMongoStatus, apiCreateMongo, @@ -39,9 +39,10 @@ import { apiSaveEnvironmentVariablesMongo, apiSaveExternalPortMongo, apiUpdateMongo, + environments, mongo as mongoTable, + projects, } from "@/server/db/schema"; -import { environments, projects } from "@/server/db/schema"; import { cancelJobs } from "@/server/utils/backup"; export const mongoRouter = createTRPCRouter({ create: protectedProcedure diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts index abb0f97a7..e611dab1d 100644 --- a/apps/dokploy/server/api/routers/mysql.ts +++ b/apps/dokploy/server/api/routers/mysql.ts @@ -17,18 +17,18 @@ import { stopServiceRemote, updateMySqlById, } from "@dokploy/server"; +import { db } from "@dokploy/server/db"; import { addNewService, checkServiceAccess, checkServicePermissionAndAccess, findMemberByUserId, } from "@dokploy/server/services/permission"; -import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { and, desc, eq, ilike, or, sql } from "drizzle-orm"; import { z } from "zod"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiChangeMySqlStatus, apiCreateMySql, diff --git a/apps/dokploy/server/api/routers/organization.ts b/apps/dokploy/server/api/routers/organization.ts index 47d0fc75f..2f9da6d71 100644 --- a/apps/dokploy/server/api/routers/organization.ts +++ b/apps/dokploy/server/api/routers/organization.ts @@ -1,10 +1,10 @@ import { db } from "@dokploy/server/db"; import { IS_CLOUD } from "@dokploy/server/index"; -import { audit } from "@/server/api/utils/audit"; import { TRPCError } from "@trpc/server"; import { and, desc, eq, exists } from "drizzle-orm"; import { nanoid } from "nanoid"; import { z } from "zod"; +import { audit } from "@/server/api/utils/audit"; import { invitation, member, diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts index 3b3cfd208..44984ee43 100644 --- a/apps/dokploy/server/api/routers/postgres.ts +++ b/apps/dokploy/server/api/routers/postgres.ts @@ -18,18 +18,18 @@ import { stopServiceRemote, updatePostgresById, } from "@dokploy/server"; +import { db } from "@dokploy/server/db"; import { addNewService, checkServiceAccess, checkServicePermissionAndAccess, findMemberByUserId, } from "@dokploy/server/services/permission"; -import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { and, desc, eq, ilike, or, sql } from "drizzle-orm"; import { z } from "zod"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiChangePostgresStatus, apiCreatePostgres, @@ -40,9 +40,10 @@ import { apiSaveEnvironmentVariablesPostgres, apiSaveExternalPortPostgres, apiUpdatePostgres, + environments, postgres as postgresTable, + projects, } from "@/server/db/schema"; -import { environments, projects } from "@/server/db/schema"; import { cancelJobs } from "@/server/utils/backup"; export const postgresRouter = createTRPCRouter({ diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts index 01d922aa4..c2c65878e 100644 --- a/apps/dokploy/server/api/routers/redis.ts +++ b/apps/dokploy/server/api/routers/redis.ts @@ -16,18 +16,18 @@ import { stopServiceRemote, updateRedisById, } from "@dokploy/server"; +import { db } from "@dokploy/server/db"; import { addNewService, checkServiceAccess, checkServicePermissionAndAccess, findMemberByUserId, } from "@dokploy/server/services/permission"; -import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { and, desc, eq, ilike, or, sql } from "drizzle-orm"; import { z } from "zod"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiChangeRedisStatus, apiCreateRedis, @@ -38,9 +38,10 @@ import { apiSaveEnvironmentVariablesRedis, apiSaveExternalPortRedis, apiUpdateRedis, + environments, + projects, redis as redisTable, } from "@/server/db/schema"; -import { environments, projects } from "@/server/db/schema"; export const redisRouter = createTRPCRouter({ create: protectedProcedure .input(apiCreateRedis) diff --git a/apps/dokploy/server/api/routers/registry.ts b/apps/dokploy/server/api/routers/registry.ts index 7e2174419..1b156c069 100644 --- a/apps/dokploy/server/api/routers/registry.ts +++ b/apps/dokploy/server/api/routers/registry.ts @@ -10,6 +10,7 @@ import { import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; +import { audit } from "@/server/api/utils/audit"; import { apiCreateRegistry, apiFindOneRegistry, @@ -19,7 +20,6 @@ import { apiUpdateRegistry, registry, } from "@/server/db/schema"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, withPermission } from "../trpc"; export const registryRouter = createTRPCRouter({ create: withPermission("registry", "create") diff --git a/apps/dokploy/server/api/routers/schedule.ts b/apps/dokploy/server/api/routers/schedule.ts index 2563fd7ac..40a7202a4 100644 --- a/apps/dokploy/server/api/routers/schedule.ts +++ b/apps/dokploy/server/api/routers/schedule.ts @@ -7,6 +7,7 @@ import { updateScheduleSchema, } from "@dokploy/server/db/schema/schedule"; import { runCommand } from "@dokploy/server/index"; +import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission"; import { createSchedule, deleteSchedule, @@ -18,7 +19,6 @@ import { desc, eq } from "drizzle-orm"; import { z } from "zod"; import { audit } from "@/server/api/utils/audit"; import { removeJob, schedule } from "@/server/utils/backup"; -import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission"; import { createTRPCRouter, protectedProcedure } from "../trpc"; export const scheduleRouter = createTRPCRouter({ create: protectedProcedure diff --git a/apps/dokploy/server/api/routers/server.ts b/apps/dokploy/server/api/routers/server.ts index bfad8836a..785be19b8 100644 --- a/apps/dokploy/server/api/routers/server.ts +++ b/apps/dokploy/server/api/routers/server.ts @@ -21,12 +21,12 @@ import { observable } from "@trpc/server/observable"; import { and, desc, eq, getTableColumns, isNotNull, sql } from "drizzle-orm"; import { z } from "zod"; import { updateServersBasedOnQuantity } from "@/pages/api/stripe/webhook"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, protectedProcedure, withPermission, } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiCreateServer, apiFindOneServer, diff --git a/apps/dokploy/server/api/routers/ssh-key.ts b/apps/dokploy/server/api/routers/ssh-key.ts index 74aeb5e58..68ab14616 100644 --- a/apps/dokploy/server/api/routers/ssh-key.ts +++ b/apps/dokploy/server/api/routers/ssh-key.ts @@ -8,8 +8,8 @@ import { import { db } from "@dokploy/server/db"; import { TRPCError } from "@trpc/server"; import { desc, eq } from "drizzle-orm"; -import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, withPermission } from "@/server/api/trpc"; +import { audit } from "@/server/api/utils/audit"; import { apiCreateSshKey, apiFindOneSshKey, diff --git a/apps/dokploy/server/api/utils/audit.ts b/apps/dokploy/server/api/utils/audit.ts index 9f73befbf..64f46dea4 100644 --- a/apps/dokploy/server/api/utils/audit.ts +++ b/apps/dokploy/server/api/utils/audit.ts @@ -1,5 +1,5 @@ -import { createAuditLog } from "@dokploy/server/services/proprietary/audit-log"; import type { AuditAction, AuditResourceType } from "@dokploy/server/db/schema"; +import { createAuditLog } from "@dokploy/server/services/proprietary/audit-log"; interface AuditCtx { user: { id: string; email: string; role: string }; diff --git a/packages/server/auth-schema2.ts b/packages/server/auth-schema2.ts index 9c163c820..cb2202832 100644 --- a/packages/server/auth-schema2.ts +++ b/packages/server/auth-schema2.ts @@ -1,11 +1,11 @@ import { relations } from "drizzle-orm"; import { + boolean, + index, + integer, pgTable, text, timestamp, - boolean, - integer, - index, uniqueIndex, } from "drizzle-orm/pg-core"; diff --git a/packages/server/src/db/schema/index.ts b/packages/server/src/db/schema/index.ts index 7873345ab..a4e613a02 100644 --- a/packages/server/src/db/schema/index.ts +++ b/packages/server/src/db/schema/index.ts @@ -1,7 +1,7 @@ export * from "./account"; export * from "./ai"; -export * from "./audit-log"; export * from "./application"; +export * from "./audit-log"; export * from "./backups"; export * from "./bitbucket"; export * from "./certificate"; diff --git a/packages/server/src/db/schema/volume-backups.ts b/packages/server/src/db/schema/volume-backups.ts index 0a5ecf898..fd3b48253 100644 --- a/packages/server/src/db/schema/volume-backups.ts +++ b/packages/server/src/db/schema/volume-backups.ts @@ -1,6 +1,5 @@ import { relations } from "drizzle-orm"; import { boolean, integer, pgTable, text } from "drizzle-orm/pg-core"; -import { serviceType } from "./mount"; import { createInsertSchema } from "drizzle-zod"; import { nanoid } from "nanoid"; import { z } from "zod"; @@ -11,6 +10,7 @@ import { destinations } from "./destination"; import { libsql } from "./libsql"; import { mariadb } from "./mariadb"; import { mongo } from "./mongo"; +import { serviceType } from "./mount"; import { mysql } from "./mysql"; import { postgres } from "./postgres"; import { redis } from "./redis"; diff --git a/packages/server/src/services/deployment.ts b/packages/server/src/services/deployment.ts index 7b6f0c730..a5ff57779 100644 --- a/packages/server/src/services/deployment.ts +++ b/packages/server/src/services/deployment.ts @@ -23,7 +23,7 @@ import { } from "@dokploy/server/utils/process/execAsync"; import { TRPCError } from "@trpc/server"; import { format } from "date-fns"; -import { desc, eq, and, inArray, or, sql } from "drizzle-orm"; +import { and, desc, eq, inArray, or, sql } from "drizzle-orm"; import type { z } from "zod"; import { type Application, diff --git a/packages/server/src/services/proprietary/audit-log.ts b/packages/server/src/services/proprietary/audit-log.ts index 157e75c9b..8cf4e0055 100644 --- a/packages/server/src/services/proprietary/audit-log.ts +++ b/packages/server/src/services/proprietary/audit-log.ts @@ -1,6 +1,6 @@ import { db } from "@dokploy/server/db"; -import { auditLog } from "@dokploy/server/db/schema"; import type { AuditAction, AuditResourceType } from "@dokploy/server/db/schema"; +import { auditLog } from "@dokploy/server/db/schema"; import { hasValidLicense } from "@dokploy/server/services/proprietary/license-key"; import { and, desc, eq, gte, ilike, lte } from "drizzle-orm"; diff --git a/packages/server/src/utils/providers/github.ts b/packages/server/src/utils/providers/github.ts index b32133681..6309cf307 100644 --- a/packages/server/src/utils/providers/github.ts +++ b/packages/server/src/utils/providers/github.ts @@ -5,8 +5,8 @@ import { findGithubById, type Github } from "@dokploy/server/services/github"; import type { InferResultType } from "@dokploy/server/types/with"; import { createAppAuth } from "@octokit/auth-app"; import { TRPCError } from "@trpc/server"; -import type { z } from "zod"; import { Octokit } from "octokit"; +import type { z } from "zod"; export const authGithub = (githubProvider: Github): Octokit => { if (!haveGithubRequirements(githubProvider)) { diff --git a/packages/server/src/utils/providers/gitlab.ts b/packages/server/src/utils/providers/gitlab.ts index e8e4af2a5..df6801a45 100644 --- a/packages/server/src/utils/providers/gitlab.ts +++ b/packages/server/src/utils/providers/gitlab.ts @@ -1,7 +1,6 @@ import { join } from "node:path"; import { paths } from "@dokploy/server/constants"; import type { apiGitlabTestConnection } from "@dokploy/server/db/schema"; -import type { z } from "zod"; import { findGitlabById, type Gitlab, @@ -9,6 +8,7 @@ import { } from "@dokploy/server/services/gitlab"; import type { InferResultType } from "@dokploy/server/types/with"; import { TRPCError } from "@trpc/server"; +import type { z } from "zod"; export const refreshGitlabToken = async (gitlabProviderId: string) => { const gitlabProvider = await findGitlabById(gitlabProviderId); From 4a7e9a200e5f4a45781134daf55211aecba88c5b Mon Sep 17 00:00:00 2001 From: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:52:36 +1100 Subject: [PATCH 08/25] fix: use slug instead of sluggish Update apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .../dashboard/settings/git/gitlab/add-gitlab-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx index 863d5d0f1..b0ecb7eef 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx @@ -283,7 +283,7 @@ export const AddGitlabProvider = () => { From dab13a52d6ea5209db09a6bc44d9e46e4be591bf Mon Sep 17 00:00:00 2001 From: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:52:51 +1100 Subject: [PATCH 09/25] fix: use slug instead of sluggish Update apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .../dashboard/settings/git/gitlab/edit-gitlab-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx index 73c3b4523..27178bff9 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx @@ -192,7 +192,7 @@ export const EditGitlabProvider = ({ gitlabId }: Props) => { From c4aca74aef98facd8df3f2e0f1338037cf48b61a Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 22:53:14 +0000 Subject: [PATCH 10/25] [autofix.ci] apply automated fixes --- .../dashboard/settings/git/gitlab/add-gitlab-provider.tsx | 2 +- .../dashboard/settings/git/gitlab/edit-gitlab-provider.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx index b0ecb7eef..b48f8253b 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/add-gitlab-provider.tsx @@ -283,7 +283,7 @@ export const AddGitlabProvider = () => { diff --git a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx index 27178bff9..43c174055 100644 --- a/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/gitlab/edit-gitlab-provider.tsx @@ -192,7 +192,7 @@ export const EditGitlabProvider = ({ gitlabId }: Props) => { From 780406f9ef7f5761ba422e39d70d0f82cc12eae2 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Mon, 30 Mar 2026 16:45:49 -0600 Subject: [PATCH 11/25] Remove unused SQL file and related journal entries for '0119_wakeful_luke_cage' notification type --- .../drizzle/0119_wakeful_luke_cage.sql | 1 - apps/dokploy/drizzle/meta/0119_snapshot.json | 6686 ----------------- apps/dokploy/drizzle/meta/_journal.json | 7 - 3 files changed, 6694 deletions(-) delete mode 100644 apps/dokploy/drizzle/0119_wakeful_luke_cage.sql delete mode 100644 apps/dokploy/drizzle/meta/0119_snapshot.json diff --git a/apps/dokploy/drizzle/0119_wakeful_luke_cage.sql b/apps/dokploy/drizzle/0119_wakeful_luke_cage.sql deleted file mode 100644 index d5bdd5b7e..000000000 --- a/apps/dokploy/drizzle/0119_wakeful_luke_cage.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "notification" ADD COLUMN "dokployBackup" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0119_snapshot.json b/apps/dokploy/drizzle/meta/0119_snapshot.json deleted file mode 100644 index fe812a7e1..000000000 --- a/apps/dokploy/drizzle/meta/0119_snapshot.json +++ /dev/null @@ -1,6686 +0,0 @@ -{ - "id": "fa97e3a5-7b0c-4d4f-8102-773064782957", - "prevId": "e7d24dad-8dc2-4c17-b27a-1f5240b8ffeb", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.account": { - "name": "account", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "account_id": { - "name": "account_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider_id": { - "name": "provider_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "id_token": { - "name": "id_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token_expires_at": { - "name": "access_token_expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "refresh_token_expires_at": { - "name": "refresh_token_expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "scope": { - "name": "scope", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "password": { - "name": "password", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "is2FAEnabled": { - "name": "is2FAEnabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "resetPasswordToken": { - "name": "resetPasswordToken", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "resetPasswordExpiresAt": { - "name": "resetPasswordExpiresAt", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "confirmationToken": { - "name": "confirmationToken", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "confirmationExpiresAt": { - "name": "confirmationExpiresAt", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "account_user_id_user_temp_id_fk": { - "name": "account_user_id_user_temp_id_fk", - "tableFrom": "account", - "tableTo": "user_temp", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.apikey": { - "name": "apikey", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "start": { - "name": "start", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "key": { - "name": "key", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "refill_interval": { - "name": "refill_interval", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "refill_amount": { - "name": "refill_amount", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_refill_at": { - "name": "last_refill_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_enabled": { - "name": "rate_limit_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "rate_limit_time_window": { - "name": "rate_limit_time_window", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "rate_limit_max": { - "name": "rate_limit_max", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "request_count": { - "name": "request_count", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "remaining": { - "name": "remaining", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "last_request": { - "name": "last_request", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "permissions": { - "name": "permissions", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "apikey_user_id_user_temp_id_fk": { - "name": "apikey_user_id_user_temp_id_fk", - "tableFrom": "apikey", - "tableTo": "user_temp", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.invitation": { - "name": "invitation", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "status": { - "name": "status", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "inviter_id": { - "name": "inviter_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "team_id": { - "name": "team_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "invitation_organization_id_organization_id_fk": { - "name": "invitation_organization_id_organization_id_fk", - "tableFrom": "invitation", - "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "invitation_inviter_id_user_temp_id_fk": { - "name": "invitation_inviter_id_user_temp_id_fk", - "tableFrom": "invitation", - "tableTo": "user_temp", - "columnsFrom": [ - "inviter_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.member": { - "name": "member", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "organization_id": { - "name": "organization_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "team_id": { - "name": "team_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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 - }, - "canAccessToGitProviders": { - "name": "canAccessToGitProviders", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "canAccessToTraefikFiles": { - "name": "canAccessToTraefikFiles", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "canDeleteEnvironments": { - "name": "canDeleteEnvironments", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "canCreateEnvironments": { - "name": "canCreateEnvironments", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "accesedProjects": { - "name": "accesedProjects", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "ARRAY[]::text[]" - }, - "accessedEnvironments": { - "name": "accessedEnvironments", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "ARRAY[]::text[]" - }, - "accesedServices": { - "name": "accesedServices", - "type": "text[]", - "primaryKey": false, - "notNull": true, - "default": "ARRAY[]::text[]" - } - }, - "indexes": {}, - "foreignKeys": { - "member_organization_id_organization_id_fk": { - "name": "member_organization_id_organization_id_fk", - "tableFrom": "member", - "tableTo": "organization", - "columnsFrom": [ - "organization_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "member_user_id_user_temp_id_fk": { - "name": "member_user_id_user_temp_id_fk", - "tableFrom": "member", - "tableTo": "user_temp", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.organization": { - "name": "organization", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "logo": { - "name": "logo", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "metadata": { - "name": "metadata", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "owner_id": { - "name": "owner_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "organization_owner_id_user_temp_id_fk": { - "name": "organization_owner_id_user_temp_id_fk", - "tableFrom": "organization", - "tableTo": "user_temp", - "columnsFrom": [ - "owner_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "organization_slug_unique": { - "name": "organization_slug_unique", - "nullsNotDistinct": false, - "columns": [ - "slug" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "backup_codes": { - "name": "backup_codes", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_user_temp_id_fk": { - "name": "two_factor_user_id_user_temp_id_fk", - "tableFrom": "two_factor", - "tableTo": "user_temp", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.verification": { - "name": "verification", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "identifier": { - "name": "identifier", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "value": { - "name": "value", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.ai": { - "name": "ai", - "schema": "", - "columns": { - "aiId": { - "name": "aiId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "apiUrl": { - "name": "apiUrl", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "apiKey": { - "name": "apiKey", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "model": { - "name": "model", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "isEnabled": { - "name": "isEnabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "ai_organizationId_organization_id_fk": { - "name": "ai_organizationId_organization_id_fk", - "tableFrom": "ai", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "previewEnv": { - "name": "previewEnv", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "watchPaths": { - "name": "watchPaths", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "previewBuildArgs": { - "name": "previewBuildArgs", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "previewBuildSecrets": { - "name": "previewBuildSecrets", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "previewLabels": { - "name": "previewLabels", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "previewWildcard": { - "name": "previewWildcard", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "previewPort": { - "name": "previewPort", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 3000 - }, - "previewHttps": { - "name": "previewHttps", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "previewPath": { - "name": "previewPath", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'/'" - }, - "certificateType": { - "name": "certificateType", - "type": "certificateType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'none'" - }, - "previewCustomCertResolver": { - "name": "previewCustomCertResolver", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "previewLimit": { - "name": "previewLimit", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 3 - }, - "isPreviewDeploymentsActive": { - "name": "isPreviewDeploymentsActive", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "previewRequireCollaboratorPermissions": { - "name": "previewRequireCollaboratorPermissions", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": true - }, - "rollbackActive": { - "name": "rollbackActive", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "buildArgs": { - "name": "buildArgs", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "buildSecrets": { - "name": "buildSecrets", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "memoryReservation": { - "name": "memoryReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "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'" - }, - "cleanCache": { - "name": "cleanCache", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "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": "'/'" - }, - "triggerType": { - "name": "triggerType", - "type": "triggerType", - "typeSchema": "public", - "primaryKey": false, - "notNull": false, - "default": "'push'" - }, - "autoDeploy": { - "name": "autoDeploy", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "gitlabProjectId": { - "name": "gitlabProjectId", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "gitlabRepository": { - "name": "gitlabRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabOwner": { - "name": "gitlabOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabBranch": { - "name": "gitlabBranch", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabBuildPath": { - "name": "gitlabBuildPath", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'/'" - }, - "gitlabPathNamespace": { - "name": "gitlabPathNamespace", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaRepository": { - "name": "giteaRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaOwner": { - "name": "giteaOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaBranch": { - "name": "giteaBranch", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaBuildPath": { - "name": "giteaBuildPath", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'/'" - }, - "bitbucketRepository": { - "name": "bitbucketRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketOwner": { - "name": "bitbucketOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketBranch": { - "name": "bitbucketBranch", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketBuildPath": { - "name": "bitbucketBuildPath", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'/'" - }, - "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 - }, - "registryUrl": { - "name": "registryUrl", - "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 - }, - "enableSubmodules": { - "name": "enableSubmodules", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "dockerfile": { - "name": "dockerfile", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "dockerContextPath": { - "name": "dockerContextPath", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "dockerBuildStage": { - "name": "dockerBuildStage", - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "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'" - }, - "railpackVersion": { - "name": "railpackVersion", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'0.2.2'" - }, - "herokuVersion": { - "name": "herokuVersion", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'24'" - }, - "publishDirectory": { - "name": "publishDirectory", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "isStaticSpa": { - "name": "isStaticSpa", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "registryId": { - "name": "registryId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "githubId": { - "name": "githubId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabId": { - "name": "gitlabId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaId": { - "name": "giteaId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketId": { - "name": "bitbucketId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "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_environmentId_environment_environmentId_fk": { - "name": "application_environmentId_environment_environmentId_fk", - "tableFrom": "application", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "application_githubId_github_githubId_fk": { - "name": "application_githubId_github_githubId_fk", - "tableFrom": "application", - "tableTo": "github", - "columnsFrom": [ - "githubId" - ], - "columnsTo": [ - "githubId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "application_gitlabId_gitlab_gitlabId_fk": { - "name": "application_gitlabId_gitlab_gitlabId_fk", - "tableFrom": "application", - "tableTo": "gitlab", - "columnsFrom": [ - "gitlabId" - ], - "columnsTo": [ - "gitlabId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "application_giteaId_gitea_giteaId_fk": { - "name": "application_giteaId_gitea_giteaId_fk", - "tableFrom": "application", - "tableTo": "gitea", - "columnsFrom": [ - "giteaId" - ], - "columnsTo": [ - "giteaId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "application_bitbucketId_bitbucket_bitbucketId_fk": { - "name": "application_bitbucketId_bitbucket_bitbucketId_fk", - "tableFrom": "application", - "tableTo": "bitbucket", - "columnsFrom": [ - "bitbucketId" - ], - "columnsTo": [ - "bitbucketId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "application_serverId_server_serverId_fk": { - "name": "application_serverId_server_serverId_fk", - "tableFrom": "application", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "application_appName_unique": { - "name": "application_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.backup": { - "name": "backup", - "schema": "", - "columns": { - "backupId": { - "name": "backupId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "appName": { - "name": "appName", - "type": "text", - "primaryKey": false, - "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 - }, - "serviceName": { - "name": "serviceName", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "destinationId": { - "name": "destinationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "keepLatestCount": { - "name": "keepLatestCount", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "backupType": { - "name": "backupType", - "type": "backupType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'database'" - }, - "databaseType": { - "name": "databaseType", - "type": "databaseType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true - }, - "composeId": { - "name": "composeId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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 - }, - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metadata": { - "name": "metadata", - "type": "jsonb", - "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_composeId_compose_composeId_fk": { - "name": "backup_composeId_compose_composeId_fk", - "tableFrom": "backup", - "tableTo": "compose", - "columnsFrom": [ - "composeId" - ], - "columnsTo": [ - "composeId" - ], - "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" - }, - "backup_userId_user_temp_id_fk": { - "name": "backup_userId_user_temp_id_fk", - "tableFrom": "backup", - "tableTo": "user_temp", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "backup_appName_unique": { - "name": "backup_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.bitbucket": { - "name": "bitbucket", - "schema": "", - "columns": { - "bitbucketId": { - "name": "bitbucketId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "bitbucketUsername": { - "name": "bitbucketUsername", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketEmail": { - "name": "bitbucketEmail", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "appPassword": { - "name": "appPassword", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "apiToken": { - "name": "apiToken", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketWorkspaceName": { - "name": "bitbucketWorkspaceName", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitProviderId": { - "name": "gitProviderId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "bitbucket_gitProviderId_git_provider_gitProviderId_fk": { - "name": "bitbucket_gitProviderId_git_provider_gitProviderId_fk", - "tableFrom": "bitbucket", - "tableTo": "git_provider", - "columnsFrom": [ - "gitProviderId" - ], - "columnsTo": [ - "gitProviderId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "certificate_organizationId_organization_id_fk": { - "name": "certificate_organizationId_organization_id_fk", - "tableFrom": "certificate", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "certificate_serverId_server_serverId_fk": { - "name": "certificate_serverId_server_serverId_fk", - "tableFrom": "certificate", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "certificate_certificatePath_unique": { - "name": "certificate_certificatePath_unique", - "nullsNotDistinct": false, - "columns": [ - "certificatePath" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "gitlabProjectId": { - "name": "gitlabProjectId", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "gitlabRepository": { - "name": "gitlabRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabOwner": { - "name": "gitlabOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabBranch": { - "name": "gitlabBranch", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabPathNamespace": { - "name": "gitlabPathNamespace", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketRepository": { - "name": "bitbucketRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketOwner": { - "name": "bitbucketOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketBranch": { - "name": "bitbucketBranch", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaRepository": { - "name": "giteaRepository", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaOwner": { - "name": "giteaOwner", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaBranch": { - "name": "giteaBranch", - "type": "text", - "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": "''" - }, - "enableSubmodules": { - "name": "enableSubmodules", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "composePath": { - "name": "composePath", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'./docker-compose.yml'" - }, - "suffix": { - "name": "suffix", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "randomize": { - "name": "randomize", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "isolatedDeployment": { - "name": "isolatedDeployment", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "isolatedDeploymentsVolume": { - "name": "isolatedDeploymentsVolume", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "triggerType": { - "name": "triggerType", - "type": "triggerType", - "typeSchema": "public", - "primaryKey": false, - "notNull": false, - "default": "'push'" - }, - "composeStatus": { - "name": "composeStatus", - "type": "applicationStatus", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'idle'" - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "watchPaths": { - "name": "watchPaths", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "githubId": { - "name": "githubId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitlabId": { - "name": "gitlabId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "bitbucketId": { - "name": "bitbucketId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "giteaId": { - "name": "giteaId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "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_environmentId_environment_environmentId_fk": { - "name": "compose_environmentId_environment_environmentId_fk", - "tableFrom": "compose", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "compose_githubId_github_githubId_fk": { - "name": "compose_githubId_github_githubId_fk", - "tableFrom": "compose", - "tableTo": "github", - "columnsFrom": [ - "githubId" - ], - "columnsTo": [ - "githubId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "compose_gitlabId_gitlab_gitlabId_fk": { - "name": "compose_gitlabId_gitlab_gitlabId_fk", - "tableFrom": "compose", - "tableTo": "gitlab", - "columnsFrom": [ - "gitlabId" - ], - "columnsTo": [ - "gitlabId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "compose_bitbucketId_bitbucket_bitbucketId_fk": { - "name": "compose_bitbucketId_bitbucket_bitbucketId_fk", - "tableFrom": "compose", - "tableTo": "bitbucket", - "columnsFrom": [ - "bitbucketId" - ], - "columnsTo": [ - "bitbucketId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "compose_giteaId_gitea_giteaId_fk": { - "name": "compose_giteaId_gitea_giteaId_fk", - "tableFrom": "compose", - "tableTo": "gitea", - "columnsFrom": [ - "giteaId" - ], - "columnsTo": [ - "giteaId" - ], - "onDelete": "set null", - "onUpdate": "no action" - }, - "compose_serverId_server_serverId_fk": { - "name": "compose_serverId_server_serverId_fk", - "tableFrom": "compose", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "pid": { - "name": "pid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applicationId": { - "name": "applicationId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "composeId": { - "name": "composeId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "isPreviewDeployment": { - "name": "isPreviewDeployment", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "previewDeploymentId": { - "name": "previewDeploymentId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "startedAt": { - "name": "startedAt", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "finishedAt": { - "name": "finishedAt", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "errorMessage": { - "name": "errorMessage", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "scheduleId": { - "name": "scheduleId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "backupId": { - "name": "backupId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "rollbackId": { - "name": "rollbackId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "volumeBackupId": { - "name": "volumeBackupId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "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" - }, - "deployment_serverId_server_serverId_fk": { - "name": "deployment_serverId_server_serverId_fk", - "tableFrom": "deployment", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "deployment_previewDeploymentId_preview_deployments_previewDeploymentId_fk": { - "name": "deployment_previewDeploymentId_preview_deployments_previewDeploymentId_fk", - "tableFrom": "deployment", - "tableTo": "preview_deployments", - "columnsFrom": [ - "previewDeploymentId" - ], - "columnsTo": [ - "previewDeploymentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "deployment_scheduleId_schedule_scheduleId_fk": { - "name": "deployment_scheduleId_schedule_scheduleId_fk", - "tableFrom": "deployment", - "tableTo": "schedule", - "columnsFrom": [ - "scheduleId" - ], - "columnsTo": [ - "scheduleId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "deployment_backupId_backup_backupId_fk": { - "name": "deployment_backupId_backup_backupId_fk", - "tableFrom": "deployment", - "tableTo": "backup", - "columnsFrom": [ - "backupId" - ], - "columnsTo": [ - "backupId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "deployment_rollbackId_rollback_rollbackId_fk": { - "name": "deployment_rollbackId_rollback_rollbackId_fk", - "tableFrom": "deployment", - "tableTo": "rollback", - "columnsFrom": [ - "rollbackId" - ], - "columnsTo": [ - "rollbackId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "deployment_volumeBackupId_volume_backup_volumeBackupId_fk": { - "name": "deployment_volumeBackupId_volume_backup_volumeBackupId_fk", - "tableFrom": "deployment", - "tableTo": "volume_backup", - "columnsFrom": [ - "volumeBackupId" - ], - "columnsTo": [ - "volumeBackupId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.destination": { - "name": "destination", - "schema": "", - "columns": { - "destinationId": { - "name": "destinationId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "provider": { - "name": "provider", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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 - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "createdAt": { - "name": "createdAt", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "destination_organizationId_organization_id_fk": { - "name": "destination_organizationId_organization_id_fk", - "tableFrom": "destination", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "customCertResolver": { - "name": "customCertResolver", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applicationId": { - "name": "applicationId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "previewDeploymentId": { - "name": "previewDeploymentId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "certificateType": { - "name": "certificateType", - "type": "certificateType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'none'" - }, - "internalPath": { - "name": "internalPath", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'/'" - }, - "stripPath": { - "name": "stripPath", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - } - }, - "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" - }, - "domain_previewDeploymentId_preview_deployments_previewDeploymentId_fk": { - "name": "domain_previewDeploymentId_preview_deployments_previewDeploymentId_fk", - "tableFrom": "domain", - "tableTo": "preview_deployments", - "columnsFrom": [ - "previewDeploymentId" - ], - "columnsTo": [ - "previewDeploymentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.environment": { - "name": "environment", - "schema": "", - "columns": { - "environmentId": { - "name": "environmentId", - "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 - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "projectId": { - "name": "projectId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "environment_projectId_project_projectId_fk": { - "name": "environment_projectId_project_projectId_fk", - "tableFrom": "environment", - "tableTo": "project", - "columnsFrom": [ - "projectId" - ], - "columnsTo": [ - "projectId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.git_provider": { - "name": "git_provider", - "schema": "", - "columns": { - "gitProviderId": { - "name": "gitProviderId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "providerType": { - "name": "providerType", - "type": "gitProviderType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'github'" - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "git_provider_organizationId_organization_id_fk": { - "name": "git_provider_organizationId_organization_id_fk", - "tableFrom": "git_provider", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "git_provider_userId_user_temp_id_fk": { - "name": "git_provider_userId_user_temp_id_fk", - "tableFrom": "git_provider", - "tableTo": "user_temp", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.gitea": { - "name": "gitea", - "schema": "", - "columns": { - "giteaId": { - "name": "giteaId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "giteaUrl": { - "name": "giteaUrl", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'https://gitea.com'" - }, - "redirect_uri": { - "name": "redirect_uri", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "client_id": { - "name": "client_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "client_secret": { - "name": "client_secret", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "gitProviderId": { - "name": "gitProviderId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "scopes": { - "name": "scopes", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'repo,repo:status,read:user,read:org'" - }, - "last_authenticated_at": { - "name": "last_authenticated_at", - "type": "integer", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "gitea_gitProviderId_git_provider_gitProviderId_fk": { - "name": "gitea_gitProviderId_git_provider_gitProviderId_fk", - "tableFrom": "gitea", - "tableTo": "git_provider", - "columnsFrom": [ - "gitProviderId" - ], - "columnsTo": [ - "gitProviderId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.github": { - "name": "github", - "schema": "", - "columns": { - "githubId": { - "name": "githubId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "githubAppName": { - "name": "githubAppName", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "githubAppId": { - "name": "githubAppId", - "type": "integer", - "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 - }, - "gitProviderId": { - "name": "gitProviderId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "github_gitProviderId_git_provider_gitProviderId_fk": { - "name": "github_gitProviderId_git_provider_gitProviderId_fk", - "tableFrom": "github", - "tableTo": "git_provider", - "columnsFrom": [ - "gitProviderId" - ], - "columnsTo": [ - "gitProviderId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.gitlab": { - "name": "gitlab", - "schema": "", - "columns": { - "gitlabId": { - "name": "gitlabId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "gitlabUrl": { - "name": "gitlabUrl", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'https://gitlab.com'" - }, - "application_id": { - "name": "application_id", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "redirect_uri": { - "name": "redirect_uri", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "access_token": { - "name": "access_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "refresh_token": { - "name": "refresh_token", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "group_name": { - "name": "group_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "expires_at": { - "name": "expires_at", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "gitProviderId": { - "name": "gitProviderId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "gitlab_gitProviderId_git_provider_gitProviderId_fk": { - "name": "gitlab_gitProviderId_git_provider_gitProviderId_fk", - "tableFrom": "gitlab", - "tableTo": "git_provider", - "columnsFrom": [ - "gitProviderId" - ], - "columnsTo": [ - "gitProviderId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": "text", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "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'" - }, - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "replicas": { - "name": "replicas", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "mariadb_environmentId_environment_environmentId_fk": { - "name": "mariadb_environmentId_environment_environmentId_fk", - "tableFrom": "mariadb", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "mariadb_serverId_server_serverId_fk": { - "name": "mariadb_serverId_server_serverId_fk", - "tableFrom": "mariadb", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mariadb_appName_unique": { - "name": "mariadb_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": "text", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "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'" - }, - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "replicas": { - "name": "replicas", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "replicaSets": { - "name": "replicaSets", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "mongo_environmentId_environment_environmentId_fk": { - "name": "mongo_environmentId_environment_environmentId_fk", - "tableFrom": "mongo", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "mongo_serverId_server_serverId_fk": { - "name": "mongo_serverId_server_serverId_fk", - "tableFrom": "mongo", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mongo_appName_unique": { - "name": "mongo_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": "text", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "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'" - }, - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "replicas": { - "name": "replicas", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "mysql_environmentId_environment_environmentId_fk": { - "name": "mysql_environmentId_environment_environmentId_fk", - "tableFrom": "mysql", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "mysql_serverId_server_serverId_fk": { - "name": "mysql_serverId_server_serverId_fk", - "tableFrom": "mysql", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mysql_appName_unique": { - "name": "mysql_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.discord": { - "name": "discord", - "schema": "", - "columns": { - "discordId": { - "name": "discordId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "webhookUrl": { - "name": "webhookUrl", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "decoration": { - "name": "decoration", - "type": "boolean", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.gotify": { - "name": "gotify", - "schema": "", - "columns": { - "gotifyId": { - "name": "gotifyId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "serverUrl": { - "name": "serverUrl", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "appToken": { - "name": "appToken", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "priority": { - "name": "priority", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 5 - }, - "decoration": { - "name": "decoration", - "type": "boolean", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.lark": { - "name": "lark", - "schema": "", - "columns": { - "larkId": { - "name": "larkId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "webhookUrl": { - "name": "webhookUrl", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "dokployBackup": { - "name": "dokployBackup", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "dockerCleanup": { - "name": "dockerCleanup", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "serverThreshold": { - "name": "serverThreshold", - "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 - }, - "gotifyId": { - "name": "gotifyId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ntfyId": { - "name": "ntfyId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "larkId": { - "name": "larkId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "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" - }, - "notification_gotifyId_gotify_gotifyId_fk": { - "name": "notification_gotifyId_gotify_gotifyId_fk", - "tableFrom": "notification", - "tableTo": "gotify", - "columnsFrom": [ - "gotifyId" - ], - "columnsTo": [ - "gotifyId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "notification_ntfyId_ntfy_ntfyId_fk": { - "name": "notification_ntfyId_ntfy_ntfyId_fk", - "tableFrom": "notification", - "tableTo": "ntfy", - "columnsFrom": [ - "ntfyId" - ], - "columnsTo": [ - "ntfyId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "notification_larkId_lark_larkId_fk": { - "name": "notification_larkId_lark_larkId_fk", - "tableFrom": "notification", - "tableTo": "lark", - "columnsFrom": [ - "larkId" - ], - "columnsTo": [ - "larkId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "notification_organizationId_organization_id_fk": { - "name": "notification_organizationId_organization_id_fk", - "tableFrom": "notification", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.ntfy": { - "name": "ntfy", - "schema": "", - "columns": { - "ntfyId": { - "name": "ntfyId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "serverUrl": { - "name": "serverUrl", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "topic": { - "name": "topic", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "accessToken": { - "name": "accessToken", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "priority": { - "name": "priority", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 3 - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "messageThreadId": { - "name": "messageThreadId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.port": { - "name": "port", - "schema": "", - "columns": { - "portId": { - "name": "portId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "publishedPort": { - "name": "publishedPort", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "publishMode": { - "name": "publishMode", - "type": "publishModeType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'host'" - }, - "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": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": "text", - "primaryKey": false, - "notNull": false - }, - "externalPort": { - "name": "externalPort", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applicationStatus": { - "name": "applicationStatus", - "type": "applicationStatus", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'idle'" - }, - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "replicas": { - "name": "replicas", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "postgres_environmentId_environment_environmentId_fk": { - "name": "postgres_environmentId_environment_environmentId_fk", - "tableFrom": "postgres", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "postgres_serverId_server_serverId_fk": { - "name": "postgres_serverId_server_serverId_fk", - "tableFrom": "postgres", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "postgres_appName_unique": { - "name": "postgres_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.preview_deployments": { - "name": "preview_deployments", - "schema": "", - "columns": { - "previewDeploymentId": { - "name": "previewDeploymentId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "branch": { - "name": "branch", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pullRequestId": { - "name": "pullRequestId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pullRequestNumber": { - "name": "pullRequestNumber", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pullRequestURL": { - "name": "pullRequestURL", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pullRequestTitle": { - "name": "pullRequestTitle", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pullRequestCommentId": { - "name": "pullRequestCommentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "previewStatus": { - "name": "previewStatus", - "type": "applicationStatus", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'idle'" - }, - "appName": { - "name": "appName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "applicationId": { - "name": "applicationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "domainId": { - "name": "domainId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "expiresAt": { - "name": "expiresAt", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "preview_deployments_applicationId_application_applicationId_fk": { - "name": "preview_deployments_applicationId_application_applicationId_fk", - "tableFrom": "preview_deployments", - "tableTo": "application", - "columnsFrom": [ - "applicationId" - ], - "columnsTo": [ - "applicationId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "preview_deployments_domainId_domain_domainId_fk": { - "name": "preview_deployments_domainId_domain_domainId_fk", - "tableFrom": "preview_deployments", - "tableTo": "domain", - "columnsFrom": [ - "domainId" - ], - "columnsTo": [ - "domainId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "preview_deployments_appName_unique": { - "name": "preview_deployments_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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 - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "env": { - "name": "env", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - } - }, - "indexes": {}, - "foreignKeys": { - "project_organizationId_organization_id_fk": { - "name": "project_organizationId_organization_id_fk", - "tableFrom": "project", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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": "text", - "primaryKey": false, - "notNull": false - }, - "memoryLimit": { - "name": "memoryLimit", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuReservation": { - "name": "cpuReservation", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "cpuLimit": { - "name": "cpuLimit", - "type": "text", - "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'" - }, - "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 - }, - "stopGracePeriodSwarm": { - "name": "stopGracePeriodSwarm", - "type": "bigint", - "primaryKey": false, - "notNull": false - }, - "replicas": { - "name": "replicas", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 1 - }, - "environmentId": { - "name": "environmentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "redis_environmentId_environment_environmentId_fk": { - "name": "redis_environmentId_environment_environmentId_fk", - "tableFrom": "redis", - "tableTo": "environment", - "columnsFrom": [ - "environmentId" - ], - "columnsTo": [ - "environmentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "redis_serverId_server_serverId_fk": { - "name": "redis_serverId_server_serverId_fk", - "tableFrom": "redis", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "redis_appName_unique": { - "name": "redis_appName_unique", - "nullsNotDistinct": false, - "columns": [ - "appName" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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, - "default": "''" - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "selfHosted": { - "name": "selfHosted", - "type": "RegistryType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'cloud'" - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "registry_organizationId_organization_id_fk": { - "name": "registry_organizationId_organization_id_fk", - "tableFrom": "registry", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.rollback": { - "name": "rollback", - "schema": "", - "columns": { - "rollbackId": { - "name": "rollbackId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "deploymentId": { - "name": "deploymentId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "version": { - "name": "version", - "type": "serial", - "primaryKey": false, - "notNull": true - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "fullContext": { - "name": "fullContext", - "type": "jsonb", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "rollback_deploymentId_deployment_deploymentId_fk": { - "name": "rollback_deploymentId_deployment_deploymentId_fk", - "tableFrom": "rollback", - "tableTo": "deployment", - "columnsFrom": [ - "deploymentId" - ], - "columnsTo": [ - "deploymentId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.schedule": { - "name": "schedule", - "schema": "", - "columns": { - "scheduleId": { - "name": "scheduleId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "cronExpression": { - "name": "cronExpression", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "appName": { - "name": "appName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serviceName": { - "name": "serviceName", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "shellType": { - "name": "shellType", - "type": "shellType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'bash'" - }, - "scheduleType": { - "name": "scheduleType", - "type": "scheduleType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'application'" - }, - "command": { - "name": "command", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "script": { - "name": "script", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "applicationId": { - "name": "applicationId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "composeId": { - "name": "composeId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": true - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "schedule_applicationId_application_applicationId_fk": { - "name": "schedule_applicationId_application_applicationId_fk", - "tableFrom": "schedule", - "tableTo": "application", - "columnsFrom": [ - "applicationId" - ], - "columnsTo": [ - "applicationId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "schedule_composeId_compose_composeId_fk": { - "name": "schedule_composeId_compose_composeId_fk", - "tableFrom": "schedule", - "tableTo": "compose", - "columnsFrom": [ - "composeId" - ], - "columnsTo": [ - "composeId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "schedule_serverId_server_serverId_fk": { - "name": "schedule_serverId_server_serverId_fk", - "tableFrom": "schedule", - "tableTo": "server", - "columnsFrom": [ - "serverId" - ], - "columnsTo": [ - "serverId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "schedule_userId_user_temp_id_fk": { - "name": "schedule_userId_user_temp_id_fk", - "tableFrom": "schedule", - "tableTo": "user_temp", - "columnsFrom": [ - "userId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "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" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.server": { - "name": "server", - "schema": "", - "columns": { - "serverId": { - "name": "serverId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ipAddress": { - "name": "ipAddress", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "port": { - "name": "port", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'root'" - }, - "appName": { - "name": "appName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enableDockerCleanup": { - "name": "enableDockerCleanup", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serverStatus": { - "name": "serverStatus", - "type": "serverStatus", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'active'" - }, - "command": { - "name": "command", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "sshKeyId": { - "name": "sshKeyId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "metricsConfig": { - "name": "metricsConfig", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{\"server\":{\"type\":\"Remote\",\"refreshRate\":60,\"port\":4500,\"token\":\"\",\"urlCallback\":\"\",\"cronJob\":\"\",\"retentionDays\":2,\"thresholds\":{\"cpu\":0,\"memory\":0}},\"containers\":{\"refreshRate\":60,\"services\":{\"include\":[],\"exclude\":[]}}}'::jsonb" - } - }, - "indexes": {}, - "foreignKeys": { - "server_organizationId_organization_id_fk": { - "name": "server_organizationId_organization_id_fk", - "tableFrom": "server", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "server_sshKeyId_ssh-key_sshKeyId_fk": { - "name": "server_sshKeyId_ssh-key_sshKeyId_fk", - "tableFrom": "server", - "tableTo": "ssh-key", - "columnsFrom": [ - "sshKeyId" - ], - "columnsTo": [ - "sshKeyId" - ], - "onDelete": "set null", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.session_temp": { - "name": "session_temp", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "token": { - "name": "token", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_agent": { - "name": "user_agent", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "impersonated_by": { - "name": "impersonated_by", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "active_organization_id": { - "name": "active_organization_id", - "type": "text", - "primaryKey": false, - "notNull": false - } - }, - "indexes": {}, - "foreignKeys": { - "session_temp_user_id_user_temp_id_fk": { - "name": "session_temp_user_id_user_temp_id_fk", - "tableFrom": "session_temp", - "tableTo": "user_temp", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "session_temp_token_unique": { - "name": "session_temp_token_unique", - "nullsNotDistinct": false, - "columns": [ - "token" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.ssh-key": { - "name": "ssh-key", - "schema": "", - "columns": { - "sshKeyId": { - "name": "sshKeyId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "privateKey": { - "name": "privateKey", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "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 - }, - "organizationId": { - "name": "organizationId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "ssh-key_organizationId_organization_id_fk": { - "name": "ssh-key_organizationId_organization_id_fk", - "tableFrom": "ssh-key", - "tableTo": "organization", - "columnsFrom": [ - "organizationId" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.user_temp": { - "name": "user_temp", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "''" - }, - "isRegistered": { - "name": "isRegistered", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "expirationDate": { - "name": "expirationDate", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false, - "default": "now()" - }, - "two_factor_enabled": { - "name": "two_factor_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "email_verified": { - "name": "email_verified", - "type": "boolean", - "primaryKey": false, - "notNull": true - }, - "image": { - "name": "image", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "banned": { - "name": "banned", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "ban_reason": { - "name": "ban_reason", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ban_expires": { - "name": "ban_expires", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true - }, - "serverIp": { - "name": "serverIp", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "certificateType": { - "name": "certificateType", - "type": "certificateType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'none'" - }, - "https": { - "name": "https", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "host": { - "name": "host", - "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 - }, - "logCleanupCron": { - "name": "logCleanupCron", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'0 0 * * *'" - }, - "role": { - "name": "role", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'user'" - }, - "enablePaidFeatures": { - "name": "enablePaidFeatures", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "allowImpersonation": { - "name": "allowImpersonation", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "metricsConfig": { - "name": "metricsConfig", - "type": "jsonb", - "primaryKey": false, - "notNull": true, - "default": "'{\"server\":{\"type\":\"Dokploy\",\"refreshRate\":60,\"port\":4500,\"token\":\"\",\"retentionDays\":2,\"cronJob\":\"\",\"urlCallback\":\"\",\"thresholds\":{\"cpu\":0,\"memory\":0}},\"containers\":{\"refreshRate\":60,\"services\":{\"include\":[],\"exclude\":[]}}}'::jsonb" - }, - "cleanupCacheApplications": { - "name": "cleanupCacheApplications", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "cleanupCacheOnPreviews": { - "name": "cleanupCacheOnPreviews", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "cleanupCacheOnCompose": { - "name": "cleanupCacheOnCompose", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "stripeCustomerId": { - "name": "stripeCustomerId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "stripeSubscriptionId": { - "name": "stripeSubscriptionId", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "serversQuantity": { - "name": "serversQuantity", - "type": "integer", - "primaryKey": false, - "notNull": true, - "default": 0 - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_temp_email_unique": { - "name": "user_temp_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - }, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - }, - "public.volume_backup": { - "name": "volume_backup", - "schema": "", - "columns": { - "volumeBackupId": { - "name": "volumeBackupId", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "volumeName": { - "name": "volumeName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "prefix": { - "name": "prefix", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serviceType": { - "name": "serviceType", - "type": "serviceType", - "typeSchema": "public", - "primaryKey": false, - "notNull": true, - "default": "'application'" - }, - "appName": { - "name": "appName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "serviceName": { - "name": "serviceName", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "turnOff": { - "name": "turnOff", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "cronExpression": { - "name": "cronExpression", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "keepLatestCount": { - "name": "keepLatestCount", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false - }, - "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 - }, - "createdAt": { - "name": "createdAt", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "destinationId": { - "name": "destinationId", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "volume_backup_applicationId_application_applicationId_fk": { - "name": "volume_backup_applicationId_application_applicationId_fk", - "tableFrom": "volume_backup", - "tableTo": "application", - "columnsFrom": [ - "applicationId" - ], - "columnsTo": [ - "applicationId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_postgresId_postgres_postgresId_fk": { - "name": "volume_backup_postgresId_postgres_postgresId_fk", - "tableFrom": "volume_backup", - "tableTo": "postgres", - "columnsFrom": [ - "postgresId" - ], - "columnsTo": [ - "postgresId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_mariadbId_mariadb_mariadbId_fk": { - "name": "volume_backup_mariadbId_mariadb_mariadbId_fk", - "tableFrom": "volume_backup", - "tableTo": "mariadb", - "columnsFrom": [ - "mariadbId" - ], - "columnsTo": [ - "mariadbId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_mongoId_mongo_mongoId_fk": { - "name": "volume_backup_mongoId_mongo_mongoId_fk", - "tableFrom": "volume_backup", - "tableTo": "mongo", - "columnsFrom": [ - "mongoId" - ], - "columnsTo": [ - "mongoId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_mysqlId_mysql_mysqlId_fk": { - "name": "volume_backup_mysqlId_mysql_mysqlId_fk", - "tableFrom": "volume_backup", - "tableTo": "mysql", - "columnsFrom": [ - "mysqlId" - ], - "columnsTo": [ - "mysqlId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_redisId_redis_redisId_fk": { - "name": "volume_backup_redisId_redis_redisId_fk", - "tableFrom": "volume_backup", - "tableTo": "redis", - "columnsFrom": [ - "redisId" - ], - "columnsTo": [ - "redisId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_composeId_compose_composeId_fk": { - "name": "volume_backup_composeId_compose_composeId_fk", - "tableFrom": "volume_backup", - "tableTo": "compose", - "columnsFrom": [ - "composeId" - ], - "columnsTo": [ - "composeId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "volume_backup_destinationId_destination_destinationId_fk": { - "name": "volume_backup_destinationId_destination_destinationId_fk", - "tableFrom": "volume_backup", - "tableTo": "destination", - "columnsFrom": [ - "destinationId" - ], - "columnsTo": [ - "destinationId" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {}, - "policies": {}, - "checkConstraints": {}, - "isRLSEnabled": false - } - }, - "enums": { - "public.buildType": { - "name": "buildType", - "schema": "public", - "values": [ - "dockerfile", - "heroku_buildpacks", - "paketo_buildpacks", - "nixpacks", - "static", - "railpack" - ] - }, - "public.sourceType": { - "name": "sourceType", - "schema": "public", - "values": [ - "docker", - "git", - "github", - "gitlab", - "bitbucket", - "gitea", - "drop" - ] - }, - "public.backupType": { - "name": "backupType", - "schema": "public", - "values": [ - "database", - "compose" - ] - }, - "public.databaseType": { - "name": "databaseType", - "schema": "public", - "values": [ - "postgres", - "mariadb", - "mysql", - "mongo", - "web-server" - ] - }, - "public.composeType": { - "name": "composeType", - "schema": "public", - "values": [ - "docker-compose", - "stack" - ] - }, - "public.sourceTypeCompose": { - "name": "sourceTypeCompose", - "schema": "public", - "values": [ - "git", - "github", - "gitlab", - "bitbucket", - "gitea", - "raw" - ] - }, - "public.deploymentStatus": { - "name": "deploymentStatus", - "schema": "public", - "values": [ - "running", - "done", - "error", - "cancelled" - ] - }, - "public.domainType": { - "name": "domainType", - "schema": "public", - "values": [ - "compose", - "application", - "preview" - ] - }, - "public.gitProviderType": { - "name": "gitProviderType", - "schema": "public", - "values": [ - "github", - "gitlab", - "bitbucket", - "gitea" - ] - }, - "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.notificationType": { - "name": "notificationType", - "schema": "public", - "values": [ - "slack", - "telegram", - "discord", - "email", - "gotify", - "ntfy", - "lark" - ] - }, - "public.protocolType": { - "name": "protocolType", - "schema": "public", - "values": [ - "tcp", - "udp" - ] - }, - "public.publishModeType": { - "name": "publishModeType", - "schema": "public", - "values": [ - "ingress", - "host" - ] - }, - "public.RegistryType": { - "name": "RegistryType", - "schema": "public", - "values": [ - "selfHosted", - "cloud" - ] - }, - "public.scheduleType": { - "name": "scheduleType", - "schema": "public", - "values": [ - "application", - "compose", - "server", - "dokploy-server" - ] - }, - "public.shellType": { - "name": "shellType", - "schema": "public", - "values": [ - "bash", - "sh" - ] - }, - "public.serverStatus": { - "name": "serverStatus", - "schema": "public", - "values": [ - "active", - "inactive" - ] - }, - "public.applicationStatus": { - "name": "applicationStatus", - "schema": "public", - "values": [ - "idle", - "running", - "done", - "error" - ] - }, - "public.certificateType": { - "name": "certificateType", - "schema": "public", - "values": [ - "letsencrypt", - "none", - "custom" - ] - }, - "public.triggerType": { - "name": "triggerType", - "schema": "public", - "values": [ - "push", - "tag" - ] - } - }, - "schemas": {}, - "sequences": {}, - "roles": {}, - "policies": {}, - "views": {}, - "_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 a87ee25ce..9d6de3b90 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -834,13 +834,6 @@ "when": 1761415824484, "tag": "0118_loose_anita_blake", "breakpoints": true - }, - { - "idx": 119, - "version": "7", - "when": 1761595174595, - "tag": "0119_wakeful_luke_cage", - "breakpoints": true } ] } \ No newline at end of file From d90722a174d314125b76d0db26681ef08570e52c Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Mon, 30 Mar 2026 16:49:04 -0600 Subject: [PATCH 12/25] feat(notifications): add switch for Dokploy backup notification trigger - Introduced a new switch control in the notifications settings to enable or disable actions triggered by Dokploy backup creation. - Enhanced user interface for better interaction with notification settings. --- .../notifications/handle-notifications.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index 4e4cec701..7f427ef07 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -1881,6 +1881,20 @@ export const HandleNotifications = ({ notificationId }: Props) => { Dokploy Backup Trigger the action when a dokploy backup is created. + +
+ + + + + )} + /> + + ( From 450d591c1ac13acdfa0c7e05541d5a815c8cf11c Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Mon, 30 Mar 2026 16:49:26 -0600 Subject: [PATCH 13/25] feat(database): add dokployBackup column to notification table and update journal - Introduced a new boolean column "dokployBackup" in the "notification" table with a default value of false. - Added journal entry for version 7 tagged as "0156_fair_vargas" to track this schema change. - Created a new snapshot file for version 7 to reflect the updated database schema. --- apps/dokploy/drizzle/0156_fair_vargas.sql | 1 + apps/dokploy/drizzle/meta/0156_snapshot.json | 8250 ++++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + 3 files changed, 8258 insertions(+) create mode 100644 apps/dokploy/drizzle/0156_fair_vargas.sql create mode 100644 apps/dokploy/drizzle/meta/0156_snapshot.json diff --git a/apps/dokploy/drizzle/0156_fair_vargas.sql b/apps/dokploy/drizzle/0156_fair_vargas.sql new file mode 100644 index 000000000..d5bdd5b7e --- /dev/null +++ b/apps/dokploy/drizzle/0156_fair_vargas.sql @@ -0,0 +1 @@ +ALTER TABLE "notification" ADD COLUMN "dokployBackup" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/apps/dokploy/drizzle/meta/0156_snapshot.json b/apps/dokploy/drizzle/meta/0156_snapshot.json new file mode 100644 index 000000000..ac270ec03 --- /dev/null +++ b/apps/dokploy/drizzle/meta/0156_snapshot.json @@ -0,0 +1,8250 @@ +{ + "id": "54d2750c-4a55-4c83-9ff9-0478689c833f", + "prevId": "61cdc4f5-a8e9-4abe-9bfb-ec338b161e1a", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is2FAEnabled": { + "name": "is2FAEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "resetPasswordToken": { + "name": "resetPasswordToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resetPasswordExpiresAt": { + "name": "resetPasswordExpiresAt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "confirmationToken": { + "name": "confirmationToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "confirmationExpiresAt": { + "name": "confirmationExpiresAt", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "config_id": { + "name": "config_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "apikey_reference_id_user_id_fk": { + "name": "apikey_reference_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "reference_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.invitation": { + "name": "invitation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.member": { + "name": "member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_default": { + "name": "is_default", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "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 + }, + "canAccessToGitProviders": { + "name": "canAccessToGitProviders", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canAccessToTraefikFiles": { + "name": "canAccessToTraefikFiles", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canDeleteEnvironments": { + "name": "canDeleteEnvironments", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "canCreateEnvironments": { + "name": "canCreateEnvironments", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "accesedProjects": { + "name": "accesedProjects", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "accessedEnvironments": { + "name": "accessedEnvironments", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "accesedServices": { + "name": "accesedServices", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + } + }, + "indexes": {}, + "foreignKeys": { + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization": { + "name": "organization", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "organization_owner_id_user_id_fk": { + "name": "organization_owner_id_user_id_fk", + "tableFrom": "organization", + "tableTo": "user", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "organization_slug_unique": { + "name": "organization_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_role": { + "name": "organization_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "organizationRole_organizationId_idx": { + "name": "organizationRole_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organizationRole_role_idx": { + "name": "organizationRole_role_idx", + "columns": [ + { + "expression": "role", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_role_organization_id_organization_id_fk": { + "name": "organization_role_organization_id_organization_id_fk", + "tableFrom": "organization_role", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.two_factor": { + "name": "two_factor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backup_codes": { + "name": "backup_codes", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "two_factor_user_id_user_id_fk": { + "name": "two_factor_user_id_user_id_fk", + "tableFrom": "two_factor", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai": { + "name": "ai", + "schema": "", + "columns": { + "aiId": { + "name": "aiId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "apiUrl": { + "name": "apiUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "apiKey": { + "name": "apiKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isEnabled": { + "name": "isEnabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ai_organizationId_organization_id_fk": { + "name": "ai_organizationId_organization_id_fk", + "tableFrom": "ai", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.audit_log": { + "name": "audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_email": { + "name": "user_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_role": { + "name": "user_role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_name": { + "name": "resource_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "auditLog_organizationId_idx": { + "name": "auditLog_organizationId_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "auditLog_userId_idx": { + "name": "auditLog_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "auditLog_createdAt_idx": { + "name": "auditLog_createdAt_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "audit_log_organization_id_organization_id_fk": { + "name": "audit_log_organization_id_organization_id_fk", + "tableFrom": "audit_log", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "audit_log_user_id_user_id_fk": { + "name": "audit_log_user_id_user_id_fk", + "tableFrom": "audit_log", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "previewEnv": { + "name": "previewEnv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "watchPaths": { + "name": "watchPaths", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "previewBuildArgs": { + "name": "previewBuildArgs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "previewBuildSecrets": { + "name": "previewBuildSecrets", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "previewLabels": { + "name": "previewLabels", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "previewWildcard": { + "name": "previewWildcard", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "previewPort": { + "name": "previewPort", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3000 + }, + "previewHttps": { + "name": "previewHttps", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "previewPath": { + "name": "previewPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "previewCustomCertResolver": { + "name": "previewCustomCertResolver", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "previewLimit": { + "name": "previewLimit", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 3 + }, + "isPreviewDeploymentsActive": { + "name": "isPreviewDeploymentsActive", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "previewRequireCollaboratorPermissions": { + "name": "previewRequireCollaboratorPermissions", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rollbackActive": { + "name": "rollbackActive", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "buildArgs": { + "name": "buildArgs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildSecrets": { + "name": "buildSecrets", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "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 + }, + "args": { + "name": "args", + "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'" + }, + "cleanCache": { + "name": "cleanCache", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "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": "'/'" + }, + "triggerType": { + "name": "triggerType", + "type": "triggerType", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'push'" + }, + "autoDeploy": { + "name": "autoDeploy", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "gitlabProjectId": { + "name": "gitlabProjectId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitlabRepository": { + "name": "gitlabRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabOwner": { + "name": "gitlabOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBranch": { + "name": "gitlabBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBuildPath": { + "name": "gitlabBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "gitlabPathNamespace": { + "name": "gitlabPathNamespace", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaRepository": { + "name": "giteaRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaOwner": { + "name": "giteaOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaBranch": { + "name": "giteaBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaBuildPath": { + "name": "giteaBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "bitbucketRepository": { + "name": "bitbucketRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketRepositorySlug": { + "name": "bitbucketRepositorySlug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketOwner": { + "name": "bitbucketOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBranch": { + "name": "bitbucketBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBuildPath": { + "name": "bitbucketBuildPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "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 + }, + "registryUrl": { + "name": "registryUrl", + "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 + }, + "enableSubmodules": { + "name": "enableSubmodules", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dockerfile": { + "name": "dockerfile", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'Dockerfile'" + }, + "dockerContextPath": { + "name": "dockerContextPath", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dockerBuildStage": { + "name": "dockerBuildStage", + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "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'" + }, + "railpackVersion": { + "name": "railpackVersion", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'0.15.4'" + }, + "herokuVersion": { + "name": "herokuVersion", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'24'" + }, + "publishDirectory": { + "name": "publishDirectory", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isStaticSpa": { + "name": "isStaticSpa", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "createEnvFile": { + "name": "createEnvFile", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "registryId": { + "name": "registryId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rollbackRegistryId": { + "name": "rollbackRegistryId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaId": { + "name": "giteaId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildServerId": { + "name": "buildServerId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildRegistryId": { + "name": "buildRegistryId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "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_rollbackRegistryId_registry_registryId_fk": { + "name": "application_rollbackRegistryId_registry_registryId_fk", + "tableFrom": "application", + "tableTo": "registry", + "columnsFrom": [ + "rollbackRegistryId" + ], + "columnsTo": [ + "registryId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_environmentId_environment_environmentId_fk": { + "name": "application_environmentId_environment_environmentId_fk", + "tableFrom": "application", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "application_githubId_github_githubId_fk": { + "name": "application_githubId_github_githubId_fk", + "tableFrom": "application", + "tableTo": "github", + "columnsFrom": [ + "githubId" + ], + "columnsTo": [ + "githubId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_gitlabId_gitlab_gitlabId_fk": { + "name": "application_gitlabId_gitlab_gitlabId_fk", + "tableFrom": "application", + "tableTo": "gitlab", + "columnsFrom": [ + "gitlabId" + ], + "columnsTo": [ + "gitlabId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_giteaId_gitea_giteaId_fk": { + "name": "application_giteaId_gitea_giteaId_fk", + "tableFrom": "application", + "tableTo": "gitea", + "columnsFrom": [ + "giteaId" + ], + "columnsTo": [ + "giteaId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_bitbucketId_bitbucket_bitbucketId_fk": { + "name": "application_bitbucketId_bitbucket_bitbucketId_fk", + "tableFrom": "application", + "tableTo": "bitbucket", + "columnsFrom": [ + "bitbucketId" + ], + "columnsTo": [ + "bitbucketId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_serverId_server_serverId_fk": { + "name": "application_serverId_server_serverId_fk", + "tableFrom": "application", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "application_buildServerId_server_serverId_fk": { + "name": "application_buildServerId_server_serverId_fk", + "tableFrom": "application", + "tableTo": "server", + "columnsFrom": [ + "buildServerId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "application_buildRegistryId_registry_registryId_fk": { + "name": "application_buildRegistryId_registry_registryId_fk", + "tableFrom": "application", + "tableTo": "registry", + "columnsFrom": [ + "buildRegistryId" + ], + "columnsTo": [ + "registryId" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "application_appName_unique": { + "name": "application_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.backup": { + "name": "backup", + "schema": "", + "columns": { + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "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 + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "keepLatestCount": { + "name": "keepLatestCount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "backupType": { + "name": "backupType", + "type": "backupType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'database'" + }, + "databaseType": { + "name": "databaseType", + "type": "databaseType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "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 + }, + "libsqlId": { + "name": "libsqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "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_composeId_compose_composeId_fk": { + "name": "backup_composeId_compose_composeId_fk", + "tableFrom": "backup", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "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" + }, + "backup_libsqlId_libsql_libsqlId_fk": { + "name": "backup_libsqlId_libsql_libsqlId_fk", + "tableFrom": "backup", + "tableTo": "libsql", + "columnsFrom": [ + "libsqlId" + ], + "columnsTo": [ + "libsqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "backup_userId_user_id_fk": { + "name": "backup_userId_user_id_fk", + "tableFrom": "backup", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "backup_appName_unique": { + "name": "backup_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.bitbucket": { + "name": "bitbucket", + "schema": "", + "columns": { + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "bitbucketUsername": { + "name": "bitbucketUsername", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketEmail": { + "name": "bitbucketEmail", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "appPassword": { + "name": "appPassword", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "apiToken": { + "name": "apiToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketWorkspaceName": { + "name": "bitbucketWorkspaceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "bitbucket_gitProviderId_git_provider_gitProviderId_fk": { + "name": "bitbucket_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "bitbucket", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "certificate_organizationId_organization_id_fk": { + "name": "certificate_organizationId_organization_id_fk", + "tableFrom": "certificate", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "certificate_serverId_server_serverId_fk": { + "name": "certificate_serverId_server_serverId_fk", + "tableFrom": "certificate", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "certificate_certificatePath_unique": { + "name": "certificate_certificatePath_unique", + "nullsNotDistinct": false, + "columns": [ + "certificatePath" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "gitlabProjectId": { + "name": "gitlabProjectId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitlabRepository": { + "name": "gitlabRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabOwner": { + "name": "gitlabOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabBranch": { + "name": "gitlabBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabPathNamespace": { + "name": "gitlabPathNamespace", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketRepository": { + "name": "bitbucketRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketRepositorySlug": { + "name": "bitbucketRepositorySlug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketOwner": { + "name": "bitbucketOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketBranch": { + "name": "bitbucketBranch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaRepository": { + "name": "giteaRepository", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaOwner": { + "name": "giteaOwner", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaBranch": { + "name": "giteaBranch", + "type": "text", + "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": "''" + }, + "enableSubmodules": { + "name": "enableSubmodules", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "composePath": { + "name": "composePath", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'./docker-compose.yml'" + }, + "suffix": { + "name": "suffix", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "randomize": { + "name": "randomize", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "isolatedDeployment": { + "name": "isolatedDeployment", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "isolatedDeploymentsVolume": { + "name": "isolatedDeploymentsVolume", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "triggerType": { + "name": "triggerType", + "type": "triggerType", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'push'" + }, + "composeStatus": { + "name": "composeStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "watchPaths": { + "name": "watchPaths", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "bitbucketId": { + "name": "bitbucketId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "giteaId": { + "name": "giteaId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "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_environmentId_environment_environmentId_fk": { + "name": "compose_environmentId_environment_environmentId_fk", + "tableFrom": "compose", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "compose_githubId_github_githubId_fk": { + "name": "compose_githubId_github_githubId_fk", + "tableFrom": "compose", + "tableTo": "github", + "columnsFrom": [ + "githubId" + ], + "columnsTo": [ + "githubId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_gitlabId_gitlab_gitlabId_fk": { + "name": "compose_gitlabId_gitlab_gitlabId_fk", + "tableFrom": "compose", + "tableTo": "gitlab", + "columnsFrom": [ + "gitlabId" + ], + "columnsTo": [ + "gitlabId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_bitbucketId_bitbucket_bitbucketId_fk": { + "name": "compose_bitbucketId_bitbucket_bitbucketId_fk", + "tableFrom": "compose", + "tableTo": "bitbucket", + "columnsFrom": [ + "bitbucketId" + ], + "columnsTo": [ + "bitbucketId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_giteaId_gitea_giteaId_fk": { + "name": "compose_giteaId_gitea_giteaId_fk", + "tableFrom": "compose", + "tableTo": "gitea", + "columnsFrom": [ + "giteaId" + ], + "columnsTo": [ + "giteaId" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "compose_serverId_server_serverId_fk": { + "name": "compose_serverId_server_serverId_fk", + "tableFrom": "compose", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "pid": { + "name": "pid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isPreviewDeployment": { + "name": "isPreviewDeployment", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "previewDeploymentId": { + "name": "previewDeploymentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "startedAt": { + "name": "startedAt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "finishedAt": { + "name": "finishedAt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "errorMessage": { + "name": "errorMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scheduleId": { + "name": "scheduleId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "backupId": { + "name": "backupId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "rollbackId": { + "name": "rollbackId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "volumeBackupId": { + "name": "volumeBackupId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "buildServerId": { + "name": "buildServerId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "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" + }, + "deployment_serverId_server_serverId_fk": { + "name": "deployment_serverId_server_serverId_fk", + "tableFrom": "deployment", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_previewDeploymentId_preview_deployments_previewDeploymentId_fk": { + "name": "deployment_previewDeploymentId_preview_deployments_previewDeploymentId_fk", + "tableFrom": "deployment", + "tableTo": "preview_deployments", + "columnsFrom": [ + "previewDeploymentId" + ], + "columnsTo": [ + "previewDeploymentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_scheduleId_schedule_scheduleId_fk": { + "name": "deployment_scheduleId_schedule_scheduleId_fk", + "tableFrom": "deployment", + "tableTo": "schedule", + "columnsFrom": [ + "scheduleId" + ], + "columnsTo": [ + "scheduleId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_backupId_backup_backupId_fk": { + "name": "deployment_backupId_backup_backupId_fk", + "tableFrom": "deployment", + "tableTo": "backup", + "columnsFrom": [ + "backupId" + ], + "columnsTo": [ + "backupId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_rollbackId_rollback_rollbackId_fk": { + "name": "deployment_rollbackId_rollback_rollbackId_fk", + "tableFrom": "deployment", + "tableTo": "rollback", + "columnsFrom": [ + "rollbackId" + ], + "columnsTo": [ + "rollbackId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_volumeBackupId_volume_backup_volumeBackupId_fk": { + "name": "deployment_volumeBackupId_volume_backup_volumeBackupId_fk", + "tableFrom": "deployment", + "tableTo": "volume_backup", + "columnsFrom": [ + "volumeBackupId" + ], + "columnsTo": [ + "volumeBackupId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "deployment_buildServerId_server_serverId_fk": { + "name": "deployment_buildServerId_server_serverId_fk", + "tableFrom": "deployment", + "tableTo": "server", + "columnsFrom": [ + "buildServerId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.destination": { + "name": "destination", + "schema": "", + "columns": { + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "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 + }, + "additionalFlags": { + "name": "additionalFlags", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "destination_organizationId_organization_id_fk": { + "name": "destination_organizationId_organization_id_fk", + "tableFrom": "destination", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "customCertResolver": { + "name": "customCertResolver", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "previewDeploymentId": { + "name": "previewDeploymentId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "internalPath": { + "name": "internalPath", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'/'" + }, + "stripPath": { + "name": "stripPath", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "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" + }, + "domain_previewDeploymentId_preview_deployments_previewDeploymentId_fk": { + "name": "domain_previewDeploymentId_preview_deployments_previewDeploymentId_fk", + "tableFrom": "domain", + "tableTo": "preview_deployments", + "columnsFrom": [ + "previewDeploymentId" + ], + "columnsTo": [ + "previewDeploymentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment": { + "name": "environment", + "schema": "", + "columns": { + "environmentId": { + "name": "environmentId", + "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 + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "environment_projectId_project_projectId_fk": { + "name": "environment_projectId_project_projectId_fk", + "tableFrom": "environment", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.git_provider": { + "name": "git_provider", + "schema": "", + "columns": { + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerType": { + "name": "providerType", + "type": "gitProviderType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'github'" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "git_provider_organizationId_organization_id_fk": { + "name": "git_provider_organizationId_organization_id_fk", + "tableFrom": "git_provider", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "git_provider_userId_user_id_fk": { + "name": "git_provider_userId_user_id_fk", + "tableFrom": "git_provider", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.gitea": { + "name": "gitea", + "schema": "", + "columns": { + "giteaId": { + "name": "giteaId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "giteaUrl": { + "name": "giteaUrl", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'https://gitea.com'" + }, + "giteaInternalUrl": { + "name": "giteaInternalUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'repo,repo:status,read:user,read:org'" + }, + "last_authenticated_at": { + "name": "last_authenticated_at", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "gitea_gitProviderId_git_provider_gitProviderId_fk": { + "name": "gitea_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "gitea", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.github": { + "name": "github", + "schema": "", + "columns": { + "githubId": { + "name": "githubId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "githubAppName": { + "name": "githubAppName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "githubAppId": { + "name": "githubAppId", + "type": "integer", + "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 + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "github_gitProviderId_git_provider_gitProviderId_fk": { + "name": "github_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "github", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.gitlab": { + "name": "gitlab", + "schema": "", + "columns": { + "gitlabId": { + "name": "gitlabId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "gitlabUrl": { + "name": "gitlabUrl", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'https://gitlab.com'" + }, + "gitlabInternalUrl": { + "name": "gitlabInternalUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "application_id": { + "name": "application_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "group_name": { + "name": "group_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "gitProviderId": { + "name": "gitProviderId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "gitlab_gitProviderId_git_provider_gitProviderId_fk": { + "name": "gitlab_gitProviderId_git_provider_gitProviderId_fk", + "tableFrom": "gitlab", + "tableTo": "git_provider", + "columnsFrom": [ + "gitProviderId" + ], + "columnsTo": [ + "gitProviderId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.libsql": { + "name": "libsql", + "schema": "", + "columns": { + "libsqlId": { + "name": "libsqlId", + "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 + }, + "sqldNode": { + "name": "sqldNode", + "type": "sqldNode", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'primary'" + }, + "sqldPrimaryUrl": { + "name": "sqldPrimaryUrl", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enableNamespaces": { + "name": "enableNamespaces", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": 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": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalGRPCPort": { + "name": "externalGRPCPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "externalAdminPort": { + "name": "externalAdminPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "libsql_environmentId_environment_environmentId_fk": { + "name": "libsql_environmentId_environment_environmentId_fk", + "tableFrom": "libsql", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "libsql_serverId_server_serverId_fk": { + "name": "libsql_serverId_server_serverId_fk", + "tableFrom": "libsql", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "libsql_appName_unique": { + "name": "libsql_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "args": { + "name": "args", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "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'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mariadb_environmentId_environment_environmentId_fk": { + "name": "mariadb_environmentId_environment_environmentId_fk", + "tableFrom": "mariadb", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mariadb_serverId_server_serverId_fk": { + "name": "mariadb_serverId_server_serverId_fk", + "tableFrom": "mariadb", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mariadb_appName_unique": { + "name": "mariadb_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "args": { + "name": "args", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "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'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "replicaSets": { + "name": "replicaSets", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "mongo_environmentId_environment_environmentId_fk": { + "name": "mongo_environmentId_environment_environmentId_fk", + "tableFrom": "mongo", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mongo_serverId_server_serverId_fk": { + "name": "mongo_serverId_server_serverId_fk", + "tableFrom": "mongo", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mongo_appName_unique": { + "name": "mongo_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "libsqlId": { + "name": "libsqlId", + "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 + }, + "postgresId": { + "name": "postgresId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redisId": { + "name": "redisId", + "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_composeId_compose_composeId_fk": { + "name": "mount_composeId_compose_composeId_fk", + "tableFrom": "mount", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mount_libsqlId_libsql_libsqlId_fk": { + "name": "mount_libsqlId_libsql_libsqlId_fk", + "tableFrom": "mount", + "tableTo": "libsql", + "columnsFrom": [ + "libsqlId" + ], + "columnsTo": [ + "libsqlId" + ], + "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_postgresId_postgres_postgresId_fk": { + "name": "mount_postgresId_postgres_postgresId_fk", + "tableFrom": "mount", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "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" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "args": { + "name": "args", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "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'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "mysql_environmentId_environment_environmentId_fk": { + "name": "mysql_environmentId_environment_environmentId_fk", + "tableFrom": "mysql", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "mysql_serverId_server_serverId_fk": { + "name": "mysql_serverId_server_serverId_fk", + "tableFrom": "mysql", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mysql_appName_unique": { + "name": "mysql_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.custom": { + "name": "custom", + "schema": "", + "columns": { + "customId": { + "name": "customId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "headers": { + "name": "headers", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.discord": { + "name": "discord", + "schema": "", + "columns": { + "discordId": { + "name": "discordId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "decoration": { + "name": "decoration", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.gotify": { + "name": "gotify", + "schema": "", + "columns": { + "gotifyId": { + "name": "gotifyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "serverUrl": { + "name": "serverUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appToken": { + "name": "appToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 5 + }, + "decoration": { + "name": "decoration", + "type": "boolean", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.lark": { + "name": "lark", + "schema": "", + "columns": { + "larkId": { + "name": "larkId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.mattermost": { + "name": "mattermost", + "schema": "", + "columns": { + "mattermostId": { + "name": "mattermostId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel": { + "name": "channel", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "volumeBackup": { + "name": "volumeBackup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dokployRestart": { + "name": "dokployRestart", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dokployBackup": { + "name": "dokployBackup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "dockerCleanup": { + "name": "dockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "serverThreshold": { + "name": "serverThreshold", + "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 + }, + "resendId": { + "name": "resendId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "gotifyId": { + "name": "gotifyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ntfyId": { + "name": "ntfyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mattermostId": { + "name": "mattermostId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "customId": { + "name": "customId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "larkId": { + "name": "larkId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pushoverId": { + "name": "pushoverId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "teamsId": { + "name": "teamsId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "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" + }, + "notification_resendId_resend_resendId_fk": { + "name": "notification_resendId_resend_resendId_fk", + "tableFrom": "notification", + "tableTo": "resend", + "columnsFrom": [ + "resendId" + ], + "columnsTo": [ + "resendId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_gotifyId_gotify_gotifyId_fk": { + "name": "notification_gotifyId_gotify_gotifyId_fk", + "tableFrom": "notification", + "tableTo": "gotify", + "columnsFrom": [ + "gotifyId" + ], + "columnsTo": [ + "gotifyId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_ntfyId_ntfy_ntfyId_fk": { + "name": "notification_ntfyId_ntfy_ntfyId_fk", + "tableFrom": "notification", + "tableTo": "ntfy", + "columnsFrom": [ + "ntfyId" + ], + "columnsTo": [ + "ntfyId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_mattermostId_mattermost_mattermostId_fk": { + "name": "notification_mattermostId_mattermost_mattermostId_fk", + "tableFrom": "notification", + "tableTo": "mattermost", + "columnsFrom": [ + "mattermostId" + ], + "columnsTo": [ + "mattermostId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_customId_custom_customId_fk": { + "name": "notification_customId_custom_customId_fk", + "tableFrom": "notification", + "tableTo": "custom", + "columnsFrom": [ + "customId" + ], + "columnsTo": [ + "customId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_larkId_lark_larkId_fk": { + "name": "notification_larkId_lark_larkId_fk", + "tableFrom": "notification", + "tableTo": "lark", + "columnsFrom": [ + "larkId" + ], + "columnsTo": [ + "larkId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_pushoverId_pushover_pushoverId_fk": { + "name": "notification_pushoverId_pushover_pushoverId_fk", + "tableFrom": "notification", + "tableTo": "pushover", + "columnsFrom": [ + "pushoverId" + ], + "columnsTo": [ + "pushoverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_teamsId_teams_teamsId_fk": { + "name": "notification_teamsId_teams_teamsId_fk", + "tableFrom": "notification", + "tableTo": "teams", + "columnsFrom": [ + "teamsId" + ], + "columnsTo": [ + "teamsId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_organizationId_organization_id_fk": { + "name": "notification_organizationId_organization_id_fk", + "tableFrom": "notification", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ntfy": { + "name": "ntfy", + "schema": "", + "columns": { + "ntfyId": { + "name": "ntfyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "serverUrl": { + "name": "serverUrl", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "topic": { + "name": "topic", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessToken": { + "name": "accessToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 3 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pushover": { + "name": "pushover", + "schema": "", + "columns": { + "pushoverId": { + "name": "pushoverId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userKey": { + "name": "userKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "apiToken": { + "name": "apiToken", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry": { + "name": "retry", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "expire": { + "name": "expire", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.resend": { + "name": "resend", + "schema": "", + "columns": { + "resendId": { + "name": "resendId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "apiKey": { + "name": "apiKey", + "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": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.teams": { + "name": "teams", + "schema": "", + "columns": { + "teamsId": { + "name": "teamsId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "webhookUrl": { + "name": "webhookUrl", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "messageThreadId": { + "name": "messageThreadId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.patch": { + "name": "patch", + "schema": "", + "columns": { + "patchId": { + "name": "patchId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "patchType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'update'" + }, + "filePath": { + "name": "filePath", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updatedAt": { + "name": "updatedAt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "patch_applicationId_application_applicationId_fk": { + "name": "patch_applicationId_application_applicationId_fk", + "tableFrom": "patch", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "patch_composeId_compose_composeId_fk": { + "name": "patch_composeId_compose_composeId_fk", + "tableFrom": "patch", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "patch_filepath_application_unique": { + "name": "patch_filepath_application_unique", + "nullsNotDistinct": false, + "columns": [ + "filePath", + "applicationId" + ] + }, + "patch_filepath_compose_unique": { + "name": "patch_filepath_compose_unique", + "nullsNotDistinct": false, + "columns": [ + "filePath", + "composeId" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.port": { + "name": "port", + "schema": "", + "columns": { + "portId": { + "name": "portId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publishedPort": { + "name": "publishedPort", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "publishMode": { + "name": "publishMode", + "type": "publishModeType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'host'" + }, + "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": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "args": { + "name": "args", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "externalPort": { + "name": "externalPort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationStatus": { + "name": "applicationStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "postgres_environmentId_environment_environmentId_fk": { + "name": "postgres_environmentId_environment_environmentId_fk", + "tableFrom": "postgres", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "postgres_serverId_server_serverId_fk": { + "name": "postgres_serverId_server_serverId_fk", + "tableFrom": "postgres", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "postgres_appName_unique": { + "name": "postgres_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.preview_deployments": { + "name": "preview_deployments", + "schema": "", + "columns": { + "previewDeploymentId": { + "name": "previewDeploymentId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pullRequestId": { + "name": "pullRequestId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pullRequestNumber": { + "name": "pullRequestNumber", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pullRequestURL": { + "name": "pullRequestURL", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pullRequestTitle": { + "name": "pullRequestTitle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pullRequestCommentId": { + "name": "pullRequestCommentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "previewStatus": { + "name": "previewStatus", + "type": "applicationStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domainId": { + "name": "domainId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "preview_deployments_applicationId_application_applicationId_fk": { + "name": "preview_deployments_applicationId_application_applicationId_fk", + "tableFrom": "preview_deployments", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "preview_deployments_domainId_domain_domainId_fk": { + "name": "preview_deployments_domainId_domain_domainId_fk", + "tableFrom": "preview_deployments", + "tableTo": "domain", + "columnsFrom": [ + "domainId" + ], + "columnsTo": [ + "domainId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "preview_deployments_appName_unique": { + "name": "preview_deployments_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": {}, + "foreignKeys": { + "project_organizationId_organization_id_fk": { + "name": "project_organizationId_organization_id_fk", + "tableFrom": "project", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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 + }, + "args": { + "name": "args", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "env": { + "name": "env", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryReservation": { + "name": "memoryReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "memoryLimit": { + "name": "memoryLimit", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuReservation": { + "name": "cpuReservation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cpuLimit": { + "name": "cpuLimit", + "type": "text", + "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'" + }, + "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 + }, + "stopGracePeriodSwarm": { + "name": "stopGracePeriodSwarm", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "endpointSpecSwarm": { + "name": "endpointSpecSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "ulimitsSwarm": { + "name": "ulimitsSwarm", + "type": "json", + "primaryKey": false, + "notNull": false + }, + "replicas": { + "name": "replicas", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "environmentId": { + "name": "environmentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "redis_environmentId_environment_environmentId_fk": { + "name": "redis_environmentId_environment_environmentId_fk", + "tableFrom": "redis", + "tableTo": "environment", + "columnsFrom": [ + "environmentId" + ], + "columnsTo": [ + "environmentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "redis_serverId_server_serverId_fk": { + "name": "redis_serverId_server_serverId_fk", + "tableFrom": "redis", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "redis_appName_unique": { + "name": "redis_appName_unique", + "nullsNotDistinct": false, + "columns": [ + "appName" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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, + "default": "''" + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "selfHosted": { + "name": "selfHosted", + "type": "RegistryType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'cloud'" + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "registry_organizationId_organization_id_fk": { + "name": "registry_organizationId_organization_id_fk", + "tableFrom": "registry", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rollback": { + "name": "rollback", + "schema": "", + "columns": { + "rollbackId": { + "name": "rollbackId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "deploymentId": { + "name": "deploymentId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "serial", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "fullContext": { + "name": "fullContext", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "rollback_deploymentId_deployment_deploymentId_fk": { + "name": "rollback_deploymentId_deployment_deploymentId_fk", + "tableFrom": "rollback", + "tableTo": "deployment", + "columnsFrom": [ + "deploymentId" + ], + "columnsTo": [ + "deploymentId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.schedule": { + "name": "schedule", + "schema": "", + "columns": { + "scheduleId": { + "name": "scheduleId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cronExpression": { + "name": "cronExpression", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "shellType": { + "name": "shellType", + "type": "shellType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'bash'" + }, + "scheduleType": { + "name": "scheduleType", + "type": "scheduleType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'application'" + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "script": { + "name": "script", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "applicationId": { + "name": "applicationId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "schedule_applicationId_application_applicationId_fk": { + "name": "schedule_applicationId_application_applicationId_fk", + "tableFrom": "schedule", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "schedule_composeId_compose_composeId_fk": { + "name": "schedule_composeId_compose_composeId_fk", + "tableFrom": "schedule", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "schedule_serverId_server_serverId_fk": { + "name": "schedule_serverId_server_serverId_fk", + "tableFrom": "schedule", + "tableTo": "server", + "columnsFrom": [ + "serverId" + ], + "columnsTo": [ + "serverId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "schedule_userId_user_id_fk": { + "name": "schedule_userId_user_id_fk", + "tableFrom": "schedule", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "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" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.server": { + "name": "server", + "schema": "", + "columns": { + "serverId": { + "name": "serverId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ipAddress": { + "name": "ipAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'root'" + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enableDockerCleanup": { + "name": "enableDockerCleanup", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serverStatus": { + "name": "serverStatus", + "type": "serverStatus", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'active'" + }, + "serverType": { + "name": "serverType", + "type": "serverType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'deploy'" + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "sshKeyId": { + "name": "sshKeyId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metricsConfig": { + "name": "metricsConfig", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{\"server\":{\"type\":\"Remote\",\"refreshRate\":60,\"port\":4500,\"token\":\"\",\"urlCallback\":\"\",\"cronJob\":\"\",\"retentionDays\":2,\"thresholds\":{\"cpu\":0,\"memory\":0}},\"containers\":{\"refreshRate\":60,\"services\":{\"include\":[],\"exclude\":[]}}}'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": { + "server_organizationId_organization_id_fk": { + "name": "server_organizationId_organization_id_fk", + "tableFrom": "server", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "server_sshKeyId_ssh-key_sshKeyId_fk": { + "name": "server_sshKeyId_ssh-key_sshKeyId_fk", + "tableFrom": "server", + "tableTo": "ssh-key", + "columnsFrom": [ + "sshKeyId" + ], + "columnsTo": [ + "sshKeyId" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh-key": { + "name": "ssh-key", + "schema": "", + "columns": { + "sshKeyId": { + "name": "sshKeyId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "privateKey": { + "name": "privateKey", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "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 + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "ssh-key_organizationId_organization_id_fk": { + "name": "ssh-key_organizationId_organization_id_fk", + "tableFrom": "ssh-key", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sso_provider": { + "name": "sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_config": { + "name": "oidc_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "saml_config": { + "name": "saml_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "sso_provider_user_id_user_id_fk": { + "name": "sso_provider_user_id_user_id_fk", + "tableFrom": "sso_provider", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sso_provider_organization_id_organization_id_fk": { + "name": "sso_provider_organization_id_organization_id_fk", + "tableFrom": "sso_provider", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sso_provider_provider_id_unique": { + "name": "sso_provider_provider_id_unique", + "nullsNotDistinct": false, + "columns": [ + "provider_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.project_tag": { + "name": "project_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "projectId": { + "name": "projectId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tagId": { + "name": "tagId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "project_tag_projectId_project_projectId_fk": { + "name": "project_tag_projectId_project_projectId_fk", + "tableFrom": "project_tag", + "tableTo": "project", + "columnsFrom": [ + "projectId" + ], + "columnsTo": [ + "projectId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_tag_tagId_tag_tagId_fk": { + "name": "project_tag_tagId_tag_tagId_fk", + "tableFrom": "project_tag", + "tableTo": "tag", + "columnsFrom": [ + "tagId" + ], + "columnsTo": [ + "tagId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_project_tag": { + "name": "unique_project_tag", + "nullsNotDistinct": false, + "columns": [ + "projectId", + "tagId" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tag": { + "name": "tag", + "schema": "", + "columns": { + "tagId": { + "name": "tagId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organizationId": { + "name": "organizationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "tag_organizationId_organization_id_fk": { + "name": "tag_organizationId_organization_id_fk", + "tableFrom": "tag", + "tableTo": "organization", + "columnsFrom": [ + "organizationId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_org_tag_name": { + "name": "unique_org_tag_name", + "nullsNotDistinct": false, + "columns": [ + "organizationId", + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "firstName": { + "name": "firstName", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "lastName": { + "name": "lastName", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "isRegistered": { + "name": "isRegistered", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "expirationDate": { + "name": "expirationDate", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "two_factor_enabled": { + "name": "two_factor_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "enablePaidFeatures": { + "name": "enablePaidFeatures", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "allowImpersonation": { + "name": "allowImpersonation", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "enableEnterpriseFeatures": { + "name": "enableEnterpriseFeatures", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "licenseKey": { + "name": "licenseKey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "isValidEnterpriseLicense": { + "name": "isValidEnterpriseLicense", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "stripeCustomerId": { + "name": "stripeCustomerId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripeSubscriptionId": { + "name": "stripeSubscriptionId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "serversQuantity": { + "name": "serversQuantity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "trustedOrigins": { + "name": "trustedOrigins", + "type": "text[]", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.volume_backup": { + "name": "volume_backup", + "schema": "", + "columns": { + "volumeBackupId": { + "name": "volumeBackupId", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "volumeName": { + "name": "volumeName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serviceType": { + "name": "serviceType", + "type": "serviceType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'application'" + }, + "appName": { + "name": "appName", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "serviceName": { + "name": "serviceName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "turnOff": { + "name": "turnOff", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "cronExpression": { + "name": "cronExpression", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "keepLatestCount": { + "name": "keepLatestCount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "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 + }, + "libsqlId": { + "name": "libsqlId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "composeId": { + "name": "composeId", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "destinationId": { + "name": "destinationId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "volume_backup_applicationId_application_applicationId_fk": { + "name": "volume_backup_applicationId_application_applicationId_fk", + "tableFrom": "volume_backup", + "tableTo": "application", + "columnsFrom": [ + "applicationId" + ], + "columnsTo": [ + "applicationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_postgresId_postgres_postgresId_fk": { + "name": "volume_backup_postgresId_postgres_postgresId_fk", + "tableFrom": "volume_backup", + "tableTo": "postgres", + "columnsFrom": [ + "postgresId" + ], + "columnsTo": [ + "postgresId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_mariadbId_mariadb_mariadbId_fk": { + "name": "volume_backup_mariadbId_mariadb_mariadbId_fk", + "tableFrom": "volume_backup", + "tableTo": "mariadb", + "columnsFrom": [ + "mariadbId" + ], + "columnsTo": [ + "mariadbId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_mongoId_mongo_mongoId_fk": { + "name": "volume_backup_mongoId_mongo_mongoId_fk", + "tableFrom": "volume_backup", + "tableTo": "mongo", + "columnsFrom": [ + "mongoId" + ], + "columnsTo": [ + "mongoId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_mysqlId_mysql_mysqlId_fk": { + "name": "volume_backup_mysqlId_mysql_mysqlId_fk", + "tableFrom": "volume_backup", + "tableTo": "mysql", + "columnsFrom": [ + "mysqlId" + ], + "columnsTo": [ + "mysqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_redisId_redis_redisId_fk": { + "name": "volume_backup_redisId_redis_redisId_fk", + "tableFrom": "volume_backup", + "tableTo": "redis", + "columnsFrom": [ + "redisId" + ], + "columnsTo": [ + "redisId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_libsqlId_libsql_libsqlId_fk": { + "name": "volume_backup_libsqlId_libsql_libsqlId_fk", + "tableFrom": "volume_backup", + "tableTo": "libsql", + "columnsFrom": [ + "libsqlId" + ], + "columnsTo": [ + "libsqlId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_composeId_compose_composeId_fk": { + "name": "volume_backup_composeId_compose_composeId_fk", + "tableFrom": "volume_backup", + "tableTo": "compose", + "columnsFrom": [ + "composeId" + ], + "columnsTo": [ + "composeId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "volume_backup_destinationId_destination_destinationId_fk": { + "name": "volume_backup_destinationId_destination_destinationId_fk", + "tableFrom": "volume_backup", + "tableTo": "destination", + "columnsFrom": [ + "destinationId" + ], + "columnsTo": [ + "destinationId" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webServerSettings": { + "name": "webServerSettings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "serverIp": { + "name": "serverIp", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "certificateType": { + "name": "certificateType", + "type": "certificateType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "https": { + "name": "https", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "host": { + "name": "host", + "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": true + }, + "logCleanupCron": { + "name": "logCleanupCron", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'0 0 * * *'" + }, + "metricsConfig": { + "name": "metricsConfig", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{\"server\":{\"type\":\"Dokploy\",\"refreshRate\":60,\"port\":4500,\"token\":\"\",\"retentionDays\":2,\"cronJob\":\"\",\"urlCallback\":\"\",\"thresholds\":{\"cpu\":0,\"memory\":0}},\"containers\":{\"refreshRate\":60,\"services\":{\"include\":[],\"exclude\":[]}}}'::jsonb" + }, + "whitelabelingConfig": { + "name": "whitelabelingConfig", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{\"appName\":null,\"appDescription\":null,\"logoUrl\":null,\"faviconUrl\":null,\"customCss\":null,\"loginLogoUrl\":null,\"supportUrl\":null,\"docsUrl\":null,\"errorPageTitle\":null,\"errorPageDescription\":null,\"metaTitle\":null,\"footerText\":null}'::jsonb" + }, + "cleanupCacheApplications": { + "name": "cleanupCacheApplications", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "cleanupCacheOnPreviews": { + "name": "cleanupCacheOnPreviews", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "cleanupCacheOnCompose": { + "name": "cleanupCacheOnCompose", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.buildType": { + "name": "buildType", + "schema": "public", + "values": [ + "dockerfile", + "heroku_buildpacks", + "paketo_buildpacks", + "nixpacks", + "static", + "railpack" + ] + }, + "public.sourceType": { + "name": "sourceType", + "schema": "public", + "values": [ + "docker", + "git", + "github", + "gitlab", + "bitbucket", + "gitea", + "drop" + ] + }, + "public.backupType": { + "name": "backupType", + "schema": "public", + "values": [ + "database", + "compose" + ] + }, + "public.databaseType": { + "name": "databaseType", + "schema": "public", + "values": [ + "postgres", + "mariadb", + "mysql", + "mongo", + "web-server", + "libsql" + ] + }, + "public.composeType": { + "name": "composeType", + "schema": "public", + "values": [ + "docker-compose", + "stack" + ] + }, + "public.sourceTypeCompose": { + "name": "sourceTypeCompose", + "schema": "public", + "values": [ + "git", + "github", + "gitlab", + "bitbucket", + "gitea", + "raw" + ] + }, + "public.deploymentStatus": { + "name": "deploymentStatus", + "schema": "public", + "values": [ + "running", + "done", + "error", + "cancelled" + ] + }, + "public.domainType": { + "name": "domainType", + "schema": "public", + "values": [ + "compose", + "application", + "preview" + ] + }, + "public.gitProviderType": { + "name": "gitProviderType", + "schema": "public", + "values": [ + "github", + "gitlab", + "bitbucket", + "gitea" + ] + }, + "public.mountType": { + "name": "mountType", + "schema": "public", + "values": [ + "bind", + "volume", + "file" + ] + }, + "public.serviceType": { + "name": "serviceType", + "schema": "public", + "values": [ + "application", + "postgres", + "mysql", + "mariadb", + "mongo", + "redis", + "compose", + "libsql" + ] + }, + "public.notificationType": { + "name": "notificationType", + "schema": "public", + "values": [ + "slack", + "telegram", + "discord", + "email", + "resend", + "gotify", + "ntfy", + "mattermost", + "pushover", + "custom", + "lark", + "teams" + ] + }, + "public.patchType": { + "name": "patchType", + "schema": "public", + "values": [ + "create", + "update", + "delete" + ] + }, + "public.protocolType": { + "name": "protocolType", + "schema": "public", + "values": [ + "tcp", + "udp" + ] + }, + "public.publishModeType": { + "name": "publishModeType", + "schema": "public", + "values": [ + "ingress", + "host" + ] + }, + "public.RegistryType": { + "name": "RegistryType", + "schema": "public", + "values": [ + "selfHosted", + "cloud" + ] + }, + "public.scheduleType": { + "name": "scheduleType", + "schema": "public", + "values": [ + "application", + "compose", + "server", + "dokploy-server" + ] + }, + "public.shellType": { + "name": "shellType", + "schema": "public", + "values": [ + "bash", + "sh" + ] + }, + "public.serverStatus": { + "name": "serverStatus", + "schema": "public", + "values": [ + "active", + "inactive" + ] + }, + "public.serverType": { + "name": "serverType", + "schema": "public", + "values": [ + "deploy", + "build" + ] + }, + "public.applicationStatus": { + "name": "applicationStatus", + "schema": "public", + "values": [ + "idle", + "running", + "done", + "error" + ] + }, + "public.certificateType": { + "name": "certificateType", + "schema": "public", + "values": [ + "letsencrypt", + "none", + "custom" + ] + }, + "public.sqldNode": { + "name": "sqldNode", + "schema": "public", + "values": [ + "primary", + "replica" + ] + }, + "public.triggerType": { + "name": "triggerType", + "schema": "public", + "values": [ + "push", + "tag" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_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 1f6d78fde..0135eb318 100644 --- a/apps/dokploy/drizzle/meta/_journal.json +++ b/apps/dokploy/drizzle/meta/_journal.json @@ -1093,6 +1093,13 @@ "when": 1774794547865, "tag": "0155_careless_clea", "breakpoints": true + }, + { + "idx": 156, + "version": "7", + "when": 1774910955774, + "tag": "0156_fair_vargas", + "breakpoints": true } ] } \ No newline at end of file From 9b108480a8d26b98e3cb4da2cff99adc3d986341 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:49:52 +0000 Subject: [PATCH 14/25] [autofix.ci] apply automated fixes --- .../src/emails/emails/dokploy-backup.tsx | 191 +++++++++--------- .../server/src/utils/backups/web-server.ts | 10 +- .../src/utils/notifications/dokploy-backup.ts | 8 +- 3 files changed, 103 insertions(+), 106 deletions(-) diff --git a/packages/server/src/emails/emails/dokploy-backup.tsx b/packages/server/src/emails/emails/dokploy-backup.tsx index ea2246eb6..327a02a5b 100644 --- a/packages/server/src/emails/emails/dokploy-backup.tsx +++ b/packages/server/src/emails/emails/dokploy-backup.tsx @@ -1,105 +1,106 @@ import { - Body, - Container, - Head, - Heading, - Html, - Img, - Preview, - Section, - Tailwind, - Text, + Body, + Container, + Head, + Heading, + Html, + Img, + Preview, + Section, + Tailwind, + Text, } from "@react-email/components"; export type TemplateProps = { - type: "error" | "success"; - errorMessage?: string; - date: string; - backupSize?: string; + type: "error" | "success"; + errorMessage?: string; + date: string; + backupSize?: string; }; export const DokployBackupEmail = ({ - type = "success", - errorMessage, - date = "2023-05-01T00:00:00.000Z", - backupSize, + type = "success", + errorMessage, + date = "2023-05-01T00:00:00.000Z", + backupSize, }: TemplateProps) => { - const previewText = `Dokploy instance backup was ${type === "success" ? "successful ✅" : "failed ❌"}`; - - return ( - - {previewText} - - - - -
- Dokploy -
- - Dokploy Instance Backup - - - Hello, - - - Your Dokploy instance backup was{" "} - {type === "success" - ? "successful ✅" - : "failed. Please check the error message below. ❌"} - . - -
- Details: - - Backup Type: Complete Dokploy Instance - - - Content: /etc/dokploy + PostgreSQL Database - - {backupSize && ( - - Backup Size: {backupSize} - - )} - - Date: {date} - - - Status: {type === "success" ? "Successful" : "Failed"} - -
- {type === "error" && errorMessage ? ( -
- Reason: - - {errorMessage || "Error message not provided"} - -
- ) : null} -
- -
- - ); + const previewText = `Dokploy instance backup was ${type === "success" ? "successful ✅" : "failed ❌"}`; + + return ( + + {previewText} + + + + +
+ Dokploy +
+ + Dokploy Instance Backup + + + Hello, + + + Your Dokploy instance backup was{" "} + {type === "success" + ? "successful ✅" + : "failed. Please check the error message below. ❌"} + . + +
+ Details: + + Backup Type: Complete Dokploy Instance + + + Content: /etc/dokploy + PostgreSQL Database + + {backupSize && ( + + Backup Size: {backupSize} + + )} + + Date: {date} + + + Status:{" "} + {type === "success" ? "Successful" : "Failed"} + +
+ {type === "error" && errorMessage ? ( +
+ Reason: + + {errorMessage || "Error message not provided"} + +
+ ) : null} +
+ +
+ + ); }; -export default DokployBackupEmail; \ No newline at end of file +export default DokployBackupEmail; diff --git a/packages/server/src/utils/backups/web-server.ts b/packages/server/src/utils/backups/web-server.ts index 04c35ed46..19dd44eed 100644 --- a/packages/server/src/utils/backups/web-server.ts +++ b/packages/server/src/utils/backups/web-server.ts @@ -124,11 +124,11 @@ export const runWebServerBackup = async (backup: BackupSchedule) => { ); writeStream.end(); await sendDokployBackupNotifications({ - type: "error", - // @ts-ignore - errorMessage: error?.message || "Error message not provided", - backupSize: formatBytes(computedBackupSize), - }); + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + backupSize: formatBytes(computedBackupSize), + }); await updateDeploymentStatus(deployment.deploymentId, "error"); throw error; } diff --git a/packages/server/src/utils/notifications/dokploy-backup.ts b/packages/server/src/utils/notifications/dokploy-backup.ts index 707f53839..580dd1baa 100644 --- a/packages/server/src/utils/notifications/dokploy-backup.ts +++ b/packages/server/src/utils/notifications/dokploy-backup.ts @@ -51,11 +51,7 @@ export const sendDokployBackupNotifications = async ({ backupSize, }), ).catch(); - await sendEmailNotification( - email, - "Dokploy instance backup", - template, - ); + await sendEmailNotification(email, "Dokploy instance backup", template); } if (discord) { @@ -319,4 +315,4 @@ export const sendDokployBackupNotifications = async ({ }); } } -}; \ No newline at end of file +}; From 365e055005e437f85cc34823df666c9da61634bd Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Wed, 1 Apr 2026 08:26:24 -0600 Subject: [PATCH 15/25] feat(notifications): integrate dokployBackup into notification handling - Added dokployBackup parameter to various notification functions and schemas to support backup notifications. - Updated HandleNotifications component to include dokployBackup in notification payloads. - Enhanced notification utilities to accommodate new backup notification types across multiple channels. --- .../notifications/handle-notifications.tsx | 10 + packages/server/src/db/schema/notification.ts | 7 + packages/server/src/services/notification.ts | 10 + .../src/utils/notifications/dokploy-backup.ts | 606 ++++++++++-------- 4 files changed, 379 insertions(+), 254 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index 7f427ef07..37463fd62 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -421,6 +421,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, volumeBackup: notification.volumeBackup, type: notification.notificationType, apiKey: notification.resend?.apiKey, @@ -469,6 +470,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, volumeBackup: notification.volumeBackup, type: notification.notificationType, webhookUrl: notification.mattermost?.webhookUrl, @@ -498,6 +500,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, volumeBackup: notification.volumeBackup, type: notification.notificationType, webhookUrl: notification.teams?.webhookUrl, @@ -511,6 +514,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, type: notification.notificationType, endpoint: notification.custom?.endpoint || "", headers: notification.custom?.headers @@ -532,6 +536,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: notification.appDeploy, dokployRestart: notification.dokployRestart, databaseBackup: notification.databaseBackup, + dokployBackup: notification.dokployBackup, volumeBackup: notification.volumeBackup, type: notification.notificationType, userKey: notification.pushover?.userKey, @@ -651,6 +656,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, volumeBackup: volumeBackup, apiKey: data.apiKey, fromAddress: data.fromAddress, @@ -701,6 +707,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, volumeBackup: volumeBackup, webhookUrl: data.webhookUrl, channel: data.channel || undefined, @@ -732,6 +739,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, volumeBackup: volumeBackup, webhookUrl: data.webhookUrl, name: data.name, @@ -758,6 +766,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, volumeBackup: volumeBackup, endpoint: data.endpoint, headers: headersRecord, @@ -777,6 +786,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { appDeploy: appDeploy, dokployRestart: dokployRestart, databaseBackup: databaseBackup, + dokployBackup: dokployBackup, volumeBackup: volumeBackup, userKey: data.userKey, apiToken: data.apiToken, diff --git a/packages/server/src/db/schema/notification.ts b/packages/server/src/db/schema/notification.ts index 94398704b..3caf23d13 100644 --- a/packages/server/src/db/schema/notification.ts +++ b/packages/server/src/db/schema/notification.ts @@ -396,6 +396,7 @@ export const apiCreateResend = notificationsSchema .pick({ appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, name: true, @@ -493,6 +494,7 @@ export const apiCreateMattermost = notificationsSchema .pick({ appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, name: true, @@ -510,6 +512,7 @@ export const apiCreateMattermost = notificationsSchema webhookUrl: true, appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, appDeploy: true, @@ -542,6 +545,7 @@ export const apiCreateCustom = notificationsSchema .pick({ appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, name: true, @@ -596,6 +600,7 @@ export const apiCreateTeams = notificationsSchema .pick({ appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, name: true, @@ -622,6 +627,7 @@ export const apiCreatePushover = notificationsSchema .pick({ appBuildError: true, databaseBackup: true, + dokployBackup: true, volumeBackup: true, dokployRestart: true, name: true, @@ -656,6 +662,7 @@ export const apiUpdatePushover = z.object({ expire: z.number().min(1).max(10800).nullish(), appBuildError: z.boolean().optional(), databaseBackup: z.boolean().optional(), + dokployBackup: z.boolean().optional(), volumeBackup: z.boolean().optional(), dokployRestart: z.boolean().optional(), name: z.string().optional(), diff --git a/packages/server/src/services/notification.ts b/packages/server/src/services/notification.ts index b689d7194..2c8247f0c 100644 --- a/packages/server/src/services/notification.ts +++ b/packages/server/src/services/notification.ts @@ -460,6 +460,7 @@ export const createResendNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -492,6 +493,7 @@ export const updateResendNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -741,6 +743,7 @@ export const createCustomNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -773,6 +776,7 @@ export const updateCustomNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -958,6 +962,7 @@ export const createTeamsNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -990,6 +995,7 @@ export const updateTeamsNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -1065,6 +1071,7 @@ export const createMattermostNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -1097,6 +1104,7 @@ export const updateMattermostNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -1161,6 +1169,7 @@ export const createPushoverNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, @@ -1193,6 +1202,7 @@ export const updatePushoverNotification = async ( appDeploy: input.appDeploy, appBuildError: input.appBuildError, databaseBackup: input.databaseBackup, + dokployBackup: input.dokployBackup, volumeBackup: input.volumeBackup, dokployRestart: input.dokployRestart, dockerCleanup: input.dockerCleanup, diff --git a/packages/server/src/utils/notifications/dokploy-backup.ts b/packages/server/src/utils/notifications/dokploy-backup.ts index 580dd1baa..26a88d657 100644 --- a/packages/server/src/utils/notifications/dokploy-backup.ts +++ b/packages/server/src/utils/notifications/dokploy-backup.ts @@ -5,12 +5,17 @@ import { renderAsync } from "@react-email/components"; import { format } from "date-fns"; import { eq } from "drizzle-orm"; import { + sendCustomNotification, sendDiscordNotification, sendEmailNotification, - sendLarkNotification, sendGotifyNotification, + sendLarkNotification, + sendMattermostNotification, sendNtfyNotification, + sendPushoverNotification, + sendResendNotification, sendSlackNotification, + sendTeamsNotification, sendTelegramNotification, } from "./utils"; @@ -32,287 +37,380 @@ export const sendDokployBackupNotifications = async ({ discord: true, telegram: true, slack: true, + resend: true, gotify: true, ntfy: true, + mattermost: true, + custom: true, lark: true, + pushover: true, + teams: true, }, }); for (const notification of notificationList) { - const { email, discord, telegram, slack, gotify, ntfy, lark } = - notification; + const { + email, + discord, + telegram, + slack, + resend, + gotify, + ntfy, + mattermost, + custom, + lark, + pushover, + teams, + } = notification; - if (email) { - const template = await renderAsync( - DokployBackupEmail({ - type, - errorMessage, - date: date.toLocaleString(), - backupSize, - }), - ).catch(); - await sendEmailNotification(email, "Dokploy instance backup", template); - } + try { + if (email || resend) { + const template = await renderAsync( + DokployBackupEmail({ + type, + errorMessage, + date: date.toLocaleString(), + backupSize, + }), + ).catch(); - if (discord) { - const decorate = (decoration: string, text: string) => - `${discord.decoration ? decoration : ""} ${text}`.trim(); + if (email) { + await sendEmailNotification( + email, + "Dokploy instance backup", + template, + ); + } - await sendDiscordNotification(discord, { - title: - type === "success" - ? decorate(">", "`✅` Dokploy Backup Successful") - : decorate(">", "`❌` Dokploy Backup Failed"), - color: type === "success" ? 0x57f287 : 0xed4245, - fields: [ - { - name: decorate("`📦`", "Backup Type"), - value: "Complete Dokploy Instance", - inline: true, + if (resend) { + await sendResendNotification( + resend, + "Dokploy instance backup", + template, + ); + } + } + + if (discord) { + const decorate = (decoration: string, text: string) => + `${discord.decoration ? decoration : ""} ${text}`.trim(); + + await sendDiscordNotification(discord, { + title: + type === "success" + ? decorate(">", "`✅` Dokploy Backup Successful") + : decorate(">", "`❌` Dokploy Backup Failed"), + color: type === "success" ? 0x57f287 : 0xed4245, + fields: [ + { + name: decorate("`📦`", "Backup Type"), + value: "Complete Dokploy Instance", + inline: true, + }, + ...(backupSize + ? [ + { + name: decorate("`💾`", "Backup Size"), + value: backupSize, + inline: true, + }, + ] + : []), + { + name: decorate("`📅`", "Date"), + value: ``, + inline: true, + }, + { + name: decorate("`⌚`", "Time"), + value: ``, + inline: true, + }, + { + name: decorate("`❓`", "Status"), + value: type + .replace("error", "Failed") + .replace("success", "Successful"), + inline: true, + }, + ...(type === "error" && errorMessage + ? [ + { + name: decorate("`⚠️`", "Error Message"), + value: `\`\`\`${errorMessage}\`\`\``, + }, + ] + : []), + ], + timestamp: date.toISOString(), + footer: { + text: "Dokploy Instance Backup Notification", }, - ...(backupSize - ? [ - { - name: decorate("`💾`", "Backup Size"), - value: backupSize, - inline: true, - }, - ] - : []), - { - name: decorate("`📅`", "Date"), - value: ``, - inline: true, - }, - { - name: decorate("`⌚`", "Time"), - value: ``, - inline: true, - }, - { - name: decorate("`❓`", "Status"), - value: type - .replace("error", "Failed") - .replace("success", "Successful"), - inline: true, - }, - ...(type === "error" && errorMessage - ? [ - { - name: decorate("`⚠️`", "Error Message"), - value: `\`\`\`${errorMessage}\`\`\``, - }, - ] - : []), - ], - timestamp: date.toISOString(), - footer: { - text: "Dokploy Instance Backup Notification", - }, - }); - } + }); + } - if (gotify) { - const decorate = (decoration: string, text: string) => - `${gotify.decoration ? decoration : ""} ${text}\n`; + if (gotify) { + const decorate = (decoration: string, text: string) => + `${gotify.decoration ? decoration : ""} ${text}\n`; - await sendGotifyNotification( - gotify, - decorate( - type === "success" ? "✅" : "❌", + await sendGotifyNotification( + gotify, + decorate( + type === "success" ? "✅" : "❌", + `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + ), + `${decorate("📦", "Backup Type: Complete Dokploy Instance")}` + + `${backupSize ? decorate("💾", `Backup Size: ${backupSize}`) : ""}` + + `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + + `${type === "error" && errorMessage ? decorate("❌", `Error:\n${errorMessage}`) : ""}`, + ); + } + + if (ntfy) { + await sendNtfyNotification( + ntfy, `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, - ), - `${decorate("📦", "Backup Type: Complete Dokploy Instance")}` + - `${backupSize ? decorate("💾", `Backup Size: ${backupSize}`) : ""}` + - `${decorate("🕒", `Date: ${date.toLocaleString()}`)}` + - `${type === "error" && errorMessage ? decorate("❌", `Error:\n${errorMessage}`) : ""}`, - ); - } + `${type === "success" ? "white_check_mark" : "x"}`, + "", + "📦Backup Type: Complete Dokploy Instance\n" + + `${backupSize ? `💾Backup Size: ${backupSize}\n` : ""}` + + `🕒Date: ${date.toLocaleString()}\n` + + `${type === "error" && errorMessage ? `❌Error:\n${errorMessage}` : ""}`, + ); + } - if (ntfy) { - await sendNtfyNotification( - ntfy, - `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, - `${type === "success" ? "white_check_mark" : "x"}`, - "", - `📦Backup Type: Complete Dokploy Instance\n` + - `${backupSize ? `💾Backup Size: ${backupSize}\n` : ""}` + - `🕒Date: ${date.toLocaleString()}\n` + - `${type === "error" && errorMessage ? `❌Error:\n${errorMessage}` : ""}`, - ); - } + if (telegram) { + const isError = type === "error" && errorMessage; - if (telegram) { - const isError = type === "error" && errorMessage; + const statusEmoji = type === "success" ? "✅" : "❌"; + const typeStatus = type === "success" ? "Successful" : "Failed"; + const errorMsg = isError + ? `\n\nError:\n
${errorMessage}
` + : ""; + const sizeInfo = backupSize + ? `\nBackup Size: ${backupSize}` + : ""; - const statusEmoji = type === "success" ? "✅" : "❌"; - const typeStatus = type === "success" ? "Successful" : "Failed"; - const errorMsg = isError - ? `\n\nError:\n
${errorMessage}
` - : ""; - const sizeInfo = backupSize ? `\nBackup Size: ${backupSize}` : ""; + const messageText = `${statusEmoji} Dokploy Backup ${typeStatus}\n\nBackup Type: Complete Dokploy Instance${sizeInfo}\nDate: ${format(date, "PP")}\nTime: ${format(date, "pp")}${isError ? errorMsg : ""}`; - const messageText = `${statusEmoji} Dokploy Backup ${typeStatus}\n\nBackup Type: Complete Dokploy Instance${sizeInfo}\nDate: ${format(date, "PP")}\nTime: ${format(date, "pp")}${isError ? errorMsg : ""}`; + await sendTelegramNotification(telegram, messageText); + } - await sendTelegramNotification(telegram, messageText); - } + if (slack) { + const { channel } = slack; + await sendSlackNotification(slack, { + channel: channel, + attachments: [ + { + color: type === "success" ? "#00FF00" : "#FF0000", + pretext: + type === "success" + ? ":white_check_mark: *Dokploy Backup Successful*" + : ":x: *Dokploy Backup Failed*", + fields: [ + ...(type === "error" && errorMessage + ? [ + { + title: "Error Message", + value: errorMessage, + short: false, + }, + ] + : []), + { + title: "Backup Type", + value: "Complete Dokploy Instance", + short: true, + }, + ...(backupSize + ? [ + { + title: "Backup Size", + value: backupSize, + short: true, + }, + ] + : []), + { + title: "Time", + value: date.toLocaleString(), + short: true, + }, + { + title: "Status", + value: type === "success" ? "Successful" : "Failed", + short: true, + }, + ], + }, + ], + }); + } - if (slack) { - const { channel } = slack; - await sendSlackNotification(slack, { - channel: channel, - attachments: [ - { - color: type === "success" ? "#00FF00" : "#FF0000", - pretext: - type === "success" - ? ":white_check_mark: *Dokploy Backup Successful*" - : ":x: *Dokploy Backup Failed*", - fields: [ - ...(type === "error" && errorMessage - ? [ - { - title: "Error Message", - value: errorMessage, - short: false, - }, - ] - : []), - { - title: "Backup Type", - value: "Complete Dokploy Instance", - short: true, - }, - ...(backupSize - ? [ - { - title: "Backup Size", - value: backupSize, - short: true, - }, - ] - : []), - { - title: "Time", - value: date.toLocaleString(), - short: true, - }, - { - title: "Status", - value: type === "success" ? "Successful" : "Failed", - short: true, - }, - ], - }, - ], - }); - } + if (lark) { + const limitCharacter = 800; + const truncatedErrorMessage = + errorMessage && errorMessage.length > limitCharacter + ? errorMessage.substring(0, limitCharacter) + : errorMessage; - if (lark) { - const limitCharacter = 800; - const truncatedErrorMessage = - errorMessage && errorMessage.length > limitCharacter - ? errorMessage.substring(0, limitCharacter) - : errorMessage; - - await sendLarkNotification(lark, { - msg_type: "interactive", - card: { - schema: "2.0", - config: { - update_multi: true, - style: { - text_size: { - normal_v2: { - default: "normal", - pc: "normal", - mobile: "heading", + await sendLarkNotification(lark, { + msg_type: "interactive", + card: { + schema: "2.0", + config: { + update_multi: true, + style: { + text_size: { + normal_v2: { + default: "normal", + pc: "normal", + mobile: "heading", + }, }, }, }, - }, - header: { - title: { - tag: "plain_text", - content: - type === "success" - ? "✅ Dokploy Backup Successful" - : "❌ Dokploy Backup Failed", - }, - subtitle: { - tag: "plain_text", - content: "", - }, - template: type === "success" ? "green" : "red", - padding: "12px 12px 12px 12px", - }, - body: { - direction: "vertical", - padding: "12px 12px 12px 12px", - elements: [ - { - tag: "column_set", - columns: [ - { - tag: "column", - width: "weighted", - elements: [ - { - tag: "markdown", - content: `**Backup Type:**\nComplete Dokploy Instance`, - text_align: "left", - text_size: "normal_v2", - }, - { - tag: "markdown", - content: `**Status:**\n${type === "success" ? "Successful" : "Failed"}`, - text_align: "left", - text_size: "normal_v2", - }, - ], - vertical_align: "top", - weight: 1, - }, - { - tag: "column", - width: "weighted", - elements: [ - ...(backupSize - ? [ - { - tag: "markdown", - content: `**Backup Size:**\n${backupSize}`, - text_align: "left", - text_size: "normal_v2", - }, - ] - : []), - { - tag: "markdown", - content: `**Date:**\n${format(date, "PP pp")}`, - text_align: "left", - text_size: "normal_v2", - }, - ], - vertical_align: "top", - weight: 1, - }, - ], + header: { + title: { + tag: "plain_text", + content: + type === "success" + ? "✅ Dokploy Backup Successful" + : "❌ Dokploy Backup Failed", }, - ...(type === "error" && truncatedErrorMessage - ? [ + subtitle: { + tag: "plain_text", + content: "", + }, + template: type === "success" ? "green" : "red", + padding: "12px 12px 12px 12px", + }, + body: { + direction: "vertical", + padding: "12px 12px 12px 12px", + elements: [ + { + tag: "column_set", + columns: [ { - tag: "markdown", - content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``, - text_align: "left", - text_size: "normal_v2", + tag: "column", + width: "weighted", + elements: [ + { + tag: "markdown", + content: + "**Backup Type:**\nComplete Dokploy Instance", + text_align: "left", + text_size: "normal_v2", + }, + { + tag: "markdown", + content: `**Status:**\n${type === "success" ? "Successful" : "Failed"}`, + text_align: "left", + text_size: "normal_v2", + }, + ], + vertical_align: "top", + weight: 1, }, - ] - : []), - ], + { + tag: "column", + width: "weighted", + elements: [ + ...(backupSize + ? [ + { + tag: "markdown", + content: `**Backup Size:**\n${backupSize}`, + text_align: "left", + text_size: "normal_v2", + }, + ] + : []), + { + tag: "markdown", + content: `**Date:**\n${format(date, "PP pp")}`, + text_align: "left", + text_size: "normal_v2", + }, + ], + vertical_align: "top", + weight: 1, + }, + ], + }, + ...(type === "error" && truncatedErrorMessage + ? [ + { + tag: "markdown", + content: `**Error Message:**\n\`\`\`\n${truncatedErrorMessage}\n\`\`\``, + text_align: "left", + text_size: "normal_v2", + }, + ] + : []), + ], + }, }, - }, - }); + }); + } + + if (mattermost) { + const statusEmoji = type === "success" ? ":white_check_mark:" : ":x:"; + const typeStatus = type === "success" ? "Successful" : "Failed"; + await sendMattermostNotification(mattermost, { + text: `${statusEmoji} **Dokploy Backup ${typeStatus}** + +**Backup Type:** Complete Dokploy Instance${backupSize ? `\n**Backup Size:** ${backupSize}` : ""} +**Date:** ${date.toLocaleString()} +**Status:** ${typeStatus}${type === "error" && errorMessage ? `\n\n**Error:**\n\`\`\`\n${errorMessage}\n\`\`\`` : ""}`, + channel: mattermost.channel, + username: mattermost.username || "Dokploy Bot", + }); + } + + if (custom) { + await sendCustomNotification(custom, { + title: `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + message: `Dokploy instance backup ${type === "success" ? "completed successfully" : "failed"}`, + backupType: "Complete Dokploy Instance", + ...(backupSize ? { backupSize } : {}), + ...(type === "error" && errorMessage ? { errorMessage } : {}), + timestamp: date.toISOString(), + date: date.toLocaleString(), + status: type, + type: "dokploy-backup", + }); + } + + if (pushover) { + await sendPushoverNotification( + pushover, + `Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + `Backup Type: Complete Dokploy Instance${backupSize ? `\nBackup Size: ${backupSize}` : ""}\nDate: ${date.toLocaleString()}${type === "error" && errorMessage ? `\nError: ${errorMessage}` : ""}`, + ); + } + + if (teams) { + await sendTeamsNotification(teams, { + title: `${type === "success" ? "✅" : "❌"} Dokploy Backup ${type === "success" ? "Successful" : "Failed"}`, + facts: [ + { name: "Backup Type", value: "Complete Dokploy Instance" }, + ...(backupSize ? [{ name: "Backup Size", value: backupSize }] : []), + { name: "Date", value: format(date, "PP pp") }, + { + name: "Status", + value: type === "success" ? "Successful" : "Failed", + }, + ...(type === "error" && errorMessage + ? [{ name: "Error Message", value: errorMessage }] + : []), + ], + }); + } + } catch (error) { + console.error(error); } } }; From e9202bfb154368ff471ca4567283d70c46ab78d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Pulpeiro?= Date: Thu, 2 Apr 2026 11:48:50 +0200 Subject: [PATCH 16/25] fix: sort schedules by name in list query Schedules were returned in arbitrary order from the database. Add orderBy clause to sort them alphabetically by name. --- apps/dokploy/server/api/routers/schedule.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/api/routers/schedule.ts b/apps/dokploy/server/api/routers/schedule.ts index 2563fd7ac..8ecc0d140 100644 --- a/apps/dokploy/server/api/routers/schedule.ts +++ b/apps/dokploy/server/api/routers/schedule.ts @@ -14,7 +14,7 @@ import { updateSchedule, } from "@dokploy/server/services/schedule"; import { TRPCError } from "@trpc/server"; -import { desc, eq } from "drizzle-orm"; +import { asc, desc, eq } from "drizzle-orm"; import { z } from "zod"; import { audit } from "@/server/api/utils/audit"; import { removeJob, schedule } from "@/server/utils/backup"; @@ -157,6 +157,7 @@ export const scheduleRouter = createTRPCRouter({ }; return db.query.schedules.findMany({ where: where[input.scheduleType], + orderBy: [asc(schedules.name)], with: { application: true, server: true, From 5978c4135e96e98d29a3f88d3be04908d9d2c5d5 Mon Sep 17 00:00:00 2001 From: Maks Pikov Date: Thu, 2 Apr 2026 22:21:42 +0000 Subject: [PATCH 17/25] fix(subscriptions): change const done to let and resolve with finally to allow while loop to exit --- apps/dokploy/server/api/routers/backup.ts | 73 ++++++++------------- apps/dokploy/server/api/routers/libsql.ts | 8 ++- apps/dokploy/server/api/routers/mongo.ts | 8 ++- apps/dokploy/server/api/routers/mysql.ts | 8 ++- apps/dokploy/server/api/routers/postgres.ts | 8 ++- apps/dokploy/server/api/routers/redis.ts | 8 ++- 6 files changed, 59 insertions(+), 54 deletions(-) diff --git a/apps/dokploy/server/api/routers/backup.ts b/apps/dokploy/server/api/routers/backup.ts index 6d358f631..98f8c658d 100644 --- a/apps/dokploy/server/api/routers/backup.ts +++ b/apps/dokploy/server/api/routers/backup.ts @@ -545,52 +545,37 @@ export const backupRouter = createTRPCRouter({ } const destination = await findDestinationById(input.destinationId); const queue: string[] = []; - const done = false; - if (input.backupType === "database") { - if (input.databaseType === "postgres") { - const postgres = await findPostgresById(input.databaseId); - - restorePostgresBackup(postgres, destination, input, (log) => { - queue.push(log); - }); + let done = false; + const onLog = (log: string) => queue.push(log); + (async () => { + if (input.backupType === "database") { + if (input.databaseType === "postgres") { + const postgres = await findPostgresById(input.databaseId); + await restorePostgresBackup(postgres, destination, input, onLog); + } else if (input.databaseType === "mysql") { + const mysql = await findMySqlById(input.databaseId); + await restoreMySqlBackup(mysql, destination, input, onLog); + } else if (input.databaseType === "mariadb") { + const mariadb = await findMariadbById(input.databaseId); + await restoreMariadbBackup(mariadb, destination, input, onLog); + } else if (input.databaseType === "mongo") { + const mongo = await findMongoById(input.databaseId); + await restoreMongoBackup(mongo, destination, input, onLog); + } else if (input.databaseType === "libsql") { + const libsql = await findLibsqlById(input.databaseId); + await restoreLibsqlBackup(libsql, destination, input, onLog); + } else if (input.databaseType === "web-server") { + await restoreWebServerBackup(destination, input.backupFile, onLog); + } + } else if (input.backupType === "compose") { + const compose = await findComposeById(input.databaseId); + await restoreComposeBackup(compose, destination, input, onLog); } - - if (input.databaseType === "mysql") { - const mysql = await findMySqlById(input.databaseId); - restoreMySqlBackup(mysql, destination, input, (log) => { - queue.push(log); - }); - } - if (input.databaseType === "mariadb") { - const mariadb = await findMariadbById(input.databaseId); - restoreMariadbBackup(mariadb, destination, input, (log) => { - queue.push(log); - }); - } - if (input.databaseType === "mongo") { - const mongo = await findMongoById(input.databaseId); - restoreMongoBackup(mongo, destination, input, (log) => { - queue.push(log); - }); - } - if (input.databaseType === "libsql") { - const libsql = await findLibsqlById(input.databaseId); - restoreLibsqlBackup(libsql, destination, input, (log) => { - queue.push(log); - }); - } - if (input.databaseType === "web-server") { - restoreWebServerBackup(destination, input.backupFile, (log) => { - queue.push(log); - }); - } - } - if (input.backupType === "compose") { - const compose = await findComposeById(input.databaseId); - restoreComposeBackup(compose, destination, input, (log) => { - queue.push(log); + })() + .catch(() => {}) + .finally(() => { + done = true; }); - } while (!done || queue.length > 0) { if (queue.length > 0) { yield queue.shift()!; diff --git a/apps/dokploy/server/api/routers/libsql.ts b/apps/dokploy/server/api/routers/libsql.ts index 614e42101..79dcc4443 100644 --- a/apps/dokploy/server/api/routers/libsql.ts +++ b/apps/dokploy/server/api/routers/libsql.ts @@ -246,11 +246,15 @@ export const libsqlRouter = createTRPCRouter({ deployment: ["create"], }); const queue: string[] = []; - const done = false; + let done = false; deployLibsql(input.libsqlId, (log) => { queue.push(log); - }); + }) + .catch(() => {}) + .finally(() => { + done = true; + }); while (!done || queue.length > 0) { if (queue.length > 0) { diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts index a64535e24..47c06f819 100644 --- a/apps/dokploy/server/api/routers/mongo.ts +++ b/apps/dokploy/server/api/routers/mongo.ts @@ -228,11 +228,15 @@ export const mongoRouter = createTRPCRouter({ deployment: ["create"], }); const queue: string[] = []; - const done = false; + let done = false; deployMongo(input.mongoId, (log) => { queue.push(log); - }); + }) + .catch(() => {}) + .finally(() => { + done = true; + }); while (!done || queue.length > 0) { if (queue.length > 0) { diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts index abb0f97a7..8e1938caa 100644 --- a/apps/dokploy/server/api/routers/mysql.ts +++ b/apps/dokploy/server/api/routers/mysql.ts @@ -230,11 +230,15 @@ export const mysqlRouter = createTRPCRouter({ }); const queue: string[] = []; - const done = false; + let done = false; deployMySql(input.mysqlId, (log) => { queue.push(log); - }); + }) + .catch(() => {}) + .finally(() => { + done = true; + }); while (!done || queue.length > 0) { if (queue.length > 0) { diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts index 3b3cfd208..b591726eb 100644 --- a/apps/dokploy/server/api/routers/postgres.ts +++ b/apps/dokploy/server/api/routers/postgres.ts @@ -233,11 +233,15 @@ export const postgresRouter = createTRPCRouter({ }); const queue: string[] = []; - const done = false; + let done = false; deployPostgres(input.postgresId, (log) => { queue.push(log); - }); + }) + .catch(() => {}) + .finally(() => { + done = true; + }); while (!done || queue.length > 0) { if (queue.length > 0) { diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts index 01d922aa4..dfd8e1a87 100644 --- a/apps/dokploy/server/api/routers/redis.ts +++ b/apps/dokploy/server/api/routers/redis.ts @@ -251,11 +251,15 @@ export const redisRouter = createTRPCRouter({ deployment: ["create"], }); const queue: string[] = []; - const done = false; + let done = false; deployRedis(input.redisId, (log) => { queue.push(log); - }); + }) + .catch(() => {}) + .finally(() => { + done = true; + }); while (!done || queue.length > 0) { if (queue.length > 0) { From 06b18aca08df3fddbf7623a4a60b978d1deba088 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Fri, 3 Apr 2026 14:29:48 -0600 Subject: [PATCH 18/25] feat(git-provider): enhance sharing and permissions management - Added functionality to toggle sharing of Git providers with the organization. - Introduced a new column "sharedWithOrganization" in the git_provider table to track sharing status. - Updated user permissions to include accessedGitProviders, allowing for more granular access control. - Enhanced API routes to support fetching accessible Git providers based on user roles and permissions. - Implemented UI components for managing Git provider sharing and permissions in the dashboard. --- .../settings/git/show-git-providers.tsx | 179 +- .../settings/users/add-permissions.tsx | 89 + .../drizzle/0157_stiff_misty_knight.sql | 2 + apps/dokploy/drizzle/meta/0157_snapshot.json | 8264 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + apps/dokploy/server/api/routers/bitbucket.ts | 5 +- .../server/api/routers/git-provider.ts | 87 +- apps/dokploy/server/api/routers/gitea.ts | 5 +- apps/dokploy/server/api/routers/github.ts | 5 +- apps/dokploy/server/api/routers/gitlab.ts | 5 +- .../api/routers/proprietary/license-key.ts | 7 +- apps/dokploy/server/api/routers/user.ts | 10 +- packages/server/src/db/schema/account.ts | 4 + packages/server/src/db/schema/git-provider.ts | 10 +- packages/server/src/db/schema/user.ts | 1 + packages/server/src/services/git-provider.ts | 53 +- 16 files changed, 8664 insertions(+), 69 deletions(-) create mode 100644 apps/dokploy/drizzle/0157_stiff_misty_knight.sql create mode 100644 apps/dokploy/drizzle/meta/0157_snapshot.json diff --git a/apps/dokploy/components/dashboard/settings/git/show-git-providers.tsx b/apps/dokploy/components/dashboard/settings/git/show-git-providers.tsx index a96bcf26c..e0806ec85 100644 --- a/apps/dokploy/components/dashboard/settings/git/show-git-providers.tsx +++ b/apps/dokploy/components/dashboard/settings/git/show-git-providers.tsx @@ -5,6 +5,7 @@ import { ImportIcon, Loader2, Trash2, + Users, } from "lucide-react"; import Link from "next/link"; import { toast } from "sonner"; @@ -24,6 +25,13 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { Switch } from "@/components/ui/switch"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { api } from "@/utils/api"; import { useUrl } from "@/utils/hooks/use-url"; import { AddBitbucketProvider } from "./bitbucket/add-bitbucket-provider"; @@ -39,6 +47,8 @@ export const ShowGitProviders = () => { const { data, isPending, refetch } = api.gitProvider.getAll.useQuery(); const { mutateAsync, isPending: isRemoving } = api.gitProvider.remove.useMutation(); + const { mutateAsync: toggleShare } = + api.gitProvider.toggleShare.useMutation(); const url = useUrl(); const getGitlabUrl = ( @@ -154,10 +164,62 @@ export const ShowGitProviders = () => { )}
+ {!gitProvider.isOwner && ( + + + Shared + + )}
+ {gitProvider.isOwner && ( + + + +
+ + { + await toggleShare({ + gitProviderId: + gitProvider.gitProviderId, + sharedWithOrganization: + checked, + }) + .then(() => { + toast.success( + checked + ? "Provider shared with organization" + : "Provider unshared", + ); + refetch(); + }) + .catch(() => { + toast.error( + "Error updating sharing", + ); + }); + }} + /> +
+
+ + Share with entire organization + +
+
+ )} + {isBitbucket && gitProvider.bitbucket?.appPassword && !gitProvider.bitbucket?.apiToken ? ( @@ -222,62 +284,75 @@ export const ShowGitProviders = () => {
)} - {isGithub && haveGithubRequirements && ( - - )} + {gitProvider.isOwner && ( + <> + {isGithub && haveGithubRequirements && ( + + )} - {isGitlab && ( - - )} + {isGitlab && ( + + )} - {isBitbucket && ( - - )} + {isBitbucket && ( + + )} - {isGitea && ( - - )} + {isGitea && ( + + )} - { - await mutateAsync({ - gitProviderId: gitProvider.gitProviderId, - }) - .then(() => { - toast.success( - "Git Provider deleted successfully", - ); - refetch(); - }) - .catch(() => { - toast.error( - "Error deleting Git Provider", - ); - }); - }} - > - - + { + await mutateAsync({ + gitProviderId: + gitProvider.gitProviderId, + }) + .then(() => { + toast.success( + "Git Provider deleted successfully", + ); + refetch(); + }) + .catch(() => { + toast.error( + "Error deleting Git Provider", + ); + }); + }} + > + + + + )}
diff --git a/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx b/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx index fdcf51ad7..5024e457f 100644 --- a/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx +++ b/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx @@ -26,6 +26,7 @@ import { FormMessage, } from "@/components/ui/form"; import { Switch } from "@/components/ui/switch"; +import { EnterpriseFeatureLocked } from "@/components/proprietary/enterprise-feature-gate"; import { api, type RouterOutputs } from "@/utils/api"; /** Shape returned by project.allForPermissions (admin only). Used for the permissions UI. */ @@ -170,6 +171,7 @@ const addPermissions = z.object({ accessedProjects: z.array(z.string()).optional(), accessedEnvironments: z.array(z.string()).optional(), accessedServices: z.array(z.string()).optional(), + accessedGitProviders: z.array(z.string()).optional(), canCreateProjects: z.boolean().optional().default(false), canCreateServices: z.boolean().optional().default(false), canDeleteProjects: z.boolean().optional().default(false), @@ -196,6 +198,15 @@ export const AddUserPermissions = ({ userId, role }: Props) => { const { data: projects } = api.project.allForPermissions.useQuery(undefined, { enabled: isOpen, }); + const { data: haveValidLicense } = + api.licenseKey.haveValidLicenseKey.useQuery(); + + const { data: gitProviders } = api.gitProvider.allForPermissions.useQuery( + undefined, + { + enabled: isOpen && !!haveValidLicense, + }, + ); const { data, refetch } = api.user.one.useQuery( { @@ -214,6 +225,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedProjects: [], accessedEnvironments: [], accessedServices: [], + accessedGitProviders: [], canDeleteEnvironments: false, canCreateProjects: false, canCreateServices: false, @@ -235,6 +247,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedProjects: data.accessedProjects || [], accessedEnvironments: data.accessedEnvironments || [], accessedServices: data.accessedServices || [], + accessedGitProviders: data.accessedGitProviders || [], canCreateProjects: data.canCreateProjects, canCreateServices: data.canCreateServices, canDeleteProjects: data.canDeleteProjects, @@ -262,6 +275,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedProjects: data.accessedProjects || [], accessedEnvironments: data.accessedEnvironments || [], accessedServices: data.accessedServices || [], + accessedGitProviders: data.accessedGitProviders || [], canAccessToDocker: data.canAccessToDocker, canAccessToAPI: data.canAccessToAPI, canAccessToSSHKeys: data.canAccessToSSHKeys, @@ -870,6 +884,81 @@ export const AddUserPermissions = ({ userId, role }: Props) => { )} /> + {haveValidLicense ? ( + ( + +
+ + Git Providers + + + Select the Git Providers that the user can access + +
+ {gitProviders?.length === 0 && ( +

+ No git providers found +

+ )} +
+ {gitProviders?.map((provider) => ( + ( + + + { + if (checked) { + field.onChange([ + ...(field.value || []), + provider.gitProviderId, + ]); + } else { + field.onChange( + field.value?.filter( + (v) => + v !== provider.gitProviderId, + ), + ); + } + }} + /> + +
+ + {provider.name} + + + ({provider.providerType}) + +
+
+ )} + /> + ))} +
+ +
+ )} + /> + ) : ( +
+ +
+ )}