mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-13 18:05:31 +02:00
Compare commits
14 Commits
v0.28.1
...
feat/add-k
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e275e9162e | ||
|
|
60a6dc5fab | ||
|
|
705c5bc1c9 | ||
|
|
8d56544c1d | ||
|
|
ca527ab6ff | ||
|
|
439fa17292 | ||
|
|
096c04486c | ||
|
|
c9e1079076 | ||
|
|
e29a86a85f | ||
|
|
1ba0eb0c2e | ||
|
|
d7dc10993e | ||
|
|
2a5d3975e8 | ||
|
|
9f3356ddb4 | ||
|
|
f5674f5bf8 |
@@ -14,13 +14,18 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
set: vi.fn(() => chain),
|
set: vi.fn(() => chain),
|
||||||
where: vi.fn(() => chain),
|
where: vi.fn(() => chain),
|
||||||
returning: vi.fn().mockResolvedValue([{}] as any),
|
returning: vi.fn().mockResolvedValue([{}] as any),
|
||||||
|
from: vi.fn(() => chain),
|
||||||
|
innerJoin: vi.fn(() => chain),
|
||||||
|
then: (resolve: (v: any) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
},
|
||||||
} as any;
|
} as any;
|
||||||
return chain;
|
return chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
select: vi.fn(),
|
select: vi.fn(() => createChainableMock()),
|
||||||
insert: vi.fn(),
|
insert: vi.fn(),
|
||||||
update: vi.fn(() => createChainableMock()),
|
update: vi.fn(() => createChainableMock()),
|
||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
@@ -31,6 +36,9 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
patch: {
|
patch: {
|
||||||
findMany: vi.fn().mockResolvedValue([]),
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
},
|
},
|
||||||
|
member: {
|
||||||
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,13 +15,18 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
set: vi.fn(() => chain),
|
set: vi.fn(() => chain),
|
||||||
where: vi.fn(() => chain),
|
where: vi.fn(() => chain),
|
||||||
returning: vi.fn().mockResolvedValue([{}]),
|
returning: vi.fn().mockResolvedValue([{}]),
|
||||||
|
from: vi.fn(() => chain),
|
||||||
|
innerJoin: vi.fn(() => chain),
|
||||||
|
then: (resolve: (v: any) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return chain;
|
return chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
select: vi.fn(),
|
select: vi.fn(() => createChainableMock()),
|
||||||
insert: vi.fn(),
|
insert: vi.fn(),
|
||||||
update: vi.fn(() => createChainableMock()),
|
update: vi.fn(() => createChainableMock()),
|
||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
@@ -32,6 +37,9 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
patch: {
|
patch: {
|
||||||
findMany: vi.fn().mockResolvedValue([]),
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
},
|
},
|
||||||
|
member: {
|
||||||
|
findMany: vi.fn().mockResolvedValue([]),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ 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([{}]);
|
||||||
chain.then = undefined;
|
chain.from = () => chain;
|
||||||
|
chain.innerJoin = () => chain;
|
||||||
|
chain.then = (resolve: (value: unknown) => void) => {
|
||||||
|
resolve([]);
|
||||||
|
};
|
||||||
|
|
||||||
const tableMock = {
|
const tableMock = {
|
||||||
findFirst: vi.fn(() => Promise.resolve(undefined)),
|
findFirst: vi.fn(() => Promise.resolve(undefined)),
|
||||||
@@ -21,7 +25,6 @@ vi.mock("@dokploy/server/db", () => {
|
|||||||
update: vi.fn(() => chain),
|
update: vi.fn(() => chain),
|
||||||
delete: vi.fn(() => chain),
|
delete: vi.fn(() => chain),
|
||||||
};
|
};
|
||||||
const createQueryMock = () => tableMock;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db: {
|
db: {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const AddGithubProvider = () => {
|
|||||||
const url = document.location.origin;
|
const url = document.location.origin;
|
||||||
const manifest = JSON.stringify(
|
const manifest = JSON.stringify(
|
||||||
{
|
{
|
||||||
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id}&userId=${session?.user?.id}`,
|
redirect_url: `${origin}/api/providers/github/setup?organizationId=${activeOrganization?.id ?? ""}&userId=${session?.user?.id ?? ""}`,
|
||||||
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}-${randomString()}`,
|
name: `Dokploy-${format(new Date(), "yyyy-MM-dd")}-${randomString()}`,
|
||||||
url: origin,
|
url: origin,
|
||||||
hook_attributes: {
|
hook_attributes: {
|
||||||
@@ -52,7 +52,7 @@ export const AddGithubProvider = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
setManifest(manifest);
|
setManifest(manifest);
|
||||||
}, [data?.id]);
|
}, [data?.id, activeOrganization?.id, session?.user?.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
@@ -131,7 +131,11 @@ export const AddGithubProvider = () => {
|
|||||||
Unsure if you already have an app?
|
Unsure if you already have an app?
|
||||||
</a>
|
</a>
|
||||||
<Button
|
<Button
|
||||||
disabled={isOrganization && organizationName.length < 1}
|
disabled={
|
||||||
|
(isOrganization && organizationName.length < 1) ||
|
||||||
|
!activeOrganization?.id ||
|
||||||
|
!session?.user?.id
|
||||||
|
}
|
||||||
type="submit"
|
type="submit"
|
||||||
className="self-end"
|
className="self-end"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BreadcrumbSidebar = ({ list }: Props) => {
|
export const BreadcrumbSidebar = ({ list }: Props) => {
|
||||||
console.log(list);
|
|
||||||
return (
|
return (
|
||||||
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
||||||
<div className="flex items-center justify-between w-full">
|
<div className="flex items-center justify-between w-full">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dokploy",
|
"name": "dokploy",
|
||||||
"version": "v0.28.1",
|
"version": "v0.28.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Proprietary Features
|
|
||||||
|
|
||||||
This directory contains all proprietary functionality of Dokploy.
|
|
||||||
|
|
||||||
## Purpose
|
|
||||||
|
|
||||||
This folder will house all **paid features** and premium functionality that are not part of the open source code.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The code in this directory is under Dokploy's proprietary license. See [LICENSE_PROPRIETARY.md](../../../LICENSE_PROPRIETARY.md) for more details.
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
If you want to learn more about our paid features or have any questions, please contact us at:
|
|
||||||
|
|
||||||
- Email: [sales@dokploy.com](mailto:sales@dokploy.com)
|
|
||||||
- Contact Form: [https://dokploy.com/contact](https://dokploy.com/contact)
|
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
findApplicationById,
|
findApplicationById,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
findGitProviderById,
|
findGitProviderById,
|
||||||
|
findMemberById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
getApplicationStats,
|
getApplicationStats,
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
@@ -32,7 +33,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
@@ -53,6 +54,8 @@ import {
|
|||||||
apiSaveGitProvider,
|
apiSaveGitProvider,
|
||||||
apiUpdateApplication,
|
apiUpdateApplication,
|
||||||
applications,
|
applications,
|
||||||
|
environments,
|
||||||
|
projects,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { deploymentWorker } from "@/server/queues/deployments-queue";
|
import { deploymentWorker } from "@/server/queues/deployments-queue";
|
||||||
import type { DeploymentJob } from "@/server/queues/queue-types";
|
import type { DeploymentJob } from "@/server/queues/queue-types";
|
||||||
@@ -1002,4 +1005,138 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
message: "Deployment cancellation only available in cloud version",
|
message: "Deployment cancellation only available in cloud version",
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
repository: z.string().optional(),
|
||||||
|
owner: z.string().optional(),
|
||||||
|
dockerImage: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(
|
||||||
|
eq(applications.environmentId, input.environmentId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(applications.name, term),
|
||||||
|
ilike(applications.appName, term),
|
||||||
|
ilike(applications.description ?? "", term),
|
||||||
|
ilike(applications.repository ?? "", term),
|
||||||
|
ilike(applications.owner ?? "", term),
|
||||||
|
ilike(applications.dockerImage ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(applications.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(applications.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
applications.description ?? "",
|
||||||
|
`%${input.description.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.repository?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(applications.repository ?? "", `%${input.repository.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.owner?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(applications.owner ?? "", `%${input.owner.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.dockerImage?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
applications.dockerImage ?? "",
|
||||||
|
`%${input.dockerImage.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${applications.applicationId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
applicationId: applications.applicationId,
|
||||||
|
name: applications.name,
|
||||||
|
appName: applications.appName,
|
||||||
|
description: applications.description,
|
||||||
|
environmentId: applications.environmentId,
|
||||||
|
applicationStatus: applications.applicationStatus,
|
||||||
|
sourceType: applications.sourceType,
|
||||||
|
createdAt: applications.createdAt,
|
||||||
|
})
|
||||||
|
.from(applications)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(applications.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(applications.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(applications)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(applications.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
total: countResult[0]?.count ?? 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
findDomainsByComposeId,
|
findDomainsByComposeId,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
findGitProviderById,
|
findGitProviderById,
|
||||||
|
findMemberById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
findServerById,
|
findServerById,
|
||||||
getComposeContainer,
|
getComposeContainer,
|
||||||
@@ -41,7 +42,7 @@ import {
|
|||||||
} from "@dokploy/server/templates/github";
|
} from "@dokploy/server/templates/github";
|
||||||
import { processTemplate } from "@dokploy/server/templates/processors";
|
import { processTemplate } from "@dokploy/server/templates/processors";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { parse } from "toml";
|
import { parse } from "toml";
|
||||||
@@ -58,6 +59,8 @@ import {
|
|||||||
apiRedeployCompose,
|
apiRedeployCompose,
|
||||||
apiUpdateCompose,
|
apiUpdateCompose,
|
||||||
compose as composeTable,
|
compose as composeTable,
|
||||||
|
environments,
|
||||||
|
projects,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { deploymentWorker } from "@/server/queues/deployments-queue";
|
import { deploymentWorker } from "@/server/queues/deployments-queue";
|
||||||
import type { DeploymentJob } from "@/server/queues/queue-types";
|
import type { DeploymentJob } from "@/server/queues/queue-types";
|
||||||
@@ -1054,4 +1057,114 @@ export const composeRouter = createTRPCRouter({
|
|||||||
message: "Deployment cancellation only available in cloud version",
|
message: "Deployment cancellation only available in cloud version",
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(
|
||||||
|
eq(composeTable.environmentId, input.environmentId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(composeTable.name, term),
|
||||||
|
ilike(composeTable.appName, term),
|
||||||
|
ilike(composeTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(composeTable.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(composeTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
composeTable.description ?? "",
|
||||||
|
`%${input.description.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${composeTable.composeId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
composeId: composeTable.composeId,
|
||||||
|
name: composeTable.name,
|
||||||
|
appName: composeTable.appName,
|
||||||
|
description: composeTable.description,
|
||||||
|
environmentId: composeTable.environmentId,
|
||||||
|
composeStatus: composeTable.composeStatus,
|
||||||
|
sourceType: composeTable.sourceType,
|
||||||
|
createdAt: composeTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(composeTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(composeTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(composeTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(composeTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(composeTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
total: countResult[0]?.count ?? 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import {
|
|||||||
findMemberById,
|
findMemberById,
|
||||||
updateEnvironmentById,
|
updateEnvironmentById,
|
||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -21,6 +23,7 @@ import {
|
|||||||
apiRemoveEnvironment,
|
apiRemoveEnvironment,
|
||||||
apiUpdateEnvironment,
|
apiUpdateEnvironment,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
import { environments, projects } from "@/server/db/schema";
|
||||||
|
|
||||||
// Helper function to filter services within an environment based on user permissions
|
// Helper function to filter services within an environment based on user permissions
|
||||||
const filterEnvironmentServices = (
|
const filterEnvironmentServices = (
|
||||||
@@ -358,4 +361,92 @@ export const environmentRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(environments.name, term),
|
||||||
|
ilike(environments.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(environments.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
environments.description ?? "",
|
||||||
|
`%${input.description.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedEnvironments } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedEnvironments.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${environments.environmentId} IN (${sql.join(
|
||||||
|
accessedEnvironments.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
environmentId: environments.environmentId,
|
||||||
|
name: environments.name,
|
||||||
|
description: environments.description,
|
||||||
|
createdAt: environments.createdAt,
|
||||||
|
env: environments.env,
|
||||||
|
projectId: environments.projectId,
|
||||||
|
isDefault: environments.isDefault,
|
||||||
|
})
|
||||||
|
.from(environments)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(environments.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(environments)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
total: countResult[0]?.count ?? 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
findMariadbById,
|
findMariadbById,
|
||||||
|
findMemberById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
rebuildDatabase,
|
rebuildDatabase,
|
||||||
@@ -22,7 +23,7 @@ import {
|
|||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { observable } from "@trpc/server/observable";
|
import { observable } from "@trpc/server/observable";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -37,6 +38,7 @@ import {
|
|||||||
apiUpdateMariaDB,
|
apiUpdateMariaDB,
|
||||||
mariadb as mariadbTable,
|
mariadb as mariadbTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
import { environments, projects } from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
export const mariadbRouter = createTRPCRouter({
|
export const mariadbRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
@@ -446,4 +448,102 @@ export const mariadbRouter = createTRPCRouter({
|
|||||||
await rebuildDatabase(mariadb.mariadbId, "mariadb");
|
await rebuildDatabase(mariadb.mariadbId, "mariadb");
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(
|
||||||
|
eq(mariadbTable.environmentId, input.environmentId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(mariadbTable.name, term),
|
||||||
|
ilike(mariadbTable.appName, term),
|
||||||
|
ilike(mariadbTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(mariadbTable.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(mariadbTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
mariadbTable.description ?? "",
|
||||||
|
`%${input.description.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${mariadbTable.mariadbId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
mariadbId: mariadbTable.mariadbId,
|
||||||
|
name: mariadbTable.name,
|
||||||
|
appName: mariadbTable.appName,
|
||||||
|
description: mariadbTable.description,
|
||||||
|
environmentId: mariadbTable.environmentId,
|
||||||
|
applicationStatus: mariadbTable.applicationStatus,
|
||||||
|
createdAt: mariadbTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(mariadbTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mariadbTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(mariadbTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(mariadbTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mariadbTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
return { items, total: countResult[0]?.count ?? 0 };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
deployMongo,
|
deployMongo,
|
||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
|
findMemberById,
|
||||||
findMongoById,
|
findMongoById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
@@ -21,7 +22,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -36,6 +37,7 @@ import {
|
|||||||
apiUpdateMongo,
|
apiUpdateMongo,
|
||||||
mongo as mongoTable,
|
mongo as mongoTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
import { environments, projects } from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
export const mongoRouter = createTRPCRouter({
|
export const mongoRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
@@ -476,4 +478,97 @@ export const mongoRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(eq(mongoTable.environmentId, input.environmentId));
|
||||||
|
}
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(mongoTable.name, term),
|
||||||
|
ilike(mongoTable.appName, term),
|
||||||
|
ilike(mongoTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(mongoTable.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(mongoTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(mongoTable.description ?? "", `%${input.description.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${mongoTable.mongoId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
mongoId: mongoTable.mongoId,
|
||||||
|
name: mongoTable.name,
|
||||||
|
appName: mongoTable.appName,
|
||||||
|
description: mongoTable.description,
|
||||||
|
environmentId: mongoTable.environmentId,
|
||||||
|
applicationStatus: mongoTable.applicationStatus,
|
||||||
|
createdAt: mongoTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(mongoTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mongoTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(mongoTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(mongoTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mongoTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
return { items, total: countResult[0]?.count ?? 0 };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
deployMySql,
|
deployMySql,
|
||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
|
findMemberById,
|
||||||
findMySqlById,
|
findMySqlById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
@@ -21,7 +22,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -34,7 +35,9 @@ import {
|
|||||||
apiSaveEnvironmentVariablesMySql,
|
apiSaveEnvironmentVariablesMySql,
|
||||||
apiSaveExternalPortMySql,
|
apiSaveExternalPortMySql,
|
||||||
apiUpdateMySql,
|
apiUpdateMySql,
|
||||||
|
environments,
|
||||||
mysql as mysqlTable,
|
mysql as mysqlTable,
|
||||||
|
projects,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
|
|
||||||
@@ -471,4 +474,97 @@ export const mysqlRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(eq(mysqlTable.environmentId, input.environmentId));
|
||||||
|
}
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(mysqlTable.name, term),
|
||||||
|
ilike(mysqlTable.appName, term),
|
||||||
|
ilike(mysqlTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(mysqlTable.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(mysqlTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(mysqlTable.description ?? "", `%${input.description.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${mysqlTable.mysqlId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
mysqlId: mysqlTable.mysqlId,
|
||||||
|
name: mysqlTable.name,
|
||||||
|
appName: mysqlTable.appName,
|
||||||
|
description: mysqlTable.description,
|
||||||
|
environmentId: mysqlTable.environmentId,
|
||||||
|
applicationStatus: mysqlTable.applicationStatus,
|
||||||
|
createdAt: mysqlTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(mysqlTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mysqlTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(mysqlTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(mysqlTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(mysqlTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
return { items, total: countResult[0]?.count ?? 0 };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
deployPostgres,
|
deployPostgres,
|
||||||
findBackupsByDbId,
|
findBackupsByDbId,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
|
findMemberById,
|
||||||
findPostgresById,
|
findPostgresById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
getMountPath,
|
getMountPath,
|
||||||
@@ -22,7 +23,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -37,6 +38,7 @@ import {
|
|||||||
apiUpdatePostgres,
|
apiUpdatePostgres,
|
||||||
postgres as postgresTable,
|
postgres as postgresTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
import { environments, projects } from "@/server/db/schema";
|
||||||
import { cancelJobs } from "@/server/utils/backup";
|
import { cancelJobs } from "@/server/utils/backup";
|
||||||
|
|
||||||
export const postgresRouter = createTRPCRouter({
|
export const postgresRouter = createTRPCRouter({
|
||||||
@@ -483,4 +485,104 @@ export const postgresRouter = createTRPCRouter({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(
|
||||||
|
eq(postgresTable.environmentId, input.environmentId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(postgresTable.name, term),
|
||||||
|
ilike(postgresTable.appName, term),
|
||||||
|
ilike(postgresTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(postgresTable.name, `%${input.name.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(postgresTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(
|
||||||
|
postgresTable.description ?? "",
|
||||||
|
`%${input.description.trim()}%`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${postgresTable.postgresId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
postgresId: postgresTable.postgresId,
|
||||||
|
name: postgresTable.name,
|
||||||
|
appName: postgresTable.appName,
|
||||||
|
description: postgresTable.description,
|
||||||
|
environmentId: postgresTable.environmentId,
|
||||||
|
applicationStatus: postgresTable.applicationStatus,
|
||||||
|
createdAt: postgresTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(postgresTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(postgresTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(postgresTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(postgresTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(postgresTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
return { items, total: countResult[0]?.count ?? 0 };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { and, desc, eq, sql } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import type { AnyPgColumn } from "drizzle-orm/pg-core";
|
import type { AnyPgColumn } from "drizzle-orm/pg-core";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
@@ -277,6 +277,83 @@ export const projectRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(projects.name, term),
|
||||||
|
ilike(projects.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(projects.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(projects.description ?? "", `%${input.description.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedProjects } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedProjects.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${projects.projectId} IN (${sql.join(
|
||||||
|
accessedProjects.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db.query.projects.findMany({
|
||||||
|
where,
|
||||||
|
limit: input.limit,
|
||||||
|
offset: input.offset,
|
||||||
|
orderBy: desc(projects.createdAt),
|
||||||
|
columns: {
|
||||||
|
projectId: true,
|
||||||
|
name: true,
|
||||||
|
description: true,
|
||||||
|
createdAt: true,
|
||||||
|
organizationId: true,
|
||||||
|
env: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(projects)
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
total: countResult[0]?.count ?? 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
remove: protectedProcedure
|
remove: protectedProcedure
|
||||||
.input(apiRemoveProject)
|
.input(apiRemoveProject)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
createRedis,
|
createRedis,
|
||||||
deployRedis,
|
deployRedis,
|
||||||
findEnvironmentById,
|
findEnvironmentById,
|
||||||
|
findMemberById,
|
||||||
findProjectById,
|
findProjectById,
|
||||||
findRedisById,
|
findRedisById,
|
||||||
IS_CLOUD,
|
IS_CLOUD,
|
||||||
@@ -20,7 +21,7 @@ import {
|
|||||||
} from "@dokploy/server";
|
} from "@dokploy/server";
|
||||||
import { db } from "@dokploy/server/db";
|
import { db } from "@dokploy/server/db";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "@/server/api/trpc";
|
||||||
import {
|
import {
|
||||||
@@ -35,6 +36,7 @@ import {
|
|||||||
apiUpdateRedis,
|
apiUpdateRedis,
|
||||||
redis as redisTable,
|
redis as redisTable,
|
||||||
} from "@/server/db/schema";
|
} from "@/server/db/schema";
|
||||||
|
import { environments, projects } from "@/server/db/schema";
|
||||||
export const redisRouter = createTRPCRouter({
|
export const redisRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
.input(apiCreateRedis)
|
.input(apiCreateRedis)
|
||||||
@@ -450,4 +452,97 @@ export const redisRouter = createTRPCRouter({
|
|||||||
await rebuildDatabase(redis.redisId, "redis");
|
await rebuildDatabase(redis.redisId, "redis");
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
|
search: protectedProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
q: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
appName: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
projectId: z.string().optional(),
|
||||||
|
environmentId: z.string().optional(),
|
||||||
|
limit: z.number().min(1).max(100).default(20),
|
||||||
|
offset: z.number().min(0).default(0),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const baseConditions = [
|
||||||
|
eq(projects.organizationId, ctx.session.activeOrganizationId),
|
||||||
|
];
|
||||||
|
if (input.projectId) {
|
||||||
|
baseConditions.push(eq(environments.projectId, input.projectId));
|
||||||
|
}
|
||||||
|
if (input.environmentId) {
|
||||||
|
baseConditions.push(eq(redisTable.environmentId, input.environmentId));
|
||||||
|
}
|
||||||
|
if (input.q?.trim()) {
|
||||||
|
const term = `%${input.q.trim()}%`;
|
||||||
|
baseConditions.push(
|
||||||
|
or(
|
||||||
|
ilike(redisTable.name, term),
|
||||||
|
ilike(redisTable.appName, term),
|
||||||
|
ilike(redisTable.description ?? "", term),
|
||||||
|
)!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.name?.trim()) {
|
||||||
|
baseConditions.push(ilike(redisTable.name, `%${input.name.trim()}%`));
|
||||||
|
}
|
||||||
|
if (input.appName?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(redisTable.appName, `%${input.appName.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (input.description?.trim()) {
|
||||||
|
baseConditions.push(
|
||||||
|
ilike(redisTable.description ?? "", `%${input.description.trim()}%`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ctx.user.role === "member") {
|
||||||
|
const { accessedServices } = await findMemberById(
|
||||||
|
ctx.user.id,
|
||||||
|
ctx.session.activeOrganizationId,
|
||||||
|
);
|
||||||
|
if (accessedServices.length === 0) return { items: [], total: 0 };
|
||||||
|
baseConditions.push(
|
||||||
|
sql`${redisTable.redisId} IN (${sql.join(
|
||||||
|
accessedServices.map((id) => sql`${id}`),
|
||||||
|
sql`, `,
|
||||||
|
)})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const where = and(...baseConditions);
|
||||||
|
const [items, countResult] = await Promise.all([
|
||||||
|
db
|
||||||
|
.select({
|
||||||
|
redisId: redisTable.redisId,
|
||||||
|
name: redisTable.name,
|
||||||
|
appName: redisTable.appName,
|
||||||
|
description: redisTable.description,
|
||||||
|
environmentId: redisTable.environmentId,
|
||||||
|
applicationStatus: redisTable.applicationStatus,
|
||||||
|
createdAt: redisTable.createdAt,
|
||||||
|
})
|
||||||
|
.from(redisTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(redisTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where)
|
||||||
|
.orderBy(desc(redisTable.createdAt))
|
||||||
|
.limit(input.limit)
|
||||||
|
.offset(input.offset),
|
||||||
|
db
|
||||||
|
.select({ count: sql<number>`count(*)::int` })
|
||||||
|
.from(redisTable)
|
||||||
|
.innerJoin(
|
||||||
|
environments,
|
||||||
|
eq(redisTable.environmentId, environments.environmentId),
|
||||||
|
)
|
||||||
|
.innerJoin(projects, eq(environments.projectId, projects.projectId))
|
||||||
|
.where(where),
|
||||||
|
]);
|
||||||
|
return { items, total: countResult[0]?.count ?? 0 };
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
38
apps/dokploy/server/db/index.ts
Normal file
38
apps/dokploy/server/db/index.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { dbUrl } from "@dokploy/server/db/constants";
|
||||||
|
import * as schema from "@dokploy/server/db/schema";
|
||||||
|
import { and, eq } from "drizzle-orm";
|
||||||
|
import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
||||||
|
import postgres from "postgres";
|
||||||
|
|
||||||
|
export { and, eq };
|
||||||
|
|
||||||
|
type Database = PostgresJsDatabase<typeof schema>;
|
||||||
|
/**
|
||||||
|
* Evita problemas de redeclaración global en monorepos.
|
||||||
|
* No usamos `declare global`.
|
||||||
|
*/
|
||||||
|
const globalForDb = globalThis as unknown as {
|
||||||
|
db?: Database;
|
||||||
|
};
|
||||||
|
|
||||||
|
let dbConnection: Database;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
// En producción no usamos global cache
|
||||||
|
dbConnection = drizzle(postgres(dbUrl), {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// En desarrollo reutilizamos conexión para evitar múltiples conexiones
|
||||||
|
if (!globalForDb.db) {
|
||||||
|
globalForDb.db = drizzle(postgres(dbUrl), {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dbConnection = globalForDb.db;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const db: Database = dbConnection;
|
||||||
|
|
||||||
|
export { dbUrl };
|
||||||
@@ -73,23 +73,25 @@ const { handler, api } = betterAuth({
|
|||||||
disabled: process.env.NODE_ENV === "production",
|
disabled: process.env.NODE_ENV === "production",
|
||||||
},
|
},
|
||||||
async trustedOrigins() {
|
async trustedOrigins() {
|
||||||
const trustedOrigins = await getTrustedOrigins();
|
|
||||||
if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
return trustedOrigins;
|
return getTrustedOrigins();
|
||||||
}
|
}
|
||||||
const settings = await getWebServerSettings();
|
const [trustedOrigins, settings] = await Promise.all([
|
||||||
if (!settings) {
|
getTrustedOrigins(),
|
||||||
return [];
|
getWebServerSettings(),
|
||||||
}
|
]);
|
||||||
return [
|
if (!settings) return [];
|
||||||
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
const devOrigins =
|
||||||
...(settings?.host ? [`https://${settings?.host}`] : []),
|
process.env.NODE_ENV === "development"
|
||||||
...(process.env.NODE_ENV === "development"
|
|
||||||
? [
|
? [
|
||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
"https://absolutely-handy-falcon.ngrok-free.app",
|
"https://absolutely-handy-falcon.ngrok-free.app",
|
||||||
]
|
]
|
||||||
: []),
|
: [];
|
||||||
|
return [
|
||||||
|
...(settings?.serverIp ? [`http://${settings?.serverIp}:3000`] : []),
|
||||||
|
...(settings?.host ? [`https://${settings?.host}`] : []),
|
||||||
|
...devOrigins,
|
||||||
...trustedOrigins,
|
...trustedOrigins,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,23 +117,33 @@ export const getDokployUrl = async () => {
|
|||||||
return `http://${settings?.serverIp}:${process.env.PORT}`;
|
return `http://${settings?.serverIp}:${process.env.PORT}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTrustedOrigins = async () => {
|
const TRUSTED_ORIGINS_CACHE_TTL_MS = 30 * 60_000;
|
||||||
const members = await db.query.member.findMany({
|
let trustedOriginsCache: { data: string[]; expiresAt: number } | null = null;
|
||||||
where: eq(member.role, "owner"),
|
|
||||||
with: {
|
|
||||||
user: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (members.length === 0) {
|
export const getTrustedOrigins = async () => {
|
||||||
return [];
|
const runQuery = async () => {
|
||||||
|
const rows = await db
|
||||||
|
.select({ trustedOrigins: user.trustedOrigins })
|
||||||
|
.from(member)
|
||||||
|
.innerJoin(user, eq(member.userId, user.id))
|
||||||
|
.where(eq(member.role, "owner"));
|
||||||
|
return Array.from(new Set(rows.flatMap((r) => r.trustedOrigins ?? [])));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IS_CLOUD) {
|
||||||
|
const now = Date.now();
|
||||||
|
if (trustedOriginsCache && now < trustedOriginsCache.expiresAt) {
|
||||||
|
return trustedOriginsCache.data;
|
||||||
|
}
|
||||||
|
const trustedOrigins = await runQuery();
|
||||||
|
trustedOriginsCache = {
|
||||||
|
data: trustedOrigins,
|
||||||
|
expiresAt: now + TRUSTED_ORIGINS_CACHE_TTL_MS,
|
||||||
|
};
|
||||||
|
return trustedOrigins;
|
||||||
}
|
}
|
||||||
|
|
||||||
const trustedOrigins = members.flatMap(
|
return runQuery();
|
||||||
(member) => member.user.trustedOrigins || [],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Array.from(new Set(trustedOrigins));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTrustedProviders = async () => {
|
export const getTrustedProviders = async () => {
|
||||||
|
|||||||
@@ -106,10 +106,6 @@ export const writeDomainsToCompose = async (
|
|||||||
compose: Compose,
|
compose: Compose,
|
||||||
domains: Domain[],
|
domains: Domain[],
|
||||||
) => {
|
) => {
|
||||||
if (!domains.length) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const composeConverted = await addDomainToCompose(compose, domains);
|
const composeConverted = await addDomainToCompose(compose, domains);
|
||||||
const path = getComposePath(compose);
|
const path = getComposePath(compose);
|
||||||
@@ -145,7 +141,7 @@ export const addDomainToCompose = async (
|
|||||||
result = await loadDockerCompose(compose);
|
result = await loadDockerCompose(compose);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result || domains.length === 0) {
|
if (!result) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user