🎉 feat: initialization
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
export const protocols = [
|
||||
"shadowsocks",
|
||||
"vmess",
|
||||
"vless",
|
||||
"trojan",
|
||||
"hysteria",
|
||||
"tuic",
|
||||
"anytls",
|
||||
"socks",
|
||||
"naive",
|
||||
"http",
|
||||
"mieru",
|
||||
] as const;
|
||||
|
||||
// Global label map for display; fallback to raw value if missing
|
||||
export const LABELS = {
|
||||
// transport
|
||||
tcp: "TCP",
|
||||
udp: "UDP",
|
||||
websocket: "WebSocket",
|
||||
grpc: "gRPC",
|
||||
mkcp: "mKCP",
|
||||
httpupgrade: "HTTP Upgrade",
|
||||
xhttp: "XHTTP",
|
||||
// security
|
||||
none: "NONE",
|
||||
tls: "TLS",
|
||||
reality: "Reality",
|
||||
// fingerprint
|
||||
chrome: "Chrome",
|
||||
firefox: "Firefox",
|
||||
safari: "Safari",
|
||||
ios: "IOS",
|
||||
android: "Android",
|
||||
edge: "edge",
|
||||
"360": "360",
|
||||
qq: "QQ",
|
||||
// multiplex
|
||||
low: "Low",
|
||||
middle: "Middle",
|
||||
high: "High",
|
||||
} as const;
|
||||
|
||||
// Flat arrays for enum-like sets
|
||||
export const SS_CIPHERS = [
|
||||
"aes-128-gcm",
|
||||
"aes-192-gcm",
|
||||
"aes-256-gcm",
|
||||
"chacha20-ietf-poly1305",
|
||||
"2022-blake3-aes-128-gcm",
|
||||
"2022-blake3-aes-256-gcm",
|
||||
"2022-blake3-chacha20-poly1305",
|
||||
] as const;
|
||||
|
||||
export const TRANSPORTS = {
|
||||
vmess: ["tcp", "websocket", "grpc"] as const,
|
||||
vless: ["tcp", "websocket", "grpc", "mkcp", "httpupgrade", "xhttp"] as const,
|
||||
trojan: ["tcp", "websocket", "grpc"] as const,
|
||||
mieru: ["tcp", "udp"] as const,
|
||||
} as const;
|
||||
|
||||
export const SECURITY = {
|
||||
shadowsocks: ["none", "http", "tls"] as const,
|
||||
vmess: ["none", "tls"] as const,
|
||||
vless: ["none", "tls", "reality"] as const,
|
||||
trojan: ["tls"] as const,
|
||||
hysteria: ["tls"] as const,
|
||||
tuic: ["tls"] as const,
|
||||
anytls: ["tls"] as const,
|
||||
naive: ["none", "tls"] as const,
|
||||
http: ["none", "tls"] as const,
|
||||
} as const;
|
||||
|
||||
export const FLOWS = {
|
||||
vless: [
|
||||
"none",
|
||||
"xtls-rprx-direct",
|
||||
"xtls-rprx-splice",
|
||||
"xtls-rprx-vision",
|
||||
] as const,
|
||||
} as const;
|
||||
|
||||
export const TUIC_UDP_RELAY_MODES = ["native", "quic"] as const;
|
||||
export const TUIC_CONGESTION = ["bbr", "cubic", "new_reno"] as const;
|
||||
export const XHTTP_MODES = [
|
||||
"auto",
|
||||
"packet-up",
|
||||
"stream-up",
|
||||
"stream-one",
|
||||
] as const;
|
||||
export const ENCRYPTION_TYPES = ["none", "mlkem768x25519plus"] as const;
|
||||
export const ENCRYPTION_MODES = ["native", "xorpub", "random"] as const;
|
||||
export const ENCRYPTION_RTT = ["0rtt", "1rtt"] as const;
|
||||
export const FINGERPRINTS = [
|
||||
"chrome",
|
||||
"firefox",
|
||||
"safari",
|
||||
"ios",
|
||||
"android",
|
||||
"edge",
|
||||
"360",
|
||||
"qq",
|
||||
] as const;
|
||||
|
||||
export const CERT_MODES = ["none", "http", "dns", "self"] as const;
|
||||
|
||||
export const multiplexLevels = ["none", "low", "middle", "high"] as const;
|
||||
|
||||
export function getLabel(value: string): string {
|
||||
const label = (LABELS as Record<string, string>)[value];
|
||||
return label ?? value.toUpperCase();
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
import { XHTTP_MODES } from "./constants";
|
||||
import type { ProtocolType } from "./types";
|
||||
|
||||
export function getProtocolDefaultConfig(proto: ProtocolType) {
|
||||
switch (proto) {
|
||||
case "shadowsocks":
|
||||
return {
|
||||
type: "shadowsocks",
|
||||
enable: false,
|
||||
port: null,
|
||||
cipher: "chacha20-ietf-poly1305",
|
||||
server_key: null,
|
||||
obfs: "none",
|
||||
obfs_host: null,
|
||||
obfs_path: null,
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "vmess":
|
||||
return {
|
||||
type: "vmess",
|
||||
enable: false,
|
||||
host: null,
|
||||
port: null,
|
||||
transport: "tcp",
|
||||
security: "none",
|
||||
path: null,
|
||||
service_name: null,
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "vless":
|
||||
return {
|
||||
type: "vless",
|
||||
enable: false,
|
||||
host: null,
|
||||
port: null,
|
||||
transport: "tcp",
|
||||
security: "none",
|
||||
flow: "none",
|
||||
path: null,
|
||||
service_name: null,
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
reality_server_addr: null,
|
||||
reality_server_port: null,
|
||||
reality_private_key: null,
|
||||
reality_public_key: null,
|
||||
reality_short_id: null,
|
||||
xhttp_mode: XHTTP_MODES[0], // 'auto'
|
||||
xhttp_extra: null,
|
||||
encryption: "none",
|
||||
encryption_mode: null,
|
||||
encryption_rtt: null,
|
||||
encryption_ticket: null,
|
||||
encryption_server_padding: null,
|
||||
encryption_private_key: null,
|
||||
encryption_client_padding: null,
|
||||
encryption_password: null,
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "trojan":
|
||||
return {
|
||||
type: "trojan",
|
||||
enable: false,
|
||||
host: null,
|
||||
port: null,
|
||||
transport: "tcp",
|
||||
security: "tls",
|
||||
path: null,
|
||||
service_name: null,
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "hysteria":
|
||||
return {
|
||||
type: "hysteria",
|
||||
enable: false,
|
||||
port: null,
|
||||
hop_ports: null,
|
||||
hop_interval: null,
|
||||
obfs: "none",
|
||||
obfs_password: null,
|
||||
security: "tls",
|
||||
up_mbps: null,
|
||||
down_mbps: null,
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "tuic":
|
||||
return {
|
||||
type: "tuic",
|
||||
enable: false,
|
||||
port: null,
|
||||
disable_sni: false,
|
||||
reduce_rtt: false,
|
||||
udp_relay_mode: "native",
|
||||
congestion_controller: "bbr",
|
||||
security: "tls",
|
||||
sni: null,
|
||||
allow_insecure: false,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "socks":
|
||||
return {
|
||||
type: "socks",
|
||||
enable: false,
|
||||
port: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "naive":
|
||||
return {
|
||||
type: "naive",
|
||||
enable: false,
|
||||
port: null,
|
||||
security: "none",
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "http":
|
||||
return {
|
||||
type: "http",
|
||||
enable: false,
|
||||
port: null,
|
||||
security: "none",
|
||||
sni: null,
|
||||
allow_insecure: null,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
case "mieru":
|
||||
return {
|
||||
type: "mieru",
|
||||
enable: false,
|
||||
port: null,
|
||||
multiplex: "none",
|
||||
transport: "tcp",
|
||||
} as any;
|
||||
case "anytls":
|
||||
return {
|
||||
type: "anytls",
|
||||
enable: false,
|
||||
port: null,
|
||||
security: "tls",
|
||||
padding_scheme: null,
|
||||
sni: null,
|
||||
allow_insecure: false,
|
||||
fingerprint: "chrome",
|
||||
cert_mode: "none",
|
||||
cert_dns_provider: null,
|
||||
cert_dns_env: null,
|
||||
ratio: 1,
|
||||
} as any;
|
||||
default:
|
||||
return {} as any;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Re-export all constants
|
||||
export {
|
||||
ENCRYPTION_MODES,
|
||||
ENCRYPTION_RTT,
|
||||
ENCRYPTION_TYPES,
|
||||
FINGERPRINTS,
|
||||
FLOWS,
|
||||
getLabel,
|
||||
LABELS,
|
||||
multiplexLevels,
|
||||
protocols,
|
||||
SECURITY,
|
||||
SS_CIPHERS,
|
||||
TRANSPORTS,
|
||||
TUIC_CONGESTION,
|
||||
TUIC_UDP_RELAY_MODES,
|
||||
XHTTP_MODES,
|
||||
} from "./constants";
|
||||
// Re-export defaults
|
||||
export { getProtocolDefaultConfig } from "./defaults";
|
||||
// Re-export all schemas
|
||||
export { formSchema, protocolApiScheme } from "./schemas";
|
||||
// Re-export all types
|
||||
export type { FieldConfig, ProtocolType } from "./types";
|
||||
// Re-export hooks
|
||||
export { useProtocolFields } from "./useProtocolFields";
|
||||
@@ -0,0 +1,225 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
CERT_MODES,
|
||||
ENCRYPTION_MODES,
|
||||
ENCRYPTION_RTT,
|
||||
ENCRYPTION_TYPES,
|
||||
FLOWS,
|
||||
multiplexLevels,
|
||||
SECURITY,
|
||||
SS_CIPHERS,
|
||||
TRANSPORTS,
|
||||
TUIC_CONGESTION,
|
||||
TUIC_UDP_RELAY_MODES,
|
||||
XHTTP_MODES,
|
||||
} from "./constants";
|
||||
|
||||
const nullableString = z.string().nullish();
|
||||
const nullableBool = z.boolean().nullish();
|
||||
const nullablePort = z.number().int().min(0).max(65_535).nullish();
|
||||
const nullableRatio = z.number().min(0).nullish();
|
||||
|
||||
const ss = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("shadowsocks"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
cipher: z.enum(SS_CIPHERS).nullish(),
|
||||
server_key: nullableString,
|
||||
obfs: z.enum(["none", "http", "tls"] as const).nullish(),
|
||||
obfs_host: nullableString,
|
||||
obfs_path: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const vmess = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("vmess"),
|
||||
enable: nullableBool,
|
||||
host: nullableString,
|
||||
port: nullablePort,
|
||||
transport: z.enum(TRANSPORTS.vmess).nullish(),
|
||||
security: z.enum(SECURITY.vmess).nullish(),
|
||||
path: nullableString,
|
||||
service_name: nullableString,
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const vless = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("vless"),
|
||||
enable: nullableBool,
|
||||
host: nullableString,
|
||||
port: nullablePort,
|
||||
transport: z.enum(TRANSPORTS.vless).nullish(),
|
||||
security: z.enum(SECURITY.vless).nullish(),
|
||||
path: nullableString,
|
||||
service_name: nullableString,
|
||||
flow: z.enum(FLOWS.vless).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
reality_server_addr: nullableString,
|
||||
reality_server_port: nullablePort,
|
||||
reality_private_key: nullableString,
|
||||
reality_public_key: nullableString,
|
||||
reality_short_id: nullableString,
|
||||
xhttp_mode: z.enum(XHTTP_MODES).nullish(),
|
||||
xhttp_extra: nullableString,
|
||||
encryption: z.enum(ENCRYPTION_TYPES).nullish(),
|
||||
encryption_mode: z.enum(ENCRYPTION_MODES).nullish(),
|
||||
encryption_rtt: z.enum(ENCRYPTION_RTT).nullish(),
|
||||
encryption_ticket: nullableString,
|
||||
encryption_server_padding: nullableString,
|
||||
encryption_private_key: nullableString,
|
||||
encryption_client_padding: nullableString,
|
||||
encryption_password: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const trojan = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("trojan"),
|
||||
enable: nullableBool,
|
||||
host: nullableString,
|
||||
port: nullablePort,
|
||||
transport: z.enum(TRANSPORTS.trojan).nullish(),
|
||||
security: z.enum(SECURITY.trojan).nullish(),
|
||||
path: nullableString,
|
||||
service_name: nullableString,
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const hysteria = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("hysteria"),
|
||||
enable: nullableBool,
|
||||
hop_ports: nullableString,
|
||||
hop_interval: z.number().nullish(),
|
||||
obfs_password: nullableString,
|
||||
obfs: z.enum(["none", "salamander"] as const).nullish(),
|
||||
port: nullablePort,
|
||||
security: z.enum(SECURITY.hysteria).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
up_mbps: z.number().nullish(),
|
||||
down_mbps: z.number().nullish(),
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const tuic = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("tuic"),
|
||||
enable: nullableBool,
|
||||
host: nullableString,
|
||||
port: nullablePort,
|
||||
disable_sni: z.boolean().nullish(),
|
||||
reduce_rtt: z.boolean().nullish(),
|
||||
udp_relay_mode: z.enum(TUIC_UDP_RELAY_MODES).nullish(),
|
||||
congestion_controller: z.enum(TUIC_CONGESTION).nullish(),
|
||||
security: z.enum(SECURITY.tuic).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const anytls = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("anytls"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
security: z.enum(SECURITY.anytls).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
padding_scheme: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const socks = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("socks"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
});
|
||||
|
||||
const naive = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("naive"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
security: z.enum(SECURITY.naive).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const http = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("http"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
security: z.enum(SECURITY.http).nullish(),
|
||||
sni: nullableString,
|
||||
allow_insecure: nullableBool,
|
||||
fingerprint: nullableString,
|
||||
cert_mode: z.enum(CERT_MODES).nullish(),
|
||||
cert_dns_provider: nullableString,
|
||||
cert_dns_env: nullableString,
|
||||
});
|
||||
|
||||
const mieru = z.object({
|
||||
ratio: nullableRatio,
|
||||
type: z.literal("mieru"),
|
||||
enable: nullableBool,
|
||||
port: nullablePort,
|
||||
multiplex: z.enum(multiplexLevels).nullish(),
|
||||
transport: z.enum(TRANSPORTS.mieru).nullish(),
|
||||
});
|
||||
|
||||
export const protocolApiScheme = z.discriminatedUnion("type", [
|
||||
ss,
|
||||
vmess,
|
||||
vless,
|
||||
trojan,
|
||||
hysteria,
|
||||
tuic,
|
||||
anytls,
|
||||
socks,
|
||||
naive,
|
||||
http,
|
||||
mieru,
|
||||
]);
|
||||
|
||||
export const formSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
address: z.string().min(1),
|
||||
country: z.string().optional(),
|
||||
city: z.string().optional(),
|
||||
protocols: z.array(protocolApiScheme),
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { protocols } from "./constants";
|
||||
|
||||
export type FieldConfig = {
|
||||
name: string;
|
||||
type: "input" | "select" | "switch" | "number" | "textarea";
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
options?: readonly string[];
|
||||
defaultValue?: any;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
suffix?: string;
|
||||
generate?: {
|
||||
function?: () =>
|
||||
| Promise<string | Record<string, string>>
|
||||
| string
|
||||
| Record<string, string>;
|
||||
functions?: {
|
||||
label: string;
|
||||
function: () =>
|
||||
| Promise<string | Record<string, string>>
|
||||
| string
|
||||
| Record<string, string>;
|
||||
}[];
|
||||
updateFields?: Record<string, string>;
|
||||
};
|
||||
condition?: (protocol: any, values: any) => boolean;
|
||||
group?:
|
||||
| "basic"
|
||||
| "transport"
|
||||
| "security"
|
||||
| "reality"
|
||||
| "obfs"
|
||||
| "encryption";
|
||||
gridSpan?: 1 | 2;
|
||||
};
|
||||
|
||||
export type ProtocolType = (typeof protocols)[number];
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user