1import { z } from "zod";
2import i18n from "i18next";
3
4const numberInterval = (v: string | null | undefined) => {
5 return v ? /^[\d-]{1,32}$/.test(v) : false;
6};
7
8const packetsInterval = (v: string | null | undefined) => {
9 return v ? /^(:?tlshello|[\d-]{1,32})$/.test(v) : false;
10};
11
12export const HostSchema = z.object({
13 remark: z.string().min(1, "Remark is required"),
14 address: z.string().min(1, "Address is required"),
15 port: z.coerce
16 .number()
17 .gte(1, "Port must be more than 1")
18 .lte(65535, "Port can not be more than 65535")
19 .or(z.string())
20 .nullable()
21 .optional(),
22 path: z.string().nullable().optional(),
23 sni: z.string().nullable().optional(),
24 host: z.string().nullable().optional(),
25 mux: z.boolean().nullable().optional(),
26 fragment: z
27 .object({
28 interval: z
29 .string()
30 .refine(
31 (v) => numberInterval(v),
32 i18n.t("page.hosts.fragment.interval-error"),
33 ),
34 length: z
35 .string()
36 .refine(
37 (v) => numberInterval(v),
38 i18n.t("page.hosts.fragment.length-error"),
39 ),
40 packets: z
41 .string()
42 .refine(
43 (v) => packetsInterval(v),
44 i18n.t("page.hosts.fragment.packets-error"),
45 ),
46 })
47 .nullable()
48 .optional(),
49 security: z
50 .enum(["inbound_default", "none", "tls"])
51 .default("inbound_default"),
52 alpn: z
53 .enum(["h2", "http/1.1", "h2,http/1.1", "none", ""])
54 .optional()
55 .default("none"),
56 allowinsecure: z.boolean().default(false).optional(),
57 fingerprint: z
58 .enum([
59 "",
60 "none",
61 "chrome",
62 "firefox",
63 "safari",
64 "ios",
65 "android",
66 "edge",
67 "360",
68 "qq",
69 "random",
70 "randomized",
71 ])
72 .optional()
73 .default("none"),
74});