mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-10-15 21:31:11 +00:00
v0.1.0 (#112)
* feat: add schema for registry and routes * feat: add docker registry upload * feat: add show cluster * refactor: set the registry url in image in case we have a registry asociated * feat: add update registry and fix the docker url markup * chore: remove --advertise-ip on swarm script * refactor: remove listen address of swarm initialize * feat: add table to show nodes and add dropdown to add manager & workers * refactor: improve interface for cluster * refactor: improve UI * feat: add experimental swarm settings * refactor: remove comments * refactor: prettify json of each setting * refactor: add interface tooltip * refactor: delete static form self registry * refactor: allow to se a empty registry * fix: remove text area warnings * feat: add network swarm json * refactor: update ui * revert: go back to swarm init config * refactor: remove initialization on server, only on setup script * Update LICENSE.MD * feat: appearance theme support system config * refactor: remove logs * fix(README-ru): hyperlink-ed docs url * feat: (#107) webhook listener filter docker events based on image tag. Fixes #107 * refactor: simplify comparison docker tags * refactor: remove return in res status * refactor: prevent to updates download automatically * feat: support code editor (#105) * feat: support code editor * Update codeblock * refactor: remove unused class --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: select the right image from sourcetype (#109) * chore: bump minor version --------- Co-authored-by: hehehai <riverhohai@gmail.com> Co-authored-by: Bayram Tagiev <bayram.tagiev.a@gmail.com> Co-authored-by: Paulo Santana <30875229+hikinine@users.noreply.github.com>
This commit is contained in:
+1
-2
@@ -26,7 +26,7 @@ FROM node:18-slim AS production
|
||||
# Install dependencies only for production
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable && apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
RUN corepack enable && apt-get update && apt-get install -y curl && apt-get install -y apache2-utils && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -47,7 +47,6 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-l
|
||||
# Install docker
|
||||
RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && rm get-docker.sh
|
||||
|
||||
|
||||
# Install Nixpacks and tsx
|
||||
# | VERBOSE=1 VERSION=1.21.0 bash
|
||||
RUN curl -sSL https://nixpacks.com/install.sh -o install.sh \
|
||||
|
||||
+7
-4
@@ -1,5 +1,7 @@
|
||||
# License
|
||||
|
||||
## Core License (Apache License 2.0)
|
||||
|
||||
Copyright 2024 Mauricio Siu.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -13,11 +15,12 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
## Appendix
|
||||
## Additional Terms for Specific Features
|
||||
|
||||
In the event of a conflict, the provisions in this appendix shall take precedence over those in the Apache License.
|
||||
The following additional terms apply to the multi-node support and Docker Compose file support features of Dokploy. In the event of a conflict, these provisions shall take precedence over those in the Apache License:
|
||||
|
||||
- **Modification Distribution:** Any modifications to the software must be distributed freely.
|
||||
- **Future Paid Features:** Any future paid features of Dokploy cannot be sold or offered as a service by any party other than the copyright holder without prior written consent.
|
||||
- **Self-Hosted Version Free**: All features of Dokploy, including multi-node support and Docker Compose file support, will always be free to use in the self-hosted version.
|
||||
- **Restriction on Resale**: The multi-node support and Docker Compose file support features cannot be sold or offered as a service by any party other than the copyright holder without prior written consent.
|
||||
- **Modification Distribution**: Any modifications to the multi-node support and Docker Compose file support features must be distributed freely and cannot be sold or offered as a service.
|
||||
|
||||
For further inquiries or permissions, please contact us directly.
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@ curl -sSL https://dokploy.com/install.sh | sh
|
||||
- Centos 9
|
||||
|
||||
## 📄 Документация
|
||||
Для подробной документации посетите docs.dokploy.com/docs.
|
||||
Для подробной документации посетите [docs.dokploy.com/docs](https://docs.dokploy.com).
|
||||
|
||||
@@ -0,0 +1,756 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { HelpCircle, Settings } from "lucide-react";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
|
||||
const HealthCheckSwarmSchema = z
|
||||
.object({
|
||||
Test: z.array(z.string()).optional(),
|
||||
Interval: z.number().optional(),
|
||||
Timeout: z.number().optional(),
|
||||
StartPeriod: z.number().optional(),
|
||||
Retries: z.number().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const RestartPolicySwarmSchema = z
|
||||
.object({
|
||||
Condition: z.string().optional(),
|
||||
Delay: z.number().optional(),
|
||||
MaxAttempts: z.number().optional(),
|
||||
Window: z.number().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const PreferenceSchema = z
|
||||
.object({
|
||||
Spread: z.object({
|
||||
SpreadDescriptor: z.string(),
|
||||
}),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const PlatformSchema = z
|
||||
.object({
|
||||
Architecture: z.string(),
|
||||
OS: z.string(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const PlacementSwarmSchema = z
|
||||
.object({
|
||||
Constraints: z.array(z.string()).optional(),
|
||||
Preferences: z.array(PreferenceSchema).optional(),
|
||||
MaxReplicas: z.number().optional(),
|
||||
Platforms: z.array(PlatformSchema).optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const UpdateConfigSwarmSchema = z
|
||||
.object({
|
||||
Parallelism: z.number(),
|
||||
Delay: z.number().optional(),
|
||||
FailureAction: z.string().optional(),
|
||||
Monitor: z.number().optional(),
|
||||
MaxFailureRatio: z.number().optional(),
|
||||
Order: z.string(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const ReplicatedSchema = z
|
||||
.object({
|
||||
Replicas: z.number().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const ReplicatedJobSchema = z
|
||||
.object({
|
||||
MaxConcurrent: z.number().optional(),
|
||||
TotalCompletions: z.number().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const ServiceModeSwarmSchema = z
|
||||
.object({
|
||||
Replicated: ReplicatedSchema.optional(),
|
||||
Global: z.object({}).optional(),
|
||||
ReplicatedJob: ReplicatedJobSchema.optional(),
|
||||
GlobalJob: z.object({}).optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
const NetworkSwarmSchema = z.array(
|
||||
z
|
||||
.object({
|
||||
Target: z.string().optional(),
|
||||
Aliases: z.array(z.string()).optional(),
|
||||
DriverOpts: z.object({}).optional(),
|
||||
})
|
||||
.strict(),
|
||||
);
|
||||
|
||||
const LabelsSwarmSchema = z.record(z.string());
|
||||
|
||||
const createStringToJSONSchema = (schema: z.ZodTypeAny) => {
|
||||
return z
|
||||
.string()
|
||||
.transform((str, ctx) => {
|
||||
if (str === null || str === "") {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
ctx.addIssue({ code: "custom", message: "Invalid JSON format" });
|
||||
return z.NEVER;
|
||||
}
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object.keys(data).length === 0) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Object cannot be empty",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const parseResult = schema.safeParse(data);
|
||||
if (!parseResult.success) {
|
||||
for (const error of parseResult.error.issues) {
|
||||
const path = error.path.join(".");
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `${path} ${error.message}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const addSwarmSettings = z.object({
|
||||
healthCheckSwarm: createStringToJSONSchema(HealthCheckSwarmSchema).nullable(),
|
||||
restartPolicySwarm: createStringToJSONSchema(
|
||||
RestartPolicySwarmSchema,
|
||||
).nullable(),
|
||||
placementSwarm: createStringToJSONSchema(PlacementSwarmSchema).nullable(),
|
||||
updateConfigSwarm: createStringToJSONSchema(
|
||||
UpdateConfigSwarmSchema,
|
||||
).nullable(),
|
||||
rollbackConfigSwarm: createStringToJSONSchema(
|
||||
UpdateConfigSwarmSchema,
|
||||
).nullable(),
|
||||
modeSwarm: createStringToJSONSchema(ServiceModeSwarmSchema).nullable(),
|
||||
labelsSwarm: createStringToJSONSchema(LabelsSwarmSchema).nullable(),
|
||||
networkSwarm: createStringToJSONSchema(NetworkSwarmSchema).nullable(),
|
||||
});
|
||||
|
||||
type AddSwarmSettings = z.infer<typeof addSwarmSettings>;
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export const AddSwarmSettings = ({ applicationId }: Props) => {
|
||||
const { data, refetch } = api.application.one.useQuery(
|
||||
{
|
||||
applicationId,
|
||||
},
|
||||
{
|
||||
enabled: !!applicationId,
|
||||
},
|
||||
);
|
||||
|
||||
const { mutateAsync, isError, error, isLoading } =
|
||||
api.application.update.useMutation();
|
||||
|
||||
const form = useForm<AddSwarmSettings>({
|
||||
defaultValues: {
|
||||
healthCheckSwarm: null,
|
||||
restartPolicySwarm: null,
|
||||
placementSwarm: null,
|
||||
updateConfigSwarm: null,
|
||||
rollbackConfigSwarm: null,
|
||||
modeSwarm: null,
|
||||
labelsSwarm: null,
|
||||
networkSwarm: null,
|
||||
},
|
||||
resolver: zodResolver(addSwarmSettings),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
form.reset({
|
||||
healthCheckSwarm: data.healthCheckSwarm
|
||||
? JSON.stringify(data.healthCheckSwarm, null, 2)
|
||||
: null,
|
||||
restartPolicySwarm: data.restartPolicySwarm
|
||||
? JSON.stringify(data.restartPolicySwarm, null, 2)
|
||||
: null,
|
||||
placementSwarm: data.placementSwarm
|
||||
? JSON.stringify(data.placementSwarm, null, 2)
|
||||
: null,
|
||||
updateConfigSwarm: data.updateConfigSwarm
|
||||
? JSON.stringify(data.updateConfigSwarm, null, 2)
|
||||
: null,
|
||||
rollbackConfigSwarm: data.rollbackConfigSwarm
|
||||
? JSON.stringify(data.rollbackConfigSwarm, null, 2)
|
||||
: null,
|
||||
modeSwarm: data.modeSwarm
|
||||
? JSON.stringify(data.modeSwarm, null, 2)
|
||||
: null,
|
||||
labelsSwarm: data.labelsSwarm
|
||||
? JSON.stringify(data.labelsSwarm, null, 2)
|
||||
: null,
|
||||
networkSwarm: data.networkSwarm
|
||||
? JSON.stringify(data.networkSwarm, null, 2)
|
||||
: null,
|
||||
});
|
||||
}
|
||||
}, [form, form.reset, data]);
|
||||
|
||||
const onSubmit = async (data: AddSwarmSettings) => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
healthCheckSwarm: data.healthCheckSwarm,
|
||||
restartPolicySwarm: data.restartPolicySwarm,
|
||||
placementSwarm: data.placementSwarm,
|
||||
updateConfigSwarm: data.updateConfigSwarm,
|
||||
rollbackConfigSwarm: data.rollbackConfigSwarm,
|
||||
modeSwarm: data.modeSwarm,
|
||||
labelsSwarm: data.labelsSwarm,
|
||||
networkSwarm: data.networkSwarm,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Swarm settings updated");
|
||||
refetch();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to update the swarm settings");
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="secondary" className="cursor-pointer w-fit">
|
||||
<Settings className="size-4 text-muted-foreground" />
|
||||
Swarm Settings
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-5xl p-0">
|
||||
<DialogHeader className="p-6">
|
||||
<DialogTitle>Swarm Settings</DialogTitle>
|
||||
<DialogDescription>
|
||||
Update certain settings using a json object.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
id="hook-form-add-permissions"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid grid-cols-1 md:grid-cols-2 w-full gap-4 relative"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="healthCheckSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pl-6 ">
|
||||
<FormLabel>Health Check</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Test?: string[] | undefined;
|
||||
Interval?: number | undefined;
|
||||
Timeout?: number | undefined;
|
||||
StartPeriod?: number | undefined;
|
||||
Retries?: number | undefined;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[11.2rem]"
|
||||
placeholder={`{
|
||||
"Test" : ["CMD-SHELL", "curl -f http://localhost:3000/health"],
|
||||
"Interval" : 10000,
|
||||
"Timeout" : 10000,
|
||||
"StartPeriod" : 10000,
|
||||
"Retries" : 10
|
||||
}`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="restartPolicySwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pr-6 ">
|
||||
<FormLabel>Restart Policy</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Condition?: string | undefined;
|
||||
Delay?: number | undefined;
|
||||
MaxAttempts?: number | undefined;
|
||||
Window?: number | undefined;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[11.2rem]"
|
||||
placeholder={`{
|
||||
"Condition" : "on-failure",
|
||||
"Delay" : 10000,
|
||||
"MaxAttempts" : 10,
|
||||
"Window" : 10000
|
||||
} `}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="placementSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pl-6 ">
|
||||
<FormLabel>Placement</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Constraints?: string[] | undefined;
|
||||
Preferences?: Array<{ Spread: { SpreadDescriptor: string } }> | undefined;
|
||||
MaxReplicas?: number | undefined;
|
||||
Platforms?:
|
||||
| Array<{
|
||||
Architecture: string;
|
||||
OS: string;
|
||||
}>
|
||||
| undefined;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[18.7rem]"
|
||||
placeholder={`{
|
||||
"Constraints" : ["node.role==manager"],
|
||||
"Preferences" : [{
|
||||
"Spread" : {
|
||||
"SpreadDescriptor" : "node.labels.region"
|
||||
}
|
||||
}],
|
||||
"MaxReplicas" : 10,
|
||||
"Platforms" : [{
|
||||
"Architecture" : "amd64",
|
||||
"OS" : "linux"
|
||||
}]
|
||||
} `}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="updateConfigSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pr-6 ">
|
||||
<FormLabel>Update Config</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Parallelism?: number;
|
||||
Delay?: number | undefined;
|
||||
FailureAction?: string | undefined;
|
||||
Monitor?: number | undefined;
|
||||
MaxFailureRatio?: number | undefined;
|
||||
Order: string;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[18.7rem]"
|
||||
placeholder={`{
|
||||
"Parallelism" : 1,
|
||||
"Delay" : 10000,
|
||||
"FailureAction" : "continue",
|
||||
"Monitor" : 10000,
|
||||
"MaxFailureRatio" : 10,
|
||||
"Order" : "start-first"
|
||||
}`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="rollbackConfigSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pl-6 ">
|
||||
<FormLabel>Rollback Config</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Parallelism?: number;
|
||||
Delay?: number | undefined;
|
||||
FailureAction?: string | undefined;
|
||||
Monitor?: number | undefined;
|
||||
MaxFailureRatio?: number | undefined;
|
||||
Order: string;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[14.8rem]"
|
||||
placeholder={`{
|
||||
"Parallelism" : 1,
|
||||
"Delay" : 10000,
|
||||
"FailureAction" : "continue",
|
||||
"Monitor" : 10000,
|
||||
"MaxFailureRatio" : 10,
|
||||
"Order" : "start-first"
|
||||
}`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="modeSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pr-6 ">
|
||||
<FormLabel>Mode</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="center"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
Replicated?: { Replicas?: number | undefined } | undefined;
|
||||
Global?: {} | undefined;
|
||||
ReplicatedJob?:
|
||||
| {
|
||||
MaxConcurrent?: number | undefined;
|
||||
TotalCompletions?: number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
GlobalJob?: {} | undefined;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[14.8rem]"
|
||||
placeholder={`{
|
||||
"Replicated" : {
|
||||
"Replicas" : 1
|
||||
},
|
||||
"Global" : {},
|
||||
"ReplicatedJob" : {
|
||||
"MaxConcurrent" : 1,
|
||||
"TotalCompletions" : 1
|
||||
},
|
||||
"GlobalJob" : {}
|
||||
}`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="networkSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pl-6 ">
|
||||
<FormLabel>Network</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`[
|
||||
{
|
||||
"Target" : string | undefined;
|
||||
"Aliases" : string[] | undefined;
|
||||
"DriverOpts" : { [key: string]: string } | undefined;
|
||||
}
|
||||
]`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[18.5rem]"
|
||||
placeholder={`[
|
||||
{
|
||||
"Target" : "dokploy-network",
|
||||
"Aliases" : ["dokploy-network"],
|
||||
"DriverOpts" : {
|
||||
"com.docker.network.driver.mtu" : "1500",
|
||||
"com.docker.network.driver.host_binding" : "true",
|
||||
"com.docker.network.driver.mtu" : "1500",
|
||||
"com.docker.network.driver.host_binding" : "true"
|
||||
}
|
||||
}
|
||||
]`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="labelsSwarm"
|
||||
render={({ field }) => (
|
||||
<FormItem className="relative max-lg:px-4 lg:pr-6 ">
|
||||
<FormLabel>Labels</FormLabel>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<FormDescription className="break-all w-fit flex flex-row gap-1 items-center">
|
||||
Check the interface
|
||||
<HelpCircle className="size-4 text-muted-foreground" />
|
||||
</FormDescription>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="w-full z-[999]"
|
||||
align="start"
|
||||
side="bottom"
|
||||
>
|
||||
<code>
|
||||
<pre>
|
||||
{`{
|
||||
[name: string]: string;
|
||||
}`}
|
||||
</pre>
|
||||
</code>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="font-mono [field-sizing:content;] min-h-[18.5rem]"
|
||||
placeholder={`{
|
||||
"com.example.app.name" : "my-app",
|
||||
"com.example.app.version" : "1.0.0"
|
||||
}`}
|
||||
{...field}
|
||||
value={field?.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<pre>
|
||||
<FormMessage />
|
||||
</pre>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<DialogFooter className="flex w-full flex-row justify-end md:col-span-2 m-0 sticky bottom-0 right-0 bg-muted border p-2 ">
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
form="hook-form-add-permissions"
|
||||
type="submit"
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,203 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { toast } from "sonner";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useEffect } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import Link from "next/link";
|
||||
import { Server } from "lucide-react";
|
||||
import { AddSwarmSettings } from "./modify-swarm-settings";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
const AddRedirectchema = z.object({
|
||||
replicas: z.number(),
|
||||
registryId: z.string(),
|
||||
});
|
||||
|
||||
type AddCommand = z.infer<typeof AddRedirectchema>;
|
||||
|
||||
export const ShowClusterSettings = ({ applicationId }: Props) => {
|
||||
const { data } = api.application.one.useQuery(
|
||||
{
|
||||
applicationId,
|
||||
},
|
||||
{ enabled: !!applicationId },
|
||||
);
|
||||
|
||||
const { data: registries } = api.registry.all.useQuery();
|
||||
|
||||
const utils = api.useUtils();
|
||||
|
||||
const { mutateAsync, isLoading } = api.application.update.useMutation();
|
||||
|
||||
const form = useForm<AddCommand>({
|
||||
defaultValues: {
|
||||
registryId: data?.registryId || "",
|
||||
replicas: data?.replicas || 1,
|
||||
},
|
||||
resolver: zodResolver(AddRedirectchema),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.command) {
|
||||
form.reset({
|
||||
registryId: data?.registryId || "",
|
||||
replicas: data?.replicas || 1,
|
||||
});
|
||||
}
|
||||
}, [form, form.reset, form.formState.isSubmitSuccessful, data?.command]);
|
||||
|
||||
const onSubmit = async (data: AddCommand) => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
registryId: data?.registryId === "none" ? null : data?.registryId,
|
||||
replicas: data?.replicas,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Command Updated");
|
||||
await utils.application.one.invalidate({
|
||||
applicationId,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to update the command");
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="bg-background">
|
||||
<CardHeader className="flex flex-row justify-between">
|
||||
<div>
|
||||
<CardTitle className="text-xl">Cluster Settings</CardTitle>
|
||||
<CardDescription>
|
||||
Add the registry and the replicas of the application
|
||||
</CardDescription>
|
||||
</div>
|
||||
<AddSwarmSettings applicationId={applicationId} />
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-4"
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="replicas"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Replicas</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="1"
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
field.onChange(Number(e.target.value));
|
||||
}}
|
||||
type="number"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{registries && registries?.length === 0 ? (
|
||||
<div className="pt-10">
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<Server className="size-8 text-muted-foreground" />
|
||||
<span className="text-base text-muted-foreground">
|
||||
To use a cluster feature, you need to configure at least a
|
||||
registry first. Please, go to{" "}
|
||||
<Link
|
||||
href="/dashboard/settings/cluster"
|
||||
className="text-foreground"
|
||||
>
|
||||
Settings
|
||||
</Link>{" "}
|
||||
to do so.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Select a registry</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a registry" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
{registries?.map((registry) => (
|
||||
<SelectItem
|
||||
key={registry.registryId}
|
||||
value={registry.registryId}
|
||||
>
|
||||
{registry.registryName}
|
||||
</SelectItem>
|
||||
))}
|
||||
<SelectItem value={"none"}>None</SelectItem>
|
||||
<SelectLabel>
|
||||
Registries ({registries?.length})
|
||||
</SelectLabel>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button isLoading={isLoading} type="submit" className="w-fit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -20,7 +20,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Pencil } from "lucide-react";
|
||||
import { PenBoxIcon, Pencil } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
@@ -99,7 +99,7 @@ export const UpdatePort = ({ portId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<Pencil className="size-4 text-muted-foreground" />
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Pencil } from "lucide-react";
|
||||
import { PenBoxIcon, Pencil } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
@@ -94,7 +94,7 @@ export const UpdateRedirect = ({ redirectId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<Pencil className="size-4 text-muted-foreground" />
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Pencil } from "lucide-react";
|
||||
import { PenBoxIcon, Pencil } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
@@ -89,7 +89,7 @@ export const UpdateSecurity = ({ securityId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<Pencil className="size-4 text-muted-foreground" />
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { api } from "@/utils/api";
|
||||
import { File } from "lucide-react";
|
||||
import { UpdateTraefikConfig } from "./update-traefik-config";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
@@ -43,11 +44,13 @@ export const ShowTraefikConfig = ({ applicationId }: Props) => {
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col pt-2 relative">
|
||||
<div className="flex flex-col gap-6 bg-input p-4 rounded-md max-h-[35rem] min-h-[10rem] overflow-y-auto">
|
||||
<div>
|
||||
<pre className="font-sans">{data || "Empty"}</pre>
|
||||
</div>
|
||||
<div className="flex justify-end absolute z-50 right-6">
|
||||
<div className="flex flex-col gap-6 max-h-[35rem] min-h-[10rem] overflow-y-auto">
|
||||
<CodeEditor
|
||||
value={data || "Empty"}
|
||||
disabled
|
||||
className="font-mono"
|
||||
/>
|
||||
<div className="flex justify-end absolute z-50 right-6 top-6">
|
||||
<UpdateTraefikConfig applicationId={applicationId} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -25,6 +24,7 @@ import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import jsyaml from "js-yaml";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
|
||||
const UpdateTraefikConfigSchema = z.object({
|
||||
traefikConfig: z.string(),
|
||||
@@ -122,7 +122,7 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
||||
<form
|
||||
id="hook-form-update-traefik-config"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full py-4"
|
||||
className="grid w-full py-4 overflow-auto"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<FormField
|
||||
@@ -132,8 +132,8 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
||||
<FormItem>
|
||||
<FormLabel>Traefik config</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="h-[35rem] font-mono"
|
||||
<CodeEditor
|
||||
wrapperClassName="h-[35rem] font-mono"
|
||||
placeholder={`http:
|
||||
routers:
|
||||
router-name:
|
||||
|
||||
@@ -25,8 +25,8 @@ export const DeleteApplication = ({ applicationId }: Props) => {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
|
||||
@@ -24,8 +24,8 @@ export const DeleteDomain = ({ domainId }: Props) => {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
|
||||
@@ -40,7 +40,9 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
</div>
|
||||
|
||||
{data && data?.length > 0 && (
|
||||
<AddDomain applicationId={applicationId} />
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent className="flex w-full flex-row gap-4">
|
||||
@@ -51,7 +53,9 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
To access to the application is required to set at least 1
|
||||
domain
|
||||
</span>
|
||||
<AddDomain applicationId={applicationId}>Add Domain</AddDomain>
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
@@ -75,8 +79,10 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
<Button variant="outline" disabled>
|
||||
{item.https ? "HTTPS" : "HTTP"}
|
||||
</Button>
|
||||
<UpdateDomain domainId={item.domainId} />
|
||||
<DeleteDomain domainId={item.domainId} />
|
||||
<div className="flex flex-row gap-1">
|
||||
<UpdateDomain domainId={item.domainId} />
|
||||
<DeleteDomain domainId={item.domainId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -115,8 +115,8 @@ export const UpdateDomain = ({ domainId }: Props) => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger className="" asChild>
|
||||
<Button>
|
||||
<PenBoxIcon className="size-4" />
|
||||
<Button variant="ghost">
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdateApplication = ({ applicationId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Pencil, CheckIcon, ChevronsUpDown } from "lucide-react";
|
||||
import { Pencil, CheckIcon, ChevronsUpDown, PenBoxIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
@@ -115,7 +115,7 @@ export const UpdateBackup = ({ backupId, refetch }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<Pencil className="size-4 text-muted-foreground" />
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -9,16 +9,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
|
||||
const UpdateServerMiddlewareConfigSchema = z.object({
|
||||
traefikConfig: z.string(),
|
||||
@@ -88,13 +87,12 @@ export const ShowTraefikFile = ({ path }: Props) => {
|
||||
return (
|
||||
<div>
|
||||
{isError && <AlertBlock type="error">{error?.message}</AlertBlock>}
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full relative"
|
||||
className="grid w-full relative z-[5]"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col overflow-auto">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="traefikConfig"
|
||||
@@ -105,8 +103,8 @@ export const ShowTraefikFile = ({ path }: Props) => {
|
||||
{path}
|
||||
</FormDescription>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="h-[35rem] font-mono"
|
||||
<CodeEditor
|
||||
wrapperClassName="h-[35rem] font-mono"
|
||||
placeholder={`http:
|
||||
routers:
|
||||
router-name:
|
||||
|
||||
@@ -14,7 +14,7 @@ export const ShowTraefikSystem = () => {
|
||||
|
||||
return (
|
||||
<div className={cn("mt-6 md:grid gap-4")}>
|
||||
<div className="flex flex-col md:flex-row gap-4 md:gap-10 w-full">
|
||||
<div className="flex flex-col lg:flex-row gap-4 md:gap-10 w-full">
|
||||
{directories?.length === 0 && (
|
||||
<div className="w-full flex-col gap-2 flex items-center justify-center h-[55vh]">
|
||||
<span className="text-muted-foreground text-lg font-medium">
|
||||
@@ -27,7 +27,7 @@ export const ShowTraefikSystem = () => {
|
||||
<>
|
||||
<Tree
|
||||
data={directories}
|
||||
className="md:max-w-[19rem] w-full md:h-[660px] border rounded-lg"
|
||||
className="lg:max-w-[19rem] w-full lg:h-[660px] border rounded-lg"
|
||||
onSelectChange={(item) => setFile(item?.id || null)}
|
||||
folderIcon={Folder}
|
||||
itemIcon={Workflow}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -16,47 +16,47 @@ import { useRouter } from "next/router";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mariadbId: string;
|
||||
mariadbId: string;
|
||||
}
|
||||
|
||||
export const DeleteMariadb = ({ mariadbId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mariadb.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mariadb.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdateMariadb = ({ mariadbId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -16,47 +16,47 @@ import { useRouter } from "next/router";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mongoId: string;
|
||||
mongoId: string;
|
||||
}
|
||||
|
||||
export const DeleteMongo = ({ mongoId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mongo.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mongoId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mongo.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mongoId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdateMongo = ({ mongoId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -16,47 +16,47 @@ import { useRouter } from "next/router";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mysqlId: string;
|
||||
mysqlId: string;
|
||||
}
|
||||
|
||||
export const DeleteMysql = ({ mysqlId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mysql.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mysqlId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mysql.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mysqlId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdateMysql = ({ mysqlId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -16,47 +16,47 @@ import { useRouter } from "next/router";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
postgresId: string;
|
||||
postgresId: string;
|
||||
}
|
||||
|
||||
export const DeletePostgres = ({ postgresId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.postgres.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
postgresId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.postgres.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
postgresId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdatePostgres = ({ postgresId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -89,9 +89,9 @@ export const ShowProjects = () => {
|
||||
<span className="flex flex-col gap-1.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<BookIcon className="size-4 text-muted-foreground" />
|
||||
<span className="text-base font-medium leading-none">
|
||||
<Link className="text-base font-medium leading-none" href={`/dashboard/project/${project.projectId}`}>
|
||||
{project.name}
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<span className="text-sm font-medium text-muted-foreground">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -16,47 +16,47 @@ import { useRouter } from "next/router";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
redisId: string;
|
||||
redisId: string;
|
||||
}
|
||||
|
||||
export const DeleteRedis = ({ redisId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.redis.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
redisId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.redis.remove.useMutation();
|
||||
const { push } = useRouter();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
redisId,
|
||||
})
|
||||
.then((data) => {
|
||||
push(`/dashboard/project/${data?.projectId}`);
|
||||
toast.success("Database delete succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export const UpdateRedis = ({ redisId }: Props) => {
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<SquarePen className="size-4" />
|
||||
<SquarePen className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-lg">
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
|
||||
const appearanceFormSchema = z.object({
|
||||
theme: z.enum(["light", "dark"], {
|
||||
theme: z.enum(["light", "dark", "system"], {
|
||||
required_error: "Please select a theme.",
|
||||
}),
|
||||
});
|
||||
@@ -34,7 +34,7 @@ type AppearanceFormValues = z.infer<typeof appearanceFormSchema>;
|
||||
|
||||
// This can come from your database or API.
|
||||
const defaultValues: Partial<AppearanceFormValues> = {
|
||||
theme: "light",
|
||||
theme: "system",
|
||||
};
|
||||
|
||||
export function AppearanceForm() {
|
||||
@@ -46,7 +46,7 @@ export function AppearanceForm() {
|
||||
|
||||
useEffect(() => {
|
||||
form.reset({
|
||||
theme: theme === "light" ? "light" : "dark",
|
||||
theme: (theme ?? "system") as AppearanceFormValues["theme"],
|
||||
});
|
||||
}, [form, theme]);
|
||||
function onSubmit(data: AppearanceFormValues) {
|
||||
@@ -81,28 +81,15 @@ export function AppearanceForm() {
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value}
|
||||
value={field.value}
|
||||
className="grid max-w-md grid-cols-1 sm:grid-cols-2 gap-8 pt-2"
|
||||
className="grid max-w-md md:max-w-lg grid-cols-1 sm:grid-cols-3 gap-8 pt-2"
|
||||
>
|
||||
<FormItem>
|
||||
<FormLabel className="[&:has([data-state=checked])>div]:border-primary">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="light" className="sr-only" />
|
||||
</FormControl>
|
||||
<div className="items-center rounded-md border-2 border-muted p-1 hover:border-accent">
|
||||
<div className="space-y-2 rounded-sm bg-[#ecedef] p-2">
|
||||
<div className="space-y-2 rounded-md bg-white p-2 shadow-sm">
|
||||
<div className="h-2 w-[80px] rounded-lg bg-[#ecedef]" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm">
|
||||
<div className="h-4 w-4 rounded-full bg-[#ecedef]" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm">
|
||||
<div className="h-4 w-4 rounded-full bg-[#ecedef]" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="items-center rounded-md border-2 border-muted p-1 hover:bg-accent transition-colors cursor-pointer">
|
||||
<img src="/images/theme-light.svg" alt="light" />
|
||||
</div>
|
||||
<span className="block w-full p-2 text-center font-normal">
|
||||
Light
|
||||
@@ -114,27 +101,30 @@ export function AppearanceForm() {
|
||||
<FormControl>
|
||||
<RadioGroupItem value="dark" className="sr-only" />
|
||||
</FormControl>
|
||||
<div className="items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground">
|
||||
<div className="space-y-2 rounded-sm bg-slate-950 p-2">
|
||||
<div className="space-y-2 rounded-md bg-slate-800 p-2 shadow-sm">
|
||||
<div className="h-2 w-[80px] rounded-lg bg-slate-400" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-slate-400" />
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm">
|
||||
<div className="h-4 w-4 rounded-full bg-slate-400" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-slate-400" />
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm">
|
||||
<div className="h-4 w-4 rounded-full bg-slate-400" />
|
||||
<div className="h-2 w-[100px] rounded-lg bg-slate-400" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="items-center rounded-md border-2 border-muted bg-popover p-1 transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer">
|
||||
<img src="/images/theme-dark.svg" alt="dark" />
|
||||
</div>
|
||||
<span className="block w-full p-2 text-center font-normal">
|
||||
Dark
|
||||
</span>
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<FormLabel className="[&:has([data-state=checked])>div]:border-primary">
|
||||
<FormControl>
|
||||
<RadioGroupItem
|
||||
value="system"
|
||||
className="sr-only"
|
||||
/>
|
||||
</FormControl>
|
||||
<div className="items-center rounded-md border-2 border-muted bg-popover p-1 transition-colors hover:bg-accent hover:text-accent-foreground cursor-pointer">
|
||||
<img src="/images/theme-system.svg" alt="system" />
|
||||
</div>
|
||||
<span className="block w-full p-2 text-center font-normal">
|
||||
System
|
||||
</span>
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
);
|
||||
|
||||
@@ -33,21 +33,23 @@ export const ShowCertificates = () => {
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-6">
|
||||
{data?.map((destination, index) => (
|
||||
<div
|
||||
key={destination.certificateId}
|
||||
className="flex items-center justify-between"
|
||||
>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{index + 1}. {destination.name}
|
||||
</span>
|
||||
<div className="flex flex-row gap-3">
|
||||
<DeleteCertificate
|
||||
certificateId={destination.certificateId}
|
||||
/>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
{data?.map((destination, index) => (
|
||||
<div
|
||||
key={destination.certificateId}
|
||||
className="flex items-center justify-between border p-4 rounded-lg"
|
||||
>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{index + 1}. {destination.name}
|
||||
</span>
|
||||
<div className="flex flex-row gap-3">
|
||||
<DeleteCertificate
|
||||
certificateId={destination.certificateId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<AddCertificate />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ExternalLink, PlusIcon } from "lucide-react";
|
||||
import { AddWorker } from "./workers/add-worker";
|
||||
import { AddManager } from "./manager/add-manager";
|
||||
import Link from "next/link";
|
||||
|
||||
export const AddNode = () => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="w-full cursor-pointer space-x-3">
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Node
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-4xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Node</DialogTitle>
|
||||
<DialogDescription className="flex flex-col gap-2">
|
||||
Follow the steps to add a new node to your cluster, before you start
|
||||
using this feature, you need to understand how docker swarm works.{" "}
|
||||
<Link
|
||||
href="https://docs.docker.com/engine/swarm/"
|
||||
target="_blank"
|
||||
className="text-primary flex flex-row gap-2 items-center"
|
||||
>
|
||||
Docker Swarm
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
href="https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/"
|
||||
target="_blank"
|
||||
className="text-primary flex flex-row gap-2 items-center"
|
||||
>
|
||||
Architecture
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</Link>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Tabs defaultValue="worker">
|
||||
<TabsList>
|
||||
<TabsTrigger value="worker">Worker</TabsTrigger>
|
||||
<TabsTrigger value="manager">Manager</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="worker" className="pt-4">
|
||||
<AddWorker />
|
||||
</TabsContent>
|
||||
<TabsContent value="manager" className="pt-4">
|
||||
<AddManager />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
import { CopyIcon } from "lucide-react";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export const AddManager = () => {
|
||||
const { data } = api.cluster.addManager.useQuery();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a new manager</DialogTitle>
|
||||
<DialogDescription>Add a new manager</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-2.5 text-sm">
|
||||
<span>1. Go to your new server and run the following command</span>
|
||||
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
||||
curl https://get.docker.com | sh -s -- --version 24.0
|
||||
<button
|
||||
type="button"
|
||||
className="self-center"
|
||||
onClick={() => {
|
||||
copy("curl https://get.docker.com | sh -s -- --version 24.0");
|
||||
toast.success("Copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2.5 text-sm">
|
||||
<span>
|
||||
2. Run the following command to add the node(manager) to your
|
||||
cluster
|
||||
</span>
|
||||
<span className="bg-muted rounded-lg p-2 flex">
|
||||
{data}
|
||||
<button
|
||||
type="button"
|
||||
className="self-start"
|
||||
onClick={() => {
|
||||
copy(data || "");
|
||||
toast.success("Copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
|
||||
interface Props {
|
||||
data: unknown;
|
||||
}
|
||||
|
||||
export const ShowNodeData = ({ data }: Props) => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer"
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
View Config
|
||||
</DropdownMenuItem>
|
||||
</DialogTrigger>
|
||||
<DialogContent className={"sm:max-w-5xl overflow-y-auto max-h-screen"}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Node Config</DialogTitle>
|
||||
<DialogDescription>
|
||||
See in detail the metadata of this node
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="text-wrap rounded-lg border p-4 text-sm sm:max-w-[59rem] bg-card">
|
||||
<code>
|
||||
<pre className="whitespace-pre-wrap break-words">
|
||||
{JSON.stringify(data, null, 2)}
|
||||
</pre>
|
||||
</code>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,162 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { DateTooltip } from "@/components/shared/date-tooltip";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { DeleteWorker } from "./workers/delete-worker";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { HelpCircle, LockIcon, MoreHorizontal } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { ShowNodeData } from "./show-node-data";
|
||||
import { AddNode } from "./add-node";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
|
||||
export const ShowNodes = () => {
|
||||
const { data, isLoading } = api.cluster.getNodes.useQuery();
|
||||
const { data: registry } = api.registry.all.useQuery();
|
||||
|
||||
const haveAtLeastOneRegistry = !!(registry && registry?.length > 0);
|
||||
return (
|
||||
<Card className="bg-transparent h-full">
|
||||
<CardHeader className="flex flex-row gap-2 justify-between w-full items-center flex-wrap">
|
||||
<div className="flex flex-col gap-2">
|
||||
<CardTitle className="text-xl">Cluster</CardTitle>
|
||||
<CardDescription>Add nodes to your cluster</CardDescription>
|
||||
</div>
|
||||
{haveAtLeastOneRegistry && (
|
||||
<div className="flex flex-row gap-2">
|
||||
<AddNode />
|
||||
</div>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{haveAtLeastOneRegistry ? (
|
||||
<div className="grid md:grid-cols-1 gap-4">
|
||||
{isLoading && <div>Loading...</div>}
|
||||
<Table>
|
||||
<TableCaption>A list of your managers / workers.</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Hostname</TableHead>
|
||||
<TableHead className="text-right">Status</TableHead>
|
||||
<TableHead className="text-right">Role</TableHead>
|
||||
<TableHead className="text-right">Availability</TableHead>
|
||||
<TableHead className="text-right">Engine Version</TableHead>
|
||||
<TableHead className="text-right">Created</TableHead>
|
||||
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{data?.map((node) => {
|
||||
const isManager = node.Spec.Role === "manager";
|
||||
return (
|
||||
<TableRow key={node.ID}>
|
||||
<TableCell className="w-[100px]">
|
||||
{node.Description.Hostname}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{node.Status.State}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<Badge variant={isManager ? "default" : "secondary"}>
|
||||
{node?.Spec?.Role}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{node.Spec.Availability}
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="text-right">
|
||||
{node?.Description.Engine.EngineVersion}
|
||||
</TableCell>
|
||||
|
||||
<TableCell className="text-right">
|
||||
<DateTooltip date={node.CreatedAt} className="text-sm">
|
||||
Created{" "}
|
||||
</DateTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="text-right flex justify-end">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<ShowNodeData data={node} />
|
||||
{!node?.ManagerStatus?.Leader && (
|
||||
<DeleteWorker nodeId={node.ID} />
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<LockIcon className="size-8 text-muted-foreground" />
|
||||
<div className="flex flex-row gap-2">
|
||||
<span className="text-base text-muted-foreground ">
|
||||
To add nodes to your cluster, you need to configure at least one
|
||||
registry.
|
||||
</span>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger className="self-center">
|
||||
<HelpCircle className="size-5 text-muted-foreground " />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Nodes need a registry to pull images from.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
|
||||
<ul className="list-disc list-inside text-sm text-muted-foreground border p-4 rounded-lg flex flex-col gap-1.5 mt-2.5">
|
||||
<li>
|
||||
<strong>Docker Registry:</strong> Use custom registries like
|
||||
Docker Hub, DigitalOcean Registry, etc.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Self-Hosted Docker Registry:</strong> Automatically set
|
||||
up a local registry to store all images.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
import {
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { CopyIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export const AddWorker = () => {
|
||||
const { data } = api.cluster.addWorker.useQuery();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CardContent className="sm:max-w-4xl max-h-screen overflow-y-auto flex flex-col gap-4 px-0">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a new worker</DialogTitle>
|
||||
<DialogDescription>Add a new worker</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-2.5 text-sm">
|
||||
<span>1. Go to your new server and run the following command</span>
|
||||
<span className="bg-muted rounded-lg p-2 flex justify-between">
|
||||
curl https://get.docker.com | sh -s -- --version 24.0
|
||||
<button
|
||||
type="button"
|
||||
className="self-center"
|
||||
onClick={() => {
|
||||
copy("curl https://get.docker.com | sh -s -- --version 24.0");
|
||||
toast.success("Copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2.5 text-sm">
|
||||
<span>
|
||||
2. Run the following command to add the node(worker) to your cluster
|
||||
</span>
|
||||
|
||||
<span className="bg-muted rounded-lg p-2 flex">
|
||||
{data}
|
||||
<button
|
||||
type="button"
|
||||
className="self-start"
|
||||
onClick={() => {
|
||||
copy(data || "");
|
||||
toast.success("Copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<CopyIcon className="h-4 w-4 cursor-pointer" />
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
|
||||
interface Props {
|
||||
nodeId: string;
|
||||
}
|
||||
export const DeleteWorker = ({ nodeId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.cluster.removeWorker.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<DropdownMenuItem onSelect={(e) => e.preventDefault()}>
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
worker.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
nodeId,
|
||||
})
|
||||
.then(async () => {
|
||||
utils.cluster.getNodes.invalidate();
|
||||
toast.success("Worker deleted succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the worker");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,251 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { AlertTriangle, Container } from "lucide-react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const AddRegistrySchema = z.object({
|
||||
registryName: z.string().min(1, {
|
||||
message: "Registry name is required",
|
||||
}),
|
||||
username: z.string().min(1, {
|
||||
message: "Username is required",
|
||||
}),
|
||||
password: z.string().min(1, {
|
||||
message: "Password is required",
|
||||
}),
|
||||
registryUrl: z.string().min(1, {
|
||||
message: "Registry URL is required",
|
||||
}),
|
||||
imagePrefix: z.string(),
|
||||
});
|
||||
|
||||
type AddRegistry = z.infer<typeof AddRegistrySchema>;
|
||||
|
||||
export const AddRegistry = () => {
|
||||
const utils = api.useUtils();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { mutateAsync, error, isError } = api.registry.create.useMutation();
|
||||
const { mutateAsync: testRegistry, isLoading } =
|
||||
api.registry.testRegistry.useMutation();
|
||||
const router = useRouter();
|
||||
const form = useForm<AddRegistry>({
|
||||
defaultValues: {
|
||||
username: "",
|
||||
password: "",
|
||||
registryUrl: "",
|
||||
imagePrefix: "",
|
||||
registryName: "",
|
||||
},
|
||||
resolver: zodResolver(AddRegistrySchema),
|
||||
});
|
||||
|
||||
const password = form.watch("password");
|
||||
const username = form.watch("username");
|
||||
const registryUrl = form.watch("registryUrl");
|
||||
const registryName = form.watch("registryName");
|
||||
const imagePrefix = form.watch("imagePrefix");
|
||||
|
||||
useEffect(() => {
|
||||
form.reset({
|
||||
username: "",
|
||||
password: "",
|
||||
registryUrl: "",
|
||||
imagePrefix: "",
|
||||
});
|
||||
}, [form, form.reset, form.formState.isSubmitSuccessful]);
|
||||
|
||||
const onSubmit = async (data: AddRegistry) => {
|
||||
await mutateAsync({
|
||||
password: data.password,
|
||||
registryName: data.registryName,
|
||||
username: data.username,
|
||||
registryUrl: data.registryUrl,
|
||||
registryType: "cloud",
|
||||
imagePrefix: data.imagePrefix,
|
||||
})
|
||||
.then(async (data) => {
|
||||
await utils.registry.all.invalidate();
|
||||
toast.success("Registry added");
|
||||
setIsOpen(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to add a registry");
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button>
|
||||
<Container className="h-4 w-4" />
|
||||
Create Registry
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:m:max-w-lg ">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a external registry</DialogTitle>
|
||||
<DialogDescription>
|
||||
Fill the next fields to add a external registry.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{isError && (
|
||||
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||
<span className="text-sm text-red-600 dark:text-red-400">
|
||||
{error?.message}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-4"
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Registry Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Registry Name" {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="username"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Username" {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Password"
|
||||
{...field}
|
||||
type="password"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="imagePrefix"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Image Prefix</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="Image Prefix" />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Registry URL</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="aws_account_id.dkr.ecr.us-west-2.amazonaws.com"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter className="flex flex-row w-full sm:justify-between gap-4 flex-wrap">
|
||||
<Button
|
||||
type="button"
|
||||
variant={"secondary"}
|
||||
isLoading={isLoading}
|
||||
onClick={async () => {
|
||||
await testRegistry({
|
||||
username: username,
|
||||
password: password,
|
||||
registryUrl: registryUrl,
|
||||
registryName: registryName,
|
||||
registryType: "cloud",
|
||||
imagePrefix: imagePrefix,
|
||||
})
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
toast.success("Registry Tested Successfully");
|
||||
} else {
|
||||
toast.error("Registry Test Failed");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to test the registry");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Test Registry
|
||||
</Button>
|
||||
<Button isLoading={form.formState.isSubmitting} type="submit">
|
||||
Create
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { AlertTriangle, Container } from "lucide-react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const AddRegistrySchema = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: "Username is required",
|
||||
})
|
||||
.regex(/^[a-zA-Z0-9]+$/, {
|
||||
message: "Username can only contain letters and numbers",
|
||||
}),
|
||||
password: z.string().min(1, {
|
||||
message: "Password is required",
|
||||
}),
|
||||
registryUrl: z.string().min(1, {
|
||||
message: "Registry URL is required",
|
||||
}),
|
||||
});
|
||||
|
||||
type AddRegistry = z.infer<typeof AddRegistrySchema>;
|
||||
|
||||
export const AddSelfHostedRegistry = () => {
|
||||
const utils = api.useUtils();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { mutateAsync, error, isError, isLoading } =
|
||||
api.registry.enableSelfHostedRegistry.useMutation();
|
||||
const router = useRouter();
|
||||
const form = useForm<AddRegistry>({
|
||||
defaultValues: {
|
||||
username: "",
|
||||
password: "",
|
||||
registryUrl: "",
|
||||
},
|
||||
resolver: zodResolver(AddRegistrySchema),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
form.reset({
|
||||
registryUrl: "",
|
||||
username: "",
|
||||
password: "",
|
||||
});
|
||||
}, [form, form.reset, form.formState.isSubmitSuccessful]);
|
||||
|
||||
const onSubmit = async (data: AddRegistry) => {
|
||||
await mutateAsync({
|
||||
registryUrl: data.registryUrl,
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
})
|
||||
.then(async (data) => {
|
||||
await utils.registry.all.invalidate();
|
||||
toast.success("Self Hosted Registry Created");
|
||||
setIsOpen(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to create a self hosted registry");
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button>
|
||||
<Container className="h-4 w-4" />
|
||||
Enable Self Hosted Registry
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:m:max-w-lg ">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add a self hosted registry</DialogTitle>
|
||||
<DialogDescription>
|
||||
Fill the next fields to add a self hosted registry.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{isError && (
|
||||
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||
<span className="text-sm text-red-600 dark:text-red-400">
|
||||
{error?.message}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-4"
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="username"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Username" {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Password"
|
||||
{...field}
|
||||
type="password"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Registry URL</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="registry.dokploy.com" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Point a DNS record to the VPS IP address.
|
||||
</FormDescription>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button isLoading={isLoading} type="submit">
|
||||
Create
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
registryId: string;
|
||||
}
|
||||
export const DeleteRegistry = ({ registryId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.registry.remove.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete the
|
||||
registry.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
registryId,
|
||||
})
|
||||
.then(async () => {
|
||||
utils.registry.all.invalidate();
|
||||
toast.success("Registry deleted");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to delete the registry");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { Server } from "lucide-react";
|
||||
import { AddRegistry } from "./add-docker-registry";
|
||||
import { AddSelfHostedRegistry } from "./add-self-docker-registry";
|
||||
import { DeleteRegistry } from "./delete-registry";
|
||||
import { UpdateDockerRegistry } from "./update-docker-registry";
|
||||
|
||||
export const ShowRegistry = () => {
|
||||
const { data } = api.registry.all.useQuery();
|
||||
|
||||
const haveSelfHostedRegistry = data?.some(
|
||||
(registry) => registry.registryType === "selfHosted",
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="h-full">
|
||||
<Card className="bg-transparent h-full">
|
||||
<CardHeader className="flex flex-row gap-2 flex-wrap justify-between w-full items-center">
|
||||
<div className="flex flex-col gap-2">
|
||||
<CardTitle className="text-xl">Registry</CardTitle>
|
||||
<CardDescription>Add registry to your application.</CardDescription>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row gap-2">
|
||||
{data && data?.length > 0 && (
|
||||
<>
|
||||
{!haveSelfHostedRegistry && <AddSelfHostedRegistry />}
|
||||
|
||||
<AddRegistry />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 pt-4 h-full">
|
||||
{data?.length === 0 ? (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<Server className="size-8 self-center text-muted-foreground" />
|
||||
<span className="text-base text-muted-foreground">
|
||||
To create a cluster is required to set a registry.
|
||||
</span>
|
||||
|
||||
<div className="flex flex-row gap-2">
|
||||
<AddSelfHostedRegistry />
|
||||
<AddRegistry />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 gap-6">
|
||||
{data?.map((registry, index) => (
|
||||
<div
|
||||
key={registry.registryId}
|
||||
className="flex items-center justify-between border p-4 rounded-lg"
|
||||
>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{index + 1}. {registry.registryName}
|
||||
</span>
|
||||
<div className="flex flex-row gap-1">
|
||||
<UpdateDockerRegistry registryId={registry.registryId} />
|
||||
<DeleteRegistry registryId={registry.registryId} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,275 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { AlertTriangle, PenBoxIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const updateRegistry = z.object({
|
||||
registryName: z.string().min(1, {
|
||||
message: "Registry name is required",
|
||||
}),
|
||||
username: z.string().min(1, {
|
||||
message: "Username is required",
|
||||
}),
|
||||
password: z.string(),
|
||||
registryUrl: z.string().min(1, {
|
||||
message: "Registry URL is required",
|
||||
}),
|
||||
imagePrefix: z.string(),
|
||||
});
|
||||
|
||||
type UpdateRegistry = z.infer<typeof updateRegistry>;
|
||||
|
||||
interface Props {
|
||||
registryId: string;
|
||||
}
|
||||
|
||||
export const UpdateDockerRegistry = ({ registryId }: Props) => {
|
||||
const utils = api.useUtils();
|
||||
const { mutateAsync: testRegistry, isLoading } =
|
||||
api.registry.testRegistry.useMutation();
|
||||
const { data, refetch } = api.registry.one.useQuery(
|
||||
{
|
||||
registryId,
|
||||
},
|
||||
{
|
||||
enabled: !!registryId,
|
||||
},
|
||||
);
|
||||
|
||||
const isCloud = data?.registryType === "cloud";
|
||||
const { mutateAsync, isError, error } = api.registry.update.useMutation();
|
||||
|
||||
const form = useForm<UpdateRegistry>({
|
||||
defaultValues: {
|
||||
imagePrefix: "",
|
||||
registryName: "",
|
||||
username: "",
|
||||
password: "",
|
||||
registryUrl: "",
|
||||
},
|
||||
resolver: zodResolver(updateRegistry),
|
||||
});
|
||||
|
||||
const password = form.watch("password");
|
||||
const username = form.watch("username");
|
||||
const registryUrl = form.watch("registryUrl");
|
||||
const registryName = form.watch("registryName");
|
||||
const imagePrefix = form.watch("imagePrefix");
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
form.reset({
|
||||
imagePrefix: data.imagePrefix || "",
|
||||
registryName: data.registryName || "",
|
||||
username: data.username || "",
|
||||
password: "",
|
||||
registryUrl: data.registryUrl || "",
|
||||
});
|
||||
}
|
||||
}, [form, form.reset, data]);
|
||||
|
||||
const onSubmit = async (data: UpdateRegistry) => {
|
||||
await mutateAsync({
|
||||
registryId,
|
||||
...(data.password ? { password: data.password } : {}),
|
||||
registryName: data.registryName,
|
||||
username: data.username,
|
||||
registryUrl: data.registryUrl,
|
||||
imagePrefix: data.imagePrefix,
|
||||
})
|
||||
.then(async (data) => {
|
||||
toast.success("Registry Updated");
|
||||
await refetch();
|
||||
await utils.registry.all.invalidate();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to update the registry");
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger className="" asChild>
|
||||
<Button variant="ghost">
|
||||
<PenBoxIcon className="size-4 text-muted-foreground" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Registry</DialogTitle>
|
||||
<DialogDescription>Update the registry information</DialogDescription>
|
||||
</DialogHeader>
|
||||
{isError && (
|
||||
<div className="flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950">
|
||||
<AlertTriangle className="text-red-600 dark:text-red-400" />
|
||||
<span className="text-sm text-red-600 dark:text-red-400">
|
||||
{error?.message}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
id="hook-form"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-8 "
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Registry Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Registry Name" {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="username"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Username" {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="Password"
|
||||
{...field}
|
||||
type="password"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{isCloud && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="imagePrefix"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Image Prefix</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="Image Prefix" />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="registryUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Registry URL</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder="https://aws_account_id.dkr.ecr.us-west-2.amazonaws.com"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<DialogFooter
|
||||
className={cn(
|
||||
isCloud ? "sm:justify-between " : "",
|
||||
"flex flex-row w-full gap-4 flex-wrap",
|
||||
)}
|
||||
>
|
||||
{isCloud && (
|
||||
<Button
|
||||
type="button"
|
||||
variant={"secondary"}
|
||||
isLoading={isLoading}
|
||||
onClick={async () => {
|
||||
await testRegistry({
|
||||
username: username,
|
||||
password: password,
|
||||
registryUrl: registryUrl,
|
||||
registryName: registryName,
|
||||
registryType: "cloud",
|
||||
imagePrefix: imagePrefix,
|
||||
})
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
toast.success("Registry Tested Successfully");
|
||||
} else {
|
||||
toast.error("Registry Test Failed");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to test the registry");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Test Registry
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
isLoading={form.formState.isSubmitting}
|
||||
form="hook-form"
|
||||
type="submit"
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -34,16 +34,16 @@ export const ShowDestinations = () => {
|
||||
<AddDestination />
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
{data?.map((destination, index) => (
|
||||
<div
|
||||
key={destination.destinationId}
|
||||
className="flex items-center justify-between"
|
||||
className="flex items-center justify-between border p-3.5 rounded-lg"
|
||||
>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{index + 1}. {destination.name}
|
||||
</span>
|
||||
<div className="flex flex-row gap-3">
|
||||
<div className="flex flex-row gap-1">
|
||||
<UpdateDestination
|
||||
destinationId={destination.destinationId}
|
||||
/>
|
||||
|
||||
@@ -87,10 +87,10 @@ export const GithubSetup = () => {
|
||||
{haveGithubConfigured ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Github account configured succesfully.
|
||||
</span>
|
||||
<BadgeCheck className="size-5 text-green-700" />
|
||||
<BadgeCheck className="size-4 text-green-700" />
|
||||
</div>
|
||||
<div className="flex items-end">
|
||||
<RemoveGithubApp />
|
||||
@@ -101,9 +101,9 @@ export const GithubSetup = () => {
|
||||
{data?.githubAppName ? (
|
||||
<div className="flex w-fit flex-col gap-4">
|
||||
<span className="text-muted-foreground">
|
||||
Youve successfully created a GitHub app named
|
||||
{data.githubAppName}! The next step is to install this app in
|
||||
your GitHub account.
|
||||
You've successfully created a github app named{" "}
|
||||
<strong>{data.githubAppName}</strong>! The next step is to
|
||||
install this app in your GitHub account.
|
||||
</span>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
@@ -121,12 +121,12 @@ export const GithubSetup = () => {
|
||||
) : (
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-muted-foreground">
|
||||
To integrate your GitHub account with our services, youll
|
||||
<p className="text-muted-foreground text-sm">
|
||||
To integrate your GitHub account with our services, you'll
|
||||
need to create and install a GitHub app. This process is
|
||||
straightforward and only takes a few minutes. Click the
|
||||
button below to get started.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex flex-col gap-4">
|
||||
|
||||
@@ -147,11 +147,11 @@ export const ProfileForm = () => {
|
||||
}}
|
||||
defaultValue={field.value}
|
||||
value={field.value}
|
||||
className="flex flex-row flex-wrap gap-2 max-xl:justify-cente"
|
||||
className="flex flex-row flex-wrap gap-2 max-xl:justify-center"
|
||||
>
|
||||
{randomImages.map((image) => (
|
||||
<FormItem key={image}>
|
||||
<FormLabel className="[&:has([data-state=checked])>img]:border-primary [&:has([data-state=checked])>img]:border-1 [&:has([data-state=checked])>img]:p-px">
|
||||
<FormLabel className="[&:has([data-state=checked])>img]:border-primary [&:has([data-state=checked])>img]:border-1 [&:has([data-state=checked])>img]:p-px cursor-pointer">
|
||||
<FormControl>
|
||||
<RadioGroupItem
|
||||
value={image}
|
||||
@@ -163,7 +163,7 @@ export const ProfileForm = () => {
|
||||
key={image}
|
||||
src={image}
|
||||
alt="avatar"
|
||||
className="h-12 w-12 rounded-full border transition-transform"
|
||||
className="h-12 w-12 rounded-full border hover:p-px hover:border-primary transition-transform"
|
||||
/>
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
|
||||
@@ -23,11 +23,11 @@ import { extractServices } from "@/pages/dashboard/project/[projectId]";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { ListTodo } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
|
||||
const addPermissions = z.object({
|
||||
accesedProjects: z.array(z.string()).optional(),
|
||||
@@ -107,9 +107,12 @@ export const AddUserPermissions = ({ userId }: Props) => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger className="" asChild>
|
||||
<Button variant="ghost">
|
||||
<ListTodo className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer"
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
Add Permissions
|
||||
</DropdownMenuItem>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-4xl">
|
||||
<DialogHeader>
|
||||
|
||||
@@ -25,6 +25,7 @@ import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
|
||||
const addUser = z.object({
|
||||
email: z
|
||||
@@ -66,7 +67,9 @@ export const AddUser = () => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger className="" asChild>
|
||||
<Button>Add User</Button>
|
||||
<Button>
|
||||
<PlusIcon className="h-4 w-4" /> Add User
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
|
||||
interface Props {
|
||||
authId: string;
|
||||
@@ -24,9 +25,12 @@ export const DeleteUser = ({ authId }: Props) => {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="ghost" isLoading={isLoading}>
|
||||
<TrashIcon className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
|
||||
onSelect={(e) => e.preventDefault()}
|
||||
>
|
||||
Delete User
|
||||
</DropdownMenuItem>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { CopyIcon, Users } from "lucide-react";
|
||||
import { MoreHorizontal, Users } from "lucide-react";
|
||||
import { AddUser } from "./add-user";
|
||||
import { DeleteUser } from "./delete-user";
|
||||
import { format } from "date-fns";
|
||||
@@ -14,7 +14,24 @@ import { useEffect, useState } from "react";
|
||||
import { AddUserPermissions } from "./add-permissions";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { toast } from "sonner";
|
||||
import { UpdateUser } from "./update-user";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
export const ShowUsers = () => {
|
||||
const { data } = api.user.all.useQuery();
|
||||
@@ -25,82 +42,109 @@ export const ShowUsers = () => {
|
||||
|
||||
return (
|
||||
<div className="h-full col-span-2">
|
||||
<Card className="bg-transparent h-full border-none">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl">Users</CardTitle>
|
||||
<CardDescription>Add, manage and delete users.</CardDescription>
|
||||
<Card className="bg-transparent h-full ">
|
||||
<CardHeader className="flex flex-row gap-2 justify-between w-full flex-wrap">
|
||||
<div className="flex flex-col gap-2">
|
||||
<CardTitle className="text-xl">Users</CardTitle>
|
||||
<CardDescription>Add, manage and delete users.</CardDescription>
|
||||
</div>
|
||||
|
||||
{data && data.length > 0 && (
|
||||
<div className="flex flex-col gap-3 items-end">
|
||||
<AddUser />
|
||||
</div>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 h-full">
|
||||
{data?.length === 0 ? (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<Users className="size-8 self-center text-muted-foreground" />
|
||||
<span className="text-base text-muted-foreground">
|
||||
To create a user is required to add
|
||||
To create a user, you need to add:
|
||||
</span>
|
||||
<AddUser />
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-6">
|
||||
{data?.map((user) => {
|
||||
return (
|
||||
<div
|
||||
key={user.userId}
|
||||
className="flex gap-2 flex-col justify-start border p-4 rounded-lg"
|
||||
>
|
||||
<span className="text-sm text-foreground">
|
||||
{user.auth.email}
|
||||
</span>
|
||||
{!user.isRegistered && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Expire In{" "}
|
||||
{format(new Date(user.expirationDate), "PPpp")}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{user.isRegistered ? "Registered" : "Not Registered"}
|
||||
</span>
|
||||
{user.auth.is2FAEnabled && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{user.auth.is2FAEnabled
|
||||
? "2FA Enabled"
|
||||
: "2FA Not Enabled"}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap flex-row gap-3">
|
||||
{!user.isRegistered && (
|
||||
<div className="overflow-x-auto flex flex-row gap-4 items-center">
|
||||
<div className="overflow-x-auto">
|
||||
<span className="text-sm text-muted-foreground ">
|
||||
{`${url}/invitation?token=${user.token}`}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
// className="absolute right-2 top-2"
|
||||
onClick={() => {
|
||||
copy(`${url}/invitation?token=${user.token}`);
|
||||
toast.success("Invitation Copied to clipboard");
|
||||
}}
|
||||
<Table>
|
||||
<TableCaption>See all users</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Email</TableHead>
|
||||
<TableHead className="text-center">Status</TableHead>
|
||||
<TableHead className="text-center">2FA</TableHead>
|
||||
<TableHead className="text-center">Expiration</TableHead>
|
||||
<TableHead className="text-right">Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{data?.map((user) => {
|
||||
return (
|
||||
<TableRow key={user.userId}>
|
||||
<TableCell className="w-[100px]">
|
||||
{user.auth.email}
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<Badge
|
||||
variant={
|
||||
user.isRegistered ? "default" : "secondary"
|
||||
}
|
||||
>
|
||||
<CopyIcon className="size-4 text-muted-foreground" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{user.isRegistered
|
||||
? "Registered"
|
||||
: "Not Registered"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
{user.auth.is2FAEnabled
|
||||
? "2FA Enabled"
|
||||
: "2FA Not Enabled"}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{format(new Date(user.expirationDate), "PPpp")}
|
||||
</span>
|
||||
</TableCell>
|
||||
|
||||
{user.isRegistered && (
|
||||
<AddUserPermissions userId={user.userId} />
|
||||
)}
|
||||
{user.isRegistered && <UpdateUser authId={user.authId} />}
|
||||
<DeleteUser authId={user.authId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex flex-col justify-end gap-3 w-full items-end">
|
||||
<AddUser />
|
||||
</div>
|
||||
<TableCell className="text-right flex justify-end">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
{!user.isRegistered && (
|
||||
<DropdownMenuItem
|
||||
className="w-full cursor-pointer"
|
||||
onSelect={(e) => {
|
||||
copy(
|
||||
`${origin}/invitation?token=${user.token}`,
|
||||
);
|
||||
toast.success(
|
||||
"Invitation Copied to clipboard",
|
||||
);
|
||||
}}
|
||||
>
|
||||
Copy Invitation
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{user.isRegistered && (
|
||||
<AddUserPermissions userId={user.userId} />
|
||||
)}
|
||||
|
||||
<DeleteUser authId={user.authId} />
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
|
||||
@@ -27,10 +27,9 @@ import { DockerTerminalModal } from "./web-server/docker-terminal-modal";
|
||||
import { ShowMainTraefikConfig } from "./web-server/show-main-traefik-config";
|
||||
import { ShowServerTraefikConfig } from "./web-server/show-server-traefik-config";
|
||||
import { ShowServerMiddlewareConfig } from "./web-server/show-server-middleware-config";
|
||||
import { UpdateWebServer } from "./web-server/update-webserver";
|
||||
import { UpdateServer } from "./web-server/update-server";
|
||||
|
||||
export const WebServer = () => {
|
||||
const [fetchAfterFirstRender, setFetchAfterFirstRender] = useState(false);
|
||||
const { data, refetch } = api.admin.one.useQuery();
|
||||
const { mutateAsync: reloadServer, isLoading } =
|
||||
api.settings.reloadServer.useMutation();
|
||||
@@ -61,13 +60,6 @@ export const WebServer = () => {
|
||||
|
||||
const { mutateAsync: updateDockerCleanup } =
|
||||
api.settings.updateDockerCleanup.useMutation();
|
||||
const { data: query } = api.settings.checkAndUpdateImage.useQuery(void 0, {
|
||||
enabled: fetchAfterFirstRender,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setFetchAfterFirstRender(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Card className="rounded-lg w-full bg-transparent">
|
||||
@@ -279,7 +271,7 @@ export const WebServer = () => {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{query ? <UpdateWebServer /> : null}
|
||||
<UpdateServer />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center flex-wrap justify-between gap-4">
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -24,6 +23,7 @@ import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config";
|
||||
|
||||
const UpdateMainTraefikConfigSchema = z.object({
|
||||
@@ -105,8 +105,8 @@ export const ShowMainTraefikConfig = ({ children }: Props) => {
|
||||
<FormItem className="relative">
|
||||
<FormLabel>Traefik config</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="h-[35rem] font-mono"
|
||||
<CodeEditor
|
||||
wrapperClassName="h-[35rem] font-mono"
|
||||
placeholder={`providers:
|
||||
docker:
|
||||
defaultRule: 'Host('dokploy.com')'
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -24,6 +23,7 @@ import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config";
|
||||
|
||||
const UpdateServerMiddlewareConfigSchema = z.object({
|
||||
@@ -98,7 +98,7 @@ export const ShowServerMiddlewareConfig = ({ children }: Props) => {
|
||||
<form
|
||||
id="hook-form-update-server-traefik-config"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full py-4 relative"
|
||||
className="grid w-full py-4 relative overflow-auto"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<FormField
|
||||
@@ -108,8 +108,8 @@ export const ShowServerMiddlewareConfig = ({ children }: Props) => {
|
||||
<FormItem className="relative">
|
||||
<FormLabel>Traefik config</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="h-[35rem] font-mono"
|
||||
<CodeEditor
|
||||
wrapperClassName="h-[35rem] font-mono"
|
||||
placeholder={`http:
|
||||
routers:
|
||||
router-name:
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -24,6 +23,7 @@ import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config";
|
||||
|
||||
const UpdateServerTraefikConfigSchema = z.object({
|
||||
@@ -98,7 +98,7 @@ export const ShowServerTraefikConfig = ({ children }: Props) => {
|
||||
<form
|
||||
id="hook-form-update-server-traefik-config"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full py-4 relative"
|
||||
className="grid w-full py-4 relative overflow-auto"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<FormField
|
||||
@@ -108,8 +108,8 @@ export const ShowServerTraefikConfig = ({ children }: Props) => {
|
||||
<FormItem className="relative">
|
||||
<FormLabel>Traefik config</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
className="h-[35rem] font-mono"
|
||||
<CodeEditor
|
||||
wrapperClassName="h-[35rem] font-mono"
|
||||
placeholder={`http:
|
||||
routers:
|
||||
router-name:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import type React from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { RefreshCcw } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import Link from "next/link";
|
||||
import { UpdateWebServer } from "./update-webserver";
|
||||
|
||||
export const UpdateServer = () => {
|
||||
const [isUpdateAvailable, setIsUpdateAvailable] = useState<null | boolean>(
|
||||
null,
|
||||
);
|
||||
const { mutateAsync: checkAndUpdateImage, isLoading } =
|
||||
api.settings.checkAndUpdateImage.useMutation();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="secondary">
|
||||
<RefreshCcw className="h-4 w-4" />
|
||||
Updates
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:m:max-w-lg ">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Web Server Update</DialogTitle>
|
||||
<DialogDescription>
|
||||
Check new releases and update your dokploy
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
We suggest to update your dokploy to the latest version only if you:
|
||||
</span>
|
||||
<ul className="list-disc list-inside text-sm text-muted-foreground">
|
||||
<li>Want to try the latest features</li>
|
||||
<li>Some bug that is blocking to use some features</li>
|
||||
</ul>
|
||||
<AlertBlock type="info">
|
||||
Please we recommend to see the latest version to see if there are
|
||||
any breaking changes before updating. Go to{" "}
|
||||
<Link
|
||||
href="https://github.com/Dokploy/dokploy/releases"
|
||||
target="_blank"
|
||||
className="text-foreground"
|
||||
>
|
||||
Dokploy Releases
|
||||
</Link>{" "}
|
||||
to check the latest version.
|
||||
</AlertBlock>
|
||||
|
||||
<div className="w-full flex flex-col gap-4">
|
||||
{isUpdateAvailable === false && (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<RefreshCcw className="size-6 self-center text-muted-foreground" />
|
||||
<span className="text-sm text-muted-foreground">
|
||||
You are using the latest version
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{isUpdateAvailable ? (
|
||||
<UpdateWebServer />
|
||||
) : (
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={async () => {
|
||||
await checkAndUpdateImage()
|
||||
.then(async (e) => {
|
||||
setIsUpdateAvailable(e);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsUpdateAvailable(false);
|
||||
toast.error("Error to check updates");
|
||||
});
|
||||
toast.success("Check updates");
|
||||
}}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
Check updates
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -19,7 +19,11 @@ export const UpdateWebServer = () => {
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button className="relative" variant="secondary" isLoading={isLoading}>
|
||||
<Button
|
||||
className="relative w-full"
|
||||
variant="secondary"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
<span className="absolute -right-1 -top-2 flex h-3 w-3">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" />
|
||||
<span className="relative inline-flex rounded-full h-3 w-3 bg-green-500" />
|
||||
|
||||
@@ -8,7 +8,7 @@ export const ProjectLayout = ({ children }: Props) => {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className="bg-radial relative flex flex-col bg-background pt-6"
|
||||
className="bg-radial relative flex flex-col bg-background"
|
||||
id="app-container"
|
||||
>
|
||||
<div className="flex items-center justify-center">
|
||||
|
||||
@@ -59,6 +59,12 @@ export const SettingsLayout = ({ children }: Props) => {
|
||||
icon: Users,
|
||||
href: "/dashboard/settings/users",
|
||||
},
|
||||
{
|
||||
title: "Cluster",
|
||||
label: "",
|
||||
icon: Server,
|
||||
href: "/dashboard/settings/cluster",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]}
|
||||
@@ -75,6 +81,7 @@ import {
|
||||
Activity,
|
||||
Database,
|
||||
Route,
|
||||
Server,
|
||||
ShieldCheck,
|
||||
User2,
|
||||
Users,
|
||||
@@ -102,7 +109,6 @@ export const Nav = ({ links }: NavProps) => {
|
||||
<nav className="grid gap-1 px-2 group-[[data-collapsed=true]]:justify-center group-[[data-collapsed=true]]:px-2">
|
||||
{links.map((link, index) => {
|
||||
const isActive = router.pathname === link.href;
|
||||
// biome-ignore lint/correctness/useJsxKeyInIterable: <explanation>
|
||||
return (
|
||||
<Link
|
||||
key={index}
|
||||
@@ -110,7 +116,7 @@ export const Nav = ({ links }: NavProps) => {
|
||||
className={cn(
|
||||
buttonVariants({ variant: "ghost", size: "sm" }),
|
||||
isActive &&
|
||||
"dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white",
|
||||
"dark:bg-muted dark:text-white dark:hover:bg-muted dark:hover:text-white bg-muted",
|
||||
"justify-start",
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import CodeMirror, { type ReactCodeMirrorProps } from "@uiw/react-codemirror";
|
||||
import { yaml } from "@codemirror/lang-yaml";
|
||||
import { json } from "@codemirror/lang-json";
|
||||
import { githubLight, githubDark } from "@uiw/codemirror-theme-github";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
interface Props extends ReactCodeMirrorProps {
|
||||
wrapperClassName?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const CodeEditor = ({
|
||||
className,
|
||||
wrapperClassName,
|
||||
...props
|
||||
}: Props) => {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<div className={cn("relative overflow-auto", wrapperClassName)}>
|
||||
<CodeMirror
|
||||
basicSetup={{
|
||||
lineNumbers: true,
|
||||
foldGutter: true,
|
||||
highlightSelectionMatches: true,
|
||||
highlightActiveLine: !props.disabled,
|
||||
allowMultipleSelections: true,
|
||||
}}
|
||||
theme={resolvedTheme === "dark" ? githubDark : githubLight}
|
||||
extensions={[yaml(), json()]}
|
||||
{...props}
|
||||
editable={!props.disabled}
|
||||
className={cn(
|
||||
"w-full h-full text-sm leading-relaxed",
|
||||
`cm-theme-${resolvedTheme}`,
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
{props.disabled && (
|
||||
<div className="absolute top-0 left-0 w-full h-full flex items-center justify-center z-[10] [background:var(--overlay)]" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -4,19 +4,26 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { format, formatDistanceToNow } from "date-fns";
|
||||
|
||||
interface Props {
|
||||
date: string;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DateTooltip = ({ date, children }: Props) => {
|
||||
export const DateTooltip = ({ date, children, className }: Props) => {
|
||||
return (
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<span className="flex items-center text-muted-foreground text-left">
|
||||
<span
|
||||
className={cn(
|
||||
"flex items-center text-muted-foreground text-left",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}{" "}
|
||||
{formatDistanceToNow(new Date(date), {
|
||||
addSuffix: true,
|
||||
|
||||
@@ -88,8 +88,7 @@ const Tree = React.forwardRef<HTMLDivElement, TreeProps>(
|
||||
const { ref: refRoot, width, height } = useResizeObserver();
|
||||
|
||||
return (
|
||||
<div ref={refRoot} className={cn("overflow-hidden", className)}>
|
||||
{/* style={{ width, height }} */}
|
||||
<div ref={refRoot} className={cn("overflow-y-auto", className)}>
|
||||
<ScrollArea>
|
||||
<div className="relative p-2">
|
||||
<TreeItem
|
||||
|
||||
@@ -147,7 +147,6 @@ const FormMessage = React.forwardRef<
|
||||
>(({ className, children, ...props }, ref) => {
|
||||
const { error, formMessageId } = useFormField();
|
||||
const body = error ? String(error?.message) : children;
|
||||
|
||||
if (!body) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ else
|
||||
fi
|
||||
|
||||
docker swarm leave --force 2>/dev/null
|
||||
docker swarm init --advertise-addr 127.0.0.1 --listen-addr 0.0.0.0;
|
||||
docker swarm init;
|
||||
|
||||
echo "Swarm initialized"
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE "RegistryType" AS ENUM('selfHosted', 'cloud');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "registry" (
|
||||
"registryId" text PRIMARY KEY NOT NULL,
|
||||
"registryName" text NOT NULL,
|
||||
"username" text NOT NULL,
|
||||
"password" text NOT NULL,
|
||||
"registryUrl" text NOT NULL,
|
||||
"createdAt" text NOT NULL,
|
||||
"selfHosted" "RegistryType" DEFAULT 'cloud' NOT NULL,
|
||||
"adminId" text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "registry" ADD CONSTRAINT "registry_adminId_admin_adminId_fk" FOREIGN KEY ("adminId") REFERENCES "admin"("adminId") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE "application" ADD COLUMN "registryId" text;--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "application" ADD CONSTRAINT "application_registryId_registry_registryId_fk" FOREIGN KEY ("registryId") REFERENCES "public"."registry"("registryId") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "application" ADD COLUMN "replicas" integer DEFAULT 1;
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE "application" DROP CONSTRAINT "application_registryId_registry_registryId_fk";
|
||||
--> statement-breakpoint
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "application" ADD CONSTRAINT "application_registryId_registry_registryId_fk" FOREIGN KEY ("registryId") REFERENCES "public"."registry"("registryId") ON DELETE set null ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "application" ALTER COLUMN "replicas" SET NOT NULL;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "registry" ADD COLUMN "imagePrefix" text NOT NULL;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "registry" ALTER COLUMN "imagePrefix" DROP NOT NULL;
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE "application" ADD COLUMN "healthCheckSwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "restartPolicySwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "placementSwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "updateConfigSwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "rollbackConfigSwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "modeSwarm" json;--> statement-breakpoint
|
||||
ALTER TABLE "application" ADD COLUMN "labelsSwarm" json;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE "application" ADD COLUMN "networkSwarm" json;
|
||||
+202
-192
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"id": "c6215051-7cd1-412d-b8df-b50d58acacff",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"version": "6",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"application": {
|
||||
"public.application": {
|
||||
"name": "application",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -234,29 +232,29 @@
|
||||
"application_projectId_project_projectId_fk": {
|
||||
"name": "application_projectId_project_projectId_fk",
|
||||
"tableFrom": "application",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"application_appName_unique": {
|
||||
"name": "application_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"public.postgres": {
|
||||
"name": "postgres",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -375,29 +373,29 @@
|
||||
"postgres_projectId_project_projectId_fk": {
|
||||
"name": "postgres_projectId_project_projectId_fk",
|
||||
"tableFrom": "postgres",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"postgres_appName_unique": {
|
||||
"name": "postgres_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -499,34 +497,34 @@
|
||||
"user_adminId_admin_adminId_fk": {
|
||||
"name": "user_adminId_admin_adminId_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"user_authId_auth_id_fk": {
|
||||
"name": "user_authId_auth_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"admin": {
|
||||
"public.admin": {
|
||||
"name": "admin",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -628,21 +626,21 @@
|
||||
"admin_authId_auth_id_fk": {
|
||||
"name": "admin_authId_auth_id_fk",
|
||||
"tableFrom": "admin",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"auth": {
|
||||
"public.auth": {
|
||||
"name": "auth",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -689,14 +687,14 @@
|
||||
"uniqueConstraints": {
|
||||
"auth_email_unique": {
|
||||
"name": "auth_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"public.project": {
|
||||
"name": "project",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -736,21 +734,21 @@
|
||||
"project_adminId_admin_adminId_fk": {
|
||||
"name": "project_adminId_admin_adminId_fk",
|
||||
"tableFrom": "project",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"domain": {
|
||||
"public.domain": {
|
||||
"name": "domain",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -818,21 +816,21 @@
|
||||
"domain_applicationId_application_applicationId_fk": {
|
||||
"name": "domain_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "domain",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mariadb": {
|
||||
"public.mariadb": {
|
||||
"name": "mariadb",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -957,29 +955,29 @@
|
||||
"mariadb_projectId_project_projectId_fk": {
|
||||
"name": "mariadb_projectId_project_projectId_fk",
|
||||
"tableFrom": "mariadb",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mariadb_appName_unique": {
|
||||
"name": "mariadb_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongo": {
|
||||
"public.mongo": {
|
||||
"name": "mongo",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1092,29 +1090,29 @@
|
||||
"mongo_projectId_project_projectId_fk": {
|
||||
"name": "mongo_projectId_project_projectId_fk",
|
||||
"tableFrom": "mongo",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mongo_appName_unique": {
|
||||
"name": "mongo_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"public.mysql": {
|
||||
"name": "mysql",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1239,29 +1237,29 @@
|
||||
"mysql_projectId_project_projectId_fk": {
|
||||
"name": "mysql_projectId_project_projectId_fk",
|
||||
"tableFrom": "mysql",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mysql_appName_unique": {
|
||||
"name": "mysql_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"backup": {
|
||||
"public.backup": {
|
||||
"name": "backup",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1337,73 +1335,73 @@
|
||||
"backup_destinationId_destination_destinationId_fk": {
|
||||
"name": "backup_destinationId_destination_destinationId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "destination",
|
||||
"columnsFrom": [
|
||||
"destinationId"
|
||||
],
|
||||
"tableTo": "destination",
|
||||
"columnsTo": [
|
||||
"destinationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_postgresId_postgres_postgresId_fk": {
|
||||
"name": "backup_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "backup_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "backup_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mongoId_mongo_mongoId_fk": {
|
||||
"name": "backup_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"destination": {
|
||||
"public.destination": {
|
||||
"name": "destination",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1461,21 +1459,21 @@
|
||||
"destination_adminId_admin_adminId_fk": {
|
||||
"name": "destination_adminId_admin_adminId_fk",
|
||||
"tableFrom": "destination",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"deployment": {
|
||||
"public.deployment": {
|
||||
"name": "deployment",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1522,21 +1520,21 @@
|
||||
"deployment_applicationId_application_applicationId_fk": {
|
||||
"name": "deployment_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "deployment",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mount": {
|
||||
"public.mount": {
|
||||
"name": "mount",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1625,86 +1623,86 @@
|
||||
"mount_applicationId_application_applicationId_fk": {
|
||||
"name": "mount_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_postgresId_postgres_postgresId_fk": {
|
||||
"name": "mount_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "mount_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mongoId_mongo_mongoId_fk": {
|
||||
"name": "mount_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "mount_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_redisId_redis_redisId_fk": {
|
||||
"name": "mount_redisId_redis_redisId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "redis",
|
||||
"columnsFrom": [
|
||||
"redisId"
|
||||
],
|
||||
"tableTo": "redis",
|
||||
"columnsTo": [
|
||||
"redisId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"certificate": {
|
||||
"public.certificate": {
|
||||
"name": "certificate",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1751,14 +1749,14 @@
|
||||
"uniqueConstraints": {
|
||||
"certificate_certificatePath_unique": {
|
||||
"name": "certificate_certificatePath_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"certificatePath"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"session": {
|
||||
"public.session": {
|
||||
"name": "session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1786,21 +1784,21 @@
|
||||
"session_user_id_auth_id_fk": {
|
||||
"name": "session_user_id_auth_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redirect": {
|
||||
"public.redirect": {
|
||||
"name": "redirect",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1853,21 +1851,21 @@
|
||||
"redirect_applicationId_application_applicationId_fk": {
|
||||
"name": "redirect_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "redirect",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"security": {
|
||||
"public.security": {
|
||||
"name": "security",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1907,30 +1905,30 @@
|
||||
"security_applicationId_application_applicationId_fk": {
|
||||
"name": "security_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "security",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"security_username_applicationId_unique": {
|
||||
"name": "security_username_applicationId_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username",
|
||||
"applicationId"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": {
|
||||
"public.port": {
|
||||
"name": "port",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1970,21 +1968,21 @@
|
||||
"port_applicationId_application_applicationId_fk": {
|
||||
"name": "port_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "port",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redis": {
|
||||
"public.redis": {
|
||||
"name": "redis",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -2091,118 +2089,130 @@
|
||||
"redis_projectId_project_projectId_fk": {
|
||||
"name": "redis_projectId_project_projectId_fk",
|
||||
"tableFrom": "redis",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"redis_appName_unique": {
|
||||
"name": "redis_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"buildType": {
|
||||
"public.buildType": {
|
||||
"name": "buildType",
|
||||
"values": {
|
||||
"dockerfile": "dockerfile",
|
||||
"heroku_buildpacks": "heroku_buildpacks",
|
||||
"paketo_buildpacks": "paketo_buildpacks",
|
||||
"nixpacks": "nixpacks"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"dockerfile",
|
||||
"heroku_buildpacks",
|
||||
"paketo_buildpacks",
|
||||
"nixpacks"
|
||||
]
|
||||
},
|
||||
"sourceType": {
|
||||
"public.sourceType": {
|
||||
"name": "sourceType",
|
||||
"values": {
|
||||
"docker": "docker",
|
||||
"git": "git",
|
||||
"github": "github"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"docker",
|
||||
"git",
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"Roles": {
|
||||
"public.Roles": {
|
||||
"name": "Roles",
|
||||
"values": {
|
||||
"admin": "admin",
|
||||
"user": "user"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
},
|
||||
"databaseType": {
|
||||
"public.databaseType": {
|
||||
"name": "databaseType",
|
||||
"values": {
|
||||
"postgres": "postgres",
|
||||
"mariadb": "mariadb",
|
||||
"mysql": "mysql",
|
||||
"mongo": "mongo"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"mysql",
|
||||
"mongo"
|
||||
]
|
||||
},
|
||||
"deploymentStatus": {
|
||||
"public.deploymentStatus": {
|
||||
"name": "deploymentStatus",
|
||||
"values": {
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"mountType": {
|
||||
"public.mountType": {
|
||||
"name": "mountType",
|
||||
"values": {
|
||||
"bind": "bind",
|
||||
"volume": "volume",
|
||||
"file": "file"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"bind",
|
||||
"volume",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"serviceType": {
|
||||
"public.serviceType": {
|
||||
"name": "serviceType",
|
||||
"values": {
|
||||
"application": "application",
|
||||
"postgres": "postgres",
|
||||
"mysql": "mysql",
|
||||
"mariadb": "mariadb",
|
||||
"mongo": "mongo",
|
||||
"redis": "redis"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis"
|
||||
]
|
||||
},
|
||||
"protocolType": {
|
||||
"public.protocolType": {
|
||||
"name": "protocolType",
|
||||
"values": {
|
||||
"tcp": "tcp",
|
||||
"udp": "udp"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"applicationStatus": {
|
||||
"public.applicationStatus": {
|
||||
"name": "applicationStatus",
|
||||
"values": {
|
||||
"idle": "idle",
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"idle",
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"certificateType": {
|
||||
"public.certificateType": {
|
||||
"name": "certificateType",
|
||||
"values": {
|
||||
"letsencrypt": "letsencrypt",
|
||||
"none": "none"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"letsencrypt",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "c6215051-7cd1-412d-b8df-b50d58acacff",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
+202
-192
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"id": "3a4dfad7-ae33-4ae3-b60e-4f40f44f5652",
|
||||
"prevId": "c6215051-7cd1-412d-b8df-b50d58acacff",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"version": "6",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"application": {
|
||||
"public.application": {
|
||||
"name": "application",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -234,29 +232,29 @@
|
||||
"application_projectId_project_projectId_fk": {
|
||||
"name": "application_projectId_project_projectId_fk",
|
||||
"tableFrom": "application",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"application_appName_unique": {
|
||||
"name": "application_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"public.postgres": {
|
||||
"name": "postgres",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -375,29 +373,29 @@
|
||||
"postgres_projectId_project_projectId_fk": {
|
||||
"name": "postgres_projectId_project_projectId_fk",
|
||||
"tableFrom": "postgres",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"postgres_appName_unique": {
|
||||
"name": "postgres_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -499,34 +497,34 @@
|
||||
"user_adminId_admin_adminId_fk": {
|
||||
"name": "user_adminId_admin_adminId_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"user_authId_auth_id_fk": {
|
||||
"name": "user_authId_auth_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"admin": {
|
||||
"public.admin": {
|
||||
"name": "admin",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -628,21 +626,21 @@
|
||||
"admin_authId_auth_id_fk": {
|
||||
"name": "admin_authId_auth_id_fk",
|
||||
"tableFrom": "admin",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"auth": {
|
||||
"public.auth": {
|
||||
"name": "auth",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -695,14 +693,14 @@
|
||||
"uniqueConstraints": {
|
||||
"auth_email_unique": {
|
||||
"name": "auth_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"public.project": {
|
||||
"name": "project",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -742,21 +740,21 @@
|
||||
"project_adminId_admin_adminId_fk": {
|
||||
"name": "project_adminId_admin_adminId_fk",
|
||||
"tableFrom": "project",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"domain": {
|
||||
"public.domain": {
|
||||
"name": "domain",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -824,21 +822,21 @@
|
||||
"domain_applicationId_application_applicationId_fk": {
|
||||
"name": "domain_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "domain",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mariadb": {
|
||||
"public.mariadb": {
|
||||
"name": "mariadb",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -963,29 +961,29 @@
|
||||
"mariadb_projectId_project_projectId_fk": {
|
||||
"name": "mariadb_projectId_project_projectId_fk",
|
||||
"tableFrom": "mariadb",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mariadb_appName_unique": {
|
||||
"name": "mariadb_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongo": {
|
||||
"public.mongo": {
|
||||
"name": "mongo",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1098,29 +1096,29 @@
|
||||
"mongo_projectId_project_projectId_fk": {
|
||||
"name": "mongo_projectId_project_projectId_fk",
|
||||
"tableFrom": "mongo",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mongo_appName_unique": {
|
||||
"name": "mongo_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"public.mysql": {
|
||||
"name": "mysql",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1245,29 +1243,29 @@
|
||||
"mysql_projectId_project_projectId_fk": {
|
||||
"name": "mysql_projectId_project_projectId_fk",
|
||||
"tableFrom": "mysql",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mysql_appName_unique": {
|
||||
"name": "mysql_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"backup": {
|
||||
"public.backup": {
|
||||
"name": "backup",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1343,73 +1341,73 @@
|
||||
"backup_destinationId_destination_destinationId_fk": {
|
||||
"name": "backup_destinationId_destination_destinationId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "destination",
|
||||
"columnsFrom": [
|
||||
"destinationId"
|
||||
],
|
||||
"tableTo": "destination",
|
||||
"columnsTo": [
|
||||
"destinationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_postgresId_postgres_postgresId_fk": {
|
||||
"name": "backup_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "backup_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "backup_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mongoId_mongo_mongoId_fk": {
|
||||
"name": "backup_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"destination": {
|
||||
"public.destination": {
|
||||
"name": "destination",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1467,21 +1465,21 @@
|
||||
"destination_adminId_admin_adminId_fk": {
|
||||
"name": "destination_adminId_admin_adminId_fk",
|
||||
"tableFrom": "destination",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"deployment": {
|
||||
"public.deployment": {
|
||||
"name": "deployment",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1528,21 +1526,21 @@
|
||||
"deployment_applicationId_application_applicationId_fk": {
|
||||
"name": "deployment_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "deployment",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mount": {
|
||||
"public.mount": {
|
||||
"name": "mount",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1631,86 +1629,86 @@
|
||||
"mount_applicationId_application_applicationId_fk": {
|
||||
"name": "mount_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_postgresId_postgres_postgresId_fk": {
|
||||
"name": "mount_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "mount_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mongoId_mongo_mongoId_fk": {
|
||||
"name": "mount_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "mount_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_redisId_redis_redisId_fk": {
|
||||
"name": "mount_redisId_redis_redisId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "redis",
|
||||
"columnsFrom": [
|
||||
"redisId"
|
||||
],
|
||||
"tableTo": "redis",
|
||||
"columnsTo": [
|
||||
"redisId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"certificate": {
|
||||
"public.certificate": {
|
||||
"name": "certificate",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1757,14 +1755,14 @@
|
||||
"uniqueConstraints": {
|
||||
"certificate_certificatePath_unique": {
|
||||
"name": "certificate_certificatePath_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"certificatePath"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"session": {
|
||||
"public.session": {
|
||||
"name": "session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1792,21 +1790,21 @@
|
||||
"session_user_id_auth_id_fk": {
|
||||
"name": "session_user_id_auth_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redirect": {
|
||||
"public.redirect": {
|
||||
"name": "redirect",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1859,21 +1857,21 @@
|
||||
"redirect_applicationId_application_applicationId_fk": {
|
||||
"name": "redirect_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "redirect",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"security": {
|
||||
"public.security": {
|
||||
"name": "security",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1913,30 +1911,30 @@
|
||||
"security_applicationId_application_applicationId_fk": {
|
||||
"name": "security_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "security",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"security_username_applicationId_unique": {
|
||||
"name": "security_username_applicationId_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username",
|
||||
"applicationId"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": {
|
||||
"public.port": {
|
||||
"name": "port",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1976,21 +1974,21 @@
|
||||
"port_applicationId_application_applicationId_fk": {
|
||||
"name": "port_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "port",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redis": {
|
||||
"public.redis": {
|
||||
"name": "redis",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -2097,118 +2095,130 @@
|
||||
"redis_projectId_project_projectId_fk": {
|
||||
"name": "redis_projectId_project_projectId_fk",
|
||||
"tableFrom": "redis",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"redis_appName_unique": {
|
||||
"name": "redis_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"buildType": {
|
||||
"public.buildType": {
|
||||
"name": "buildType",
|
||||
"values": {
|
||||
"dockerfile": "dockerfile",
|
||||
"heroku_buildpacks": "heroku_buildpacks",
|
||||
"paketo_buildpacks": "paketo_buildpacks",
|
||||
"nixpacks": "nixpacks"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"dockerfile",
|
||||
"heroku_buildpacks",
|
||||
"paketo_buildpacks",
|
||||
"nixpacks"
|
||||
]
|
||||
},
|
||||
"sourceType": {
|
||||
"public.sourceType": {
|
||||
"name": "sourceType",
|
||||
"values": {
|
||||
"docker": "docker",
|
||||
"git": "git",
|
||||
"github": "github"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"docker",
|
||||
"git",
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"Roles": {
|
||||
"public.Roles": {
|
||||
"name": "Roles",
|
||||
"values": {
|
||||
"admin": "admin",
|
||||
"user": "user"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
},
|
||||
"databaseType": {
|
||||
"public.databaseType": {
|
||||
"name": "databaseType",
|
||||
"values": {
|
||||
"postgres": "postgres",
|
||||
"mariadb": "mariadb",
|
||||
"mysql": "mysql",
|
||||
"mongo": "mongo"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"mysql",
|
||||
"mongo"
|
||||
]
|
||||
},
|
||||
"deploymentStatus": {
|
||||
"public.deploymentStatus": {
|
||||
"name": "deploymentStatus",
|
||||
"values": {
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"mountType": {
|
||||
"public.mountType": {
|
||||
"name": "mountType",
|
||||
"values": {
|
||||
"bind": "bind",
|
||||
"volume": "volume",
|
||||
"file": "file"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"bind",
|
||||
"volume",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"serviceType": {
|
||||
"public.serviceType": {
|
||||
"name": "serviceType",
|
||||
"values": {
|
||||
"application": "application",
|
||||
"postgres": "postgres",
|
||||
"mysql": "mysql",
|
||||
"mariadb": "mariadb",
|
||||
"mongo": "mongo",
|
||||
"redis": "redis"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis"
|
||||
]
|
||||
},
|
||||
"protocolType": {
|
||||
"public.protocolType": {
|
||||
"name": "protocolType",
|
||||
"values": {
|
||||
"tcp": "tcp",
|
||||
"udp": "udp"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"applicationStatus": {
|
||||
"public.applicationStatus": {
|
||||
"name": "applicationStatus",
|
||||
"values": {
|
||||
"idle": "idle",
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"idle",
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"certificateType": {
|
||||
"public.certificateType": {
|
||||
"name": "certificateType",
|
||||
"values": {
|
||||
"letsencrypt": "letsencrypt",
|
||||
"none": "none"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"letsencrypt",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "3a4dfad7-ae33-4ae3-b60e-4f40f44f5652",
|
||||
"prevId": "c6215051-7cd1-412d-b8df-b50d58acacff"
|
||||
}
|
||||
+202
-192
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"id": "665483bd-5123-4c2b-beef-bfa9b91b9356",
|
||||
"prevId": "3a4dfad7-ae33-4ae3-b60e-4f40f44f5652",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"version": "6",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"application": {
|
||||
"public.application": {
|
||||
"name": "application",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -234,29 +232,29 @@
|
||||
"application_projectId_project_projectId_fk": {
|
||||
"name": "application_projectId_project_projectId_fk",
|
||||
"tableFrom": "application",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"application_appName_unique": {
|
||||
"name": "application_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"public.postgres": {
|
||||
"name": "postgres",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -375,29 +373,29 @@
|
||||
"postgres_projectId_project_projectId_fk": {
|
||||
"name": "postgres_projectId_project_projectId_fk",
|
||||
"tableFrom": "postgres",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"postgres_appName_unique": {
|
||||
"name": "postgres_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -499,34 +497,34 @@
|
||||
"user_adminId_admin_adminId_fk": {
|
||||
"name": "user_adminId_admin_adminId_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"user_authId_auth_id_fk": {
|
||||
"name": "user_authId_auth_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"admin": {
|
||||
"public.admin": {
|
||||
"name": "admin",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -628,21 +626,21 @@
|
||||
"admin_authId_auth_id_fk": {
|
||||
"name": "admin_authId_auth_id_fk",
|
||||
"tableFrom": "admin",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"auth": {
|
||||
"public.auth": {
|
||||
"name": "auth",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -702,14 +700,14 @@
|
||||
"uniqueConstraints": {
|
||||
"auth_email_unique": {
|
||||
"name": "auth_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"public.project": {
|
||||
"name": "project",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -749,21 +747,21 @@
|
||||
"project_adminId_admin_adminId_fk": {
|
||||
"name": "project_adminId_admin_adminId_fk",
|
||||
"tableFrom": "project",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"domain": {
|
||||
"public.domain": {
|
||||
"name": "domain",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -831,21 +829,21 @@
|
||||
"domain_applicationId_application_applicationId_fk": {
|
||||
"name": "domain_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "domain",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mariadb": {
|
||||
"public.mariadb": {
|
||||
"name": "mariadb",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -970,29 +968,29 @@
|
||||
"mariadb_projectId_project_projectId_fk": {
|
||||
"name": "mariadb_projectId_project_projectId_fk",
|
||||
"tableFrom": "mariadb",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mariadb_appName_unique": {
|
||||
"name": "mariadb_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongo": {
|
||||
"public.mongo": {
|
||||
"name": "mongo",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1105,29 +1103,29 @@
|
||||
"mongo_projectId_project_projectId_fk": {
|
||||
"name": "mongo_projectId_project_projectId_fk",
|
||||
"tableFrom": "mongo",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mongo_appName_unique": {
|
||||
"name": "mongo_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"public.mysql": {
|
||||
"name": "mysql",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1252,29 +1250,29 @@
|
||||
"mysql_projectId_project_projectId_fk": {
|
||||
"name": "mysql_projectId_project_projectId_fk",
|
||||
"tableFrom": "mysql",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mysql_appName_unique": {
|
||||
"name": "mysql_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"backup": {
|
||||
"public.backup": {
|
||||
"name": "backup",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1350,73 +1348,73 @@
|
||||
"backup_destinationId_destination_destinationId_fk": {
|
||||
"name": "backup_destinationId_destination_destinationId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "destination",
|
||||
"columnsFrom": [
|
||||
"destinationId"
|
||||
],
|
||||
"tableTo": "destination",
|
||||
"columnsTo": [
|
||||
"destinationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_postgresId_postgres_postgresId_fk": {
|
||||
"name": "backup_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "backup_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "backup_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mongoId_mongo_mongoId_fk": {
|
||||
"name": "backup_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"destination": {
|
||||
"public.destination": {
|
||||
"name": "destination",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1474,21 +1472,21 @@
|
||||
"destination_adminId_admin_adminId_fk": {
|
||||
"name": "destination_adminId_admin_adminId_fk",
|
||||
"tableFrom": "destination",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"deployment": {
|
||||
"public.deployment": {
|
||||
"name": "deployment",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1535,21 +1533,21 @@
|
||||
"deployment_applicationId_application_applicationId_fk": {
|
||||
"name": "deployment_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "deployment",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mount": {
|
||||
"public.mount": {
|
||||
"name": "mount",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1638,86 +1636,86 @@
|
||||
"mount_applicationId_application_applicationId_fk": {
|
||||
"name": "mount_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_postgresId_postgres_postgresId_fk": {
|
||||
"name": "mount_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "mount_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mongoId_mongo_mongoId_fk": {
|
||||
"name": "mount_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "mount_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_redisId_redis_redisId_fk": {
|
||||
"name": "mount_redisId_redis_redisId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "redis",
|
||||
"columnsFrom": [
|
||||
"redisId"
|
||||
],
|
||||
"tableTo": "redis",
|
||||
"columnsTo": [
|
||||
"redisId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"certificate": {
|
||||
"public.certificate": {
|
||||
"name": "certificate",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1764,14 +1762,14 @@
|
||||
"uniqueConstraints": {
|
||||
"certificate_certificatePath_unique": {
|
||||
"name": "certificate_certificatePath_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"certificatePath"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"session": {
|
||||
"public.session": {
|
||||
"name": "session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1799,21 +1797,21 @@
|
||||
"session_user_id_auth_id_fk": {
|
||||
"name": "session_user_id_auth_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redirect": {
|
||||
"public.redirect": {
|
||||
"name": "redirect",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1866,21 +1864,21 @@
|
||||
"redirect_applicationId_application_applicationId_fk": {
|
||||
"name": "redirect_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "redirect",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"security": {
|
||||
"public.security": {
|
||||
"name": "security",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1920,30 +1918,30 @@
|
||||
"security_applicationId_application_applicationId_fk": {
|
||||
"name": "security_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "security",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"security_username_applicationId_unique": {
|
||||
"name": "security_username_applicationId_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username",
|
||||
"applicationId"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": {
|
||||
"public.port": {
|
||||
"name": "port",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1983,21 +1981,21 @@
|
||||
"port_applicationId_application_applicationId_fk": {
|
||||
"name": "port_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "port",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redis": {
|
||||
"public.redis": {
|
||||
"name": "redis",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -2104,118 +2102,130 @@
|
||||
"redis_projectId_project_projectId_fk": {
|
||||
"name": "redis_projectId_project_projectId_fk",
|
||||
"tableFrom": "redis",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"redis_appName_unique": {
|
||||
"name": "redis_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"buildType": {
|
||||
"public.buildType": {
|
||||
"name": "buildType",
|
||||
"values": {
|
||||
"dockerfile": "dockerfile",
|
||||
"heroku_buildpacks": "heroku_buildpacks",
|
||||
"paketo_buildpacks": "paketo_buildpacks",
|
||||
"nixpacks": "nixpacks"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"dockerfile",
|
||||
"heroku_buildpacks",
|
||||
"paketo_buildpacks",
|
||||
"nixpacks"
|
||||
]
|
||||
},
|
||||
"sourceType": {
|
||||
"public.sourceType": {
|
||||
"name": "sourceType",
|
||||
"values": {
|
||||
"docker": "docker",
|
||||
"git": "git",
|
||||
"github": "github"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"docker",
|
||||
"git",
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"Roles": {
|
||||
"public.Roles": {
|
||||
"name": "Roles",
|
||||
"values": {
|
||||
"admin": "admin",
|
||||
"user": "user"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
},
|
||||
"databaseType": {
|
||||
"public.databaseType": {
|
||||
"name": "databaseType",
|
||||
"values": {
|
||||
"postgres": "postgres",
|
||||
"mariadb": "mariadb",
|
||||
"mysql": "mysql",
|
||||
"mongo": "mongo"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"mysql",
|
||||
"mongo"
|
||||
]
|
||||
},
|
||||
"deploymentStatus": {
|
||||
"public.deploymentStatus": {
|
||||
"name": "deploymentStatus",
|
||||
"values": {
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"mountType": {
|
||||
"public.mountType": {
|
||||
"name": "mountType",
|
||||
"values": {
|
||||
"bind": "bind",
|
||||
"volume": "volume",
|
||||
"file": "file"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"bind",
|
||||
"volume",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"serviceType": {
|
||||
"public.serviceType": {
|
||||
"name": "serviceType",
|
||||
"values": {
|
||||
"application": "application",
|
||||
"postgres": "postgres",
|
||||
"mysql": "mysql",
|
||||
"mariadb": "mariadb",
|
||||
"mongo": "mongo",
|
||||
"redis": "redis"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis"
|
||||
]
|
||||
},
|
||||
"protocolType": {
|
||||
"public.protocolType": {
|
||||
"name": "protocolType",
|
||||
"values": {
|
||||
"tcp": "tcp",
|
||||
"udp": "udp"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"applicationStatus": {
|
||||
"public.applicationStatus": {
|
||||
"name": "applicationStatus",
|
||||
"values": {
|
||||
"idle": "idle",
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"idle",
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"certificateType": {
|
||||
"public.certificateType": {
|
||||
"name": "certificateType",
|
||||
"values": {
|
||||
"letsencrypt": "letsencrypt",
|
||||
"none": "none"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"letsencrypt",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "665483bd-5123-4c2b-beef-bfa9b91b9356",
|
||||
"prevId": "3a4dfad7-ae33-4ae3-b60e-4f40f44f5652"
|
||||
}
|
||||
+202
-192
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"id": "5a1d3f2b-9c31-4125-9645-015170550b51",
|
||||
"prevId": "665483bd-5123-4c2b-beef-bfa9b91b9356",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"version": "6",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"application": {
|
||||
"public.application": {
|
||||
"name": "application",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -234,29 +232,29 @@
|
||||
"application_projectId_project_projectId_fk": {
|
||||
"name": "application_projectId_project_projectId_fk",
|
||||
"tableFrom": "application",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"application_appName_unique": {
|
||||
"name": "application_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"public.postgres": {
|
||||
"name": "postgres",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -375,29 +373,29 @@
|
||||
"postgres_projectId_project_projectId_fk": {
|
||||
"name": "postgres_projectId_project_projectId_fk",
|
||||
"tableFrom": "postgres",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"postgres_appName_unique": {
|
||||
"name": "postgres_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -506,34 +504,34 @@
|
||||
"user_adminId_admin_adminId_fk": {
|
||||
"name": "user_adminId_admin_adminId_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"user_authId_auth_id_fk": {
|
||||
"name": "user_authId_auth_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"admin": {
|
||||
"public.admin": {
|
||||
"name": "admin",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -635,21 +633,21 @@
|
||||
"admin_authId_auth_id_fk": {
|
||||
"name": "admin_authId_auth_id_fk",
|
||||
"tableFrom": "admin",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"auth": {
|
||||
"public.auth": {
|
||||
"name": "auth",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -709,14 +707,14 @@
|
||||
"uniqueConstraints": {
|
||||
"auth_email_unique": {
|
||||
"name": "auth_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"public.project": {
|
||||
"name": "project",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -756,21 +754,21 @@
|
||||
"project_adminId_admin_adminId_fk": {
|
||||
"name": "project_adminId_admin_adminId_fk",
|
||||
"tableFrom": "project",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"domain": {
|
||||
"public.domain": {
|
||||
"name": "domain",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -838,21 +836,21 @@
|
||||
"domain_applicationId_application_applicationId_fk": {
|
||||
"name": "domain_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "domain",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mariadb": {
|
||||
"public.mariadb": {
|
||||
"name": "mariadb",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -977,29 +975,29 @@
|
||||
"mariadb_projectId_project_projectId_fk": {
|
||||
"name": "mariadb_projectId_project_projectId_fk",
|
||||
"tableFrom": "mariadb",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mariadb_appName_unique": {
|
||||
"name": "mariadb_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongo": {
|
||||
"public.mongo": {
|
||||
"name": "mongo",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1112,29 +1110,29 @@
|
||||
"mongo_projectId_project_projectId_fk": {
|
||||
"name": "mongo_projectId_project_projectId_fk",
|
||||
"tableFrom": "mongo",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mongo_appName_unique": {
|
||||
"name": "mongo_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"public.mysql": {
|
||||
"name": "mysql",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1259,29 +1257,29 @@
|
||||
"mysql_projectId_project_projectId_fk": {
|
||||
"name": "mysql_projectId_project_projectId_fk",
|
||||
"tableFrom": "mysql",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mysql_appName_unique": {
|
||||
"name": "mysql_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"backup": {
|
||||
"public.backup": {
|
||||
"name": "backup",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1357,73 +1355,73 @@
|
||||
"backup_destinationId_destination_destinationId_fk": {
|
||||
"name": "backup_destinationId_destination_destinationId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "destination",
|
||||
"columnsFrom": [
|
||||
"destinationId"
|
||||
],
|
||||
"tableTo": "destination",
|
||||
"columnsTo": [
|
||||
"destinationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_postgresId_postgres_postgresId_fk": {
|
||||
"name": "backup_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "backup_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "backup_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mongoId_mongo_mongoId_fk": {
|
||||
"name": "backup_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"destination": {
|
||||
"public.destination": {
|
||||
"name": "destination",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1481,21 +1479,21 @@
|
||||
"destination_adminId_admin_adminId_fk": {
|
||||
"name": "destination_adminId_admin_adminId_fk",
|
||||
"tableFrom": "destination",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"deployment": {
|
||||
"public.deployment": {
|
||||
"name": "deployment",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1542,21 +1540,21 @@
|
||||
"deployment_applicationId_application_applicationId_fk": {
|
||||
"name": "deployment_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "deployment",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mount": {
|
||||
"public.mount": {
|
||||
"name": "mount",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1645,86 +1643,86 @@
|
||||
"mount_applicationId_application_applicationId_fk": {
|
||||
"name": "mount_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_postgresId_postgres_postgresId_fk": {
|
||||
"name": "mount_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "mount_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mongoId_mongo_mongoId_fk": {
|
||||
"name": "mount_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "mount_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_redisId_redis_redisId_fk": {
|
||||
"name": "mount_redisId_redis_redisId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "redis",
|
||||
"columnsFrom": [
|
||||
"redisId"
|
||||
],
|
||||
"tableTo": "redis",
|
||||
"columnsTo": [
|
||||
"redisId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"certificate": {
|
||||
"public.certificate": {
|
||||
"name": "certificate",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1771,14 +1769,14 @@
|
||||
"uniqueConstraints": {
|
||||
"certificate_certificatePath_unique": {
|
||||
"name": "certificate_certificatePath_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"certificatePath"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"session": {
|
||||
"public.session": {
|
||||
"name": "session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1806,21 +1804,21 @@
|
||||
"session_user_id_auth_id_fk": {
|
||||
"name": "session_user_id_auth_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redirect": {
|
||||
"public.redirect": {
|
||||
"name": "redirect",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1873,21 +1871,21 @@
|
||||
"redirect_applicationId_application_applicationId_fk": {
|
||||
"name": "redirect_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "redirect",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"security": {
|
||||
"public.security": {
|
||||
"name": "security",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1927,30 +1925,30 @@
|
||||
"security_applicationId_application_applicationId_fk": {
|
||||
"name": "security_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "security",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"security_username_applicationId_unique": {
|
||||
"name": "security_username_applicationId_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username",
|
||||
"applicationId"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": {
|
||||
"public.port": {
|
||||
"name": "port",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1990,21 +1988,21 @@
|
||||
"port_applicationId_application_applicationId_fk": {
|
||||
"name": "port_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "port",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redis": {
|
||||
"public.redis": {
|
||||
"name": "redis",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -2111,118 +2109,130 @@
|
||||
"redis_projectId_project_projectId_fk": {
|
||||
"name": "redis_projectId_project_projectId_fk",
|
||||
"tableFrom": "redis",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"redis_appName_unique": {
|
||||
"name": "redis_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"buildType": {
|
||||
"public.buildType": {
|
||||
"name": "buildType",
|
||||
"values": {
|
||||
"dockerfile": "dockerfile",
|
||||
"heroku_buildpacks": "heroku_buildpacks",
|
||||
"paketo_buildpacks": "paketo_buildpacks",
|
||||
"nixpacks": "nixpacks"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"dockerfile",
|
||||
"heroku_buildpacks",
|
||||
"paketo_buildpacks",
|
||||
"nixpacks"
|
||||
]
|
||||
},
|
||||
"sourceType": {
|
||||
"public.sourceType": {
|
||||
"name": "sourceType",
|
||||
"values": {
|
||||
"docker": "docker",
|
||||
"git": "git",
|
||||
"github": "github"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"docker",
|
||||
"git",
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"Roles": {
|
||||
"public.Roles": {
|
||||
"name": "Roles",
|
||||
"values": {
|
||||
"admin": "admin",
|
||||
"user": "user"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
},
|
||||
"databaseType": {
|
||||
"public.databaseType": {
|
||||
"name": "databaseType",
|
||||
"values": {
|
||||
"postgres": "postgres",
|
||||
"mariadb": "mariadb",
|
||||
"mysql": "mysql",
|
||||
"mongo": "mongo"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"mysql",
|
||||
"mongo"
|
||||
]
|
||||
},
|
||||
"deploymentStatus": {
|
||||
"public.deploymentStatus": {
|
||||
"name": "deploymentStatus",
|
||||
"values": {
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"mountType": {
|
||||
"public.mountType": {
|
||||
"name": "mountType",
|
||||
"values": {
|
||||
"bind": "bind",
|
||||
"volume": "volume",
|
||||
"file": "file"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"bind",
|
||||
"volume",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"serviceType": {
|
||||
"public.serviceType": {
|
||||
"name": "serviceType",
|
||||
"values": {
|
||||
"application": "application",
|
||||
"postgres": "postgres",
|
||||
"mysql": "mysql",
|
||||
"mariadb": "mariadb",
|
||||
"mongo": "mongo",
|
||||
"redis": "redis"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis"
|
||||
]
|
||||
},
|
||||
"protocolType": {
|
||||
"public.protocolType": {
|
||||
"name": "protocolType",
|
||||
"values": {
|
||||
"tcp": "tcp",
|
||||
"udp": "udp"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"applicationStatus": {
|
||||
"public.applicationStatus": {
|
||||
"name": "applicationStatus",
|
||||
"values": {
|
||||
"idle": "idle",
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"idle",
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"certificateType": {
|
||||
"public.certificateType": {
|
||||
"name": "certificateType",
|
||||
"values": {
|
||||
"letsencrypt": "letsencrypt",
|
||||
"none": "none"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"letsencrypt",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "5a1d3f2b-9c31-4125-9645-015170550b51",
|
||||
"prevId": "665483bd-5123-4c2b-beef-bfa9b91b9356"
|
||||
}
|
||||
+202
-192
@@ -1,10 +1,8 @@
|
||||
{
|
||||
"id": "7bb4bbcf-791c-4888-919e-f74bc0528b5f",
|
||||
"prevId": "5a1d3f2b-9c31-4125-9645-015170550b51",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"version": "6",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"application": {
|
||||
"public.application": {
|
||||
"name": "application",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -210,29 +208,29 @@
|
||||
"application_projectId_project_projectId_fk": {
|
||||
"name": "application_projectId_project_projectId_fk",
|
||||
"tableFrom": "application",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"application_appName_unique": {
|
||||
"name": "application_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"public.postgres": {
|
||||
"name": "postgres",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -351,29 +349,29 @@
|
||||
"postgres_projectId_project_projectId_fk": {
|
||||
"name": "postgres_projectId_project_projectId_fk",
|
||||
"tableFrom": "postgres",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"postgres_appName_unique": {
|
||||
"name": "postgres_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"public.user": {
|
||||
"name": "user",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -482,34 +480,34 @@
|
||||
"user_adminId_admin_adminId_fk": {
|
||||
"name": "user_adminId_admin_adminId_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"user_authId_auth_id_fk": {
|
||||
"name": "user_authId_auth_id_fk",
|
||||
"tableFrom": "user",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"admin": {
|
||||
"public.admin": {
|
||||
"name": "admin",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -611,21 +609,21 @@
|
||||
"admin_authId_auth_id_fk": {
|
||||
"name": "admin_authId_auth_id_fk",
|
||||
"tableFrom": "admin",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"authId"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"auth": {
|
||||
"public.auth": {
|
||||
"name": "auth",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -685,14 +683,14 @@
|
||||
"uniqueConstraints": {
|
||||
"auth_email_unique": {
|
||||
"name": "auth_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"public.project": {
|
||||
"name": "project",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -732,21 +730,21 @@
|
||||
"project_adminId_admin_adminId_fk": {
|
||||
"name": "project_adminId_admin_adminId_fk",
|
||||
"tableFrom": "project",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"domain": {
|
||||
"public.domain": {
|
||||
"name": "domain",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -814,21 +812,21 @@
|
||||
"domain_applicationId_application_applicationId_fk": {
|
||||
"name": "domain_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "domain",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mariadb": {
|
||||
"public.mariadb": {
|
||||
"name": "mariadb",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -953,29 +951,29 @@
|
||||
"mariadb_projectId_project_projectId_fk": {
|
||||
"name": "mariadb_projectId_project_projectId_fk",
|
||||
"tableFrom": "mariadb",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mariadb_appName_unique": {
|
||||
"name": "mariadb_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongo": {
|
||||
"public.mongo": {
|
||||
"name": "mongo",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1088,29 +1086,29 @@
|
||||
"mongo_projectId_project_projectId_fk": {
|
||||
"name": "mongo_projectId_project_projectId_fk",
|
||||
"tableFrom": "mongo",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mongo_appName_unique": {
|
||||
"name": "mongo_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"mysql": {
|
||||
"public.mysql": {
|
||||
"name": "mysql",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1235,29 +1233,29 @@
|
||||
"mysql_projectId_project_projectId_fk": {
|
||||
"name": "mysql_projectId_project_projectId_fk",
|
||||
"tableFrom": "mysql",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"mysql_appName_unique": {
|
||||
"name": "mysql_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"backup": {
|
||||
"public.backup": {
|
||||
"name": "backup",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1333,73 +1331,73 @@
|
||||
"backup_destinationId_destination_destinationId_fk": {
|
||||
"name": "backup_destinationId_destination_destinationId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "destination",
|
||||
"columnsFrom": [
|
||||
"destinationId"
|
||||
],
|
||||
"tableTo": "destination",
|
||||
"columnsTo": [
|
||||
"destinationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_postgresId_postgres_postgresId_fk": {
|
||||
"name": "backup_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "backup_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "backup_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"backup_mongoId_mongo_mongoId_fk": {
|
||||
"name": "backup_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "backup",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"destination": {
|
||||
"public.destination": {
|
||||
"name": "destination",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1457,21 +1455,21 @@
|
||||
"destination_adminId_admin_adminId_fk": {
|
||||
"name": "destination_adminId_admin_adminId_fk",
|
||||
"tableFrom": "destination",
|
||||
"tableTo": "admin",
|
||||
"columnsFrom": [
|
||||
"adminId"
|
||||
],
|
||||
"tableTo": "admin",
|
||||
"columnsTo": [
|
||||
"adminId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"deployment": {
|
||||
"public.deployment": {
|
||||
"name": "deployment",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1518,21 +1516,21 @@
|
||||
"deployment_applicationId_application_applicationId_fk": {
|
||||
"name": "deployment_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "deployment",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"mount": {
|
||||
"public.mount": {
|
||||
"name": "mount",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1621,86 +1619,86 @@
|
||||
"mount_applicationId_application_applicationId_fk": {
|
||||
"name": "mount_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_postgresId_postgres_postgresId_fk": {
|
||||
"name": "mount_postgresId_postgres_postgresId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "postgres",
|
||||
"columnsFrom": [
|
||||
"postgresId"
|
||||
],
|
||||
"tableTo": "postgres",
|
||||
"columnsTo": [
|
||||
"postgresId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mariadbId_mariadb_mariadbId_fk": {
|
||||
"name": "mount_mariadbId_mariadb_mariadbId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mariadb",
|
||||
"columnsFrom": [
|
||||
"mariadbId"
|
||||
],
|
||||
"tableTo": "mariadb",
|
||||
"columnsTo": [
|
||||
"mariadbId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mongoId_mongo_mongoId_fk": {
|
||||
"name": "mount_mongoId_mongo_mongoId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mongo",
|
||||
"columnsFrom": [
|
||||
"mongoId"
|
||||
],
|
||||
"tableTo": "mongo",
|
||||
"columnsTo": [
|
||||
"mongoId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_mysqlId_mysql_mysqlId_fk": {
|
||||
"name": "mount_mysqlId_mysql_mysqlId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "mysql",
|
||||
"columnsFrom": [
|
||||
"mysqlId"
|
||||
],
|
||||
"tableTo": "mysql",
|
||||
"columnsTo": [
|
||||
"mysqlId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
},
|
||||
"mount_redisId_redis_redisId_fk": {
|
||||
"name": "mount_redisId_redis_redisId_fk",
|
||||
"tableFrom": "mount",
|
||||
"tableTo": "redis",
|
||||
"columnsFrom": [
|
||||
"redisId"
|
||||
],
|
||||
"tableTo": "redis",
|
||||
"columnsTo": [
|
||||
"redisId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"certificate": {
|
||||
"public.certificate": {
|
||||
"name": "certificate",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1747,14 +1745,14 @@
|
||||
"uniqueConstraints": {
|
||||
"certificate_certificatePath_unique": {
|
||||
"name": "certificate_certificatePath_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"certificatePath"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"session": {
|
||||
"public.session": {
|
||||
"name": "session",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1782,21 +1780,21 @@
|
||||
"session_user_id_auth_id_fk": {
|
||||
"name": "session_user_id_auth_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "auth",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "auth",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redirect": {
|
||||
"public.redirect": {
|
||||
"name": "redirect",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1849,21 +1847,21 @@
|
||||
"redirect_applicationId_application_applicationId_fk": {
|
||||
"name": "redirect_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "redirect",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"security": {
|
||||
"public.security": {
|
||||
"name": "security",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1903,30 +1901,30 @@
|
||||
"security_applicationId_application_applicationId_fk": {
|
||||
"name": "security_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "security",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"security_username_applicationId_unique": {
|
||||
"name": "security_username_applicationId_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"username",
|
||||
"applicationId"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"port": {
|
||||
"public.port": {
|
||||
"name": "port",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -1966,21 +1964,21 @@
|
||||
"port_applicationId_application_applicationId_fk": {
|
||||
"name": "port_applicationId_application_applicationId_fk",
|
||||
"tableFrom": "port",
|
||||
"tableTo": "application",
|
||||
"columnsFrom": [
|
||||
"applicationId"
|
||||
],
|
||||
"tableTo": "application",
|
||||
"columnsTo": [
|
||||
"applicationId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"redis": {
|
||||
"public.redis": {
|
||||
"name": "redis",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
@@ -2087,118 +2085,130 @@
|
||||
"redis_projectId_project_projectId_fk": {
|
||||
"name": "redis_projectId_project_projectId_fk",
|
||||
"tableFrom": "redis",
|
||||
"tableTo": "project",
|
||||
"columnsFrom": [
|
||||
"projectId"
|
||||
],
|
||||
"tableTo": "project",
|
||||
"columnsTo": [
|
||||
"projectId"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"redis_appName_unique": {
|
||||
"name": "redis_appName_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"appName"
|
||||
]
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"buildType": {
|
||||
"public.buildType": {
|
||||
"name": "buildType",
|
||||
"values": {
|
||||
"dockerfile": "dockerfile",
|
||||
"heroku_buildpacks": "heroku_buildpacks",
|
||||
"paketo_buildpacks": "paketo_buildpacks",
|
||||
"nixpacks": "nixpacks"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"dockerfile",
|
||||
"heroku_buildpacks",
|
||||
"paketo_buildpacks",
|
||||
"nixpacks"
|
||||
]
|
||||
},
|
||||
"sourceType": {
|
||||
"public.sourceType": {
|
||||
"name": "sourceType",
|
||||
"values": {
|
||||
"docker": "docker",
|
||||
"git": "git",
|
||||
"github": "github"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"docker",
|
||||
"git",
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"Roles": {
|
||||
"public.Roles": {
|
||||
"name": "Roles",
|
||||
"values": {
|
||||
"admin": "admin",
|
||||
"user": "user"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"admin",
|
||||
"user"
|
||||
]
|
||||
},
|
||||
"databaseType": {
|
||||
"public.databaseType": {
|
||||
"name": "databaseType",
|
||||
"values": {
|
||||
"postgres": "postgres",
|
||||
"mariadb": "mariadb",
|
||||
"mysql": "mysql",
|
||||
"mongo": "mongo"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"postgres",
|
||||
"mariadb",
|
||||
"mysql",
|
||||
"mongo"
|
||||
]
|
||||
},
|
||||
"deploymentStatus": {
|
||||
"public.deploymentStatus": {
|
||||
"name": "deploymentStatus",
|
||||
"values": {
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"mountType": {
|
||||
"public.mountType": {
|
||||
"name": "mountType",
|
||||
"values": {
|
||||
"bind": "bind",
|
||||
"volume": "volume",
|
||||
"file": "file"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"bind",
|
||||
"volume",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"serviceType": {
|
||||
"public.serviceType": {
|
||||
"name": "serviceType",
|
||||
"values": {
|
||||
"application": "application",
|
||||
"postgres": "postgres",
|
||||
"mysql": "mysql",
|
||||
"mariadb": "mariadb",
|
||||
"mongo": "mongo",
|
||||
"redis": "redis"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"application",
|
||||
"postgres",
|
||||
"mysql",
|
||||
"mariadb",
|
||||
"mongo",
|
||||
"redis"
|
||||
]
|
||||
},
|
||||
"protocolType": {
|
||||
"public.protocolType": {
|
||||
"name": "protocolType",
|
||||
"values": {
|
||||
"tcp": "tcp",
|
||||
"udp": "udp"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"applicationStatus": {
|
||||
"public.applicationStatus": {
|
||||
"name": "applicationStatus",
|
||||
"values": {
|
||||
"idle": "idle",
|
||||
"running": "running",
|
||||
"done": "done",
|
||||
"error": "error"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"idle",
|
||||
"running",
|
||||
"done",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"certificateType": {
|
||||
"public.certificateType": {
|
||||
"name": "certificateType",
|
||||
"values": {
|
||||
"letsencrypt": "letsencrypt",
|
||||
"none": "none"
|
||||
}
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"letsencrypt",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
},
|
||||
"id": "7bb4bbcf-791c-4888-919e-f74bc0528b5f",
|
||||
"prevId": "5a1d3f2b-9c31-4125-9645-015170550b51"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,69 @@
|
||||
"when": 1714004732716,
|
||||
"tag": "0004_nice_tenebrous",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "5",
|
||||
"when": 1715551130605,
|
||||
"tag": "0005_cute_terror",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"version": "6",
|
||||
"when": 1715563165991,
|
||||
"tag": "0006_oval_jimmy_woo",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "6",
|
||||
"when": 1715563497100,
|
||||
"tag": "0007_cute_guardsmen",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"version": "6",
|
||||
"when": 1715564143641,
|
||||
"tag": "0008_lazy_sage",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"version": "6",
|
||||
"when": 1715564774423,
|
||||
"tag": "0009_majestic_spencer_smythe",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"version": "6",
|
||||
"when": 1715574037832,
|
||||
"tag": "0010_lean_black_widow",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "6",
|
||||
"when": 1715574230599,
|
||||
"tag": "0011_petite_calypso",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "6",
|
||||
"when": 1716015716708,
|
||||
"tag": "0012_chubby_umar",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "6",
|
||||
"when": 1716076179443,
|
||||
"tag": "0013_blushing_starjammers",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
-6
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dokploy",
|
||||
"version": "v0.0.4",
|
||||
"version": "v0.1.0",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
"type": "module",
|
||||
@@ -12,15 +12,17 @@
|
||||
"setup": "tsx -r dotenv/config setup.ts && sleep 5 && pnpm run migration:run",
|
||||
"reset-password": "node dist/reset-password.mjs",
|
||||
"dev": "tsx watch -r dotenv/config ./server/server.ts --project tsconfig.server.json ",
|
||||
"migration:generate": "drizzle-kit generate:pg --config ./server/db/drizzle.config.ts",
|
||||
"studio":"drizzle-kit studio --config ./server/db/drizzle.config.ts",
|
||||
"migration:generate": "drizzle-kit generate --config ./server/db/drizzle.config.ts",
|
||||
"migration:run": "tsx -r dotenv/config migration.ts",
|
||||
"migration:up":"drizzle-kit up --config ./server/db/drizzle.config.ts",
|
||||
"migration:drop": "drizzle-kit drop --config ./server/db/drizzle.config.ts",
|
||||
"db:push": "drizzle-kit push:pg --config ./server/db/drizzle.config.ts",
|
||||
"db:push": "drizzle-kit --config ./server/db/drizzle.config.ts",
|
||||
"db:truncate": "tsx -r dotenv/config ./server/db/reset.ts",
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"lint": "biome lint",
|
||||
"db:seed": "dotenv tsx ./server/db/seed.ts",
|
||||
"db:clean": "dotenv tsx ./server/db/reset.ts",
|
||||
"db:seed": "tsx -r dotenv/config ./server/db/seed.ts",
|
||||
"db:clean": "tsx -r dotenv/config ./server/db/reset.ts",
|
||||
"docker:build": "./docker/build.sh",
|
||||
"docker:push": "./docker/push.sh",
|
||||
"docker:build:canary": "./docker/build.sh canary",
|
||||
@@ -29,6 +31,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.515.0",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@lucia-auth/adapter-drizzle": "1.0.7",
|
||||
@@ -57,6 +61,8 @@
|
||||
"@trpc/next": "^10.43.6",
|
||||
"@trpc/react-query": "^10.43.6",
|
||||
"@trpc/server": "^10.43.6",
|
||||
"@uiw/codemirror-theme-github": "^4.22.1",
|
||||
"@uiw/react-codemirror": "^4.22.1",
|
||||
"@xterm/addon-attach": "0.10.0",
|
||||
"@xterm/xterm": "^5.4.0",
|
||||
"bcrypt": "5.1.1",
|
||||
@@ -116,7 +122,7 @@
|
||||
"@types/tar-fs": "2.0.4",
|
||||
"@types/ws": "8.5.10",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"drizzle-kit": "^0.20.14",
|
||||
"drizzle-kit": "^0.21.1",
|
||||
"esbuild": "0.20.2",
|
||||
"localtunnel": "2.0.2",
|
||||
"postcss": "^8.4.31",
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@ export default function Custom404({ statusCode }: Props) {
|
||||
<div className="container mx-auto h-screen items-center justify-center flex">
|
||||
<div className="-mx-4 flex">
|
||||
<div className="w-full px-4">
|
||||
<div className="mx-auto max-w-[400px] text-center">
|
||||
<h2 className="mb-2 text-[50px] font-bold leading-none text-white sm:text-[80px] md:text-[100px]">
|
||||
<div className="mx-auto max-w-[700px] text-center">
|
||||
<h2 className="mb-2 text-[50px] font-bold leading-none text-white sm:text-[80px]">
|
||||
{statusCode
|
||||
? `An error ${statusCode} occurred on server`
|
||||
: "An error occurred on client"}
|
||||
|
||||
@@ -35,7 +35,25 @@ export default async function handler(
|
||||
const deploymentTitle = extractCommitMessage(req.headers, req.body);
|
||||
|
||||
const sourceType = application.sourceType;
|
||||
if (sourceType === "github") {
|
||||
|
||||
if (sourceType === "docker") {
|
||||
const applicationDockerTag = extractImageTag(application.dockerImage);
|
||||
const webhookDockerTag = extractImageTagFromRequest(
|
||||
req.headers,
|
||||
req.body,
|
||||
);
|
||||
if (
|
||||
applicationDockerTag &&
|
||||
webhookDockerTag &&
|
||||
webhookDockerTag !== applicationDockerTag
|
||||
) {
|
||||
res.status(301).json({
|
||||
message: `Application Image Tag (${applicationDockerTag}) doesn't match request event payload Image Tag (${webhookDockerTag}).`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (sourceType === "github") {
|
||||
const branchName = extractBranchName(req.headers, req.body);
|
||||
if (!branchName || branchName !== application.branch) {
|
||||
res.status(301).json({ message: "Branch Not Match" });
|
||||
@@ -79,6 +97,36 @@ export default async function handler(
|
||||
res.status(400).json({ message: "Error To Deploy Application", error });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last part of the image name, which is the tag
|
||||
* Example: "my-image" => null
|
||||
* Example: "my-image:latest" => "latest"
|
||||
* Example: "my-image:1.0.0" => "1.0.0"
|
||||
* Example: "myregistryhost:5000/fedora/httpd:version1.0" => "version1.0"
|
||||
* @link https://docs.docker.com/reference/cli/docker/image/tag/
|
||||
*/
|
||||
function extractImageTag(dockerImage: string | null) {
|
||||
if (!dockerImage || typeof dockerImage !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tag = dockerImage.split(":").pop();
|
||||
return tag === dockerImage ? "latest" : tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://docs.docker.com/docker-hub/webhooks/#example-webhook-payload
|
||||
*/
|
||||
function extractImageTagFromRequest(headers: any, body: any): string | null {
|
||||
if (headers["user-agent"]?.includes("Go-http-client")) {
|
||||
if (body.push_data && body.repository) {
|
||||
return body.push_data.tag;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function extractCommitMessage(headers: any, body: any) {
|
||||
// GitHub
|
||||
if (headers["x-github-event"]) {
|
||||
|
||||
@@ -212,7 +212,7 @@ const Project = (
|
||||
}}
|
||||
className="group relative cursor-pointer bg-transparent transition-colors hover:bg-card h-fit"
|
||||
>
|
||||
<div className="absolute -right-1 -top-1">
|
||||
<div className="absolute -right-1 -top-2">
|
||||
<StatusTooltip status={service.status} />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ShowClusterSettings } from "@/components/dashboard/application/advanced/cluster/show-cluster-settings";
|
||||
import { AddCommand } from "@/components/dashboard/application/advanced/general/add-command";
|
||||
import { ShowPorts } from "@/components/dashboard/application/advanced/ports/show-port";
|
||||
import { ShowRedirects } from "@/components/dashboard/application/advanced/redirects/show-redirects";
|
||||
@@ -134,7 +135,7 @@ const Service = (
|
||||
<TabsTrigger value="domains">Domains</TabsTrigger>
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdateApplication applicationId={applicationId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeleteApplication applicationId={applicationId} />
|
||||
@@ -175,6 +176,7 @@ const Service = (
|
||||
<TabsContent value="advanced">
|
||||
<div className="flex flex-col gap-4 pt-2.5">
|
||||
<AddCommand applicationId={applicationId} />
|
||||
<ShowClusterSettings applicationId={applicationId} />
|
||||
<ShowApplicationResources applicationId={applicationId} />
|
||||
<ShowVolumes applicationId={applicationId} />
|
||||
<ShowRedirects applicationId={applicationId} />
|
||||
|
||||
@@ -116,7 +116,7 @@ const Mariadb = (
|
||||
<TabsTrigger value="logs">Logs</TabsTrigger>
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdateMariadb mariadbId={mariadbId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeleteMariadb mariadbId={mariadbId} />
|
||||
|
||||
@@ -118,7 +118,7 @@ const Mongo = (
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdateMongo mongoId={mongoId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeleteMongo mongoId={mongoId} />
|
||||
|
||||
@@ -117,7 +117,7 @@ const MySql = (
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdateMysql mysqlId={mysqlId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeleteMysql mysqlId={mysqlId} />
|
||||
|
||||
@@ -118,7 +118,7 @@ const Postgresql = (
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdatePostgres postgresId={postgresId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeletePostgres postgresId={postgresId} />
|
||||
|
||||
@@ -116,7 +116,7 @@ const Redis = (
|
||||
<TabsTrigger value="advanced">Advanced</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<div className="flex flex-row gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<UpdateRedis redisId={redisId} />
|
||||
{(auth?.rol === "admin" || user?.canDeleteServices) && (
|
||||
<DeleteRedis redisId={redisId} />
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { ShowRegistry } from "@/components/dashboard/settings/cluster/registry/show-registry";
|
||||
import { ShowNodes } from "@/components/dashboard/settings/cluster/nodes/show-nodes";
|
||||
import { DashboardLayout } from "@/components/layouts/dashboard-layout";
|
||||
import { SettingsLayout } from "@/components/layouts/settings-layout";
|
||||
import { validateRequest } from "@/server/auth/auth";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import React, { type ReactElement } from "react";
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<ShowRegistry />
|
||||
<ShowNodes />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
||||
Page.getLayout = (page: ReactElement) => {
|
||||
return (
|
||||
<DashboardLayout tab={"settings"}>
|
||||
<SettingsLayout>{page}</SettingsLayout>
|
||||
</DashboardLayout>
|
||||
);
|
||||
};
|
||||
export async function getServerSideProps(
|
||||
ctx: GetServerSidePropsContext<{ serviceId: string }>,
|
||||
) {
|
||||
const { user, session } = await validateRequest(ctx.req, ctx.res);
|
||||
if (!user || user.rol === "user") {
|
||||
return {
|
||||
redirect: {
|
||||
permanent: true,
|
||||
destination: "/",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
||||
+1
-1
@@ -193,7 +193,7 @@ export default function Home({ hasAdmin }: Props) {
|
||||
<div className="mt-4 text-sm flex flex-row justify-center gap-2">
|
||||
<Link
|
||||
className="hover:underline text-muted-foreground"
|
||||
href="https://docs.dokploy.com/reset-password"
|
||||
href="https://docs.dokploy.com/get-started/reset-password"
|
||||
target="_blank"
|
||||
>
|
||||
Lost your password?
|
||||
|
||||
Generated
+254
-30
@@ -8,6 +8,12 @@ dependencies:
|
||||
'@aws-sdk/client-s3':
|
||||
specifier: 3.515.0
|
||||
version: 3.515.0
|
||||
'@codemirror/lang-json':
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
'@codemirror/lang-yaml':
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.1(@codemirror/view@6.26.3)
|
||||
'@faker-js/faker':
|
||||
specifier: ^8.4.1
|
||||
version: 8.4.1
|
||||
@@ -92,6 +98,12 @@ dependencies:
|
||||
'@trpc/server':
|
||||
specifier: ^10.43.6
|
||||
version: 10.45.2
|
||||
'@uiw/codemirror-theme-github':
|
||||
specifier: ^4.22.1
|
||||
version: 4.22.1(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)
|
||||
'@uiw/react-codemirror':
|
||||
specifier: ^4.22.1
|
||||
version: 4.22.1(@babel/runtime@7.24.0)(@codemirror/autocomplete@6.16.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.26.3)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@xterm/addon-attach':
|
||||
specifier: 0.10.0
|
||||
version: 0.10.0(@xterm/xterm@5.4.0)
|
||||
@@ -266,8 +278,8 @@ devDependencies:
|
||||
specifier: ^10.4.14
|
||||
version: 10.4.18(postcss@8.4.35)
|
||||
drizzle-kit:
|
||||
specifier: ^0.20.14
|
||||
version: 0.20.14
|
||||
specifier: ^0.21.1
|
||||
version: 0.21.1
|
||||
esbuild:
|
||||
specifier: 0.20.2
|
||||
version: 0.20.2
|
||||
@@ -983,6 +995,7 @@ packages:
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
@@ -992,6 +1005,7 @@ packages:
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
@@ -1001,6 +1015,7 @@ packages:
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
@@ -1010,6 +1025,7 @@ packages:
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
@@ -1032,11 +1048,96 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@drizzle-team/studio@0.0.39:
|
||||
resolution: {integrity: sha512-c5Hkm7MmQC2n5qAsKShjQrHoqlfGslB8+qWzsGGZ+2dHMRTNG60UuzalF0h0rvBax5uzPXuGkYLGaQ+TUX3yMw==}
|
||||
/@codemirror/autocomplete@6.16.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)(@lezer/common@1.2.1):
|
||||
resolution: {integrity: sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==}
|
||||
peerDependencies:
|
||||
'@codemirror/language': ^6.0.0
|
||||
'@codemirror/state': ^6.0.0
|
||||
'@codemirror/view': ^6.0.0
|
||||
'@lezer/common': ^1.0.0
|
||||
dependencies:
|
||||
superjson: 2.2.1
|
||||
dev: true
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
'@lezer/common': 1.2.1
|
||||
dev: false
|
||||
|
||||
/@codemirror/commands@6.5.0:
|
||||
resolution: {integrity: sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==}
|
||||
dependencies:
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
'@lezer/common': 1.2.1
|
||||
dev: false
|
||||
|
||||
/@codemirror/lang-json@6.0.1:
|
||||
resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==}
|
||||
dependencies:
|
||||
'@codemirror/language': 6.10.1
|
||||
'@lezer/json': 1.0.2
|
||||
dev: false
|
||||
|
||||
/@codemirror/lang-yaml@6.1.1(@codemirror/view@6.26.3):
|
||||
resolution: {integrity: sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==}
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.16.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)(@lezer/common@1.2.1)
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/state': 6.4.1
|
||||
'@lezer/common': 1.2.1
|
||||
'@lezer/highlight': 1.2.0
|
||||
'@lezer/yaml': 1.0.3
|
||||
transitivePeerDependencies:
|
||||
- '@codemirror/view'
|
||||
dev: false
|
||||
|
||||
/@codemirror/language@6.10.1:
|
||||
resolution: {integrity: sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==}
|
||||
dependencies:
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
'@lezer/common': 1.2.1
|
||||
'@lezer/highlight': 1.2.0
|
||||
'@lezer/lr': 1.4.0
|
||||
style-mod: 4.1.2
|
||||
dev: false
|
||||
|
||||
/@codemirror/lint@6.8.0:
|
||||
resolution: {integrity: sha512-lsFofvaw0lnPRJlQylNsC4IRt/1lI4OD/yYslrSGVndOJfStc58v+8p9dgGiD90ktOfL7OhBWns1ZETYgz0EJA==}
|
||||
dependencies:
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
crelt: 1.0.6
|
||||
dev: false
|
||||
|
||||
/@codemirror/search@6.5.6:
|
||||
resolution: {integrity: sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==}
|
||||
dependencies:
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
crelt: 1.0.6
|
||||
dev: false
|
||||
|
||||
/@codemirror/state@6.4.1:
|
||||
resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==}
|
||||
dev: false
|
||||
|
||||
/@codemirror/theme-one-dark@6.1.2:
|
||||
resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
|
||||
dependencies:
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
'@lezer/highlight': 1.2.0
|
||||
dev: false
|
||||
|
||||
/@codemirror/view@6.26.3:
|
||||
resolution: {integrity: sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==}
|
||||
dependencies:
|
||||
'@codemirror/state': 6.4.1
|
||||
style-mod: 4.1.2
|
||||
w3c-keyname: 2.2.8
|
||||
dev: false
|
||||
|
||||
/@emnapi/core@0.45.0:
|
||||
resolution: {integrity: sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw==}
|
||||
@@ -1769,6 +1870,38 @@ packages:
|
||||
resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==}
|
||||
dev: false
|
||||
|
||||
/@lezer/common@1.2.1:
|
||||
resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
|
||||
dev: false
|
||||
|
||||
/@lezer/highlight@1.2.0:
|
||||
resolution: {integrity: sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==}
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.1
|
||||
dev: false
|
||||
|
||||
/@lezer/json@1.0.2:
|
||||
resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==}
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.1
|
||||
'@lezer/highlight': 1.2.0
|
||||
'@lezer/lr': 1.4.0
|
||||
dev: false
|
||||
|
||||
/@lezer/lr@1.4.0:
|
||||
resolution: {integrity: sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==}
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.1
|
||||
dev: false
|
||||
|
||||
/@lezer/yaml@1.0.3:
|
||||
resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==}
|
||||
dependencies:
|
||||
'@lezer/common': 1.2.1
|
||||
'@lezer/highlight': 1.2.0
|
||||
'@lezer/lr': 1.4.0
|
||||
dev: false
|
||||
|
||||
/@lucia-auth/adapter-drizzle@1.0.7(lucia@3.1.1):
|
||||
resolution: {integrity: sha512-X/V7fLBca8EC/gPXCntwbQpb0+F9oEuRoHElvsi9rCrdnGhCMNxHgwAvgiQ6pes+rIYpyvx4n3hvjqo/fPo03A==}
|
||||
peerDependencies:
|
||||
@@ -1880,6 +2013,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -1889,6 +2023,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -1898,6 +2033,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -1907,6 +2043,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -1997,6 +2134,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2006,6 +2144,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2015,6 +2154,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2024,6 +2164,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2144,6 +2285,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2153,6 +2295,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2162,6 +2305,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -2171,6 +2315,7 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
@@ -4392,6 +4537,75 @@ packages:
|
||||
'@types/node': 18.19.24
|
||||
dev: true
|
||||
|
||||
/@uiw/codemirror-extensions-basic-setup@4.22.1(@codemirror/autocomplete@6.16.0)(@codemirror/commands@6.5.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3):
|
||||
resolution: {integrity: sha512-Iz8eFaZBNrwjaAADszOxOv2byDMn4rqob/luuSPAzJjTrSn5KawRXcoNLoWGPGNO6Mils6bIly/g2LaU34otNw==}
|
||||
peerDependencies:
|
||||
'@codemirror/autocomplete': '>=6.0.0'
|
||||
'@codemirror/commands': '>=6.0.0'
|
||||
'@codemirror/language': '>=6.0.0'
|
||||
'@codemirror/lint': '>=6.0.0'
|
||||
'@codemirror/search': '>=6.0.0'
|
||||
'@codemirror/state': '>=6.0.0'
|
||||
'@codemirror/view': '>=6.0.0'
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.16.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)(@lezer/common@1.2.1)
|
||||
'@codemirror/commands': 6.5.0
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/lint': 6.8.0
|
||||
'@codemirror/search': 6.5.6
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
dev: false
|
||||
|
||||
/@uiw/codemirror-theme-github@4.22.1(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3):
|
||||
resolution: {integrity: sha512-trotMuMd8PQjvst4hg9b5Mz5qlD5HQzPVAZQFlQKaaF8mEKMk77nFCPhfD3Rg2WEq02lx6fqmOcErQjY0GRHew==}
|
||||
dependencies:
|
||||
'@uiw/codemirror-themes': 4.22.1(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)
|
||||
transitivePeerDependencies:
|
||||
- '@codemirror/language'
|
||||
- '@codemirror/state'
|
||||
- '@codemirror/view'
|
||||
dev: false
|
||||
|
||||
/@uiw/codemirror-themes@4.22.1(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3):
|
||||
resolution: {integrity: sha512-5TeB8wCc0aNd3YEhzOvgekpAFQfEm4fCTUcGmEIQqaRNgKAM83HYNpE1JF2j7x2oDFugdiO0yJynS6bo1zVOuw==}
|
||||
peerDependencies:
|
||||
'@codemirror/language': '>=6.0.0'
|
||||
'@codemirror/state': '>=6.0.0'
|
||||
'@codemirror/view': '>=6.0.0'
|
||||
dependencies:
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
dev: false
|
||||
|
||||
/@uiw/react-codemirror@4.22.1(@babel/runtime@7.24.0)(@codemirror/autocomplete@6.16.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.26.3)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-yrq9FdGZ6E4Rh+7W0xyirSEeESGyG/k54/DfFqSk40fqel/3x/3fqjIImEZUYPxxgFPmZ3RtP+O0Em46nwRvgg==}
|
||||
peerDependencies:
|
||||
'@babel/runtime': '>=7.11.0'
|
||||
'@codemirror/state': '>=6.0.0'
|
||||
'@codemirror/theme-one-dark': '>=6.0.0'
|
||||
'@codemirror/view': '>=6.0.0'
|
||||
codemirror: '>=6.0.0'
|
||||
react: '>=16.8.0'
|
||||
react-dom: '>=16.8.0'
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.0
|
||||
'@codemirror/commands': 6.5.0
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/theme-one-dark': 6.1.2
|
||||
'@codemirror/view': 6.26.3
|
||||
'@uiw/codemirror-extensions-basic-setup': 4.22.1(@codemirror/autocomplete@6.16.0)(@codemirror/commands@6.5.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.8.0)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)
|
||||
codemirror: 6.0.1(@lezer/common@1.2.1)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- '@codemirror/autocomplete'
|
||||
- '@codemirror/language'
|
||||
- '@codemirror/lint'
|
||||
- '@codemirror/search'
|
||||
dev: false
|
||||
|
||||
/@xterm/addon-attach@0.10.0(@xterm/xterm@5.4.0):
|
||||
resolution: {integrity: sha512-ES/XO8pC1tPHSkh4j7qzM8ajFt++u8KMvfRc9vKIbjHTDOxjl9IUVo+vcQgLn3FTCM3w2czTvBss8nMWlD83Cg==}
|
||||
peerDependencies:
|
||||
@@ -4728,19 +4942,9 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/camelcase@7.0.1:
|
||||
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
|
||||
engines: {node: '>=14.16'}
|
||||
dev: true
|
||||
|
||||
/caniuse-lite@1.0.30001598:
|
||||
resolution: {integrity: sha512-j8mQRDziG94uoBfeFuqsJUNECW37DXpnvhcMJMdlH2u3MRkq1sAI0LJcXP1i/Py0KbSIC4UDj8YHPrTn5YsL+Q==}
|
||||
|
||||
/chalk@5.3.0:
|
||||
resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
|
||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/chokidar@3.6.0:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
@@ -4841,6 +5045,20 @@ packages:
|
||||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/codemirror@6.0.1(@lezer/common@1.2.1):
|
||||
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||
dependencies:
|
||||
'@codemirror/autocomplete': 6.16.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.3)(@lezer/common@1.2.1)
|
||||
'@codemirror/commands': 6.5.0
|
||||
'@codemirror/language': 6.10.1
|
||||
'@codemirror/lint': 6.8.0
|
||||
'@codemirror/search': 6.5.6
|
||||
'@codemirror/state': 6.4.1
|
||||
'@codemirror/view': 6.26.3
|
||||
transitivePeerDependencies:
|
||||
- '@lezer/common'
|
||||
dev: false
|
||||
|
||||
/color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -4877,6 +5095,7 @@ packages:
|
||||
engines: {node: '>=12.13'}
|
||||
dependencies:
|
||||
is-what: 4.1.16
|
||||
dev: false
|
||||
|
||||
/copy-to-clipboard@3.3.3:
|
||||
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
|
||||
@@ -4894,6 +5113,10 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/crelt@1.0.6:
|
||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||
dev: false
|
||||
|
||||
/cron-parser@4.9.0:
|
||||
resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -5143,14 +5366,11 @@ packages:
|
||||
wordwrap: 1.0.0
|
||||
dev: true
|
||||
|
||||
/drizzle-kit@0.20.14:
|
||||
resolution: {integrity: sha512-0fHv3YIEaUcSVPSGyaaBfOi9bmpajjhbJNdPsRMIUvYdLVxBu9eGjH8mRc3Qk7HVmEidFc/lhG1YyJhoXrn5yA==}
|
||||
/drizzle-kit@0.21.1:
|
||||
resolution: {integrity: sha512-Sp7OnCdROiE2ebMuHsAfrnRoHVGYCvErQxUh7/0l6R1caHssZu9oZu/hW9rLU19xnTK4/y3iSe3sL0Cc530wCg==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@drizzle-team/studio': 0.0.39
|
||||
'@esbuild-kit/esm-loader': 2.6.5
|
||||
camelcase: 7.0.1
|
||||
chalk: 5.3.0
|
||||
commander: 9.5.0
|
||||
env-paths: 3.0.0
|
||||
esbuild: 0.19.12
|
||||
@@ -5158,8 +5378,6 @@ packages:
|
||||
glob: 8.1.0
|
||||
hanji: 0.0.5
|
||||
json-diff: 0.9.0
|
||||
minimatch: 7.4.6
|
||||
semver: 7.6.0
|
||||
zod: 3.23.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -5834,6 +6052,7 @@ packages:
|
||||
/is-what@4.1.16:
|
||||
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
|
||||
engines: {node: '>=12.13'}
|
||||
dev: false
|
||||
|
||||
/isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
@@ -6015,6 +6234,7 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/lru-queue@0.1.0:
|
||||
resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
|
||||
@@ -6095,13 +6315,6 @@ packages:
|
||||
brace-expansion: 2.0.1
|
||||
dev: true
|
||||
|
||||
/minimatch@7.4.6:
|
||||
resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
brace-expansion: 2.0.1
|
||||
dev: true
|
||||
|
||||
/minimatch@9.0.3:
|
||||
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
@@ -6909,6 +7122,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: false
|
||||
|
||||
/set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
@@ -7038,6 +7252,10 @@ packages:
|
||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||
dev: false
|
||||
|
||||
/style-mod@4.1.2:
|
||||
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
|
||||
dev: false
|
||||
|
||||
/styled-jsx@5.1.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -7073,6 +7291,7 @@ packages:
|
||||
engines: {node: '>=16'}
|
||||
dependencies:
|
||||
copy-anything: 3.0.5
|
||||
dev: false
|
||||
|
||||
/supports-preserve-symlinks-flag@1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
@@ -7351,6 +7570,10 @@ packages:
|
||||
d3-timer: 3.0.1
|
||||
dev: false
|
||||
|
||||
/w3c-keyname@2.2.8:
|
||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||
dev: false
|
||||
|
||||
/webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
dev: false
|
||||
@@ -7456,6 +7679,7 @@ packages:
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: false
|
||||
|
||||
/yaml@2.4.1:
|
||||
resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user