Merge pull request #784 from Dokploy/754-dokploy-ui-duplicate-deployments

fix: add missing server flag boolean
This commit is contained in:
Mauricio Siu
2024-11-28 23:35:53 -06:00
committed by GitHub
21 changed files with 318 additions and 352 deletions

View File

@@ -202,7 +202,6 @@ export const SaveBitbucketProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -281,7 +280,6 @@ export const SaveBitbucketProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -193,7 +193,6 @@ export const SaveGithubProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -272,7 +271,6 @@ export const SaveGithubProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -209,7 +209,6 @@ export const SaveGitlabProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -297,7 +296,6 @@ export const SaveGitlabProvider = ({ applicationId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -204,7 +204,6 @@ export const SaveBitbucketProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -283,7 +282,6 @@ export const SaveBitbucketProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -195,7 +195,6 @@ export const SaveGithubProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -274,7 +273,6 @@ export const SaveGithubProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -211,7 +211,6 @@ export const SaveGitlabProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",
@@ -299,7 +298,6 @@ export const SaveGitlabProviderCompose = ({ composeId }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
" w-full justify-between !bg-input", " w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -160,7 +160,6 @@ export const AddBackup = ({ databaseId, databaseType, refetch }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -144,7 +144,6 @@ export const UpdateBackup = ({ backupId, refetch }: Props) => {
<FormControl> <FormControl>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"w-full justify-between !bg-input", "w-full justify-between !bg-input",
!field.value && "text-muted-foreground", !field.value && "text-muted-foreground",

View File

@@ -86,14 +86,12 @@ export const ShowVolumes = ({ mysqlId }: Props) => {
)} )}
{mount.type === "file" && ( {mount.type === "file" && (
<> <div className="flex flex-col gap-1">
<div className="flex flex-col gap-1"> <span className="font-medium">Content</span>
<span className="font-medium">Content</span> <span className="text-sm text-muted-foreground">
<span className="text-sm text-muted-foreground"> {mount.content}
{mount.content} </span>
</span> </div>
</div>
</>
)} )}
{mount.type === "bind" && ( {mount.type === "bind" && (
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">

View File

@@ -127,7 +127,6 @@ export const AddTemplate = ({ projectId }: Props) => {
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button <Button
variant="outline" variant="outline"
role="combobox"
className={cn( className={cn(
"md:max-w-[15rem] w-full justify-between !bg-input", "md:max-w-[15rem] w-full justify-between !bg-input",
)} )}

View File

@@ -89,18 +89,14 @@ export const ShowBilling = () => {
<div className="pb-5"> <div className="pb-5">
<Progress value={safePercentage} className="max-w-lg" /> <Progress value={safePercentage} className="max-w-lg" />
</div> </div>
{admin && ( {admin && admin.serversQuantity! <= servers?.length! && (
<> <div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center">
{admin.serversQuantity! <= servers?.length! && ( <AlertTriangle className="text-yellow-600 dark:text-yellow-400" />
<div className="flex flex-row gap-4 p-2 bg-yellow-50 dark:bg-yellow-950 rounded-lg items-center"> <span className="text-sm text-yellow-600 dark:text-yellow-400">
<AlertTriangle className="text-yellow-600 dark:text-yellow-400" /> You have reached the maximum number of servers you can create,
<span className="text-sm text-yellow-600 dark:text-yellow-400"> please upgrade your plan to add more servers.
You have reached the maximum number of servers you can </span>
create, please upgrade your plan to add more servers. </div>
</span>
</div>
)}
</>
)} )}
</div> </div>
)} )}
@@ -188,7 +184,6 @@ export const ShowBilling = () => {
</p> </p>
<ul <ul
role="list"
className={clsx( className={clsx(
" mt-4 flex flex-col gap-y-2 text-sm", " mt-4 flex flex-col gap-y-2 text-sm",
featured ? "text-white" : "text-slate-200", featured ? "text-white" : "text-slate-200",

View File

@@ -28,11 +28,7 @@ export const ShowRegistry = () => {
</div> </div>
<div className="flex flex-row gap-2"> <div className="flex flex-row gap-2">
{data && data?.length > 0 && ( {data && data?.length > 0 && <AddRegistry />}
<>
<AddRegistry />
</>
)}
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="space-y-2 pt-4 h-full"> <CardContent className="space-y-2 pt-4 h-full">

View File

@@ -397,25 +397,23 @@ export const AddNotification = () => {
)} )}
{type === "discord" && ( {type === "discord" && (
<> <FormField
<FormField control={form.control}
control={form.control} name="webhookUrl"
name="webhookUrl" render={({ field }) => (
render={({ field }) => ( <FormItem>
<FormItem> <FormLabel>Webhook URL</FormLabel>
<FormLabel>Webhook URL</FormLabel> <FormControl>
<FormControl> <Input
<Input placeholder="https://discord.com/api/webhooks/123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ"
placeholder="https://discord.com/api/webhooks/123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ" {...field}
{...field} />
/> </FormControl>
</FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
</>
)} )}
{type === "email" && ( {type === "email" && (

View File

@@ -356,25 +356,23 @@ export const UpdateNotification = ({ notificationId }: Props) => {
)} )}
{type === "discord" && ( {type === "discord" && (
<> <FormField
<FormField control={form.control}
control={form.control} name="webhookUrl"
name="webhookUrl" render={({ field }) => (
render={({ field }) => ( <FormItem>
<FormItem> <FormLabel>Webhook URL</FormLabel>
<FormLabel>Webhook URL</FormLabel> <FormControl>
<FormControl> <Input
<Input placeholder="https://discord.com/api/webhooks/123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ"
placeholder="https://discord.com/api/webhooks/123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ" {...field}
{...field} />
/> </FormControl>
</FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
</>
)} )}
{type === "email" && ( {type === "email" && (
<> <>

View File

@@ -228,21 +228,17 @@ export const ShowServers = () => {
</DropdownMenuItem> </DropdownMenuItem>
</DialogAction> </DialogAction>
{isActive && ( {isActive && server.sshKeyId && (
<> <>
{server.sshKeyId && ( <DropdownMenuSeparator />
<> <DropdownMenuLabel>Extra</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuLabel>Extra</DropdownMenuLabel>
<ShowTraefikFileSystemModal <ShowTraefikFileSystemModal
serverId={server.serverId} serverId={server.serverId}
/> />
<ShowDockerContainersModal <ShowDockerContainersModal
serverId={server.serverId} serverId={server.serverId}
/> />
</>
)}
</> </>
)} )}
</DropdownMenuContent> </DropdownMenuContent>

View File

@@ -61,7 +61,7 @@ const InputOTPSeparator = React.forwardRef<
React.ElementRef<"div">, React.ElementRef<"div">,
React.ComponentPropsWithoutRef<"div"> React.ComponentPropsWithoutRef<"div">
>(({ ...props }, ref) => ( >(({ ...props }, ref) => (
<div ref={ref} role="separator" {...props}> <div ref={ref} {...props}>
<Dot /> <Dot />
</div> </div>
)); ));

View File

@@ -10,137 +10,138 @@ import type { NextApiRequest, NextApiResponse } from "next";
import { extractCommitMessage, extractHash } from "./[refreshToken]"; import { extractCommitMessage, extractHash } from "./[refreshToken]";
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse, res: NextApiResponse
) { ) {
const signature = req.headers["x-hub-signature-256"]; const signature = req.headers["x-hub-signature-256"];
const githubBody = req.body; const githubBody = req.body;
if (!githubBody?.installation?.id) { if (!githubBody?.installation?.id) {
res.status(400).json({ message: "Github Installation not found" }); res.status(400).json({ message: "Github Installation not found" });
return; return;
} }
const githubResult = await db.query.github.findFirst({ const githubResult = await db.query.github.findFirst({
where: eq(github.githubInstallationId, githubBody.installation.id), where: eq(github.githubInstallationId, githubBody.installation.id),
}); });
if (!githubResult) { if (!githubResult) {
res.status(400).json({ message: "Github Installation not found" }); res.status(400).json({ message: "Github Installation not found" });
return; return;
} }
if (!githubResult.githubWebhookSecret) { if (!githubResult.githubWebhookSecret) {
res.status(400).json({ message: "Github Webhook Secret not set" }); res.status(400).json({ message: "Github Webhook Secret not set" });
return; return;
} }
const webhooks = new Webhooks({ const webhooks = new Webhooks({
secret: githubResult.githubWebhookSecret, secret: githubResult.githubWebhookSecret,
}); });
const verified = await webhooks.verify( const verified = await webhooks.verify(
JSON.stringify(githubBody), JSON.stringify(githubBody),
signature as string, signature as string
); );
if (!verified) { if (!verified) {
res.status(401).json({ message: "Unauthorized" }); res.status(401).json({ message: "Unauthorized" });
return; return;
} }
if (req.headers["x-github-event"] === "ping") { if (req.headers["x-github-event"] === "ping") {
res.status(200).json({ message: "Ping received, webhook is active" }); res.status(200).json({ message: "Ping received, webhook is active" });
return; return;
} }
if (req.headers["x-github-event"] !== "push") { if (req.headers["x-github-event"] !== "push") {
res.status(400).json({ message: "We only accept push events" }); res.status(400).json({ message: "We only accept push events" });
return; return;
} }
try { try {
const branchName = githubBody?.ref?.replace("refs/heads/", ""); const branchName = githubBody?.ref?.replace("refs/heads/", "");
const repository = githubBody?.repository?.name; const repository = githubBody?.repository?.name;
const deploymentTitle = extractCommitMessage(req.headers, req.body); const deploymentTitle = extractCommitMessage(req.headers, req.body);
const deploymentHash = extractHash(req.headers, req.body); const deploymentHash = extractHash(req.headers, req.body);
const apps = await db.query.applications.findMany({ const apps = await db.query.applications.findMany({
where: and( where: and(
eq(applications.sourceType, "github"), eq(applications.sourceType, "github"),
eq(applications.autoDeploy, true), eq(applications.autoDeploy, true),
eq(applications.branch, branchName), eq(applications.branch, branchName),
eq(applications.repository, repository), eq(applications.repository, repository)
), ),
}); });
for (const app of apps) { for (const app of apps) {
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
applicationId: app.applicationId as string, applicationId: app.applicationId as string,
titleLog: deploymentTitle, titleLog: deploymentTitle,
descriptionLog: `Hash: ${deploymentHash}`, descriptionLog: `Hash: ${deploymentHash}`,
type: "deploy", type: "deploy",
applicationType: "application", applicationType: "application",
server: !!app.serverId, server: !!app.serverId,
}; };
if (IS_CLOUD && app.serverId) { if (IS_CLOUD && app.serverId) {
jobData.serverId = app.serverId; jobData.serverId = app.serverId;
await deploy(jobData); await deploy(jobData);
return true; return true;
} }
await myQueue.add( await myQueue.add(
"deployments", "deployments",
{ ...jobData }, { ...jobData },
{ {
removeOnComplete: true, removeOnComplete: true,
removeOnFail: true, removeOnFail: true,
}, }
); );
} }
const composeApps = await db.query.compose.findMany({ const composeApps = await db.query.compose.findMany({
where: and( where: and(
eq(compose.sourceType, "github"), eq(compose.sourceType, "github"),
eq(compose.autoDeploy, true), eq(compose.autoDeploy, true),
eq(compose.branch, branchName), eq(compose.branch, branchName),
eq(compose.repository, repository), eq(compose.repository, repository)
), ),
}); });
for (const composeApp of composeApps) { for (const composeApp of composeApps) {
const jobData: DeploymentJob = { const jobData: DeploymentJob = {
composeId: composeApp.composeId as string, composeId: composeApp.composeId as string,
titleLog: deploymentTitle, titleLog: deploymentTitle,
type: "deploy", type: "deploy",
applicationType: "compose", applicationType: "compose",
descriptionLog: `Hash: ${deploymentHash}`, descriptionLog: `Hash: ${deploymentHash}`,
}; server: !!composeApp.serverId,
};
if (IS_CLOUD && composeApp.serverId) { if (IS_CLOUD && composeApp.serverId) {
jobData.serverId = composeApp.serverId; jobData.serverId = composeApp.serverId;
await deploy(jobData); await deploy(jobData);
return true; return true;
} }
await myQueue.add( await myQueue.add(
"deployments", "deployments",
{ ...jobData }, { ...jobData },
{ {
removeOnComplete: true, removeOnComplete: true,
removeOnFail: true, removeOnFail: true,
}, }
); );
} }
const totalApps = apps.length + composeApps.length; const totalApps = apps.length + composeApps.length;
const emptyApps = totalApps === 0; const emptyApps = totalApps === 0;
if (emptyApps) { if (emptyApps) {
res.status(200).json({ message: "No apps to deploy" }); res.status(200).json({ message: "No apps to deploy" });
return; return;
} }
res.status(200).json({ message: `Deployed ${totalApps} apps` }); res.status(200).json({ message: `Deployed ${totalApps} apps` });
} catch (error) { } catch (error) {
res.status(400).json({ message: "Error To Deploy Application", error }); res.status(400).json({ message: "Error To Deploy Application", error });
} }
} }

View File

@@ -3,173 +3,173 @@
@tailwind utilities; @tailwind utilities;
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; --background: 0 0% 100%;
--foreground: 240 10% 3.9%; --foreground: 240 10% 3.9%;
--card: 0 0% 100%; --card: 0 0% 100%;
--card-foreground: 240 10% 3.9%; --card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%; --popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%; --primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%; --primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%; --secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%; --secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%; --muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%; --muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%; --accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%; --accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%; --destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%; --border: 240 5.9% 90%;
--input: 240 5.9% 90%; --input: 240 5.9% 90%;
--ring: 240 10% 3.9%; --ring: 240 10% 3.9%;
--radius: 0.5rem; --radius: 0.5rem;
--overlay: rgba(0, 0, 0, 0.2); --overlay: rgba(0, 0, 0, 0.2);
--chart-1: 173 58% 39%; --chart-1: 173 58% 39%;
--chart-2: 12 76% 61%; --chart-2: 12 76% 61%;
--chart-3: 197 37% 24%; --chart-3: 197 37% 24%;
--chart-4: 43 74% 66%; --chart-4: 43 74% 66%;
--chart-5: 27 87% 67%; --chart-5: 27 87% 67%;
} }
.dark { .dark {
--background: 0 0% 0%; --background: 0 0% 0%;
--foreground: 0 0% 98%; --foreground: 0 0% 98%;
--card: 240 4% 10%; --card: 240 4% 10%;
--card-foreground: 0 0% 98%; --card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%; --popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%; --popover-foreground: 0 0% 98%;
--primary: 0 0% 98%; --primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%; --primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%; --secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%; --secondary-foreground: 0 0% 98%;
--muted: 240 4% 10%; --muted: 240 4% 10%;
--muted-foreground: 240 5% 64.9%; --muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%; --accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%; --accent-foreground: 0 0% 98%;
--destructive: 0 84.2% 60.2%; --destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%; --border: 240 3.7% 15.9%;
--input: 240 4% 10%; --input: 240 4% 10%;
--ring: 240 4.9% 83.9%; --ring: 240 4.9% 83.9%;
--overlay: rgba(0, 0, 0, 0.5); --overlay: rgba(0, 0, 0, 0.5);
--chart-1: 220 70% 50%; --chart-1: 220 70% 50%;
--chart-5: 160 60% 45%; --chart-5: 160 60% 45%;
--chart-3: 30 80% 55%; --chart-3: 30 80% 55%;
--chart-4: 280 65% 60%; --chart-4: 280 65% 60%;
--chart-2: 340 75% 55%; --chart-2: 340 75% 55%;
} }
} }
@layer base { @layer base {
* { * {
@apply border-border; @apply border-border;
} }
body { body {
@apply bg-background text-foreground; @apply bg-background text-foreground;
} }
} }
.xterm-viewport { .xterm-viewport {
border-radius: 0.75rem /* 12px */ !important; border-radius: 0.75rem /* 12px */ !important;
} }
.xterm .xterm-viewport { .xterm .xterm-viewport {
overflow-y: auto !important; overflow-y: auto !important;
} }
.xterm .xterm-screen { .xterm .xterm-screen {
overflow: hidden; overflow: hidden;
} }
@layer utilities { @layer utilities {
/* Chrome, Safari and Opera */ /* Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar { .no-scrollbar::-webkit-scrollbar {
display: none; display: none;
} }
.no-scrollbar { .no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */ -ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */ scrollbar-width: none; /* Firefox */
} }
} }
/* Codemirror */ /* Codemirror */
.cm-editor { .cm-editor {
@apply w-full h-full rounded-md overflow-hidden border border-solid border-border outline-none; @apply w-full h-full rounded-md overflow-hidden border border-solid border-border outline-none;
} }
.cm-editor .cm-scroller { .cm-editor .cm-scroller {
font-family: inherit; font-family: inherit;
line-height: inherit; line-height: inherit;
} }
.cm-editor.cm-focused { .cm-editor.cm-focused {
@apply outline-none; @apply outline-none;
} }
/* fix: placeholder bg */ /* fix: placeholder bg */
.cm-editor .cm-activeLine:has(.cm-placeholder) { .cm-editor .cm-activeLine:has(.cm-placeholder) {
background-color: transparent; background-color: transparent;
} }
.compose-file-editor .cm-editor { .compose-file-editor .cm-editor {
@apply min-h-[25rem]; @apply min-h-[25rem];
} }
@keyframes heartbeat { @keyframes heartbeat {
0% { 0% {
transform: scale(1); transform: scale(1);
opacity: 0.7; opacity: 0.7;
} }
25% { 25% {
transform: scale(1.1); transform: scale(1.1);
opacity: 1; opacity: 1;
} }
50% { 50% {
transform: scale(1); transform: scale(1);
opacity: 0.7; opacity: 0.7;
} }
75% { 75% {
transform: scale(1.1); transform: scale(1.1);
opacity: 1; opacity: 1;
} }
100% { 100% {
transform: scale(1); transform: scale(1);
opacity: 0.7; opacity: 0.7;
} }
} }
.animate-heartbeat { .animate-heartbeat {
animation: heartbeat 2.5s infinite; animation: heartbeat 2.5s infinite;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.swagger-ui { .swagger-ui {
background-color: white; background-color: white;
} }
.swagger-ui .info { .swagger-ui .info {
margin: 0px !important; margin: 0px !important;
padding-top: 1rem !important; padding-top: 1rem !important;
} }
} }

View File

@@ -41,5 +41,5 @@ commit-msg:
pre-commit: pre-commit:
commands: commands:
lint-staged: check:
run: "pnpm check && npx lint-staged" run: "pnpm check"

View File

@@ -13,7 +13,6 @@
"server:build": "pnpm --filter=server run build", "server:build": "pnpm --filter=server run build",
"docker:build:canary": "./apps/dokploy/docker/build.sh canary", "docker:build:canary": "./apps/dokploy/docker/build.sh canary",
"typecheck": "pnpm -r run typecheck", "typecheck": "pnpm -r run typecheck",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"build": "pnpm -r run build", "build": "pnpm -r run build",
"format-and-lint": "biome check .", "format-and-lint": "biome check .",
"check": "biome check --write --no-errors-on-unmatched --files-ignore-unknown=true", "check": "biome check --write --no-errors-on-unmatched --files-ignore-unknown=true",
@@ -24,7 +23,7 @@
"esbuild": "0.20.2", "esbuild": "0.20.2",
"tsx": "4.16.2", "tsx": "4.16.2",
"lint-staged": "^15.2.7", "lint-staged": "^15.2.7",
"@biomejs/biome": "1.8.3", "@biomejs/biome": "1.9.4",
"lefthook": "1.8.4", "lefthook": "1.8.4",
"@commitlint/cli": "^19.3.0", "@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2", "@commitlint/config-conventional": "^19.2.2",

74
pnpm-lock.yaml generated
View File

@@ -13,8 +13,8 @@ importers:
.: .:
devDependencies: devDependencies:
'@biomejs/biome': '@biomejs/biome':
specifier: 1.8.3 specifier: 1.9.4
version: 1.8.3 version: 1.9.4
'@commitlint/cli': '@commitlint/cli':
specifier: ^19.3.0 specifier: ^19.3.0
version: 19.3.0(@types/node@18.19.42)(typescript@5.5.3) version: 19.3.0(@types/node@18.19.42)(typescript@5.5.3)
@@ -682,55 +682,55 @@ packages:
'@balena/dockerignore@1.0.2': '@balena/dockerignore@1.0.2':
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
'@biomejs/biome@1.8.3': '@biomejs/biome@1.9.4':
resolution: {integrity: sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==} resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
hasBin: true hasBin: true
'@biomejs/cli-darwin-arm64@1.8.3': '@biomejs/cli-darwin-arm64@1.9.4':
resolution: {integrity: sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==} resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@biomejs/cli-darwin-x64@1.8.3': '@biomejs/cli-darwin-x64@1.9.4':
resolution: {integrity: sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==} resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@biomejs/cli-linux-arm64-musl@1.8.3': '@biomejs/cli-linux-arm64-musl@1.9.4':
resolution: {integrity: sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==} resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@biomejs/cli-linux-arm64@1.8.3': '@biomejs/cli-linux-arm64@1.9.4':
resolution: {integrity: sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==} resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@biomejs/cli-linux-x64-musl@1.8.3': '@biomejs/cli-linux-x64-musl@1.9.4':
resolution: {integrity: sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==} resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@biomejs/cli-linux-x64@1.8.3': '@biomejs/cli-linux-x64@1.9.4':
resolution: {integrity: sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==} resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@biomejs/cli-win32-arm64@1.8.3': '@biomejs/cli-win32-arm64@1.9.4':
resolution: {integrity: sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==} resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@biomejs/cli-win32-x64@1.8.3': '@biomejs/cli-win32-x64@1.9.4':
resolution: {integrity: sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==} resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==}
engines: {node: '>=14.21.3'} engines: {node: '>=14.21.3'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@@ -6869,39 +6869,39 @@ snapshots:
'@balena/dockerignore@1.0.2': {} '@balena/dockerignore@1.0.2': {}
'@biomejs/biome@1.8.3': '@biomejs/biome@1.9.4':
optionalDependencies: optionalDependencies:
'@biomejs/cli-darwin-arm64': 1.8.3 '@biomejs/cli-darwin-arm64': 1.9.4
'@biomejs/cli-darwin-x64': 1.8.3 '@biomejs/cli-darwin-x64': 1.9.4
'@biomejs/cli-linux-arm64': 1.8.3 '@biomejs/cli-linux-arm64': 1.9.4
'@biomejs/cli-linux-arm64-musl': 1.8.3 '@biomejs/cli-linux-arm64-musl': 1.9.4
'@biomejs/cli-linux-x64': 1.8.3 '@biomejs/cli-linux-x64': 1.9.4
'@biomejs/cli-linux-x64-musl': 1.8.3 '@biomejs/cli-linux-x64-musl': 1.9.4
'@biomejs/cli-win32-arm64': 1.8.3 '@biomejs/cli-win32-arm64': 1.9.4
'@biomejs/cli-win32-x64': 1.8.3 '@biomejs/cli-win32-x64': 1.9.4
'@biomejs/cli-darwin-arm64@1.8.3': '@biomejs/cli-darwin-arm64@1.9.4':
optional: true optional: true
'@biomejs/cli-darwin-x64@1.8.3': '@biomejs/cli-darwin-x64@1.9.4':
optional: true optional: true
'@biomejs/cli-linux-arm64-musl@1.8.3': '@biomejs/cli-linux-arm64-musl@1.9.4':
optional: true optional: true
'@biomejs/cli-linux-arm64@1.8.3': '@biomejs/cli-linux-arm64@1.9.4':
optional: true optional: true
'@biomejs/cli-linux-x64-musl@1.8.3': '@biomejs/cli-linux-x64-musl@1.9.4':
optional: true optional: true
'@biomejs/cli-linux-x64@1.8.3': '@biomejs/cli-linux-x64@1.9.4':
optional: true optional: true
'@biomejs/cli-win32-arm64@1.8.3': '@biomejs/cli-win32-arm64@1.9.4':
optional: true optional: true
'@biomejs/cli-win32-x64@1.8.3': '@biomejs/cli-win32-x64@1.9.4':
optional: true optional: true
'@braintree/sanitize-url@7.0.2': {} '@braintree/sanitize-url@7.0.2': {}