diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8584fdf6..c64d0672 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,86 +165,8 @@ Thank you for your contribution! ## Templates -To add a new template, go to `templates` folder and create a new folder with the name of the template. +To add a new template, go to `https://github.com/Dokploy/templates` repository and read the README.md file. -Let's take the example of `plausible` template. - -1. create a folder in `templates/plausible` -2. create a `docker-compose.yml` file inside the folder with the content of compose. -3. create a `index.ts` file inside the folder with the following code as base: -4. When creating a pull request, please provide a video of the template working in action. - -```typescript -// EXAMPLE -import { - generateBase64, - generateHash, - generateRandomDomain, - type Template, - type Schema, - type DomainSchema, -} from "../utils"; - -export function generate(schema: Schema): Template { - // do your stuff here, like create a new domain, generate random passwords, mounts. - const mainServiceHash = generateHash(schema.projectName); - const mainDomain = generateRandomDomain(schema); - const secretBase = generateBase64(64); - const toptKeyBase = generateBase64(32); - - const domains: DomainSchema[] = [ - { - host: mainDomain, - port: 8000, - serviceName: "plausible", - }, - ]; - - const envs = [ - `BASE_URL=http://${mainDomain}`, - `SECRET_KEY_BASE=${secretBase}`, - `TOTP_VAULT_KEY=${toptKeyBase}`, - `HASH=${mainServiceHash}`, - ]; - - const mounts: Template["mounts"] = [ - { - filePath: "./clickhouse/clickhouse-config.xml", - content: "some content......", - }, - ]; - - return { - envs, - mounts, - domains, - }; -} -``` - -4. Now you need to add the information about the template to the `templates/templates.ts` is a object with the following properties: - -**Make sure the id of the template is the same as the folder name and don't have any spaces, only slugified names and lowercase.** - -```typescript -{ - id: "plausible", - name: "Plausible", - version: "v2.1.0", - description: - "Plausible is a open source, self-hosted web analytics platform that lets you track website traffic and user behavior.", - logo: "plausible.svg", // we defined the name and the extension of the logo - links: { - github: "https://github.com/plausible/plausible", - website: "https://plausible.io/", - docs: "https://plausible.io/docs", - }, - tags: ["analytics"], - load: () => import("./plausible/index").then((m) => m.generate), -}, -``` - -5. Add the logo or image of the template to `public/templates/plausible.svg` ### Recommendations diff --git a/apps/dokploy/CONTRIBUTING.md b/apps/dokploy/CONTRIBUTING.md deleted file mode 100644 index 8686b98a..00000000 --- a/apps/dokploy/CONTRIBUTING.md +++ /dev/null @@ -1,242 +0,0 @@ - - -# Contributing - -Hey, thanks for your interest in contributing to Dokploy! We appreciate your help and taking your time to contribute. - - -Before you start, please first discuss the feature/bug you want to add with the owners and comunity via github issues. - -We have a few guidelines to follow when contributing to this project: - -- [Commit Convention](#commit-convention) -- [Setup](#setup) -- [Development](#development) -- [Build](#build) -- [Pull Request](#pull-request) - -## Commit Convention - -Before you craete a Pull Request, please make sure your commit message follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. - -### Commit Message Format -``` -[optional scope]: - -[optional body] - -[optional footer(s)] -``` - -#### Type -Must be one of the following: - -* **feat**: A new feature -* **fix**: A bug fix -* **docs**: Documentation only changes -* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) -* **refactor**: A code change that neither fixes a bug nor adds a feature -* **perf**: A code change that improves performance -* **test**: Adding missing tests or correcting existing tests -* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) -* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) -* **chore**: Other changes that don't modify `src` or `test` files -* **revert**: Reverts a previous commit - -Example: -``` -feat: add new feature -``` - - - - -## Setup - -Before you start, please make the clone based on the `canary` branch, since the `main` branch is the source of truth and should always reflect the latest stable release, also the PRs will be merged to the `canary` branch. - -```bash -git clone https://github.com/dokploy/dokploy.git -cd dokploy -pnpm install -cp .env.example .env -``` - -## Development - -Is required to have **Docker** installed on your machine. - - -### Setup - -Run the command that will spin up all the required services and files. - -```bash -pnpm run setup -``` - -Now run the development server. - -```bash -pnpm run dev -``` - - -Go to http://localhost:3000 to see the development server - -## Build - -```bash -pnpm run build -``` - -## Docker - -To build the docker image -```bash -pnpm run docker:build -``` - -To push the docker image -```bash -pnpm run docker:push -``` - -## Password Reset - -In the case you lost your password, you can reset it using the following command - -```bash -pnpm run reset-password -``` - -If you want to test the webhooks on development mode using localtunnel, make sure to install `localtunnel` - -```bash -bunx lt --port 3000 -``` - -If you run into permission issues of docker run the following command - -```bash -sudo chown -R USERNAME dokploy or sudo chown -R $(whoami) ~/.docker -``` - -## Application deploy - -In case you want to deploy the application on your machine and you selected nixpacks or buildpacks, you need to install first. - -```bash -# Install Nixpacks -curl -sSL https://nixpacks.com/install.sh -o install.sh \ - && chmod +x install.sh \ - && ./install.sh -``` - -```bash -# Install Buildpacks -curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -C /usr/local/bin/ --no-same-owner -xzv pack -``` - - -## Pull Request - -- The `main` branch is the source of truth and should always reflect the latest stable release. -- Create a new branch for each feature or bug fix. -- Make sure to add tests for your changes. -- Make sure to update the documentation for any changes Go to the [docs.dokploy.com](https://docs.dokploy.com) website to see the changes. -- When creating a pull request, please provide a clear and concise description of the changes made. -- If you include a video or screenshot, would be awesome so we can see the changes in action. -- If your pull request fixes an open issue, please reference the issue in the pull request description. -- Once your pull request is merged, you will be automatically added as a contributor to the project. - -Thank you for your contribution! - - - - - -## Templates - -To add a new template, go to `templates` folder and create a new folder with the name of the template. - -Let's take the example of `plausible` template. - -1. create a folder in `templates/plausible` -2. create a `docker-compose.yml` file inside the folder with the content of compose. -3. create a `index.ts` file inside the folder with the following code as base: -4. When creating a pull request, please provide a video of the template working in action. - -```typescript -// EXAMPLE -import { - generateHash, - generateRandomDomain, - type Template, - type Schema, -} from "../utils"; - - -export function generate(schema: Schema): Template { - - // do your stuff here, like create a new domain, generate random passwords, mounts. - const mainServiceHash = generateHash(schema.projectName); - const randomDomain = generateRandomDomain(schema); - const secretBase = generateBase64(64); - const toptKeyBase = generateBase64(32); - - const envs = [ -// If you want to show a domain in the UI, please add the prefix _HOST at the end of the variable name. - `PLAUSIBLE_HOST=${randomDomain}`, - "PLAUSIBLE_PORT=8000", - `BASE_URL=http://${randomDomain}`, - `SECRET_KEY_BASE=${secretBase}`, - `TOTP_VAULT_KEY=${toptKeyBase}`, - `HASH=${mainServiceHash}`, - ]; - - const mounts: Template["mounts"] = [ - { - mountPath: "./clickhouse/clickhouse-config.xml", - content: `some content......`, - }, - ]; - - return { - envs, - mounts, - }; -} -``` - -4. Now you need to add the information about the template to the `templates/templates.ts` is a object with the following properties: - -**Make sure the id of the template is the same as the folder name and don't have any spaces, only slugified names and lowercase.** - -```typescript -{ - id: "plausible", - name: "Plausible", - version: "v2.1.0", - description: - "Plausible is a open source, self-hosted web analytics platform that lets you track website traffic and user behavior.", - logo: "plausible.svg", // we defined the name and the extension of the logo - links: { - github: "https://github.com/plausible/plausible", - website: "https://plausible.io/", - docs: "https://plausible.io/docs", - }, - tags: ["analytics"], - load: () => import("./plausible/index").then((m) => m.generate), -}, -``` - -5. Add the logo or image of the template to `public/templates/plausible.svg` - - -### Recomendations -- Use the same name of the folder as the id of the template. -- The logo should be in the public folder. -- If you want to show a domain in the UI, please add the prefix _HOST at the end of the variable name. -- Test first on a vps or a server to make sure the template works. - diff --git a/apps/dokploy/components/dashboard/application/general/generic/save-github-provider.tsx b/apps/dokploy/components/dashboard/application/general/generic/save-github-provider.tsx index 257e48ea..202c7f88 100644 --- a/apps/dokploy/components/dashboard/application/general/generic/save-github-provider.tsx +++ b/apps/dokploy/components/dashboard/application/general/generic/save-github-provider.tsx @@ -468,16 +468,6 @@ export const SaveGithubProvider = ({ applicationId }: Props) => { Save - {/* create github link */} -
- - Repository - -
diff --git a/apps/dokploy/components/dashboard/application/update-application.tsx b/apps/dokploy/components/dashboard/application/update-application.tsx index 90b63f08..934a596d 100644 --- a/apps/dokploy/components/dashboard/application/update-application.tsx +++ b/apps/dokploy/components/dashboard/application/update-application.tsx @@ -121,7 +121,7 @@ export const UpdateApplication = ({ applicationId }: Props) => { Name - + diff --git a/apps/dokploy/components/dashboard/compose/update-compose.tsx b/apps/dokploy/components/dashboard/compose/update-compose.tsx index 3120f2d4..c8961860 100644 --- a/apps/dokploy/components/dashboard/compose/update-compose.tsx +++ b/apps/dokploy/components/dashboard/compose/update-compose.tsx @@ -121,7 +121,7 @@ export const UpdateCompose = ({ composeId }: Props) => { Name - + diff --git a/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx b/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx index 4a5c43a2..a281f125 100644 --- a/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx +++ b/apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx @@ -1,5 +1,6 @@ import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -23,6 +24,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import Link from "next/link"; const DockerProviderSchema = z.object({ externalPort: z.preprocess((a) => { @@ -106,6 +108,17 @@ export const ShowExternalMariadbCredentials = ({ mariadbId }: Props) => { + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )}
{ Name - + diff --git a/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx b/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx index 9fe6e713..b845004f 100644 --- a/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx +++ b/apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx @@ -1,5 +1,6 @@ import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -23,6 +24,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import Link from "next/link"; const DockerProviderSchema = z.object({ externalPort: z.preprocess((a) => { @@ -106,6 +108,17 @@ export const ShowExternalMongoCredentials = ({ mongoId }: Props) => { + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} { Name - + 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 968cf9c2..117fae38 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 @@ -218,7 +218,7 @@ export const ContainerFreeMonitoring = ({
- Used: {currentData.cpu.value}% + Used: {currentData.cpu.value} diff --git a/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx b/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx index 7a0527b1..12b3eb06 100644 --- a/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx +++ b/apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx @@ -1,5 +1,6 @@ import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -23,6 +24,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import Link from "next/link"; const DockerProviderSchema = z.object({ externalPort: z.preprocess((a) => { @@ -106,6 +108,17 @@ export const ShowExternalMysqlCredentials = ({ mysqlId }: Props) => { + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} { Name - + diff --git a/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx b/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx index dbd57d0b..7643be2d 100644 --- a/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx +++ b/apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx @@ -1,5 +1,6 @@ import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -23,6 +24,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import Link from "next/link"; const DockerProviderSchema = z.object({ externalPort: z.preprocess((a) => { @@ -108,6 +110,17 @@ export const ShowExternalPostgresCredentials = ({ postgresId }: Props) => { + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} { Name - + diff --git a/apps/dokploy/components/dashboard/project/add-template.tsx b/apps/dokploy/components/dashboard/project/add-template.tsx index e2e64e4d..8abc8b40 100644 --- a/apps/dokploy/components/dashboard/project/add-template.tsx +++ b/apps/dokploy/components/dashboard/project/add-template.tsx @@ -324,7 +324,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => { )} > { Name - + diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx index b3caef7d..f5566143 100644 --- a/apps/dokploy/components/dashboard/projects/show.tsx +++ b/apps/dokploy/components/dashboard/projects/show.tsx @@ -115,7 +115,7 @@ export const ShowProjects = () => {
)} -
+
{filteredProjects?.map((project) => { const emptyServices = project?.mariadb.length === 0 && diff --git a/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx b/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx index 75112cf6..5abf0bc1 100644 --- a/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx +++ b/apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx @@ -1,5 +1,6 @@ import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import { Button } from "@/components/ui/button"; +import { AlertBlock } from "@/components/shared/alert-block"; import { Card, CardContent, @@ -23,6 +24,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import Link from "next/link"; const DockerProviderSchema = z.object({ externalPort: z.preprocess((a) => { @@ -100,6 +102,17 @@ export const ShowExternalRedisCredentials = ({ redisId }: Props) => { + {!getIp && ( + + You need to set an IP address in your{" "} + + {data?.serverId + ? "Remote Servers -> Server -> Edit Server -> Update IP Address" + : "Web Server -> Server -> Update Server IP"} + {" "} + to fix the database url connection. + + )} { Name - + diff --git a/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx b/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx index f47c8d9c..6cf2c6a5 100644 --- a/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx +++ b/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx @@ -64,12 +64,12 @@ export const Enable2FA = () => { const handlePasswordSubmit = async (formData: PasswordForm) => { setIsPasswordLoading(true); try { - const { data: enableData } = await authClient.twoFactor.enable({ + const { data: enableData, error } = await authClient.twoFactor.enable({ password: formData.password, }); if (!enableData) { - throw new Error("No data received from server"); + throw new Error(error?.message || "Error enabling 2FA"); } if (enableData.backupCodes) { @@ -95,7 +95,8 @@ export const Enable2FA = () => { error instanceof Error ? error.message : "Error setting up 2FA", ); passwordForm.setError("password", { - message: "Error verifying password", + message: + error instanceof Error ? error.message : "Error setting up 2FA", }); } finally { setIsPasswordLoading(false); diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx index b43686bd..c0c45e14 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx @@ -59,9 +59,7 @@ export const ShowTraefikActions = ({ serverId }: Props) => { .then(async () => { toast.success("Traefik Reloaded"); }) - .catch(() => { - toast.error("Error reloading Traefik"); - }); + .catch(() => {}); }} className="cursor-pointer" > diff --git a/apps/dokploy/components/dashboard/settings/web-server/docker-terminal-modal.tsx b/apps/dokploy/components/dashboard/settings/web-server/docker-terminal-modal.tsx index fa9f1a41..44dda0d3 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/docker-terminal-modal.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/docker-terminal-modal.tsx @@ -1,3 +1,4 @@ +import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -23,6 +24,7 @@ import { Loader2 } from "lucide-react"; import dynamic from "next/dynamic"; import type React from "react"; import { useEffect, useState } from "react"; +import { badgeStateColor } from "../../application/logs/show"; const Terminal = dynamic( () => @@ -109,7 +111,10 @@ export const DockerTerminalModal = ({ children, appName, serverId }: Props) => { key={container.containerId} value={container.containerId} > - {container.name} ({container.containerId}) {container.state} + {container.name} ({container.containerId}){" "} + + {container.state} + ))} Containers ({data?.length}) diff --git a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx index a6958b16..92ef9f12 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/manage-traefik-ports.tsx @@ -19,13 +19,6 @@ import { } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; import { ArrowRightLeft, Plus, Trash2 } from "lucide-react"; @@ -44,7 +37,6 @@ interface Props { const PortSchema = z.object({ targetPort: z.number().min(1, "Target port is required"), publishedPort: z.number().min(1, "Published port is required"), - publishMode: z.enum(["ingress", "host"]), }); const TraefikPortsSchema = z.object({ @@ -88,7 +80,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => { }, [currentPorts, form]); const handleAddPort = () => { - append({ targetPort: 0, publishedPort: 0, publishMode: "host" }); + append({ targetPort: 0, publishedPort: 0 }); }; const onSubmit = async (data: TraefikPortsForm) => { @@ -99,9 +91,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => { }); toast.success(t("settings.server.webServer.traefik.portsUpdated")); setOpen(false); - } catch (_error) { - toast.error(t("settings.server.webServer.traefik.portsUpdateError")); - } + } catch (_error) {} }; return ( @@ -154,7 +144,7 @@ export const ManageTraefikPorts = ({ children, serverId }: Props) => {
{fields.map((field, index) => ( - + { )} /> - ( - - - {t( - "settings.server.webServer.traefik.publishMode", - )} - - - - - )} - /> -
diff --git a/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx b/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx index 43b1838d..a19d4fb7 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx @@ -21,6 +21,8 @@ import { Loader2 } from "lucide-react"; import dynamic from "next/dynamic"; import type React from "react"; import { useEffect, useState } from "react"; +import { badgeStateColor } from "../../application/logs/show"; +import { Badge } from "@/components/ui/badge"; export const DockerLogsId = dynamic( () => @@ -90,7 +92,10 @@ export const ShowModalLogs = ({ key={container.containerId} value={container.containerId} > - {container.name} ({container.containerId}) {container.state} + {container.name} ({container.containerId}){" "} + + {container.state} + ))} Containers ({data?.length}) diff --git a/apps/dokploy/components/dashboard/swarm/monitoring-card.tsx b/apps/dokploy/components/dashboard/swarm/monitoring-card.tsx index 0c38b509..5ab93610 100644 --- a/apps/dokploy/components/dashboard/swarm/monitoring-card.tsx +++ b/apps/dokploy/components/dashboard/swarm/monitoring-card.tsx @@ -176,7 +176,7 @@ export default function SwarmMonitorCard({ serverId }: Props) {
-
+
{nodes.map((node) => ( ))} diff --git a/apps/dokploy/components/layouts/side.tsx b/apps/dokploy/components/layouts/side.tsx index 0b29112a..15d8728b 100644 --- a/apps/dokploy/components/layouts/side.tsx +++ b/apps/dokploy/components/layouts/side.tsx @@ -908,7 +908,7 @@ export default function Page({ children }: Props) { Settings - + {filteredSettings.map((item) => { const isSingle = item.isSingle !== false; const isActive = isSingle @@ -1068,7 +1068,7 @@ export default function Page({ children }: Props) { )} -
{children}
+
{children}
); diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index 22fe71be..64ed2655 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -1,6 +1,6 @@ { "name": "dokploy", - "version": "v0.20.2", + "version": "v0.20.3", "private": true, "license": "Apache-2.0", "type": "module", @@ -93,7 +93,7 @@ "adm-zip": "^0.5.14", "ai": "^4.0.23", "bcrypt": "5.1.1", - "better-auth": "1.2.0", + "better-auth": "1.2.4", "bl": "6.0.11", "boxen": "^7.1.1", "bullmq": "5.4.2", diff --git a/apps/dokploy/public/locales/en/settings.json b/apps/dokploy/public/locales/en/settings.json index ebc5ea62..699a456e 100644 --- a/apps/dokploy/public/locales/en/settings.json +++ b/apps/dokploy/public/locales/en/settings.json @@ -1,6 +1,6 @@ { "settings.common.save": "Save", - "settings.common.enterTerminal": "Enter the terminal", + "settings.common.enterTerminal": "Terminal", "settings.server.domain.title": "Server Domain", "settings.server.domain.description": "Add a domain to your server application.", "settings.server.domain.form.domain": "Domain", @@ -14,7 +14,7 @@ "settings.server.webServer.description": "Reload or clean the web server.", "settings.server.webServer.actions": "Actions", "settings.server.webServer.reload": "Reload", - "settings.server.webServer.watchLogs": "Watch logs", + "settings.server.webServer.watchLogs": "View Logs", "settings.server.webServer.updateServerIp": "Update Server IP", "settings.server.webServer.server.label": "Server", "settings.server.webServer.traefik.label": "Traefik", diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index acb8e172..cab9bc41 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -437,13 +437,12 @@ export const composeRouter = createTRPCRouter({ serverIp = "127.0.0.1"; } + const projectName = slugify(`${project.name} ${input.id}`); const generate = processTemplate(template.config, { serverIp: serverIp, - projectName: project.name, + projectName: projectName, }); - const projectName = slugify(`${project.name} ${input.id}`); - const compose = await createComposeByTemplate({ ...input, composeFile: template.dockerCompose, diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 461d3e1f..a51ff5d1 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -97,14 +97,20 @@ export const settingsRouter = createTRPCRouter({ toggleDashboard: adminProcedure .input(apiEnableDashboard) .mutation(async ({ input }) => { + const ports = (await getTraefikPorts(input.serverId)).filter( + (port) => + port.targetPort !== 80 && + port.targetPort !== 443 && + port.targetPort !== 8080, + ); await initializeTraefik({ + additionalPorts: ports, enableDashboard: input.enableDashboard, serverId: input.serverId, force: true, }); return true; }), - cleanUnusedImages: adminProcedure .input(apiServerSchema) .mutation(async ({ input }) => { @@ -749,7 +755,6 @@ export const settingsRouter = createTRPCRouter({ z.object({ targetPort: z.number(), publishedPort: z.number(), - publishMode: z.enum(["ingress", "host"]).default("host"), }), ), }), @@ -782,59 +787,7 @@ export const settingsRouter = createTRPCRouter({ getTraefikPorts: adminProcedure .input(apiServerSchema) .query(async ({ input }) => { - const command = `docker container inspect --format='{{json .NetworkSettings.Ports}}' dokploy-traefik`; - - try { - let stdout = ""; - if (input?.serverId) { - const result = await execAsyncRemote(input.serverId, command); - stdout = result.stdout; - } else if (!IS_CLOUD) { - const result = await execAsync(command); - stdout = result.stdout; - } - - const portsMap = JSON.parse(stdout.trim()); - const additionalPorts: Array<{ - targetPort: number; - publishedPort: number; - publishMode: "host" | "ingress"; - }> = []; - - // Convert the Docker container port format to our expected format - for (const [containerPort, bindings] of Object.entries(portsMap)) { - if (!bindings) continue; - - const [port = ""] = containerPort.split("/"); - if (!port) continue; - - const targetPortNum = Number.parseInt(port, 10); - if (Number.isNaN(targetPortNum)) continue; - - // Skip default ports - if ([80, 443, 8080].includes(targetPortNum)) continue; - - for (const binding of bindings as Array<{ HostPort: string }>) { - if (!binding.HostPort) continue; - const publishedPort = Number.parseInt(binding.HostPort, 10); - if (Number.isNaN(publishedPort)) continue; - - additionalPorts.push({ - targetPort: targetPortNum, - publishedPort, - publishMode: "host", // Docker standalone uses host mode by default - }); - } - } - - return additionalPorts; - } catch (error) { - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "Failed to get Traefik ports", - cause: error, - }); - } + return await getTraefikPorts(input?.serverId); }), updateLogCleanup: adminProcedure .input( @@ -853,3 +806,56 @@ export const settingsRouter = createTRPCRouter({ return getLogCleanupStatus(); }), }); + +export const getTraefikPorts = async (serverId?: string) => { + const command = `docker container inspect --format='{{json .NetworkSettings.Ports}}' dokploy-traefik`; + try { + let stdout = ""; + if (serverId) { + const result = await execAsyncRemote(serverId, command); + stdout = result.stdout; + } else if (!IS_CLOUD) { + const result = await execAsync(command); + stdout = result.stdout; + } + + const portsMap = JSON.parse(stdout.trim()); + const additionalPorts: Array<{ + targetPort: number; + publishedPort: number; + }> = []; + + // Convert the Docker container port format to our expected format + for (const [containerPort, bindings] of Object.entries(portsMap)) { + if (!bindings) continue; + + const [port = ""] = containerPort.split("/"); + if (!port) continue; + + const targetPortNum = Number.parseInt(port, 10); + if (Number.isNaN(targetPortNum)) continue; + + // Skip default ports + if ([80, 443].includes(targetPortNum)) continue; + + for (const binding of bindings as Array<{ HostPort: string }>) { + if (!binding.HostPort) continue; + const publishedPort = Number.parseInt(binding.HostPort, 10); + if (Number.isNaN(publishedPort)) continue; + + additionalPorts.push({ + targetPort: targetPortNum, + publishedPort, + }); + } + } + + return additionalPorts; + } catch (error) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "Failed to get Traefik ports", + cause: error, + }); + } +}; diff --git a/apps/dokploy/server/wss/listen-deployment.ts b/apps/dokploy/server/wss/listen-deployment.ts index 4a25c6f0..581c04d7 100644 --- a/apps/dokploy/server/wss/listen-deployment.ts +++ b/apps/dokploy/server/wss/listen-deployment.ts @@ -61,7 +61,6 @@ export const setupDeploymentLogsWebSocketServer = ( } stream .on("close", () => { - console.log("Connection closed ✅"); client.end(); ws.close(); }) @@ -86,7 +85,6 @@ export const setupDeploymentLogsWebSocketServer = ( }); ws.on("close", () => { - console.log("Connection closed ✅, From WS"); client.end(); }); } else { diff --git a/apps/dokploy/tailwind.config.ts b/apps/dokploy/tailwind.config.ts index a128b87f..be1f8986 100644 --- a/apps/dokploy/tailwind.config.ts +++ b/apps/dokploy/tailwind.config.ts @@ -22,6 +22,9 @@ const config = { fontFamily: { sans: ["var(--font-inter)", ...defaultTheme.fontFamily.sans], }, + screens: { + "3xl": "120rem", + }, maxWidth: { "2xl": "40rem", "8xl": "85rem", diff --git a/packages/server/package.json b/packages/server/package.json index 8c153e34..6a81b808 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -40,7 +40,7 @@ "@oslojs/encoding":"1.1.0", "@oslojs/crypto":"1.0.1", "drizzle-dbml-generator":"0.10.0", - "better-auth":"1.2.0", + "better-auth":"1.2.4", "@faker-js/faker": "^8.4.1", "@lucia-auth/adapter-drizzle": "1.0.7", "@octokit/auth-app": "^6.0.4", diff --git a/packages/server/src/lib/auth.ts b/packages/server/src/lib/auth.ts index 1efa1730..9043f203 100644 --- a/packages/server/src/lib/auth.ts +++ b/packages/server/src/lib/auth.ts @@ -28,6 +28,26 @@ const { handler, api } = betterAuth({ clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, + ...(!IS_CLOUD && { + async trustedOrigins() { + const admin = await db.query.member.findFirst({ + where: eq(schema.member.role, "owner"), + with: { + user: true, + }, + }); + + if (admin) { + return [ + ...(admin.user.serverIp + ? [`http://${admin.user.serverIp}:3000`] + : []), + ...(admin.user.host ? [`https://${admin.user.host}`] : []), + ]; + } + return []; + }, + }), emailVerification: { sendOnSignUp: true, autoSignInAfterVerification: true, @@ -117,6 +137,10 @@ const { handler, api } = betterAuth({ }, }, }, + session: { + expiresIn: 60 * 60 * 24 * 3, + updateAge: 60 * 60 * 24, + }, user: { modelName: "users_temp", additionalFields: { diff --git a/packages/server/src/services/compose.ts b/packages/server/src/services/compose.ts index a3ebc26c..54aa5f1e 100644 --- a/packages/server/src/services/compose.ts +++ b/packages/server/src/services/compose.ts @@ -289,11 +289,11 @@ export const rebuildCompose = async ({ // if (admin.cleanupCacheOnCompose) { // await cleanupFullDocker(compose?.serverId); // } - if (compose.serverId) { - await getBuildComposeCommand(compose, deployment.logPath); - } else { - await buildCompose(compose, deployment.logPath); + + if (compose.sourceType === "raw") { + await createComposeFile(compose, deployment.logPath); } + await buildCompose(compose, deployment.logPath); await updateDeploymentStatus(deployment.deploymentId, "done"); await updateCompose(composeId, { @@ -433,6 +433,10 @@ export const rebuildRemoteCompose = async ({ // if (admin.cleanupCacheOnCompose) { // await cleanupFullDocker(compose?.serverId); // } + if (compose.sourceType === "raw") { + const command = getCreateComposeFileCommand(compose, deployment.logPath); + await execAsyncRemote(compose.serverId, command); + } if (compose.serverId) { await getBuildComposeCommand(compose, deployment.logPath); } diff --git a/packages/server/src/services/docker.ts b/packages/server/src/services/docker.ts index 69ae446a..bb70d28f 100644 --- a/packages/server/src/services/docker.ts +++ b/packages/server/src/services/docker.ts @@ -136,26 +136,24 @@ export const getContainersByAppNameMatch = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim() - : "No state"; - return { - containerId, - name, - state, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const state = parts[2] + ? parts[2].replace("State: ", "").trim() + : "No state"; + return { + containerId, + name, + state, + }; + }); return containers || []; } catch (_error) {} @@ -192,30 +190,28 @@ export const getStackContainersByAppName = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim().toLowerCase() - : "No state"; - const node = parts[3] - ? parts[3].replace("Node: ", "").trim() - : "No specific node"; - return { - containerId, - name, - state, - node, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const state = parts[2] + ? parts[2].replace("State: ", "").trim().toLowerCase() + : "No state"; + const node = parts[3] + ? parts[3].replace("Node: ", "").trim() + : "No specific node"; + return { + containerId, + name, + state, + node, + }; + }); return containers || []; } catch (_error) {} @@ -253,31 +249,29 @@ export const getServiceContainersByAppName = async ( result = stdout.trim().split("\n"); } - const containers = result - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; + const containers = result.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim().toLowerCase() - : "No state"; + const state = parts[2] + ? parts[2].replace("State: ", "").trim().toLowerCase() + : "No state"; - const node = parts[3] - ? parts[3].replace("Node: ", "").trim() - : "No specific node"; - return { - containerId, - name, - state, - node, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const node = parts[3] + ? parts[3].replace("Node: ", "").trim() + : "No specific node"; + return { + containerId, + name, + state, + node, + }; + }); return containers || []; } catch (_error) {} @@ -318,25 +312,23 @@ export const getContainersByAppLabel = async ( const lines = stdout.trim().split("\n"); - const containers = lines - .map((line) => { - const parts = line.split(" | "); - const containerId = parts[0] - ? parts[0].replace("CONTAINER ID : ", "").trim() - : "No container id"; - const name = parts[1] - ? parts[1].replace("Name: ", "").trim() - : "No container name"; - const state = parts[2] - ? parts[2].replace("State: ", "").trim() - : "No state"; - return { - containerId, - name, - state, - }; - }) - .sort((a, b) => a.name.localeCompare(b.name)); + const containers = lines.map((line) => { + const parts = line.split(" | "); + const containerId = parts[0] + ? parts[0].replace("CONTAINER ID : ", "").trim() + : "No container id"; + const name = parts[1] + ? parts[1].replace("Name: ", "").trim() + : "No container name"; + const state = parts[2] + ? parts[2].replace("State: ", "").trim() + : "No state"; + return { + containerId, + name, + state, + }; + }); return containers || []; } catch (_error) {} diff --git a/packages/server/src/setup/traefik-setup.ts b/packages/server/src/setup/traefik-setup.ts index fc6d04fc..4c8a3274 100644 --- a/packages/server/src/setup/traefik-setup.ts +++ b/packages/server/src/setup/traefik-setup.ts @@ -22,7 +22,6 @@ interface TraefikOptions { additionalPorts?: { targetPort: number; publishedPort: number; - publishMode?: "ingress" | "host"; }[]; force?: boolean; } diff --git a/packages/server/src/utils/builders/railpack.ts b/packages/server/src/utils/builders/railpack.ts index ae55a638..9cfd1a07 100644 --- a/packages/server/src/utils/builders/railpack.ts +++ b/packages/server/src/utils/builders/railpack.ts @@ -17,32 +17,68 @@ export const buildRailpack = async ( ); try { - // Ensure buildkit container is running, create if it doesn't exist await execAsync( - "docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit", + "docker buildx create --use --name builder-containerd --driver docker-container || true", ); - // Build the application using railpack - const args = ["build", buildAppDirectory, "--name", appName]; + await execAsync("docker buildx use builder-containerd"); - // Add environment variables + // First prepare the build plan and info + const prepareArgs = [ + "prepare", + buildAppDirectory, + "--plan-out", + `${buildAppDirectory}/railpack-plan.json`, + "--info-out", + `${buildAppDirectory}/railpack-info.json`, + ]; + + // Add environment variables to prepare command for (const env of envVariables) { - args.push("--env", env); + prepareArgs.push("--env", env); } + // Run prepare command + await spawnAsync("railpack", prepareArgs, (data) => { + if (writeStream.writable) { + writeStream.write(data); + } + }); + + // Build with BuildKit using the Railpack frontend + const buildArgs = [ + "buildx", + "build", + "--build-arg", + "BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55", + "-f", + `${buildAppDirectory}/railpack-plan.json`, + "--output", + `type=docker,name=${appName}`, + ]; + + // Add secrets properly formatted + const env: { [key: string]: string } = {}; + for (const envVar of envVariables) { + const [key, value] = envVar.split("="); + if (key && value) { + buildArgs.push("--secret", `id=${key},env=${key}`); + env[key] = value; + } + } + + buildArgs.push(buildAppDirectory); + await spawnAsync( - "railpack", - args, + "docker", + buildArgs, (data) => { if (writeStream.writable) { writeStream.write(data); } }, { - env: { - ...process.env, - BUILDKIT_HOST: "docker-container://buildkit", - }, + env: { ...process.env, ...env }, }, ); @@ -63,25 +99,65 @@ export const getRailpackCommand = ( application.project.env, ); - // Build the application using railpack - const args = ["build", buildAppDirectory, "--name", appName]; + // Prepare command + const prepareArgs = [ + "prepare", + buildAppDirectory, + "--plan-out", + `${buildAppDirectory}/railpack-plan.json`, + "--info-out", + `${buildAppDirectory}/railpack-info.json`, + ]; - // Add environment variables for (const env of envVariables) { - args.push("--env", env); + prepareArgs.push("--env", env); } - const command = `railpack ${args.join(" ")}`; + // Build command + const buildArgs = [ + "buildx", + "build", + "--build-arg", + "BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55", + "-f", + `${buildAppDirectory}/railpack-plan.json`, + "--output", + `type=docker,name=${appName}`, + ]; + + // Add secrets properly formatted + const exportEnvs = []; + for (const envVar of envVariables) { + const [key, value] = envVar.split("="); + if (key && value) { + buildArgs.push("--secret", `id=${key},env=${key}`); + exportEnvs.push(`export ${key}=${value}`); + } + } + + buildArgs.push(buildAppDirectory); + const bashCommand = ` - echo "Building with Railpack..." >> "${logPath}"; - docker container inspect buildkit >/dev/null 2>&1 || docker run --rm --privileged -d --name buildkit moby/buildkit; - export BUILDKIT_HOST=docker-container://buildkit; - ${command} >> ${logPath} 2>> ${logPath} || { - echo "❌ Railpack build failed" >> ${logPath}; - exit 1; - } - echo "✅ Railpack build completed." >> ${logPath}; - `; +# Ensure we have a builder with containerd +docker buildx create --use --name builder-containerd --driver docker-container || true +docker buildx use builder-containerd + +echo "Preparing Railpack build plan..." >> "${logPath}"; +railpack ${prepareArgs.join(" ")} >> ${logPath} 2>> ${logPath} || { + echo "❌ Railpack prepare failed" >> ${logPath}; + exit 1; +} +echo "✅ Railpack prepare completed." >> ${logPath}; + +echo "Building with Railpack frontend..." >> "${logPath}"; +# Export environment variables for secrets +${exportEnvs.join("\n")} +docker ${buildArgs.join(" ")} >> ${logPath} 2>> ${logPath} || { + echo "❌ Railpack build failed" >> ${logPath}; + exit 1; +} +echo "✅ Railpack build completed." >> ${logPath}; +`; return bashCommand; }; diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts index bb2f5ca1..1c3c2289 100644 --- a/packages/server/src/utils/docker/domain.ts +++ b/packages/server/src/utils/docker/domain.ts @@ -238,9 +238,9 @@ export const addDomainToCompose = async ( if (Array.isArray(labels)) { if (!labels.includes("traefik.enable=true")) { - labels.push("traefik.enable=true"); + labels.unshift("traefik.enable=true"); } - labels.push(...httpLabels); + labels.unshift(...httpLabels); } if (!compose.isolatedDeployment) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa137511..9ddbc702 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -269,8 +269,8 @@ importers: specifier: 5.1.1 version: 5.1.1(encoding@0.1.13) better-auth: - specifier: 1.2.0 - version: 1.2.0(typescript@5.5.3) + specifier: 1.2.4 + version: 1.2.4(typescript@5.5.3) bl: specifier: 6.0.11 version: 6.0.11 @@ -303,10 +303,10 @@ importers: version: 16.4.5 drizzle-orm: specifier: ^0.39.1 - version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) + version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) drizzle-zod: specifier: 0.5.1 - version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8) fancy-ansi: specifier: ^0.1.3 version: 0.1.3 @@ -547,7 +547,7 @@ importers: version: 16.4.5 drizzle-orm: specifier: ^0.39.1 - version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) + version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) hono: specifier: ^4.5.8 version: 4.5.8 @@ -646,8 +646,8 @@ importers: specifier: 5.1.1 version: 5.1.1(encoding@0.1.13) better-auth: - specifier: 1.2.0 - version: 1.2.0(typescript@5.5.3) + specifier: 1.2.4 + version: 1.2.4(typescript@5.5.3) bl: specifier: 6.0.11 version: 6.0.11 @@ -665,13 +665,13 @@ importers: version: 16.4.5 drizzle-dbml-generator: specifier: 0.10.0 - version: 0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)) + version: 0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)) drizzle-orm: specifier: ^0.39.1 - version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) + version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) drizzle-zod: specifier: 0.5.1 - version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8) hi-base32: specifier: ^0.5.1 version: 0.5.1 @@ -4030,8 +4030,8 @@ packages: before-after-hook@2.2.3: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - better-auth@1.2.0: - resolution: {integrity: sha512-eIRGOXfix25bh4fgs8jslZAZssufpIkxfEeEokQu5G4wICoDee1wPctkFb8v80PvhtI4dPm28SuAoZaAdRc6Wg==} + better-auth@1.2.4: + resolution: {integrity: sha512-/ZK2jbUjm8JwdeCLFrUWUBmexPyI9PkaLVXWLWtN60sMDHTY8B5G72wcHglo1QMFBaw4G0qFkP5ayl9k6XfDaA==} better-call@1.0.3: resolution: {integrity: sha512-DUKImKoDIy5UtCvQbHTg0wuBRse6gu1Yvznn7+1B3I5TeY8sclRPFce0HI+4WF2bcb+9PqmkET8nXZubrHQh9A==} @@ -5486,8 +5486,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kysely@0.27.5: - resolution: {integrity: sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA==} + kysely@0.27.6: + resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==} engines: {node: '>=14.0.0'} leac@0.6.0: @@ -10902,7 +10902,7 @@ snapshots: before-after-hook@2.2.3: {} - better-auth@1.2.0(typescript@5.5.3): + better-auth@1.2.4(typescript@5.5.3): dependencies: '@better-auth/utils': 0.2.3 '@better-fetch/fetch': 1.1.15 @@ -10913,7 +10913,7 @@ snapshots: better-call: 1.0.3 defu: 6.1.4 jose: 5.9.6 - kysely: 0.27.5 + kysely: 0.27.6 nanostores: 0.11.3 valibot: 1.0.0-beta.15(typescript@5.5.3) zod: 3.24.1 @@ -11534,9 +11534,9 @@ snapshots: drange@1.1.1: {} - drizzle-dbml-generator@0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)): + drizzle-dbml-generator@0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)): dependencies: - drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) + drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) drizzle-kit@0.30.4: dependencies: @@ -11547,18 +11547,18 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7): + drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7): optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/react': 18.3.5 - kysely: 0.27.5 + kysely: 0.27.6 postgres: 3.4.4 react: 18.2.0 sqlite3: 5.1.7 - drizzle-zod@0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8): dependencies: - drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) + drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.6)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -12450,7 +12450,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - kysely@0.27.5: {} + kysely@0.27.6: {} leac@0.6.0: {}