mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-10 16:35:26 +02:00
Compare commits
3 Commits
copilot/fi
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4ec77ade8 | ||
|
|
5f441f5b54 | ||
|
|
ed1e3244c6 |
@@ -206,38 +206,4 @@ describe("getRegistryTag", () => {
|
|||||||
expect(result).toBe("docker.io/myuser/repo");
|
expect(result).toBe("docker.io/myuser/repo");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("special characters in username", () => {
|
|
||||||
it("should handle Harbor robot account username with $ (e.g. robot$library+dokploy)", () => {
|
|
||||||
const registry = createMockRegistry({
|
|
||||||
username: "robot$library+dokploy",
|
|
||||||
});
|
|
||||||
const result = getRegistryTag(registry, "nginx");
|
|
||||||
expect(result).toBe("docker.io/robot$library+dokploy/nginx");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should handle username with $ and other special characters", () => {
|
|
||||||
const registry = createMockRegistry({
|
|
||||||
username: "robot$test+app",
|
|
||||||
});
|
|
||||||
const result = getRegistryTag(registry, "myapp:latest");
|
|
||||||
expect(result).toBe("docker.io/robot$test+app/myapp:latest");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should handle username with multiple $ symbols", () => {
|
|
||||||
const registry = createMockRegistry({
|
|
||||||
username: "user$name$test",
|
|
||||||
});
|
|
||||||
const result = getRegistryTag(registry, "app");
|
|
||||||
expect(result).toBe("docker.io/user$name$test/app");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should handle username with + and - symbols", () => {
|
|
||||||
const registry = createMockRegistry({
|
|
||||||
username: "robot+test-user",
|
|
||||||
});
|
|
||||||
const result = getRegistryTag(registry, "nginx:latest");
|
|
||||||
expect(result).toBe("docker.io/robot+test-user/nginx:latest");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Domain } from "@dokploy/server";
|
import type { Domain } from "@dokploy/server";
|
||||||
import { createDomainLabels } from "@dokploy/server";
|
import { createDomainLabels } from "@dokploy/server";
|
||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { parse, stringify } from "yaml";
|
import { parse, stringify } from "yaml";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regression tests for Traefik Host rule label format.
|
* Regression tests for Traefik Host rule label format.
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import {
|
import { Input } from "@/components/ui/input";
|
||||||
createConverter,
|
|
||||||
NumberInputWithSteps,
|
|
||||||
} from "@/components/ui/number-input";
|
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
@@ -33,23 +30,6 @@ import {
|
|||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
const CPU_STEP = 0.25;
|
|
||||||
const MEMORY_STEP_MB = 256;
|
|
||||||
|
|
||||||
const formatNumber = (value: number, decimals = 2): string =>
|
|
||||||
Number.isInteger(value) ? String(value) : value.toFixed(decimals);
|
|
||||||
|
|
||||||
const cpuConverter = createConverter(1_000_000_000, (cpu) =>
|
|
||||||
cpu <= 0 ? "" : `${formatNumber(cpu)} CPU`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const memoryConverter = createConverter(1024 * 1024, (mb) => {
|
|
||||||
if (mb <= 0) return "";
|
|
||||||
return mb >= 1024
|
|
||||||
? `${formatNumber(mb / 1024)} GB`
|
|
||||||
: `${formatNumber(mb)} MB`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const addResourcesSchema = z.object({
|
const addResourcesSchema = z.object({
|
||||||
memoryReservation: z.string().optional(),
|
memoryReservation: z.string().optional(),
|
||||||
cpuLimit: z.string().optional(),
|
cpuLimit: z.string().optional(),
|
||||||
@@ -71,7 +51,6 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddResources = z.infer<typeof addResourcesSchema>;
|
type AddResources = z.infer<typeof addResourcesSchema>;
|
||||||
|
|
||||||
export const ShowResources = ({ id, type }: Props) => {
|
export const ShowResources = ({ id, type }: Props) => {
|
||||||
const queryMap = {
|
const queryMap = {
|
||||||
postgres: () =>
|
postgres: () =>
|
||||||
@@ -184,20 +163,16 @@ export const ShowResources = ({ id, type }: Props) => {
|
|||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
Memory hard limit in bytes. Example: 1GB =
|
Memory hard limit in bytes. Example: 1GB =
|
||||||
1073741824 bytes. Use +/- buttons to adjust by
|
1073741824 bytes
|
||||||
256 MB.
|
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<NumberInputWithSteps
|
<Input
|
||||||
value={field.value}
|
|
||||||
onChange={field.onChange}
|
|
||||||
placeholder="1073741824 (1GB in bytes)"
|
placeholder="1073741824 (1GB in bytes)"
|
||||||
step={MEMORY_STEP_MB}
|
{...field}
|
||||||
converter={memoryConverter}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -223,20 +198,16 @@ export const ShowResources = ({ id, type }: Props) => {
|
|||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
Memory soft limit in bytes. Example: 256MB =
|
Memory soft limit in bytes. Example: 256MB =
|
||||||
268435456 bytes. Use +/- buttons to adjust by 256
|
268435456 bytes
|
||||||
MB.
|
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<NumberInputWithSteps
|
<Input
|
||||||
value={field.value}
|
|
||||||
onChange={field.onChange}
|
|
||||||
placeholder="268435456 (256MB in bytes)"
|
placeholder="268435456 (256MB in bytes)"
|
||||||
step={MEMORY_STEP_MB}
|
{...field}
|
||||||
converter={memoryConverter}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -263,20 +234,17 @@ export const ShowResources = ({ id, type }: Props) => {
|
|||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
CPU quota in units of 10^-9 CPUs. Example: 2
|
CPU quota in units of 10^-9 CPUs. Example: 2
|
||||||
CPUs = 2000000000. Use +/- buttons to adjust by
|
CPUs = 2000000000
|
||||||
0.25 CPU.
|
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<NumberInputWithSteps
|
<Input
|
||||||
value={field.value}
|
|
||||||
onChange={field.onChange}
|
|
||||||
placeholder="2000000000 (2 CPUs)"
|
placeholder="2000000000 (2 CPUs)"
|
||||||
step={CPU_STEP}
|
{...field}
|
||||||
converter={cpuConverter}
|
value={field.value?.toString() || ""}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -303,21 +271,14 @@ export const ShowResources = ({ id, type }: Props) => {
|
|||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>
|
<p>
|
||||||
CPU shares (relative weight). Example: 1 CPU =
|
CPU shares (relative weight). Example: 1 CPU =
|
||||||
1000000000. Use +/- buttons to adjust by 0.25
|
1000000000
|
||||||
CPU.
|
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<NumberInputWithSteps
|
<Input placeholder="1000000000 (1 CPU)" {...field} />
|
||||||
value={field.value}
|
|
||||||
onChange={field.onChange}
|
|
||||||
placeholder="1000000000 (1 CPU)"
|
|
||||||
step={CPU_STEP}
|
|
||||||
converter={cpuConverter}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export const ShowPreviewSettings = ({ applicationId }: Props) => {
|
|||||||
previewCertificateType: data.previewCertificateType || "none",
|
previewCertificateType: data.previewCertificateType || "none",
|
||||||
previewCustomCertResolver: data.previewCustomCertResolver || "",
|
previewCustomCertResolver: data.previewCustomCertResolver || "",
|
||||||
previewRequireCollaboratorPermissions:
|
previewRequireCollaboratorPermissions:
|
||||||
data.previewRequireCollaboratorPermissions ?? true,
|
data.previewRequireCollaboratorPermissions || true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
|
||||||
ChevronsUpDown,
|
|
||||||
DatabaseZap,
|
DatabaseZap,
|
||||||
Info,
|
Info,
|
||||||
PenBoxIcon,
|
PenBoxIcon,
|
||||||
@@ -15,14 +13,6 @@ import { z } from "zod";
|
|||||||
import { AlertBlock } from "@/components/shared/alert-block";
|
import { AlertBlock } from "@/components/shared/alert-block";
|
||||||
import { CodeEditor } from "@/components/shared/code-editor";
|
import { CodeEditor } from "@/components/shared/code-editor";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from "@/components/ui/command";
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -41,12 +31,6 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from "@/components/ui/popover";
|
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@@ -64,7 +48,6 @@ import {
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import type { CacheType } from "../domains/handle-domain";
|
import type { CacheType } from "../domains/handle-domain";
|
||||||
import { getTimezoneLabel, TIMEZONES } from "./timezones";
|
|
||||||
|
|
||||||
export const commonCronExpressions = [
|
export const commonCronExpressions = [
|
||||||
{ label: "Every minute", value: "* * * * *" },
|
{ label: "Every minute", value: "* * * * *" },
|
||||||
@@ -77,6 +60,30 @@ export const commonCronExpressions = [
|
|||||||
{ label: "Custom", value: "custom" },
|
{ label: "Custom", value: "custom" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const commonTimezones = [
|
||||||
|
{ label: "UTC (Coordinated Universal Time)", value: "UTC" },
|
||||||
|
{ label: "America/New_York (Eastern Time)", value: "America/New_York" },
|
||||||
|
{ label: "America/Chicago (Central Time)", value: "America/Chicago" },
|
||||||
|
{ label: "America/Denver (Mountain Time)", value: "America/Denver" },
|
||||||
|
{ label: "America/Los_Angeles (Pacific Time)", value: "America/Los_Angeles" },
|
||||||
|
{
|
||||||
|
label: "America/Mexico_City (Central Mexico)",
|
||||||
|
value: "America/Mexico_City",
|
||||||
|
},
|
||||||
|
{ label: "America/Sao_Paulo (Brasilia Time)", value: "America/Sao_Paulo" },
|
||||||
|
{ label: "Europe/London (Greenwich Mean Time)", value: "Europe/London" },
|
||||||
|
{ label: "Europe/Paris (Central European Time)", value: "Europe/Paris" },
|
||||||
|
{ label: "Europe/Berlin (Central European Time)", value: "Europe/Berlin" },
|
||||||
|
{ label: "Asia/Tokyo (Japan Standard Time)", value: "Asia/Tokyo" },
|
||||||
|
{ label: "Asia/Shanghai (China Standard Time)", value: "Asia/Shanghai" },
|
||||||
|
{ label: "Asia/Dubai (Gulf Standard Time)", value: "Asia/Dubai" },
|
||||||
|
{ label: "Asia/Kolkata (India Standard Time)", value: "Asia/Kolkata" },
|
||||||
|
{
|
||||||
|
label: "Australia/Sydney (Australian Eastern Time)",
|
||||||
|
value: "Australia/Sydney",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const formSchema = z
|
const formSchema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().min(1, "Name is required"),
|
name: z.string().min(1, "Name is required"),
|
||||||
@@ -505,60 +512,25 @@ export const HandleSchedules = ({ id, scheduleId, scheduleType }: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Popover>
|
<Select
|
||||||
<PopoverTrigger asChild>
|
onValueChange={(value) => {
|
||||||
<FormControl>
|
field.onChange(value);
|
||||||
<Button
|
}}
|
||||||
variant="outline"
|
value={field.value}
|
||||||
className={cn(
|
>
|
||||||
"w-full justify-between !bg-input",
|
<FormControl>
|
||||||
!field.value && "text-muted-foreground",
|
<SelectTrigger>
|
||||||
)}
|
<SelectValue placeholder="UTC (default)" />
|
||||||
>
|
</SelectTrigger>
|
||||||
{getTimezoneLabel(field.value)}
|
</FormControl>
|
||||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
<SelectContent>
|
||||||
</Button>
|
{commonTimezones.map((tz) => (
|
||||||
</FormControl>
|
<SelectItem key={tz.value} value={tz.value}>
|
||||||
</PopoverTrigger>
|
{tz.label}
|
||||||
<PopoverContent className="w-[400px] p-0" align="start">
|
</SelectItem>
|
||||||
<Command>
|
))}
|
||||||
<CommandInput
|
</SelectContent>
|
||||||
placeholder="Search timezone..."
|
</Select>
|
||||||
className="h-9"
|
|
||||||
/>
|
|
||||||
<CommandList>
|
|
||||||
<CommandEmpty>No timezone found.</CommandEmpty>
|
|
||||||
<ScrollArea className="h-72">
|
|
||||||
{Object.entries(TIMEZONES).map(
|
|
||||||
([region, zones]) => (
|
|
||||||
<CommandGroup key={region} heading={region}>
|
|
||||||
{zones.map((tz) => (
|
|
||||||
<CommandItem
|
|
||||||
key={tz.value}
|
|
||||||
value={`${region} ${tz.label} ${tz.value}`}
|
|
||||||
onSelect={() => {
|
|
||||||
field.onChange(tz.value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tz.value}
|
|
||||||
<CheckIcon
|
|
||||||
className={cn(
|
|
||||||
"ml-auto h-4 w-4",
|
|
||||||
field.value === tz.value
|
|
||||||
? "opacity-100"
|
|
||||||
: "opacity-0",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</CommandItem>
|
|
||||||
))}
|
|
||||||
</CommandGroup>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</ScrollArea>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Optional: Choose a timezone for the schedule execution time
|
Optional: Choose a timezone for the schedule execution time
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
|
|||||||
@@ -1,458 +0,0 @@
|
|||||||
// Complete list of IANA timezones grouped by region
|
|
||||||
export const TIMEZONES: Record<
|
|
||||||
string,
|
|
||||||
Array<{ label: string; value: string }>
|
|
||||||
> = {
|
|
||||||
Common: [{ label: "UTC (Coordinated Universal Time)", value: "UTC" }],
|
|
||||||
Africa: [
|
|
||||||
{ label: "Abidjan", value: "Africa/Abidjan" },
|
|
||||||
{ label: "Accra", value: "Africa/Accra" },
|
|
||||||
{ label: "Addis Ababa", value: "Africa/Addis_Ababa" },
|
|
||||||
{ label: "Algiers", value: "Africa/Algiers" },
|
|
||||||
{ label: "Asmara", value: "Africa/Asmara" },
|
|
||||||
{ label: "Bamako", value: "Africa/Bamako" },
|
|
||||||
{ label: "Bangui", value: "Africa/Bangui" },
|
|
||||||
{ label: "Banjul", value: "Africa/Banjul" },
|
|
||||||
{ label: "Bissau", value: "Africa/Bissau" },
|
|
||||||
{ label: "Blantyre", value: "Africa/Blantyre" },
|
|
||||||
{ label: "Brazzaville", value: "Africa/Brazzaville" },
|
|
||||||
{ label: "Bujumbura", value: "Africa/Bujumbura" },
|
|
||||||
{ label: "Cairo", value: "Africa/Cairo" },
|
|
||||||
{ label: "Casablanca", value: "Africa/Casablanca" },
|
|
||||||
{ label: "Ceuta", value: "Africa/Ceuta" },
|
|
||||||
{ label: "Conakry", value: "Africa/Conakry" },
|
|
||||||
{ label: "Dakar", value: "Africa/Dakar" },
|
|
||||||
{ label: "Dar es Salaam", value: "Africa/Dar_es_Salaam" },
|
|
||||||
{ label: "Djibouti", value: "Africa/Djibouti" },
|
|
||||||
{ label: "Douala", value: "Africa/Douala" },
|
|
||||||
{ label: "El Aaiun", value: "Africa/El_Aaiun" },
|
|
||||||
{ label: "Freetown", value: "Africa/Freetown" },
|
|
||||||
{ label: "Gaborone", value: "Africa/Gaborone" },
|
|
||||||
{ label: "Harare", value: "Africa/Harare" },
|
|
||||||
{ label: "Johannesburg", value: "Africa/Johannesburg" },
|
|
||||||
{ label: "Juba", value: "Africa/Juba" },
|
|
||||||
{ label: "Kampala", value: "Africa/Kampala" },
|
|
||||||
{ label: "Khartoum", value: "Africa/Khartoum" },
|
|
||||||
{ label: "Kigali", value: "Africa/Kigali" },
|
|
||||||
{ label: "Kinshasa", value: "Africa/Kinshasa" },
|
|
||||||
{ label: "Lagos", value: "Africa/Lagos" },
|
|
||||||
{ label: "Libreville", value: "Africa/Libreville" },
|
|
||||||
{ label: "Lome", value: "Africa/Lome" },
|
|
||||||
{ label: "Luanda", value: "Africa/Luanda" },
|
|
||||||
{ label: "Lubumbashi", value: "Africa/Lubumbashi" },
|
|
||||||
{ label: "Lusaka", value: "Africa/Lusaka" },
|
|
||||||
{ label: "Malabo", value: "Africa/Malabo" },
|
|
||||||
{ label: "Maputo", value: "Africa/Maputo" },
|
|
||||||
{ label: "Maseru", value: "Africa/Maseru" },
|
|
||||||
{ label: "Mbabane", value: "Africa/Mbabane" },
|
|
||||||
{ label: "Mogadishu", value: "Africa/Mogadishu" },
|
|
||||||
{ label: "Monrovia", value: "Africa/Monrovia" },
|
|
||||||
{ label: "Nairobi", value: "Africa/Nairobi" },
|
|
||||||
{ label: "Ndjamena", value: "Africa/Ndjamena" },
|
|
||||||
{ label: "Niamey", value: "Africa/Niamey" },
|
|
||||||
{ label: "Nouakchott", value: "Africa/Nouakchott" },
|
|
||||||
{ label: "Ouagadougou", value: "Africa/Ouagadougou" },
|
|
||||||
{ label: "Porto-Novo", value: "Africa/Porto-Novo" },
|
|
||||||
{ label: "Sao Tome", value: "Africa/Sao_Tome" },
|
|
||||||
{ label: "Tripoli", value: "Africa/Tripoli" },
|
|
||||||
{ label: "Tunis", value: "Africa/Tunis" },
|
|
||||||
{ label: "Windhoek", value: "Africa/Windhoek" },
|
|
||||||
],
|
|
||||||
America: [
|
|
||||||
{ label: "Adak", value: "America/Adak" },
|
|
||||||
{ label: "Anchorage", value: "America/Anchorage" },
|
|
||||||
{ label: "Anguilla", value: "America/Anguilla" },
|
|
||||||
{ label: "Antigua", value: "America/Antigua" },
|
|
||||||
{ label: "Araguaina", value: "America/Araguaina" },
|
|
||||||
{
|
|
||||||
label: "Argentina/Buenos Aires",
|
|
||||||
value: "America/Argentina/Buenos_Aires",
|
|
||||||
},
|
|
||||||
{ label: "Argentina/Catamarca", value: "America/Argentina/Catamarca" },
|
|
||||||
{ label: "Argentina/Cordoba", value: "America/Argentina/Cordoba" },
|
|
||||||
{ label: "Argentina/Jujuy", value: "America/Argentina/Jujuy" },
|
|
||||||
{ label: "Argentina/La Rioja", value: "America/Argentina/La_Rioja" },
|
|
||||||
{ label: "Argentina/Mendoza", value: "America/Argentina/Mendoza" },
|
|
||||||
{
|
|
||||||
label: "Argentina/Rio Gallegos",
|
|
||||||
value: "America/Argentina/Rio_Gallegos",
|
|
||||||
},
|
|
||||||
{ label: "Argentina/Salta", value: "America/Argentina/Salta" },
|
|
||||||
{ label: "Argentina/San Juan", value: "America/Argentina/San_Juan" },
|
|
||||||
{ label: "Argentina/San Luis", value: "America/Argentina/San_Luis" },
|
|
||||||
{ label: "Argentina/Tucuman", value: "America/Argentina/Tucuman" },
|
|
||||||
{ label: "Argentina/Ushuaia", value: "America/Argentina/Ushuaia" },
|
|
||||||
{ label: "Aruba", value: "America/Aruba" },
|
|
||||||
{ label: "Asuncion", value: "America/Asuncion" },
|
|
||||||
{ label: "Atikokan", value: "America/Atikokan" },
|
|
||||||
{ label: "Bahia", value: "America/Bahia" },
|
|
||||||
{ label: "Bahia Banderas", value: "America/Bahia_Banderas" },
|
|
||||||
{ label: "Barbados", value: "America/Barbados" },
|
|
||||||
{ label: "Belem", value: "America/Belem" },
|
|
||||||
{ label: "Belize", value: "America/Belize" },
|
|
||||||
{ label: "Blanc-Sablon", value: "America/Blanc-Sablon" },
|
|
||||||
{ label: "Boa Vista", value: "America/Boa_Vista" },
|
|
||||||
{ label: "Bogota", value: "America/Bogota" },
|
|
||||||
{ label: "Boise", value: "America/Boise" },
|
|
||||||
{ label: "Cambridge Bay", value: "America/Cambridge_Bay" },
|
|
||||||
{ label: "Campo Grande", value: "America/Campo_Grande" },
|
|
||||||
{ label: "Cancun", value: "America/Cancun" },
|
|
||||||
{ label: "Caracas", value: "America/Caracas" },
|
|
||||||
{ label: "Cayenne", value: "America/Cayenne" },
|
|
||||||
{ label: "Cayman", value: "America/Cayman" },
|
|
||||||
{ label: "Chicago (Central Time)", value: "America/Chicago" },
|
|
||||||
{ label: "Chihuahua", value: "America/Chihuahua" },
|
|
||||||
{ label: "Ciudad Juarez", value: "America/Ciudad_Juarez" },
|
|
||||||
{ label: "Costa Rica", value: "America/Costa_Rica" },
|
|
||||||
{ label: "Creston", value: "America/Creston" },
|
|
||||||
{ label: "Cuiaba", value: "America/Cuiaba" },
|
|
||||||
{ label: "Curacao", value: "America/Curacao" },
|
|
||||||
{ label: "Danmarkshavn", value: "America/Danmarkshavn" },
|
|
||||||
{ label: "Dawson", value: "America/Dawson" },
|
|
||||||
{ label: "Dawson Creek", value: "America/Dawson_Creek" },
|
|
||||||
{ label: "Denver (Mountain Time)", value: "America/Denver" },
|
|
||||||
{ label: "Detroit", value: "America/Detroit" },
|
|
||||||
{ label: "Dominica", value: "America/Dominica" },
|
|
||||||
{ label: "Edmonton", value: "America/Edmonton" },
|
|
||||||
{ label: "Eirunepe", value: "America/Eirunepe" },
|
|
||||||
{ label: "El Salvador", value: "America/El_Salvador" },
|
|
||||||
{ label: "Fort Nelson", value: "America/Fort_Nelson" },
|
|
||||||
{ label: "Fortaleza", value: "America/Fortaleza" },
|
|
||||||
{ label: "Glace Bay", value: "America/Glace_Bay" },
|
|
||||||
{ label: "Goose Bay", value: "America/Goose_Bay" },
|
|
||||||
{ label: "Grand Turk", value: "America/Grand_Turk" },
|
|
||||||
{ label: "Grenada", value: "America/Grenada" },
|
|
||||||
{ label: "Guadeloupe", value: "America/Guadeloupe" },
|
|
||||||
{ label: "Guatemala", value: "America/Guatemala" },
|
|
||||||
{ label: "Guayaquil", value: "America/Guayaquil" },
|
|
||||||
{ label: "Guyana", value: "America/Guyana" },
|
|
||||||
{ label: "Halifax", value: "America/Halifax" },
|
|
||||||
{ label: "Havana", value: "America/Havana" },
|
|
||||||
{ label: "Hermosillo", value: "America/Hermosillo" },
|
|
||||||
{ label: "Indiana/Indianapolis", value: "America/Indiana/Indianapolis" },
|
|
||||||
{ label: "Indiana/Knox", value: "America/Indiana/Knox" },
|
|
||||||
{ label: "Indiana/Marengo", value: "America/Indiana/Marengo" },
|
|
||||||
{ label: "Indiana/Petersburg", value: "America/Indiana/Petersburg" },
|
|
||||||
{ label: "Indiana/Tell City", value: "America/Indiana/Tell_City" },
|
|
||||||
{ label: "Indiana/Vevay", value: "America/Indiana/Vevay" },
|
|
||||||
{ label: "Indiana/Vincennes", value: "America/Indiana/Vincennes" },
|
|
||||||
{ label: "Indiana/Winamac", value: "America/Indiana/Winamac" },
|
|
||||||
{ label: "Inuvik", value: "America/Inuvik" },
|
|
||||||
{ label: "Iqaluit", value: "America/Iqaluit" },
|
|
||||||
{ label: "Jamaica", value: "America/Jamaica" },
|
|
||||||
{ label: "Juneau", value: "America/Juneau" },
|
|
||||||
{ label: "Kentucky/Louisville", value: "America/Kentucky/Louisville" },
|
|
||||||
{ label: "Kentucky/Monticello", value: "America/Kentucky/Monticello" },
|
|
||||||
{ label: "Kralendijk", value: "America/Kralendijk" },
|
|
||||||
{ label: "La Paz", value: "America/La_Paz" },
|
|
||||||
{ label: "Lima", value: "America/Lima" },
|
|
||||||
{ label: "Los Angeles (Pacific Time)", value: "America/Los_Angeles" },
|
|
||||||
{ label: "Lower Princes", value: "America/Lower_Princes" },
|
|
||||||
{ label: "Maceio", value: "America/Maceio" },
|
|
||||||
{ label: "Managua", value: "America/Managua" },
|
|
||||||
{ label: "Manaus", value: "America/Manaus" },
|
|
||||||
{ label: "Marigot", value: "America/Marigot" },
|
|
||||||
{ label: "Martinique", value: "America/Martinique" },
|
|
||||||
{ label: "Matamoros", value: "America/Matamoros" },
|
|
||||||
{ label: "Mazatlan", value: "America/Mazatlan" },
|
|
||||||
{ label: "Menominee", value: "America/Menominee" },
|
|
||||||
{ label: "Merida", value: "America/Merida" },
|
|
||||||
{ label: "Metlakatla", value: "America/Metlakatla" },
|
|
||||||
{ label: "Mexico City (Central Mexico)", value: "America/Mexico_City" },
|
|
||||||
{ label: "Miquelon", value: "America/Miquelon" },
|
|
||||||
{ label: "Moncton", value: "America/Moncton" },
|
|
||||||
{ label: "Monterrey", value: "America/Monterrey" },
|
|
||||||
{ label: "Montevideo", value: "America/Montevideo" },
|
|
||||||
{ label: "Montserrat", value: "America/Montserrat" },
|
|
||||||
{ label: "Nassau", value: "America/Nassau" },
|
|
||||||
{ label: "New York (Eastern Time)", value: "America/New_York" },
|
|
||||||
{ label: "Nome", value: "America/Nome" },
|
|
||||||
{ label: "Noronha", value: "America/Noronha" },
|
|
||||||
{ label: "North Dakota/Beulah", value: "America/North_Dakota/Beulah" },
|
|
||||||
{ label: "North Dakota/Center", value: "America/North_Dakota/Center" },
|
|
||||||
{
|
|
||||||
label: "North Dakota/New Salem",
|
|
||||||
value: "America/North_Dakota/New_Salem",
|
|
||||||
},
|
|
||||||
{ label: "Nuuk", value: "America/Nuuk" },
|
|
||||||
{ label: "Ojinaga", value: "America/Ojinaga" },
|
|
||||||
{ label: "Panama", value: "America/Panama" },
|
|
||||||
{ label: "Paramaribo", value: "America/Paramaribo" },
|
|
||||||
{ label: "Phoenix", value: "America/Phoenix" },
|
|
||||||
{ label: "Port-au-Prince", value: "America/Port-au-Prince" },
|
|
||||||
{ label: "Port of Spain", value: "America/Port_of_Spain" },
|
|
||||||
{ label: "Porto Velho", value: "America/Porto_Velho" },
|
|
||||||
{ label: "Puerto Rico", value: "America/Puerto_Rico" },
|
|
||||||
{ label: "Punta Arenas", value: "America/Punta_Arenas" },
|
|
||||||
{ label: "Rankin Inlet", value: "America/Rankin_Inlet" },
|
|
||||||
{ label: "Recife", value: "America/Recife" },
|
|
||||||
{ label: "Regina", value: "America/Regina" },
|
|
||||||
{ label: "Resolute", value: "America/Resolute" },
|
|
||||||
{ label: "Rio Branco", value: "America/Rio_Branco" },
|
|
||||||
{ label: "Santarem", value: "America/Santarem" },
|
|
||||||
{ label: "Santiago", value: "America/Santiago" },
|
|
||||||
{ label: "Santo Domingo", value: "America/Santo_Domingo" },
|
|
||||||
{ label: "Sao Paulo (Brasilia Time)", value: "America/Sao_Paulo" },
|
|
||||||
{ label: "Scoresbysund", value: "America/Scoresbysund" },
|
|
||||||
{ label: "Sitka", value: "America/Sitka" },
|
|
||||||
{ label: "St Barthelemy", value: "America/St_Barthelemy" },
|
|
||||||
{ label: "St Johns", value: "America/St_Johns" },
|
|
||||||
{ label: "St Kitts", value: "America/St_Kitts" },
|
|
||||||
{ label: "St Lucia", value: "America/St_Lucia" },
|
|
||||||
{ label: "St Thomas", value: "America/St_Thomas" },
|
|
||||||
{ label: "St Vincent", value: "America/St_Vincent" },
|
|
||||||
{ label: "Swift Current", value: "America/Swift_Current" },
|
|
||||||
{ label: "Tegucigalpa", value: "America/Tegucigalpa" },
|
|
||||||
{ label: "Thule", value: "America/Thule" },
|
|
||||||
{ label: "Tijuana", value: "America/Tijuana" },
|
|
||||||
{ label: "Toronto", value: "America/Toronto" },
|
|
||||||
{ label: "Tortola", value: "America/Tortola" },
|
|
||||||
{ label: "Vancouver", value: "America/Vancouver" },
|
|
||||||
{ label: "Whitehorse", value: "America/Whitehorse" },
|
|
||||||
{ label: "Winnipeg", value: "America/Winnipeg" },
|
|
||||||
{ label: "Yakutat", value: "America/Yakutat" },
|
|
||||||
],
|
|
||||||
Antarctica: [
|
|
||||||
{ label: "Casey", value: "Antarctica/Casey" },
|
|
||||||
{ label: "Davis", value: "Antarctica/Davis" },
|
|
||||||
{ label: "DumontDUrville", value: "Antarctica/DumontDUrville" },
|
|
||||||
{ label: "Macquarie", value: "Antarctica/Macquarie" },
|
|
||||||
{ label: "Mawson", value: "Antarctica/Mawson" },
|
|
||||||
{ label: "McMurdo", value: "Antarctica/McMurdo" },
|
|
||||||
{ label: "Palmer", value: "Antarctica/Palmer" },
|
|
||||||
{ label: "Rothera", value: "Antarctica/Rothera" },
|
|
||||||
{ label: "Syowa", value: "Antarctica/Syowa" },
|
|
||||||
{ label: "Troll", value: "Antarctica/Troll" },
|
|
||||||
{ label: "Vostok", value: "Antarctica/Vostok" },
|
|
||||||
],
|
|
||||||
Arctic: [{ label: "Longyearbyen", value: "Arctic/Longyearbyen" }],
|
|
||||||
Asia: [
|
|
||||||
{ label: "Aden", value: "Asia/Aden" },
|
|
||||||
{ label: "Almaty", value: "Asia/Almaty" },
|
|
||||||
{ label: "Amman", value: "Asia/Amman" },
|
|
||||||
{ label: "Anadyr", value: "Asia/Anadyr" },
|
|
||||||
{ label: "Aqtau", value: "Asia/Aqtau" },
|
|
||||||
{ label: "Aqtobe", value: "Asia/Aqtobe" },
|
|
||||||
{ label: "Ashgabat", value: "Asia/Ashgabat" },
|
|
||||||
{ label: "Atyrau", value: "Asia/Atyrau" },
|
|
||||||
{ label: "Baghdad", value: "Asia/Baghdad" },
|
|
||||||
{ label: "Bahrain", value: "Asia/Bahrain" },
|
|
||||||
{ label: "Baku", value: "Asia/Baku" },
|
|
||||||
{ label: "Bangkok", value: "Asia/Bangkok" },
|
|
||||||
{ label: "Barnaul", value: "Asia/Barnaul" },
|
|
||||||
{ label: "Beirut", value: "Asia/Beirut" },
|
|
||||||
{ label: "Bishkek", value: "Asia/Bishkek" },
|
|
||||||
{ label: "Brunei", value: "Asia/Brunei" },
|
|
||||||
{ label: "Chita", value: "Asia/Chita" },
|
|
||||||
{ label: "Choibalsan", value: "Asia/Choibalsan" },
|
|
||||||
{ label: "Colombo", value: "Asia/Colombo" },
|
|
||||||
{ label: "Damascus", value: "Asia/Damascus" },
|
|
||||||
{ label: "Dhaka", value: "Asia/Dhaka" },
|
|
||||||
{ label: "Dili", value: "Asia/Dili" },
|
|
||||||
{ label: "Dubai (Gulf Standard Time)", value: "Asia/Dubai" },
|
|
||||||
{ label: "Dushanbe", value: "Asia/Dushanbe" },
|
|
||||||
{ label: "Famagusta", value: "Asia/Famagusta" },
|
|
||||||
{ label: "Gaza", value: "Asia/Gaza" },
|
|
||||||
{ label: "Hebron", value: "Asia/Hebron" },
|
|
||||||
{ label: "Ho Chi Minh", value: "Asia/Ho_Chi_Minh" },
|
|
||||||
{ label: "Hong Kong", value: "Asia/Hong_Kong" },
|
|
||||||
{ label: "Hovd", value: "Asia/Hovd" },
|
|
||||||
{ label: "Irkutsk", value: "Asia/Irkutsk" },
|
|
||||||
{ label: "Jakarta", value: "Asia/Jakarta" },
|
|
||||||
{ label: "Jayapura", value: "Asia/Jayapura" },
|
|
||||||
{ label: "Jerusalem", value: "Asia/Jerusalem" },
|
|
||||||
{ label: "Kabul", value: "Asia/Kabul" },
|
|
||||||
{ label: "Kamchatka", value: "Asia/Kamchatka" },
|
|
||||||
{ label: "Karachi", value: "Asia/Karachi" },
|
|
||||||
{ label: "Kathmandu", value: "Asia/Kathmandu" },
|
|
||||||
{ label: "Khandyga", value: "Asia/Khandyga" },
|
|
||||||
{ label: "Kolkata (India Standard Time)", value: "Asia/Kolkata" },
|
|
||||||
{ label: "Krasnoyarsk", value: "Asia/Krasnoyarsk" },
|
|
||||||
{ label: "Kuala Lumpur", value: "Asia/Kuala_Lumpur" },
|
|
||||||
{ label: "Kuching", value: "Asia/Kuching" },
|
|
||||||
{ label: "Kuwait", value: "Asia/Kuwait" },
|
|
||||||
{ label: "Macau", value: "Asia/Macau" },
|
|
||||||
{ label: "Magadan", value: "Asia/Magadan" },
|
|
||||||
{ label: "Makassar", value: "Asia/Makassar" },
|
|
||||||
{ label: "Manila", value: "Asia/Manila" },
|
|
||||||
{ label: "Muscat", value: "Asia/Muscat" },
|
|
||||||
{ label: "Nicosia", value: "Asia/Nicosia" },
|
|
||||||
{ label: "Novokuznetsk", value: "Asia/Novokuznetsk" },
|
|
||||||
{ label: "Novosibirsk", value: "Asia/Novosibirsk" },
|
|
||||||
{ label: "Omsk", value: "Asia/Omsk" },
|
|
||||||
{ label: "Oral", value: "Asia/Oral" },
|
|
||||||
{ label: "Phnom Penh", value: "Asia/Phnom_Penh" },
|
|
||||||
{ label: "Pontianak", value: "Asia/Pontianak" },
|
|
||||||
{ label: "Pyongyang", value: "Asia/Pyongyang" },
|
|
||||||
{ label: "Qatar", value: "Asia/Qatar" },
|
|
||||||
{ label: "Qostanay", value: "Asia/Qostanay" },
|
|
||||||
{ label: "Qyzylorda", value: "Asia/Qyzylorda" },
|
|
||||||
{ label: "Riyadh", value: "Asia/Riyadh" },
|
|
||||||
{ label: "Sakhalin", value: "Asia/Sakhalin" },
|
|
||||||
{ label: "Samarkand", value: "Asia/Samarkand" },
|
|
||||||
{ label: "Seoul", value: "Asia/Seoul" },
|
|
||||||
{ label: "Shanghai (China Standard Time)", value: "Asia/Shanghai" },
|
|
||||||
{ label: "Singapore", value: "Asia/Singapore" },
|
|
||||||
{ label: "Srednekolymsk", value: "Asia/Srednekolymsk" },
|
|
||||||
{ label: "Taipei", value: "Asia/Taipei" },
|
|
||||||
{ label: "Tashkent", value: "Asia/Tashkent" },
|
|
||||||
{ label: "Tbilisi", value: "Asia/Tbilisi" },
|
|
||||||
{ label: "Tehran", value: "Asia/Tehran" },
|
|
||||||
{ label: "Thimphu", value: "Asia/Thimphu" },
|
|
||||||
{ label: "Tokyo (Japan Standard Time)", value: "Asia/Tokyo" },
|
|
||||||
{ label: "Tomsk", value: "Asia/Tomsk" },
|
|
||||||
{ label: "Ulaanbaatar", value: "Asia/Ulaanbaatar" },
|
|
||||||
{ label: "Urumqi", value: "Asia/Urumqi" },
|
|
||||||
{ label: "Ust-Nera", value: "Asia/Ust-Nera" },
|
|
||||||
{ label: "Vientiane", value: "Asia/Vientiane" },
|
|
||||||
{ label: "Vladivostok", value: "Asia/Vladivostok" },
|
|
||||||
{ label: "Yakutsk", value: "Asia/Yakutsk" },
|
|
||||||
{ label: "Yangon", value: "Asia/Yangon" },
|
|
||||||
{ label: "Yekaterinburg", value: "Asia/Yekaterinburg" },
|
|
||||||
{ label: "Yerevan", value: "Asia/Yerevan" },
|
|
||||||
],
|
|
||||||
Atlantic: [
|
|
||||||
{ label: "Azores", value: "Atlantic/Azores" },
|
|
||||||
{ label: "Bermuda", value: "Atlantic/Bermuda" },
|
|
||||||
{ label: "Canary", value: "Atlantic/Canary" },
|
|
||||||
{ label: "Cape Verde", value: "Atlantic/Cape_Verde" },
|
|
||||||
{ label: "Faroe", value: "Atlantic/Faroe" },
|
|
||||||
{ label: "Madeira", value: "Atlantic/Madeira" },
|
|
||||||
{ label: "Reykjavik", value: "Atlantic/Reykjavik" },
|
|
||||||
{ label: "South Georgia", value: "Atlantic/South_Georgia" },
|
|
||||||
{ label: "St Helena", value: "Atlantic/St_Helena" },
|
|
||||||
{ label: "Stanley", value: "Atlantic/Stanley" },
|
|
||||||
],
|
|
||||||
Australia: [
|
|
||||||
{ label: "Adelaide", value: "Australia/Adelaide" },
|
|
||||||
{ label: "Brisbane", value: "Australia/Brisbane" },
|
|
||||||
{ label: "Broken Hill", value: "Australia/Broken_Hill" },
|
|
||||||
{ label: "Darwin", value: "Australia/Darwin" },
|
|
||||||
{ label: "Eucla", value: "Australia/Eucla" },
|
|
||||||
{ label: "Hobart", value: "Australia/Hobart" },
|
|
||||||
{ label: "Lindeman", value: "Australia/Lindeman" },
|
|
||||||
{ label: "Lord Howe", value: "Australia/Lord_Howe" },
|
|
||||||
{ label: "Melbourne", value: "Australia/Melbourne" },
|
|
||||||
{ label: "Perth", value: "Australia/Perth" },
|
|
||||||
{ label: "Sydney (Australian Eastern Time)", value: "Australia/Sydney" },
|
|
||||||
],
|
|
||||||
Europe: [
|
|
||||||
{ label: "Amsterdam", value: "Europe/Amsterdam" },
|
|
||||||
{ label: "Andorra", value: "Europe/Andorra" },
|
|
||||||
{ label: "Astrakhan", value: "Europe/Astrakhan" },
|
|
||||||
{ label: "Athens", value: "Europe/Athens" },
|
|
||||||
{ label: "Belgrade", value: "Europe/Belgrade" },
|
|
||||||
{ label: "Berlin (Central European Time)", value: "Europe/Berlin" },
|
|
||||||
{ label: "Bratislava", value: "Europe/Bratislava" },
|
|
||||||
{ label: "Brussels", value: "Europe/Brussels" },
|
|
||||||
{ label: "Bucharest", value: "Europe/Bucharest" },
|
|
||||||
{ label: "Budapest", value: "Europe/Budapest" },
|
|
||||||
{ label: "Busingen", value: "Europe/Busingen" },
|
|
||||||
{ label: "Chisinau", value: "Europe/Chisinau" },
|
|
||||||
{ label: "Copenhagen", value: "Europe/Copenhagen" },
|
|
||||||
{ label: "Dublin", value: "Europe/Dublin" },
|
|
||||||
{ label: "Gibraltar", value: "Europe/Gibraltar" },
|
|
||||||
{ label: "Guernsey", value: "Europe/Guernsey" },
|
|
||||||
{ label: "Helsinki", value: "Europe/Helsinki" },
|
|
||||||
{ label: "Isle of Man", value: "Europe/Isle_of_Man" },
|
|
||||||
{ label: "Istanbul", value: "Europe/Istanbul" },
|
|
||||||
{ label: "Jersey", value: "Europe/Jersey" },
|
|
||||||
{ label: "Kaliningrad", value: "Europe/Kaliningrad" },
|
|
||||||
{ label: "Kirov", value: "Europe/Kirov" },
|
|
||||||
{ label: "Kyiv", value: "Europe/Kyiv" },
|
|
||||||
{ label: "Lisbon", value: "Europe/Lisbon" },
|
|
||||||
{ label: "Ljubljana", value: "Europe/Ljubljana" },
|
|
||||||
{ label: "London (Greenwich Mean Time)", value: "Europe/London" },
|
|
||||||
{ label: "Luxembourg", value: "Europe/Luxembourg" },
|
|
||||||
{ label: "Madrid", value: "Europe/Madrid" },
|
|
||||||
{ label: "Malta", value: "Europe/Malta" },
|
|
||||||
{ label: "Mariehamn", value: "Europe/Mariehamn" },
|
|
||||||
{ label: "Minsk", value: "Europe/Minsk" },
|
|
||||||
{ label: "Monaco", value: "Europe/Monaco" },
|
|
||||||
{ label: "Moscow", value: "Europe/Moscow" },
|
|
||||||
{ label: "Oslo", value: "Europe/Oslo" },
|
|
||||||
{ label: "Paris (Central European Time)", value: "Europe/Paris" },
|
|
||||||
{ label: "Podgorica", value: "Europe/Podgorica" },
|
|
||||||
{ label: "Prague", value: "Europe/Prague" },
|
|
||||||
{ label: "Riga", value: "Europe/Riga" },
|
|
||||||
{ label: "Rome", value: "Europe/Rome" },
|
|
||||||
{ label: "Samara", value: "Europe/Samara" },
|
|
||||||
{ label: "San Marino", value: "Europe/San_Marino" },
|
|
||||||
{ label: "Sarajevo", value: "Europe/Sarajevo" },
|
|
||||||
{ label: "Saratov", value: "Europe/Saratov" },
|
|
||||||
{ label: "Simferopol", value: "Europe/Simferopol" },
|
|
||||||
{ label: "Skopje", value: "Europe/Skopje" },
|
|
||||||
{ label: "Sofia", value: "Europe/Sofia" },
|
|
||||||
{ label: "Stockholm", value: "Europe/Stockholm" },
|
|
||||||
{ label: "Tallinn", value: "Europe/Tallinn" },
|
|
||||||
{ label: "Tirane", value: "Europe/Tirane" },
|
|
||||||
{ label: "Ulyanovsk", value: "Europe/Ulyanovsk" },
|
|
||||||
{ label: "Vaduz", value: "Europe/Vaduz" },
|
|
||||||
{ label: "Vatican", value: "Europe/Vatican" },
|
|
||||||
{ label: "Vienna", value: "Europe/Vienna" },
|
|
||||||
{ label: "Vilnius", value: "Europe/Vilnius" },
|
|
||||||
{ label: "Volgograd", value: "Europe/Volgograd" },
|
|
||||||
{ label: "Warsaw", value: "Europe/Warsaw" },
|
|
||||||
{ label: "Zagreb", value: "Europe/Zagreb" },
|
|
||||||
{ label: "Zurich", value: "Europe/Zurich" },
|
|
||||||
],
|
|
||||||
Indian: [
|
|
||||||
{ label: "Antananarivo", value: "Indian/Antananarivo" },
|
|
||||||
{ label: "Chagos", value: "Indian/Chagos" },
|
|
||||||
{ label: "Christmas", value: "Indian/Christmas" },
|
|
||||||
{ label: "Cocos", value: "Indian/Cocos" },
|
|
||||||
{ label: "Comoro", value: "Indian/Comoro" },
|
|
||||||
{ label: "Kerguelen", value: "Indian/Kerguelen" },
|
|
||||||
{ label: "Mahe", value: "Indian/Mahe" },
|
|
||||||
{ label: "Maldives", value: "Indian/Maldives" },
|
|
||||||
{ label: "Mauritius", value: "Indian/Mauritius" },
|
|
||||||
{ label: "Mayotte", value: "Indian/Mayotte" },
|
|
||||||
{ label: "Reunion", value: "Indian/Reunion" },
|
|
||||||
],
|
|
||||||
Pacific: [
|
|
||||||
{ label: "Apia", value: "Pacific/Apia" },
|
|
||||||
{ label: "Auckland", value: "Pacific/Auckland" },
|
|
||||||
{ label: "Bougainville", value: "Pacific/Bougainville" },
|
|
||||||
{ label: "Chatham", value: "Pacific/Chatham" },
|
|
||||||
{ label: "Chuuk", value: "Pacific/Chuuk" },
|
|
||||||
{ label: "Easter", value: "Pacific/Easter" },
|
|
||||||
{ label: "Efate", value: "Pacific/Efate" },
|
|
||||||
{ label: "Fakaofo", value: "Pacific/Fakaofo" },
|
|
||||||
{ label: "Fiji", value: "Pacific/Fiji" },
|
|
||||||
{ label: "Funafuti", value: "Pacific/Funafuti" },
|
|
||||||
{ label: "Galapagos", value: "Pacific/Galapagos" },
|
|
||||||
{ label: "Gambier", value: "Pacific/Gambier" },
|
|
||||||
{ label: "Guadalcanal", value: "Pacific/Guadalcanal" },
|
|
||||||
{ label: "Guam", value: "Pacific/Guam" },
|
|
||||||
{ label: "Honolulu", value: "Pacific/Honolulu" },
|
|
||||||
{ label: "Kanton", value: "Pacific/Kanton" },
|
|
||||||
{ label: "Kiritimati", value: "Pacific/Kiritimati" },
|
|
||||||
{ label: "Kosrae", value: "Pacific/Kosrae" },
|
|
||||||
{ label: "Kwajalein", value: "Pacific/Kwajalein" },
|
|
||||||
{ label: "Majuro", value: "Pacific/Majuro" },
|
|
||||||
{ label: "Marquesas", value: "Pacific/Marquesas" },
|
|
||||||
{ label: "Midway", value: "Pacific/Midway" },
|
|
||||||
{ label: "Nauru", value: "Pacific/Nauru" },
|
|
||||||
{ label: "Niue", value: "Pacific/Niue" },
|
|
||||||
{ label: "Norfolk", value: "Pacific/Norfolk" },
|
|
||||||
{ label: "Noumea", value: "Pacific/Noumea" },
|
|
||||||
{ label: "Pago Pago", value: "Pacific/Pago_Pago" },
|
|
||||||
{ label: "Palau", value: "Pacific/Palau" },
|
|
||||||
{ label: "Pitcairn", value: "Pacific/Pitcairn" },
|
|
||||||
{ label: "Pohnpei", value: "Pacific/Pohnpei" },
|
|
||||||
{ label: "Port Moresby", value: "Pacific/Port_Moresby" },
|
|
||||||
{ label: "Rarotonga", value: "Pacific/Rarotonga" },
|
|
||||||
{ label: "Saipan", value: "Pacific/Saipan" },
|
|
||||||
{ label: "Tahiti", value: "Pacific/Tahiti" },
|
|
||||||
{ label: "Tarawa", value: "Pacific/Tarawa" },
|
|
||||||
{ label: "Tongatapu", value: "Pacific/Tongatapu" },
|
|
||||||
{ label: "Wake", value: "Pacific/Wake" },
|
|
||||||
{ label: "Wallis", value: "Pacific/Wallis" },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper to get display label for a timezone value
|
|
||||||
export function getTimezoneLabel(value: string | undefined): string {
|
|
||||||
if (!value) return "UTC (default)";
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
@@ -108,8 +108,7 @@ export const getLogType = (message: string): LogStyle => {
|
|||||||
/(?:might|may|could)\s+(?:not|cause|lead\s+to)/i.test(lowerMessage) ||
|
/(?:might|may|could)\s+(?:not|cause|lead\s+to)/i.test(lowerMessage) ||
|
||||||
/(?:!+\s*(?:warning|caution|attention)\s*!+)/i.test(lowerMessage) ||
|
/(?:!+\s*(?:warning|caution|attention)\s*!+)/i.test(lowerMessage) ||
|
||||||
/\b(?:deprecated|obsolete)\b/i.test(lowerMessage) ||
|
/\b(?:deprecated|obsolete)\b/i.test(lowerMessage) ||
|
||||||
/\b(?:unstable|experimental)\b/i.test(lowerMessage) ||
|
/\b(?:unstable|experimental)\b/i.test(lowerMessage)
|
||||||
/⚠|⚠️/i.test(lowerMessage)
|
|
||||||
) {
|
) {
|
||||||
return LOG_STYLES.warning;
|
return LOG_STYLES.warning;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,9 +190,7 @@ export const ShowProjects = () => {
|
|||||||
Create and manage your projects
|
Create and manage your projects
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
{(auth?.role === "owner" ||
|
{(auth?.role === "owner" || auth?.canCreateProjects) && (
|
||||||
auth?.role === "admin" ||
|
|
||||||
auth?.canCreateProjects) && (
|
|
||||||
<div className="">
|
<div className="">
|
||||||
<HandleProject />
|
<HandleProject />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Activity } from "lucide-react";
|
import { Activity } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -8,6 +7,7 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||||
import { ShowStorageActions } from "./show-storage-actions";
|
import { ShowStorageActions } from "./show-storage-actions";
|
||||||
import { ShowTraefikActions } from "./show-traefik-actions";
|
import { ShowTraefikActions } from "./show-traefik-actions";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Pencil, PlusIcon } from "lucide-react";
|
import { PlusIcon, Pencil } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import {
|
import {
|
||||||
Clock,
|
|
||||||
Key,
|
|
||||||
KeyIcon,
|
KeyIcon,
|
||||||
Loader2,
|
Loader2,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
Network,
|
|
||||||
Pencil,
|
|
||||||
ServerIcon,
|
ServerIcon,
|
||||||
Settings,
|
Clock,
|
||||||
Terminal,
|
|
||||||
Trash2,
|
|
||||||
User,
|
User,
|
||||||
|
Key,
|
||||||
|
Network,
|
||||||
|
Terminal,
|
||||||
|
Settings,
|
||||||
|
Pencil,
|
||||||
|
Trash2,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { ChevronDown } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
|
import { ChevronDown } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
BreadcrumbItem,
|
BreadcrumbItem,
|
||||||
BreadcrumbLink,
|
BreadcrumbLink,
|
||||||
BreadcrumbList,
|
BreadcrumbList,
|
||||||
BreadcrumbPage,
|
|
||||||
BreadcrumbSeparator,
|
BreadcrumbSeparator,
|
||||||
|
BreadcrumbPage,
|
||||||
} from "@/components/ui/breadcrumb";
|
} from "@/components/ui/breadcrumb";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import { MinusIcon, PlusIcon } from "lucide-react";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
|
|
||||||
export interface UnitConverter {
|
|
||||||
toValue: (raw: string | undefined) => number;
|
|
||||||
fromValue: (value: number) => string;
|
|
||||||
formatDisplay: (value: number) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createConverter = (
|
|
||||||
multiplier: number,
|
|
||||||
formatDisplay: (value: number) => string,
|
|
||||||
): UnitConverter => ({
|
|
||||||
toValue: (raw) => {
|
|
||||||
if (!raw) return 0;
|
|
||||||
const value = Number.parseInt(raw, 10);
|
|
||||||
return Number.isNaN(value) ? 0 : value / multiplier;
|
|
||||||
},
|
|
||||||
fromValue: (value) =>
|
|
||||||
value <= 0 ? "" : String(Math.round(value * multiplier)),
|
|
||||||
formatDisplay,
|
|
||||||
});
|
|
||||||
|
|
||||||
interface NumberInputWithStepsProps {
|
|
||||||
value: string | undefined;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
placeholder: string;
|
|
||||||
step: number;
|
|
||||||
converter: UnitConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const NumberInputWithSteps = ({
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
placeholder,
|
|
||||||
step,
|
|
||||||
converter,
|
|
||||||
}: NumberInputWithStepsProps) => {
|
|
||||||
const numericValue = converter.toValue(value);
|
|
||||||
const displayValue = converter.formatDisplay(numericValue);
|
|
||||||
|
|
||||||
const handleIncrement = () =>
|
|
||||||
onChange(converter.fromValue(numericValue + step));
|
|
||||||
const handleDecrement = () =>
|
|
||||||
onChange(converter.fromValue(Math.max(0, numericValue - step)));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
className="h-9 w-9 shrink-0"
|
|
||||||
onClick={handleDecrement}
|
|
||||||
disabled={numericValue <= 0}
|
|
||||||
>
|
|
||||||
<MinusIcon className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
<Input
|
|
||||||
placeholder={placeholder}
|
|
||||||
value={value || ""}
|
|
||||||
onChange={(e) => onChange(e.target.value)}
|
|
||||||
className="text-center"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
className="h-9 w-9 shrink-0"
|
|
||||||
onClick={handleIncrement}
|
|
||||||
>
|
|
||||||
<PlusIcon className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{displayValue && (
|
|
||||||
<span className="text-xs text-muted-foreground text-center">
|
|
||||||
{displayValue}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"docker:build:canary": "./docker/build.sh canary",
|
"docker:build:canary": "./docker/build.sh canary",
|
||||||
"docker:push:canary": "./docker/push.sh canary",
|
"docker:push:canary": "./docker/push.sh canary",
|
||||||
"version": "echo $(node -p \"require('./package.json').version\")",
|
"version": "echo $(node -p \"require('./package.json').version\")",
|
||||||
"test": "vitest --config __test__/vitest.config.ts",
|
"test": "vitest --config __test__/vitest.config.ts volume-backups",
|
||||||
"generate:openapi": "tsx -r dotenv/config scripts/generate-openapi.ts"
|
"generate:openapi": "tsx -r dotenv/config scripts/generate-openapi.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -68,40 +68,6 @@ export const aiRouter = createTRPCRouter({
|
|||||||
{ headers: {} },
|
{ headers: {} },
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "perplexity":
|
|
||||||
// Perplexity doesn't have a /models endpoint, return hardcoded list
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: "sonar-deep-research",
|
|
||||||
object: "model",
|
|
||||||
created: Date.now(),
|
|
||||||
owned_by: "perplexity",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "sonar-reasoning-pro",
|
|
||||||
object: "model",
|
|
||||||
created: Date.now(),
|
|
||||||
owned_by: "perplexity",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "sonar-reasoning",
|
|
||||||
object: "model",
|
|
||||||
created: Date.now(),
|
|
||||||
owned_by: "perplexity",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "sonar-pro",
|
|
||||||
object: "model",
|
|
||||||
created: Date.now(),
|
|
||||||
owned_by: "perplexity",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "sonar",
|
|
||||||
object: "model",
|
|
||||||
created: Date.now(),
|
|
||||||
owned_by: "perplexity",
|
|
||||||
},
|
|
||||||
] as Model[];
|
|
||||||
default:
|
default:
|
||||||
if (!input.apiKey)
|
if (!input.apiKey)
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
|
|||||||
@@ -1,32 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "@dokploy/server",
|
"name": "@dokploy/server",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "./dist/index.js",
|
"main": "./src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": "./src/index.ts",
|
||||||
"import": "./dist/index.js",
|
|
||||||
"require": "./dist/index.cjs.js"
|
|
||||||
},
|
|
||||||
"./db": {
|
"./db": {
|
||||||
"import": "./dist/db/index.js",
|
"import": "./src/db/index.ts",
|
||||||
"require": "./dist/db/index.cjs.js"
|
"require": "./dist/db/index.cjs.js"
|
||||||
},
|
},
|
||||||
"./*": {
|
"./setup/*": {
|
||||||
"import": "./dist/*",
|
"import": "./src/setup/*.ts",
|
||||||
"require": "./dist/*.cjs"
|
"require": "./dist/setup/index.cjs.js"
|
||||||
},
|
},
|
||||||
"./dist": {
|
"./constants": {
|
||||||
"import": "./dist/index.js",
|
"import": "./src/constants/index.ts",
|
||||||
"require": "./dist/index.cjs.js"
|
"require": "./dist/constants.cjs.js"
|
||||||
},
|
|
||||||
"./dist/db": {
|
|
||||||
"import": "./dist/db/index.js",
|
|
||||||
"require": "./dist/db/index.cjs.js"
|
|
||||||
},
|
|
||||||
"./dist/db/schema": {
|
|
||||||
"import": "./dist/db/schema/index.js",
|
|
||||||
"require": "./dist/db/schema/index.cjs.js"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const getRegistryCommands = (
|
|||||||
): string => {
|
): string => {
|
||||||
return `
|
return `
|
||||||
echo "📦 [Enabled Registry] Uploading image to '${registry.registryType}' | '${registryTag}'" ;
|
echo "📦 [Enabled Registry] Uploading image to '${registry.registryType}' | '${registryTag}'" ;
|
||||||
echo "${registry.password}" | docker login ${registry.registryUrl} -u '${registry.username}' --password-stdin || {
|
echo "${registry.password}" | docker login ${registry.registryUrl} -u ${registry.username} --password-stdin || {
|
||||||
echo "❌ DockerHub Failed" ;
|
echo "❌ DockerHub Failed" ;
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,17 +146,17 @@ export const getContainerByName = (name: string): Promise<ContainerInfo> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Docker commands sent using this method are held in a hold when Docker is busy.
|
* Docker commands passed through this method are held during Docker's build or pull process.
|
||||||
*
|
*
|
||||||
* https://github.com/Dokploy/dokploy/pull/3064
|
* https://github.com/Dokploy/dokploy/pull/3064
|
||||||
|
* https://github.com/fir4tozden
|
||||||
*/
|
*/
|
||||||
export const dockerSafeExec = (exec: string) => `
|
export const dockerSafeExec = (exec: string) => `CHECK_INTERVAL=10
|
||||||
CHECK_INTERVAL=10
|
|
||||||
|
|
||||||
echo "Preparing for execution..."
|
echo "Preparing for execution..."
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
PROCESSES=$(ps aux | grep -E "^.*docker [A-Za-z]" | grep -v grep)
|
PROCESSES=$(ps aux | grep -E "docker build|docker pull" | grep -v grep)
|
||||||
|
|
||||||
if [ -z "$PROCESSES" ]; then
|
if [ -z "$PROCESSES" ]; then
|
||||||
echo "Docker is idle. Starting execution..."
|
echo "Docker is idle. Starting execution..."
|
||||||
@@ -167,23 +167,16 @@ while true; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Execute command and capture exit code
|
|
||||||
${exec}
|
${exec}
|
||||||
EXIT_CODE=$?
|
|
||||||
|
|
||||||
# Wait for all background processes to complete to prevent zombie processes
|
echo "Execution completed."`;
|
||||||
wait
|
|
||||||
|
|
||||||
echo "Execution completed with exit code: $EXIT_CODE"
|
|
||||||
exit $EXIT_CODE
|
|
||||||
`;
|
|
||||||
|
|
||||||
const cleanupCommands = {
|
const cleanupCommands = {
|
||||||
containers: "docker container prune --force",
|
containers: "docker container prune --force",
|
||||||
images: "docker image prune --all --force",
|
images: "docker image prune --all --force",
|
||||||
volumes: "docker volume prune --all --force",
|
|
||||||
builders: "docker builder prune --all --force",
|
builders: "docker builder prune --all --force",
|
||||||
system: "docker system prune --all --force",
|
system: "docker system prune --all --force",
|
||||||
|
volumes: "docker volume prune --all --force",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cleanupContainers = async (serverId?: string) => {
|
export const cleanupContainers = async (serverId?: string) => {
|
||||||
@@ -264,48 +257,24 @@ export const cleanupSystem = async (serverId?: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Volume cleanup should always be performed manually by the user. The reason is that during automatic cleanup, a volume may be deleted due to a stopped container, which is a dangerous situation.
|
|
||||||
*
|
|
||||||
* https://github.com/Dokploy/dokploy/pull/3267
|
|
||||||
*/
|
|
||||||
const excludedCleanupAllCommands: (keyof typeof cleanupCommands)[] = [
|
|
||||||
"volumes",
|
|
||||||
];
|
|
||||||
|
|
||||||
export const cleanupAll = async (serverId?: string) => {
|
export const cleanupAll = async (serverId?: string) => {
|
||||||
for (const [key, command] of Object.entries(cleanupCommands) as [
|
await cleanupContainers(serverId);
|
||||||
keyof typeof cleanupCommands,
|
await cleanupImages(serverId);
|
||||||
string,
|
await cleanupBuilders(serverId);
|
||||||
][]) {
|
await cleanupSystem(serverId);
|
||||||
if (excludedCleanupAllCommands.includes(key)) continue;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (serverId) {
|
|
||||||
await execAsyncRemote(serverId, dockerSafeExec(command));
|
|
||||||
} else {
|
|
||||||
await execAsync(dockerSafeExec(command));
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cleanupAllBackground = async (serverId?: string) => {
|
export const cleanupAllBackground = async (serverId?: string) => {
|
||||||
Promise.allSettled(
|
Promise.allSettled(
|
||||||
(
|
Object.values(cleanupCommands).map(async (command) => {
|
||||||
Object.entries(cleanupCommands) as [
|
try {
|
||||||
keyof typeof cleanupCommands,
|
|
||||||
string,
|
|
||||||
][]
|
|
||||||
)
|
|
||||||
.filter(([key]) => !excludedCleanupAllCommands.includes(key))
|
|
||||||
.map(async ([, command]) => {
|
|
||||||
if (serverId) {
|
if (serverId) {
|
||||||
await execAsyncRemote(serverId, dockerSafeExec(command));
|
await execAsyncRemote(serverId, dockerSafeExec(command));
|
||||||
} else {
|
} else {
|
||||||
await execAsync(dockerSafeExec(command));
|
await execAsync(dockerSafeExec(command));
|
||||||
}
|
}
|
||||||
}),
|
} catch (error) {}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.then((results) => {
|
.then((results) => {
|
||||||
const failed = results.filter((r) => r.status === "rejected");
|
const failed = results.filter((r) => r.status === "rejected");
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ export const backupVolume = async (
|
|||||||
echo "Turning off volume backup: ${turnOff ? "Yes" : "No"}"
|
echo "Turning off volume backup: ${turnOff ? "Yes" : "No"}"
|
||||||
echo "Starting volume backup"
|
echo "Starting volume backup"
|
||||||
echo "Dir: ${volumeBackupPath}"
|
echo "Dir: ${volumeBackupPath}"
|
||||||
|
echo "Ensuring ubuntu image is available..."
|
||||||
|
docker image inspect ubuntu:latest > /dev/null 2>&1 || docker pull ubuntu:latest
|
||||||
|
echo "Ubuntu image ready ✅"
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v ${volumeName}:/volume_data \
|
-v ${volumeName}:/volume_data \
|
||||||
-v ${volumeBackupPath}:/backup \
|
-v ${volumeBackupPath}:/backup \
|
||||||
|
|||||||
Reference in New Issue
Block a user