mirror of
https://github.com/andwati/dokploy.git
synced 2026-11-07 20:45:17 +00:00
chore: Reorder and clean up imports, update openapi schema, and improve
cache invalidation logic
This commit is contained in:
@@ -12,6 +12,7 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
chain.where = () => chain;
|
chain.where = () => chain;
|
||||||
chain.values = () => chain;
|
chain.values = () => chain;
|
||||||
chain.returning = () => Promise.resolve([{}]);
|
chain.returning = () => Promise.resolve([{}]);
|
||||||
|
// biome-ignore lint/suspicious/noThenProperty: this is for testing
|
||||||
chain.then = undefined;
|
chain.then = undefined;
|
||||||
|
|
||||||
const tableMock = {
|
const tableMock = {
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CodeEditor } from "@/components/shared/code-editor";
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -24,7 +25,6 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const AddCompose = ({ environmentId, projectName }: Props) => {
|
|||||||
api.compose.create.useMutation();
|
api.compose.create.useMutation();
|
||||||
|
|
||||||
// Get environment data to extract projectId
|
// Get environment data to extract projectId
|
||||||
const { data: environment } = api.environment.one.useQuery({ environmentId });
|
// const { data: environment } = api.environment.one.useQuery({ environmentId });
|
||||||
|
|
||||||
const hasServers = servers && servers.length > 0;
|
const hasServers = servers && servers.length > 0;
|
||||||
// Show dropdown logic based on cloud environment
|
// Show dropdown logic based on cloud environment
|
||||||
@@ -117,6 +117,8 @@ export const AddCompose = ({ environmentId, projectName }: Props) => {
|
|||||||
await utils.environment.one.invalidate({
|
await utils.environment.one.invalidate({
|
||||||
environmentId,
|
environmentId,
|
||||||
});
|
});
|
||||||
|
// Invalidate the project query to refresh the project data for the advance-breadcrumb
|
||||||
|
await utils.project.all.invalidate();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
toast.error("Error creating the compose");
|
toast.error("Error creating the compose");
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ export const AdvancedEnvironmentSelector = ({
|
|||||||
|
|
||||||
toast.success("Environment created successfully");
|
toast.success("Environment created successfully");
|
||||||
utils.environment.byProjectId.invalidate({ projectId });
|
utils.environment.byProjectId.invalidate({ projectId });
|
||||||
|
// Invalidate the project query to refresh the project data for the advance-breadcrumb
|
||||||
|
utils.project.all.invalidate();
|
||||||
setIsCreateDialogOpen(false);
|
setIsCreateDialogOpen(false);
|
||||||
setName("");
|
setName("");
|
||||||
setDescription("");
|
setDescription("");
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormDescription,
|
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormDescription,
|
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormDescription,
|
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormDescription,
|
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useHealthCheckAfterMutation } from "@/hooks/use-health-check-after-mutation";
|
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
@@ -24,6 +23,7 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
|
import { useHealthCheckAfterMutation } from "@/hooks/use-health-check-after-mutation";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { ArrowRightLeft, Plus, Trash2 } from "lucide-react";
|
import { ArrowRightLeft, Plus, Trash2 } from "lucide-react";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { useHealthCheckAfterMutation } from "@/hooks/use-health-check-after-mutation";
|
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useFieldArray, useForm } from "react-hook-form";
|
import { useFieldArray, useForm } from "react-hook-form";
|
||||||
@@ -36,6 +35,7 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
import { useHealthCheckAfterMutation } from "@/hooks/use-health-check-after-mutation";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { authClient } from "@/lib/auth-client";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { authClient } from "@/lib/auth-client";
|
||||||
|
|
||||||
export function SignInWithGithub() {
|
export function SignInWithGithub() {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { authClient } from "@/lib/auth-client";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { authClient } from "@/lib/auth-client";
|
||||||
|
|
||||||
export function SignInWithGoogle() {
|
export function SignInWithGoogle() {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import { mountRouter } from "./routers/mount";
|
|||||||
import { mysqlRouter } from "./routers/mysql";
|
import { mysqlRouter } from "./routers/mysql";
|
||||||
import { notificationRouter } from "./routers/notification";
|
import { notificationRouter } from "./routers/notification";
|
||||||
import { organizationRouter } from "./routers/organization";
|
import { organizationRouter } from "./routers/organization";
|
||||||
import { licenseKeyRouter } from "./routers/proprietary/license-key";
|
|
||||||
import { ssoRouter } from "./routers/proprietary/sso";
|
|
||||||
import { portRouter } from "./routers/port";
|
import { portRouter } from "./routers/port";
|
||||||
import { postgresRouter } from "./routers/postgres";
|
import { postgresRouter } from "./routers/postgres";
|
||||||
import { previewDeploymentRouter } from "./routers/preview-deployment";
|
import { previewDeploymentRouter } from "./routers/preview-deployment";
|
||||||
import { projectRouter } from "./routers/project";
|
import { projectRouter } from "./routers/project";
|
||||||
|
import { licenseKeyRouter } from "./routers/proprietary/license-key";
|
||||||
|
import { ssoRouter } from "./routers/proprietary/sso";
|
||||||
import { redirectsRouter } from "./routers/redirects";
|
import { redirectsRouter } from "./routers/redirects";
|
||||||
import { redisRouter } from "./routers/redis";
|
import { redisRouter } from "./routers/redis";
|
||||||
import { registryRouter } from "./routers/registry";
|
import { registryRouter } from "./routers/registry";
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { exit } from "node:process";
|
|
||||||
import { exec } from "node:child_process";
|
import { exec } from "node:child_process";
|
||||||
|
import { exit } from "node:process";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
import { setupDirectories } from "@dokploy/server/setup/config-paths";
|
import { setupDirectories } from "@dokploy/server/setup/config-paths";
|
||||||
import { initializePostgres } from "@dokploy/server/setup/postgres-setup";
|
import { initializePostgres } from "@dokploy/server/setup/postgres-setup";
|
||||||
import { initializeRedis } from "@dokploy/server/setup/redis-setup";
|
import { initializeRedis } from "@dokploy/server/setup/redis-setup";
|
||||||
|
|||||||
+2287
-184
File diff suppressed because it is too large
Load Diff
@@ -105,21 +105,21 @@ export const suggestVariants = async ({
|
|||||||
}),
|
}),
|
||||||
prompt: `
|
prompt: `
|
||||||
Act as advanced DevOps engineer and analyze the user's request to determine the appropriate suggestions (up to 3 items).
|
Act as advanced DevOps engineer and analyze the user's request to determine the appropriate suggestions (up to 3 items).
|
||||||
|
|
||||||
CRITICAL - Read the user's request carefully and follow the appropriate strategy:
|
CRITICAL - Read the user's request carefully and follow the appropriate strategy:
|
||||||
|
|
||||||
Strategy A - If the user specifies a PARTICULAR APPLICATION/SERVICE (e.g., "deploy Chatwoot", "install sendingtk/chatwoot:develop", "setup Bitwarden"):
|
Strategy A - If the user specifies a PARTICULAR APPLICATION/SERVICE (e.g., "deploy Chatwoot", "install sendingtk/chatwoot:develop", "setup Bitwarden"):
|
||||||
- Generate different deployment VARIANTS of that SAME application
|
- Generate different deployment VARIANTS of that SAME application
|
||||||
- Each variant should be a different configuration (minimal, full stack, with different databases, development vs production, etc.)
|
- Each variant should be a different configuration (minimal, full stack, with different databases, development vs production, etc.)
|
||||||
- Example: For "Chatwoot" → "Chatwoot with PostgreSQL", "Chatwoot Development", "Chatwoot Full Stack"
|
- Example: For "Chatwoot" → "Chatwoot with PostgreSQL", "Chatwoot Development", "Chatwoot Full Stack"
|
||||||
- The name MUST include the specific application name the user mentioned
|
- The name MUST include the specific application name the user mentioned
|
||||||
|
|
||||||
Strategy B - If the user describes a GENERAL NEED or USE CASE (e.g., "personal blog", "project management tool", "chat application"):
|
Strategy B - If the user describes a GENERAL NEED or USE CASE (e.g., "personal blog", "project management tool", "chat application"):
|
||||||
- Suggest different open source projects that fulfill that need
|
- Suggest different open source projects that fulfill that need
|
||||||
- Each suggestion should be a different tool/platform that solves the same problem
|
- Each suggestion should be a different tool/platform that solves the same problem
|
||||||
- Example: For "personal blog" → "WordPress", "Ghost", "Hugo with Nginx"
|
- Example: For "personal blog" → "WordPress", "Ghost", "Hugo with Nginx"
|
||||||
- The name should be the actual project name
|
- The name should be the actual project name
|
||||||
|
|
||||||
Return your response as a JSON object with the following structure:
|
Return your response as a JSON object with the following structure:
|
||||||
{
|
{
|
||||||
"suggestions": [
|
"suggestions": [
|
||||||
@@ -131,7 +131,7 @@ export const suggestVariants = async ({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Important rules for the response:
|
Important rules for the response:
|
||||||
1. Use slug format for the id field (lowercase, hyphenated)
|
1. Use slug format for the id field (lowercase, hyphenated)
|
||||||
2. Determine which strategy to use based on whether the user specified a particular application or described a general need
|
2. Determine which strategy to use based on whether the user specified a particular application or described a general need
|
||||||
@@ -142,9 +142,9 @@ export const suggestVariants = async ({
|
|||||||
7. The shortDescription should be a single-line summary focusing on key technologies or differentiators
|
7. The shortDescription should be a single-line summary focusing on key technologies or differentiators
|
||||||
8. All suggestions should be installable in docker and have docker compose support
|
8. All suggestions should be installable in docker and have docker compose support
|
||||||
9. Provide variety in your suggestions - different complexity levels, tech stacks, or approaches
|
9. Provide variety in your suggestions - different complexity levels, tech stacks, or approaches
|
||||||
|
|
||||||
User wants to create a new project with the following details:
|
User wants to create a new project with the following details:
|
||||||
|
|
||||||
${input}
|
${input}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
@@ -182,7 +182,7 @@ export const suggestVariants = async ({
|
|||||||
}),
|
}),
|
||||||
prompt: `
|
prompt: `
|
||||||
Act as advanced DevOps engineer and generate docker compose with environment variables and domain configurations needed to install the following project.
|
Act as advanced DevOps engineer and generate docker compose with environment variables and domain configurations needed to install the following project.
|
||||||
|
|
||||||
Return your response as a JSON object with this structure:
|
Return your response as a JSON object with this structure:
|
||||||
{
|
{
|
||||||
"dockerCompose": "yaml string here",
|
"dockerCompose": "yaml string here",
|
||||||
@@ -190,9 +190,9 @@ export const suggestVariants = async ({
|
|||||||
"domains": [{"host": "domain.com", "port": 3000, "serviceName": "service"}],
|
"domains": [{"host": "domain.com", "port": 3000, "serviceName": "service"}],
|
||||||
"configFiles": [{"content": "file content", "filePath": "path/to/file"}]
|
"configFiles": [{"content": "file content", "filePath": "path/to/file"}]
|
||||||
}
|
}
|
||||||
|
|
||||||
Note: configFiles is optional - only include it if configuration files are absolutely required.
|
Note: configFiles is optional - only include it if configuration files are absolutely required.
|
||||||
|
|
||||||
Follow these rules:
|
Follow these rules:
|
||||||
|
|
||||||
Docker Compose Rules:
|
Docker Compose Rules:
|
||||||
@@ -242,16 +242,16 @@ export const suggestVariants = async ({
|
|||||||
4. ONLY include environment variables that are actually used in the docker-compose
|
4. ONLY include environment variables that are actually used in the docker-compose
|
||||||
5. Every environment variable referenced in the docker-compose MUST have a corresponding entry in envVariables
|
5. Every environment variable referenced in the docker-compose MUST have a corresponding entry in envVariables
|
||||||
6. Do not include environment variables for services that don't exist in the docker-compose
|
6. Do not include environment variables for services that don't exist in the docker-compose
|
||||||
|
|
||||||
For each service that needs to be exposed to the internet:
|
For each service that needs to be exposed to the internet:
|
||||||
1. Define a domain configuration with:
|
1. Define a domain configuration with:
|
||||||
- host: the domain name for the service in format: {service-name}-{random-3-chars-hex}-${ip ? ip.replaceAll(".", "-") : ""}.traefik.me
|
- host: the domain name for the service in format: {service-name}-{random-3-chars-hex}-${ip ? ip.replaceAll(".", "-") : ""}.traefik.me
|
||||||
- port: the internal port the service runs on
|
- port: the internal port the service runs on
|
||||||
- serviceName: the name of the service in the docker-compose
|
- serviceName: the name of the service in the docker-compose
|
||||||
2. Make sure the service is properly configured to work with the specified port
|
2. Make sure the service is properly configured to work with the specified port
|
||||||
|
|
||||||
User's original request: ${input}
|
User's original request: ${input}
|
||||||
|
|
||||||
Project details:
|
Project details:
|
||||||
${suggestion?.description}
|
${suggestion?.description}
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const createDomain = async (input: typeof apiCreateDomain._type) => {
|
|||||||
|
|
||||||
export const generateTraefikMeDomain = async (
|
export const generateTraefikMeDomain = async (
|
||||||
appName: string,
|
appName: string,
|
||||||
userId: string,
|
_userId: string,
|
||||||
serverId?: string,
|
serverId?: string,
|
||||||
) => {
|
) => {
|
||||||
if (serverId) {
|
if (serverId) {
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ const generateWildcardDomain = async (
|
|||||||
baseDomain: string,
|
baseDomain: string,
|
||||||
appName: string,
|
appName: string,
|
||||||
serverIp: string,
|
serverIp: string,
|
||||||
userId: string,
|
_userId: string,
|
||||||
): Promise<string> => {
|
): Promise<string> => {
|
||||||
if (!baseDomain.startsWith("*.")) {
|
if (!baseDomain.startsWith("*.")) {
|
||||||
throw new Error('The base domain must start with "*."');
|
throw new Error('The base domain must start with "*."');
|
||||||
|
|||||||
Reference in New Issue
Block a user