@gozargah/xray-schema 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1309 @@
1
+ import z from "zod";
2
+ //#region src/transport/version/version.ts
3
+ const versionSchema = z.object({
4
+ min: z.string().optional(),
5
+ max: z.string().optional()
6
+ });
7
+ //#endregion
8
+ //#region src/log/log.ts
9
+ const logSchema = z.object({
10
+ access: z.union([z.string(), z.literal("none")]).default("").optional(),
11
+ error: z.union([z.string(), z.literal("none")]).optional().default("").optional(),
12
+ loglevel: z.enum([
13
+ "debug",
14
+ "info",
15
+ "warning",
16
+ "error",
17
+ "none"
18
+ ]).default("warning").optional(),
19
+ dnsLog: z.boolean().optional().default(false).optional(),
20
+ maskAddress: z.union([
21
+ z.literal(""),
22
+ z.enum([
23
+ "quarter",
24
+ "half",
25
+ "full"
26
+ ]),
27
+ z.string().regex(/^\/(?:0|8|16|24|32)\+\/(?:12[0-8]|1[01][0-9]|[0-9]{1,2})$/)
28
+ ]).default("").optional()
29
+ });
30
+ //#endregion
31
+ //#region src/api/api.ts
32
+ const apiServices = z.union([
33
+ z.literal("HandlerService"),
34
+ z.literal("RoutingService"),
35
+ z.literal("LoggerService"),
36
+ z.literal("StatsService"),
37
+ z.literal("ReflectionService")
38
+ ]);
39
+ const apiSchema = z.object({
40
+ tag: z.string(),
41
+ listen: z.string().optional(),
42
+ services: z.array(apiServices).optional()
43
+ });
44
+ //#endregion
45
+ //#region src/dns/dnsObject/dnsObject.ts
46
+ const dnsObject = z.object({
47
+ address: z.string(),
48
+ port: z.number().optional(),
49
+ domains: z.array(z.string()).optional(),
50
+ expectedIPs: z.array(z.string()).optional(),
51
+ unexpectedIPs: z.array(z.string()).optional(),
52
+ skipFallback: z.boolean().default(false).optional(),
53
+ finalQuery: z.boolean().default(false).optional(),
54
+ tag: z.string().optional(),
55
+ clientIP: z.string().optional(),
56
+ queryStrategy: z.enum([
57
+ "UseIP",
58
+ "UseIPv4",
59
+ "UseIPv6",
60
+ "UseSystem"
61
+ ]).default("UseIP").optional(),
62
+ disableCache: z.boolean().default(false).optional()
63
+ });
64
+ //#endregion
65
+ //#region src/dns/dns.ts
66
+ const dnsSchema = z.object({
67
+ hosts: z.record(z.string(), z.union([z.string(), z.array(z.string())])).optional(),
68
+ servers: z.array(z.union([z.string(), dnsObject])).optional(),
69
+ tag: z.string().optional(),
70
+ clientIP: z.string().optional(),
71
+ queryStrategy: z.enum([
72
+ "UseIP",
73
+ "UseIPv4",
74
+ "UseIPv6",
75
+ "UseSystem"
76
+ ]).default("UseIP").optional(),
77
+ disableCache: z.boolean().default(false).optional(),
78
+ disableFallback: z.boolean().default(false).optional(),
79
+ disableFallbackIfMatch: z.boolean().default(false).optional(),
80
+ useSystemHosts: z.boolean().default(false).optional(),
81
+ enableParallelQuery: z.boolean().default(false).optional(),
82
+ serveStale: z.boolean().default(false).optional(),
83
+ serveExpiredTTL: z.number().default(0).optional()
84
+ }).loose();
85
+ //#endregion
86
+ //#region src/routing/ruleObject/ruleObject.ts
87
+ const routingRule = z.object({
88
+ domain: z.array(z.string()).optional(),
89
+ ip: z.array(z.string()).optional(),
90
+ port: z.union([z.string(), z.number()]).optional(),
91
+ sourcePort: z.union([z.string(), z.number()]).optional(),
92
+ network: z.enum([
93
+ "tcp",
94
+ "udp",
95
+ "tcp,udp"
96
+ ]).optional(),
97
+ source: z.array(z.string()).optional(),
98
+ sourceIP: z.array(z.string()).optional(),
99
+ user: z.array(z.string()).optional(),
100
+ vlessRoute: z.string().optional(),
101
+ inboundTag: z.array(z.string()).optional(),
102
+ protocol: z.array(z.string()).optional(),
103
+ attrs: z.record(z.string(), z.unknown()).optional(),
104
+ process: z.array(z.string()).optional(),
105
+ outboundTag: z.string().optional(),
106
+ balancerTag: z.string().optional(),
107
+ ruleTag: z.string().optional(),
108
+ webhook: z.object({
109
+ url: z.string(),
110
+ deduplication: z.number().optional(),
111
+ headers: z.object().loose()
112
+ }).optional()
113
+ }).loose();
114
+ //#endregion
115
+ //#region src/routing/balancerObject/strategyObject/leastLoadSettingsObject.ts
116
+ const costsObject = z.object({
117
+ regexp: z.boolean().default(false).optional(),
118
+ match: z.string().optional(),
119
+ value: z.float32().optional()
120
+ });
121
+ const leastLoadSettingsObject = z.object({
122
+ expected: z.number().optional(),
123
+ maxRTT: z.string().optional(),
124
+ tolerance: z.float32().optional(),
125
+ baselines: z.array(z.string()).optional(),
126
+ costs: z.array(costsObject).default([]).optional()
127
+ });
128
+ //#endregion
129
+ //#region src/routing/balancerObject/strategyObject/strategyObject.ts
130
+ const strategyObject = z.discriminatedUnion("type", [
131
+ z.object({ type: z.literal("random") }),
132
+ z.object({ type: z.literal("roundRobin") }),
133
+ z.object({ type: z.literal("leastPing") }),
134
+ z.object({
135
+ type: z.literal("leastLoad"),
136
+ settings: leastLoadSettingsObject.optional()
137
+ })
138
+ ]);
139
+ //#endregion
140
+ //#region src/routing/balancerObject/balancerObject.ts
141
+ const balancerObject = z.object({
142
+ tag: z.string().optional(),
143
+ selector: z.array(z.string()).optional(),
144
+ fallbackTag: z.string().optional(),
145
+ strategy: strategyObject
146
+ });
147
+ //#endregion
148
+ //#region src/routing/routing.ts
149
+ const routingSchema = z.object({
150
+ domainStrategy: z.union([
151
+ z.literal("AsIs"),
152
+ z.literal("IPIfNonMatch"),
153
+ z.literal("IPOnDemand")
154
+ ]).optional(),
155
+ rules: z.array(routingRule).optional(),
156
+ balancers: z.array(balancerObject).optional()
157
+ }).loose();
158
+ //#endregion
159
+ //#region src/policy/policy.ts
160
+ const policySchema = z.object({
161
+ levels: z.record(z.string(), z.object({
162
+ handshake: z.number().default(4).optional(),
163
+ connIdle: z.number().default(300).optional(),
164
+ uplinkOnly: z.number().default(2).optional(),
165
+ downlinkOnly: z.number().default(5).optional(),
166
+ statsUserUplink: z.boolean().default(false).optional(),
167
+ statsUserDownlink: z.boolean().default(false).optional(),
168
+ statsUserOnline: z.boolean().default(false).optional(),
169
+ bufferSize: z.number().optional()
170
+ })).optional(),
171
+ system: z.object({
172
+ statsInboundUplink: z.boolean().default(false).optional(),
173
+ statsInboundDownlink: z.boolean().default(false).optional(),
174
+ statsOutboundUplink: z.boolean().default(false).optional(),
175
+ statsOutboundDownlink: z.boolean().default(false).optional()
176
+ }).optional()
177
+ });
178
+ //#endregion
179
+ //#region src/inbounds/sniffing/sniffing.ts
180
+ const sniffingSchema = z.object({
181
+ enabled: z.boolean().default(true).optional(),
182
+ destOverride: z.array(z.enum([
183
+ "http",
184
+ "tls",
185
+ "quic",
186
+ "fakedns"
187
+ ])).default([
188
+ "http",
189
+ "tls",
190
+ "fakedns"
191
+ ]),
192
+ metadataOnly: z.boolean().default(false).optional(),
193
+ domainsExcluded: z.array(z.string()).default([]).optional(),
194
+ ipsExcluded: z.array(z.string()).default([]).optional(),
195
+ routeOnly: z.boolean().default(false).optional()
196
+ });
197
+ //#endregion
198
+ //#region src/transport/finalmask/customSettingsObject.ts
199
+ const headerCustomSettingsObject = z.object({
200
+ delay: z.int().default(0).optional(),
201
+ rand: z.int().default(0).optional(),
202
+ randRange: z.string().default("0-255").optional(),
203
+ type: z.enum([
204
+ "array",
205
+ "str",
206
+ "hex",
207
+ "base64"
208
+ ]).default("array").optional(),
209
+ packet: z.array(z.any()).optional()
210
+ });
211
+ //#endregion
212
+ //#region src/transport/finalmask/sudoku.ts
213
+ const sudoku = z.object({
214
+ type: z.literal("sudoku"),
215
+ settings: z.object({
216
+ password: z.string(),
217
+ ascii: z.string(),
218
+ customTable: z.string(),
219
+ customTables: z.array(z.string()),
220
+ paddingMin: z.int(),
221
+ paddingMax: z.int()
222
+ })
223
+ });
224
+ //#endregion
225
+ //#region src/transport/finalmask/tcpFinalmask.ts
226
+ const tcpHeaderCustom$1 = z.object({
227
+ type: z.literal("header-custom"),
228
+ settings: z.object({
229
+ clients: z.array(z.array(headerCustomSettingsObject)),
230
+ servers: z.array(z.array(headerCustomSettingsObject)),
231
+ errors: z.array(z.array(headerCustomSettingsObject))
232
+ })
233
+ });
234
+ const tcpFragment = z.object({
235
+ type: z.literal("fragment"),
236
+ settings: z.object({
237
+ packets: z.enum(["1-3", "tlshello"]),
238
+ length: z.string(),
239
+ delay: z.string(),
240
+ maxSplit: z.string()
241
+ })
242
+ });
243
+ const tcpFinalmask = z.array(z.discriminatedUnion("type", [
244
+ tcpHeaderCustom$1,
245
+ tcpFragment,
246
+ sudoku
247
+ ]));
248
+ //#endregion
249
+ //#region src/transport/finalmask/udpFinalmask.ts
250
+ const tcpHeaderCustom = z.object({
251
+ type: z.literal("header-custom"),
252
+ settings: z.object({
253
+ client: z.array(headerCustomSettingsObject),
254
+ server: z.array(headerCustomSettingsObject)
255
+ })
256
+ });
257
+ const headerDns = z.object({
258
+ type: z.literal("header-dns"),
259
+ settings: z.object({ domain: z.string() })
260
+ });
261
+ const mkcpAes128gcm = z.object({
262
+ type: z.literal("mkcp-aes128gcm"),
263
+ settings: z.object({ password: z.string() })
264
+ });
265
+ const noise$1 = z.object({
266
+ type: z.literal("noise"),
267
+ settings: z.object({
268
+ reset: z.int(),
269
+ noise: z.array(z.object({
270
+ rand: z.string(),
271
+ randRange: z.string(),
272
+ type: z.string(),
273
+ packet: z.array(z.any()),
274
+ delay: z.string()
275
+ }))
276
+ })
277
+ });
278
+ const salamander = z.object({
279
+ type: z.literal("salamander"),
280
+ settings: z.object({ password: z.string() })
281
+ });
282
+ const xdns = z.object({
283
+ type: z.literal("xdns"),
284
+ settings: z.object({ domains: z.array(z.string()).min(1) }).or(z.object({ resolvers: z.array(z.string()).min(1) }))
285
+ });
286
+ const xicmp = z.object({
287
+ type: z.literal("xicmp"),
288
+ settings: z.object({
289
+ dgram: z.boolean().default(false).optional(),
290
+ ips: z.array(z.string()).default([]).optional()
291
+ })
292
+ });
293
+ const realm = z.object({
294
+ type: z.literal("realm"),
295
+ settings: z.object({
296
+ url: z.string().min(1),
297
+ stunServers: z.array(z.string()).min(1),
298
+ tlsConfig: z.object({}).loose()
299
+ })
300
+ });
301
+ const udpFinalmask = z.array(z.discriminatedUnion("type", [
302
+ tcpHeaderCustom,
303
+ headerDns,
304
+ mkcpAes128gcm,
305
+ noise$1,
306
+ salamander,
307
+ sudoku,
308
+ xdns,
309
+ xicmp,
310
+ realm
311
+ ]));
312
+ //#endregion
313
+ //#region src/transport/finalmask/quicParams.ts
314
+ const udpHop = z.object({
315
+ ports: z.string(),
316
+ interval: z.number().or(z.string()).default(30).optional()
317
+ });
318
+ const quicParams = z.object({
319
+ congestion: z.enum([
320
+ "reno",
321
+ "bbr",
322
+ "brutal",
323
+ "force-brutal"
324
+ ]).optional(),
325
+ bbrProfile: z.enum([
326
+ "conservative",
327
+ "standard",
328
+ "aggressive"
329
+ ]).optional(),
330
+ debug: z.boolean().default(false).optional(),
331
+ brutalUp: z.string().or(z.int()).default(0).optional(),
332
+ brutalDown: z.string().or(z.int()).default(0).optional(),
333
+ udpHop: udpHop.optional(),
334
+ initStreamReceiveWindow: z.int().default(8388608).optional(),
335
+ maxStreamReceiveWindow: z.int().default(8388608).optional(),
336
+ initConnectionReceiveWindow: z.int().default(20971520).optional(),
337
+ maxConnectionReceiveWindow: z.int().default(20971520).optional(),
338
+ maxIdleTimeout: z.int().default(30).optional(),
339
+ keepAlivePeriod: z.int().default(0).optional(),
340
+ disablePathMTUDiscovery: z.boolean().default(false).optional(),
341
+ maxIncomingStreams: z.int().min(8).default(1024).optional()
342
+ });
343
+ //#endregion
344
+ //#region src/transport/finalmask/finalmask.ts
345
+ const finalmask = z.object({
346
+ tcp: tcpFinalmask.optional(),
347
+ udp: udpFinalmask.optional(),
348
+ quicParams: quicParams.optional()
349
+ });
350
+ //#endregion
351
+ //#region src/transport/sockopt/sockopt.ts
352
+ const happyEyeballs = z.object({
353
+ tryDelayMs: z.int().default(0).optional(),
354
+ prioritizeIPv6: z.boolean().default(false).optional(),
355
+ interleave: z.int().default(1).optional(),
356
+ maxConcurrentTry: z.int().default(4).optional()
357
+ });
358
+ const customSockoptObject = z.object({
359
+ system: z.enum([
360
+ "linux",
361
+ "windows",
362
+ "darwin",
363
+ ""
364
+ ]).or(z.string()).optional(),
365
+ type: z.enum(["int", "str"]),
366
+ level: z.string().or(z.int()).default("6").optional(),
367
+ opt: z.string().or(z.int()),
368
+ value: z.string().or(z.int())
369
+ });
370
+ const sockopt = z.object({
371
+ mark: z.int().optional(),
372
+ tcpMaxSeg: z.int().optional(),
373
+ tcpFastOpen: z.boolean().or(z.number()).optional(),
374
+ tproxy: z.enum([
375
+ "redirect",
376
+ "tproxy",
377
+ "off"
378
+ ]).default("off").optional(),
379
+ domainStrategy: z.enum([
380
+ "AsIs",
381
+ "UseIP",
382
+ "UseIPv6v4",
383
+ "UseIPv6",
384
+ "UseIPv4v6",
385
+ "UseIPv4",
386
+ "ForceIP",
387
+ "ForceIPv6v4",
388
+ "ForceIPv6",
389
+ "ForceIPv4v6",
390
+ "ForceIPv4"
391
+ ]).default("AsIs").optional(),
392
+ happyEyeballs: happyEyeballs.default({}).optional(),
393
+ dialerProxy: z.string().optional(),
394
+ acceptProxyProtocol: z.boolean().default(false).optional(),
395
+ trustedXForwardedFor: z.array(z.string()).optional(),
396
+ tcpKeepAliveInterval: z.int().optional(),
397
+ tcpKeepAliveIdle: z.int().optional(),
398
+ tcpUserTimeout: z.int().optional(),
399
+ tcpcongestion: z.enum([
400
+ "bbr",
401
+ "cubic",
402
+ "reno",
403
+ ""
404
+ ]).optional(),
405
+ interface: z.string().optional(),
406
+ V6Only: z.boolean().default(false).optional(),
407
+ tcpWindowClamp: z.int().optional(),
408
+ tcpMptcp: z.boolean().default(false).optional(),
409
+ addressPortStrategy: z.enum([
410
+ "none",
411
+ "SrvPortOnly",
412
+ "SrvAddressOnly",
413
+ "SrvPortAndAddress",
414
+ "TxtPortOnly",
415
+ "TxtAddressOnly",
416
+ "TxtPortAndAddress",
417
+ "none"
418
+ ]).default("none").optional(),
419
+ customSockopt: z.array(customSockoptObject).optional()
420
+ });
421
+ //#endregion
422
+ //#region src/transport/base.ts
423
+ const transportBase = z.object({
424
+ finalmask: finalmask.optional(),
425
+ sockopt: sockopt.optional()
426
+ });
427
+ //#endregion
428
+ //#region src/transport/raw/raw.ts
429
+ const nonHeaderSchema = z.object({ type: z.literal("none") });
430
+ const httpHeaderRequestSchema = z.object({
431
+ version: z.string().default("1.1").optional(),
432
+ method: z.string().default("GET").optional(),
433
+ path: z.array(z.string()).default(["/"]).optional(),
434
+ headers: z.record(z.string(), z.union([z.string(), z.array(z.string())])).default({}).optional()
435
+ });
436
+ const httpHeaderResponseSchema = z.object({
437
+ version: z.string().default("1.1").optional(),
438
+ status: z.string().default("200").optional(),
439
+ reason: z.string().default("OK").optional(),
440
+ headers: z.record(z.string(), z.union([z.string(), z.array(z.string())])).default({}).optional()
441
+ });
442
+ const httpHeaderSchema = z.object({
443
+ type: z.literal("http"),
444
+ request: httpHeaderRequestSchema.default({}).optional(),
445
+ response: httpHeaderResponseSchema.default({}).optional()
446
+ });
447
+ const rawSettingsHeaderSchema = z.discriminatedUnion("type", [nonHeaderSchema, httpHeaderSchema]);
448
+ const rawSettings = z.object({
449
+ acceptProxyProtocol: z.boolean().default(false).optional(),
450
+ header: rawSettingsHeaderSchema.default({ type: "none" }).optional()
451
+ }).optional();
452
+ const rawStream = transportBase.extend({
453
+ network: z.literal("raw"),
454
+ rawSettings
455
+ });
456
+ const tcpStream = transportBase.extend({
457
+ network: z.literal("tcp").optional(),
458
+ tcpSettings: rawSettings
459
+ });
460
+ //#endregion
461
+ //#region src/transport/mkcp/mkcp.ts
462
+ const mkcpStream = transportBase.extend({
463
+ network: z.literal("kcp").or(z.literal("mkcp")),
464
+ kcpSettings: z.object({
465
+ mtu: z.number().int().nonnegative().default(1350).optional(),
466
+ tti: z.number().int().nonnegative().default(50).optional(),
467
+ uplinkCapacity: z.number().int().nonnegative().default(5).optional(),
468
+ downlinkCapacity: z.number().int().nonnegative().default(20).optional(),
469
+ congestion: z.boolean().default(false).optional(),
470
+ readBufferSize: z.number().int().nonnegative().default(2).optional(),
471
+ writeBufferSize: z.number().int().nonnegative().default(2).optional()
472
+ }).optional()
473
+ });
474
+ //#endregion
475
+ //#region src/transport/websocket/websocket.ts
476
+ const websocketStream = transportBase.extend({
477
+ network: z.literal("websocket").or(z.literal("ws")),
478
+ wsSettings: z.object({
479
+ acceptProxyProtocol: z.boolean().default(false).optional(),
480
+ path: z.string().default("/").optional(),
481
+ host: z.string().default("").optional(),
482
+ headers: z.record(z.string(), z.string()).default({}).optional(),
483
+ heartbeatPeriod: z.number().int().nonnegative().default(0).optional()
484
+ }).optional()
485
+ });
486
+ //#endregion
487
+ //#region src/transport/grpc/grpc.ts
488
+ const grpcStream = transportBase.extend({
489
+ network: z.literal("grpc"),
490
+ grpcSettings: z.object({
491
+ authority: z.string().optional(),
492
+ serviceName: z.string().default("").optional(),
493
+ multiMode: z.boolean().default(false).optional(),
494
+ user_agent: z.string().optional(),
495
+ idle_timeout: z.number().int().nonnegative().transform((t) => t && t < 10 ? 10 : t).optional(),
496
+ health_check_timeout: z.number().int().nonnegative().default(20).optional(),
497
+ permit_without_stream: z.boolean().default(false).optional(),
498
+ initial_windows_size: z.number().int().nonnegative().default(0).optional()
499
+ }).optional()
500
+ });
501
+ //#endregion
502
+ //#region src/transport/hysteria/hysteria.ts
503
+ const masquerade = z.object({
504
+ type: z.enum([
505
+ "file",
506
+ "proxy",
507
+ "string",
508
+ ""
509
+ ]).default("").optional(),
510
+ dir: z.string().default("").optional(),
511
+ url: z.string().default("").optional(),
512
+ rewriteHost: z.boolean().default(false).optional(),
513
+ insecure: z.boolean().default(false).optional(),
514
+ content: z.string().default("").optional(),
515
+ headers: z.record(z.string(), z.string()).default({}).optional(),
516
+ statusCode: z.number().int().default(0).optional()
517
+ });
518
+ const hysteriaStream = transportBase.extend({
519
+ network: z.literal("hysteria"),
520
+ hysteriaSettings: z.object({
521
+ version: z.literal(2).default(2),
522
+ auth: z.string(),
523
+ udpIdleTimeout: z.number().int().nonnegative().default(60).optional(),
524
+ masquerade: masquerade.optional()
525
+ }).optional()
526
+ });
527
+ //#endregion
528
+ //#region src/transport/httpupgrade/httpupgrade.ts
529
+ const httpUpgradeStream = transportBase.extend({
530
+ network: z.literal("httpupgrade"),
531
+ httpupgradeSettings: z.object({
532
+ acceptProxyProtocol: z.boolean().default(false).optional(),
533
+ path: z.string().default("/").optional(),
534
+ host: z.string().default("").optional(),
535
+ headers: z.record(z.string(), z.string()).default({}).optional()
536
+ }).optional()
537
+ });
538
+ //#endregion
539
+ //#region src/transport/security/fingerprint.ts
540
+ const fingerprintSchema = z.enum([
541
+ "chrome",
542
+ "firefox",
543
+ "safari",
544
+ "ios",
545
+ "android",
546
+ "edge",
547
+ "360",
548
+ "qq",
549
+ "random",
550
+ "randomized"
551
+ ]).or(z.string());
552
+ //#endregion
553
+ //#region src/transport/security/tls/tls.ts
554
+ const certificateObject = z.object({
555
+ ocspStapling: z.number().int().nonnegative().default(0).optional(),
556
+ oneTimeLoading: z.boolean().default(false).optional(),
557
+ usage: z.enum([
558
+ "encipherment",
559
+ "verify",
560
+ "issue"
561
+ ]).default("encipherment").optional(),
562
+ buildChain: z.boolean().default(false).optional(),
563
+ certificateFile: z.string().optional(),
564
+ keyFile: z.string().optional(),
565
+ certificate: z.array(z.string()).optional(),
566
+ key: z.array(z.string()).optional()
567
+ });
568
+ const tls = z.object({
569
+ security: z.literal("tls"),
570
+ tlsSettings: z.object({
571
+ serverName: z.string().or(z.literal("fromMitm")).default("").optional(),
572
+ verifyPeerCertByName: z.string().or(z.literal("fromMitm")).optional(),
573
+ rejectUnknownSni: z.boolean().default(false).optional(),
574
+ allowInsecure: z.boolean().default(false).optional(),
575
+ alpn: z.array(z.enum([
576
+ "http/1.1",
577
+ "h2",
578
+ "h3",
579
+ "fromMitm"
580
+ ])).default(["h2", "http/1.1"]).optional(),
581
+ minVersion: z.string().optional(),
582
+ maxVersion: z.string().optional(),
583
+ cipherSuites: z.string().optional(),
584
+ certificates: z.array(certificateObject).optional(),
585
+ disableSystemRoot: z.boolean().default(false).optional(),
586
+ enableSessionResumption: z.boolean().default(false).optional(),
587
+ fingerprint: fingerprintSchema.optional(),
588
+ pinnedPeerCertSha256: z.string().optional(),
589
+ curvePreferences: z.array(z.enum([
590
+ "CurveP256",
591
+ "CurveP384",
592
+ "CurveP521",
593
+ "X25519",
594
+ "X25519MLKEM768",
595
+ "SecP256r1MLKEM768*",
596
+ "SecP384r1MLKEM1024*"
597
+ ])).optional(),
598
+ masterKeyLog: z.string().optional(),
599
+ echServerKeys: z.string().optional(),
600
+ echConfigList: z.string().optional(),
601
+ echSockopt: sockopt.optional()
602
+ }).optional()
603
+ });
604
+ //#endregion
605
+ //#region src/transport/security/reality/reality.ts
606
+ const limitFallbackObject = z.object({
607
+ afterBytes: z.number().int().nonnegative().default(0).optional(),
608
+ bytesPerSec: z.number().int().nonnegative().default(0).optional(),
609
+ burstBytesPerSec: z.number().int().nonnegative().default(0).optional()
610
+ }).optional();
611
+ const realitySettingsServer = z.object({
612
+ show: z.boolean().default(false).optional(),
613
+ target: z.string().min(1).optional(),
614
+ dest: z.string().min(1).optional(),
615
+ xver: z.number().default(0).optional(),
616
+ serverNames: z.array(z.string()).min(1),
617
+ privateKey: z.string().min(1),
618
+ minClientVer: z.string().optional(),
619
+ maxClientVer: z.string().optional(),
620
+ maxTimeDiff: z.number().int().nonnegative().default(0).optional(),
621
+ shortIds: z.array(z.string()).min(1),
622
+ mldsa65Seed: z.string().default("").optional(),
623
+ limitFallbackUpload: limitFallbackObject.optional(),
624
+ limitFallbackDownload: limitFallbackObject.optional()
625
+ });
626
+ const base = z.object({
627
+ serverName: z.string().optional(),
628
+ fingerprint: fingerprintSchema.optional(),
629
+ shortId: z.string(),
630
+ mldsa65Verify: z.string().optional(),
631
+ spiderX: z.string().optional()
632
+ });
633
+ const realitySettingsClient = z.union([base.merge(z.object({ password: z.string() })), base.merge(z.object({ publicKey: z.string() }))]);
634
+ const reality = z.object({
635
+ security: z.literal("reality"),
636
+ realitySettings: realitySettingsServer.or(realitySettingsClient)
637
+ });
638
+ //#endregion
639
+ //#region src/transport/xhttp/xhttp.ts
640
+ const intOrRange = z.union([z.number().int(), z.string().regex(/^-?\d+-\d+$/)]);
641
+ const xmux = z.object({
642
+ maxConcurrency: intOrRange.default("16-32").optional(),
643
+ maxConnections: intOrRange.default(0).optional(),
644
+ cMaxReuseTimes: intOrRange.default(0).optional(),
645
+ hMaxRequestTimes: intOrRange.optional(),
646
+ hMaxReusableSecs: intOrRange.optional(),
647
+ hKeepAlivePeriod: z.number().int().default(0).optional()
648
+ });
649
+ const downloadXhttpSettings = z.object({
650
+ host: z.string().default("").optional(),
651
+ path: z.string().default("/").optional(),
652
+ mode: z.enum([
653
+ "auto",
654
+ "packet-up",
655
+ "stream-up",
656
+ "stream-one"
657
+ ]).default("auto").optional()
658
+ });
659
+ const xhttpSettingsCommonFields = z.object({
660
+ address: z.string(),
661
+ port: z.number().int().nonnegative(),
662
+ network: z.literal("xhttp"),
663
+ xhttpSettings: downloadXhttpSettings.optional(),
664
+ sockopt: sockopt.optional()
665
+ });
666
+ const downloadSettings = z.discriminatedUnion("security", [tls.merge(xhttpSettingsCommonFields), reality.merge(xhttpSettingsCommonFields)]).optional();
667
+ const extra = z.object({
668
+ headers: z.record(z.string(), z.string()).optional(),
669
+ xPaddingBytes: intOrRange.default("100-1000").optional(),
670
+ noGRPCHeader: z.boolean().default(false).optional(),
671
+ noSSEHeader: z.boolean().default(false).optional(),
672
+ scMaxEachPostBytes: intOrRange.optional(),
673
+ scMinPostsIntervalMs: intOrRange.optional(),
674
+ scMaxBufferedPosts: z.number().int().optional(),
675
+ scStreamUpServerSecs: intOrRange.optional(),
676
+ xmux: xmux.optional(),
677
+ downloadSettings: downloadSettings.optional()
678
+ }).passthrough().optional();
679
+ const xhttpSettings = z.object({
680
+ host: z.string().default("").optional(),
681
+ path: z.string().default("/").optional(),
682
+ mode: z.enum([
683
+ "auto",
684
+ "packet-up",
685
+ "stream-up",
686
+ "stream-one"
687
+ ]).default("auto").optional(),
688
+ extra
689
+ });
690
+ const xhttpStream = transportBase.extend({
691
+ network: z.literal("xhttp"),
692
+ xhttpSettings: xhttpSettings.optional()
693
+ });
694
+ const splithttpStream = transportBase.extend({
695
+ network: z.literal("splithttp"),
696
+ xhttpSettings: xhttpSettings.optional()
697
+ });
698
+ //#endregion
699
+ //#region src/transport/transport.ts
700
+ const noSecurity = z.object({ security: z.literal("none").optional() });
701
+ const mergeStreamWithOtherFields = (schema) => {
702
+ return [
703
+ z.object({
704
+ ...schema.shape,
705
+ ...reality.shape
706
+ }),
707
+ z.object({
708
+ ...schema.shape,
709
+ ...tls.shape
710
+ }),
711
+ z.object({
712
+ ...schema.shape,
713
+ ...noSecurity.shape
714
+ })
715
+ ];
716
+ };
717
+ const streamSettings = z.union([
718
+ ...mergeStreamWithOtherFields(tcpStream),
719
+ ...mergeStreamWithOtherFields(rawStream),
720
+ ...mergeStreamWithOtherFields(mkcpStream),
721
+ ...mergeStreamWithOtherFields(websocketStream),
722
+ ...mergeStreamWithOtherFields(grpcStream),
723
+ ...mergeStreamWithOtherFields(hysteriaStream),
724
+ ...mergeStreamWithOtherFields(httpUpgradeStream),
725
+ ...mergeStreamWithOtherFields(xhttpStream),
726
+ ...mergeStreamWithOtherFields(splithttpStream)
727
+ ]);
728
+ //#endregion
729
+ //#region src/inbounds/baseInbound/baseInbound.ts
730
+ const portLikeSchema = z.union([
731
+ z.number().int().min(1).max(65535),
732
+ z.string().regex(/^\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*$/),
733
+ z.string().regex(/^env:[A-Za-z_][A-Za-z0-9_]*$/)
734
+ ]);
735
+ const generalInboundSchema = z.object({
736
+ tag: z.string().optional(),
737
+ listen: z.string().optional(),
738
+ port: portLikeSchema.optional(),
739
+ streamSettings: streamSettings.optional(),
740
+ sniffing: sniffingSchema.optional()
741
+ });
742
+ //#endregion
743
+ //#region src/inbounds/protocols/http/http.ts
744
+ const httpUserSchema = z.object({
745
+ user: z.string().min(1),
746
+ pass: z.string().min(1)
747
+ });
748
+ const httpSettingsSchema = z.object({
749
+ users: z.array(httpUserSchema).default([]).optional(),
750
+ allowTransparent: z.boolean().default(false).optional(),
751
+ userLevel: z.number().default(0).optional()
752
+ });
753
+ const httpInboundSchema = generalInboundSchema.extend({
754
+ protocol: z.literal("http"),
755
+ settings: httpSettingsSchema.optional()
756
+ });
757
+ //#endregion
758
+ //#region src/inbounds/protocols/dokodemo-door/dokodemo-door.ts
759
+ const tunnelSettingsSchema = z.object({
760
+ allowedNetwork: z.enum([
761
+ "tcp",
762
+ "udp",
763
+ "tcp,udp"
764
+ ]).default("tcp").optional(),
765
+ rewriteAddress: z.string().default("localhost").optional(),
766
+ rewritePort: z.number().int().min(0).max(65535).optional(),
767
+ portMap: z.record(z.string(), z.string()).optional(),
768
+ followRedirect: z.boolean().default(false).optional(),
769
+ userLevel: z.number().default(0).optional()
770
+ });
771
+ const dokodemoDoorInboundSchema = generalInboundSchema.extend({
772
+ protocol: z.literal("dokodemo-door").or(z.literal("tunnel")),
773
+ settings: tunnelSettingsSchema
774
+ });
775
+ //#endregion
776
+ //#region src/inbounds/protocols/socks/socks.ts
777
+ const socksSettingsBaseSchema = z.object({
778
+ udp: z.boolean().default(false).optional(),
779
+ ip: z.string().optional(),
780
+ userLevel: z.number().default(0).optional()
781
+ });
782
+ const socksAccount = z.object({
783
+ user: z.string().min(1),
784
+ pass: z.string().min(1)
785
+ });
786
+ const socksSettingsSchema = z.discriminatedUnion("auth", [socksSettingsBaseSchema.extend({ auth: z.literal("noauth").optional() }).loose(), socksSettingsBaseSchema.extend({
787
+ auth: z.literal("password"),
788
+ users: z.array(socksAccount).default([]).optional()
789
+ }).loose()]);
790
+ const socksInboundSchema = generalInboundSchema.extend({
791
+ protocol: z.literal("socks").or(z.literal("mixed")),
792
+ settings: socksSettingsSchema.optional()
793
+ });
794
+ //#endregion
795
+ //#region src/inbounds/protocols/shadowsocks/shadowsocks.ts
796
+ const ss22Methods = z.enum([
797
+ "2022-blake3-aes-128-gcm",
798
+ "2022-blake3-aes-256-gcm",
799
+ "2022-blake3-chacha20-poly1305"
800
+ ]);
801
+ const ss22UserSchema = z.object({
802
+ password: z.string().optional(),
803
+ level: z.number().default(0).optional(),
804
+ email: z.string().min(1)
805
+ });
806
+ const ssMethods = z.enum([
807
+ "aes-256-gcm",
808
+ "aes-128-gcm",
809
+ "chacha20-poly1305",
810
+ "chacha20-ietf-poly1305",
811
+ "xchacha20-poly1305",
812
+ "xchacha20-ietf-poly1305",
813
+ "none",
814
+ ""
815
+ ]);
816
+ const ssUserSchema = z.object({
817
+ password: z.string().optional(),
818
+ level: z.number().default(0).optional(),
819
+ email: z.string().min(1),
820
+ method: ssMethods.optional()
821
+ });
822
+ const ssSettingsBaseSchema = z.object({
823
+ network: z.enum([
824
+ "tcp",
825
+ "udp",
826
+ "tcp,udp"
827
+ ]).default("tcp").optional(),
828
+ level: z.number().int().default(0).optional(),
829
+ password: z.string().min(1).optional(),
830
+ email: z.string().optional()
831
+ });
832
+ const shadowsocksSettingsSchema = z.discriminatedUnion("method", [ssSettingsBaseSchema.extend({
833
+ method: ss22Methods,
834
+ password: z.string().min(1),
835
+ users: z.array(ss22UserSchema).optional()
836
+ }), ssSettingsBaseSchema.extend({
837
+ method: ssMethods,
838
+ users: z.array(ssUserSchema).optional()
839
+ })]);
840
+ const shadowsocksInboundSchema = generalInboundSchema.extend({
841
+ protocol: z.literal("shadowsocks"),
842
+ settings: shadowsocksSettingsSchema
843
+ });
844
+ //#endregion
845
+ //#region src/inbounds/protocols/vless/vless.ts
846
+ const vlessClient = z.object({
847
+ id: z.string().min(1),
848
+ level: z.number().default(0).optional(),
849
+ email: z.string().optional(),
850
+ flow: z.enum(["", "xtls-rprx-vision"]).default("").optional(),
851
+ reverse: z.object({ tag: z.string().min(1).optional() }).default({}).optional()
852
+ });
853
+ const vlessFallbackSchema = z.object({
854
+ name: z.string().default("").optional(),
855
+ alpn: z.string().default("").optional(),
856
+ path: z.string().default("").optional(),
857
+ dest: z.string().or(z.number()).optional(),
858
+ xver: z.number().default(0).optional()
859
+ });
860
+ const baseVlessSettings = z.object({
861
+ decryption: z.literal("none").or(z.string()),
862
+ fallbacks: z.array(vlessFallbackSchema).optional()
863
+ });
864
+ const vlessInboundSchema = generalInboundSchema.extend({
865
+ protocol: z.literal("vless"),
866
+ settings: baseVlessSettings.extend({ users: z.array(vlessClient.loose()).default([]).optional() }).or(baseVlessSettings.extend({ clients: z.array(vlessClient.loose()).default([]).optional() }))
867
+ });
868
+ //#endregion
869
+ //#region src/inbounds/protocols/vmess/vmess.ts
870
+ const vmessClients = z.object({
871
+ id: z.string().min(1),
872
+ level: z.number().optional(),
873
+ email: z.string().optional()
874
+ });
875
+ const baseVmessSettings = z.object({ default: z.object({ level: z.number() }).optional() });
876
+ const vmessInboundSchema = generalInboundSchema.extend({
877
+ protocol: z.literal("vmess"),
878
+ settings: baseVmessSettings.extend({ clients: z.array(vmessClients).default([]).optional() }).or(baseVmessSettings.extend({ users: z.array(vmessClients).default([]).optional() }))
879
+ });
880
+ //#endregion
881
+ //#region src/inbounds/protocols/wireguard/wireguard.ts
882
+ const wireguardPeerSchema = z.object({
883
+ publicKey: z.string().min(1),
884
+ allowedIPs: z.array(z.string().min(1))
885
+ });
886
+ const wireguardInboundSchema = generalInboundSchema.extend({
887
+ protocol: z.literal("wireguard"),
888
+ settings: z.object({
889
+ secretKey: z.string(),
890
+ peers: z.array(wireguardPeerSchema).default([]).optional(),
891
+ mtu: z.number().default(1420).optional()
892
+ })
893
+ });
894
+ //#endregion
895
+ //#region src/inbounds/protocols/trojan/trojan.ts
896
+ const trojanUser = z.object({
897
+ email: z.string().min(1),
898
+ password: z.string().min(1),
899
+ level: z.number().int().default(0).optional()
900
+ });
901
+ const trojanFallback = z.object({
902
+ name: z.string().default("").optional(),
903
+ alpn: z.string().default("").optional(),
904
+ path: z.string().default("").optional(),
905
+ dest: z.string().or(z.number()).optional(),
906
+ xver: z.number().default(0).optional()
907
+ });
908
+ const trojanInboundSchema = generalInboundSchema.extend({
909
+ protocol: z.literal("trojan"),
910
+ settings: z.object({
911
+ users: z.array(trojanUser).default([]).optional(),
912
+ fallbacks: z.array(trojanFallback).optional()
913
+ })
914
+ });
915
+ //#endregion
916
+ //#region src/inbounds/protocols/tun/tun.ts
917
+ const tunInboundSchema = generalInboundSchema.extend({
918
+ protocol: z.literal("tun"),
919
+ settings: z.object({
920
+ name: z.string().default("xray0").optional(),
921
+ mtu: z.number().int().default(1500).optional(),
922
+ userLevel: z.number().int().default(0).optional(),
923
+ gateway: z.array(z.string()),
924
+ dns: z.array(z.string()).default(["1.1.1.1", "8.8.8.8"]),
925
+ autoSystemRoutingTable: z.array(z.string()).optional(),
926
+ autoOutboundsInterface: z.string().or(z.literal("auto")).nullable().default(null).optional()
927
+ })
928
+ });
929
+ //#endregion
930
+ //#region src/inbounds/protocols/hysteria/hysteria.ts
931
+ const hysteriaUser = z.object({
932
+ auth: z.string().min(1),
933
+ email: z.string().min(1),
934
+ level: z.number().int().default(0).optional()
935
+ });
936
+ const hysteriaInboundSchema = generalInboundSchema.extend({
937
+ protocol: z.literal("hysteria"),
938
+ settings: z.object({
939
+ version: z.literal(2),
940
+ users: z.array(hysteriaUser).default([]).optional()
941
+ })
942
+ });
943
+ //#endregion
944
+ //#region src/inbounds/inbounds.ts
945
+ const inbound = z.discriminatedUnion("protocol", [
946
+ dokodemoDoorInboundSchema,
947
+ httpInboundSchema,
948
+ socksInboundSchema,
949
+ shadowsocksInboundSchema,
950
+ vlessInboundSchema,
951
+ vmessInboundSchema,
952
+ wireguardInboundSchema,
953
+ trojanInboundSchema,
954
+ tunInboundSchema,
955
+ hysteriaInboundSchema
956
+ ]);
957
+ //#endregion
958
+ //#region src/stats/stats.ts
959
+ const stats = z.looseObject({});
960
+ //#endregion
961
+ //#region src/metrics/metrics.ts
962
+ const metrics = z.object({
963
+ tag: z.string(),
964
+ listen: z.string().optional()
965
+ }).or(z.object({
966
+ tag: z.string().optional(),
967
+ listen: z.string()
968
+ }));
969
+ //#endregion
970
+ //#region src/observatory/observatory.ts
971
+ const observatory = z.object({
972
+ subjectSelector: z.array(z.string()),
973
+ probeUrl: z.string().default("https://www.google.com/generate_204"),
974
+ probeInterval: z.string(),
975
+ enableConcurrency: z.boolean().default(false).optional()
976
+ });
977
+ //#endregion
978
+ //#region src/burstObservatory/burstObservatory.ts
979
+ const durationSchema = z.templateLiteral([z.number().int().nonnegative().min(1), z.literal([
980
+ "ns",
981
+ "us",
982
+ "ms",
983
+ "s",
984
+ "m",
985
+ "h"
986
+ ])]);
987
+ const burstObservatoryPingConfig = z.object({
988
+ destination: z.string().default("https://connectivitycheck.gstatic.com/generate_204").optional(),
989
+ connectivity: z.string().default("").optional(),
990
+ interval: durationSchema.default("1m").optional(),
991
+ sampling: z.number().int().nonnegative().default(10).optional(),
992
+ timeout: durationSchema.default("5s").optional(),
993
+ httpMethod: z.enum([
994
+ "GET",
995
+ "POST",
996
+ "HEAD",
997
+ "DELETE",
998
+ "PATCH",
999
+ "PUT"
1000
+ ]).default("HEAD").optional()
1001
+ });
1002
+ const burstObservatory = z.object({
1003
+ subjectSelector: z.array(z.string()),
1004
+ pingConfig: burstObservatoryPingConfig.optional()
1005
+ });
1006
+ //#endregion
1007
+ //#region src/reverse/reverse.ts
1008
+ const bridgeObject = z.object({
1009
+ tag: z.string().optional(),
1010
+ domain: z.string().optional()
1011
+ });
1012
+ const portalObject = z.object({
1013
+ tag: z.string().optional(),
1014
+ domain: z.string().optional()
1015
+ });
1016
+ const reverse = z.object({
1017
+ bridges: z.array(bridgeObject).optional(),
1018
+ portals: z.array(portalObject).min(1)
1019
+ }).or(z.object({
1020
+ bridges: z.array(bridgeObject).min(1),
1021
+ portals: z.array(portalObject).optional()
1022
+ }));
1023
+ //#endregion
1024
+ //#region src/outbounds/baseOutbound/baseOutbound.ts
1025
+ const outboundSchemaBase = z.object({
1026
+ sendThrough: z.string().or(z.enum(["origin", "srcip"])).optional(),
1027
+ tag: z.string().optional(),
1028
+ streamSettings: streamSettings.optional(),
1029
+ targetStrategy: z.enum([
1030
+ "AsIs",
1031
+ "UseIP",
1032
+ "UseIPv6v4",
1033
+ "UseIPv6",
1034
+ "UseIPv4v6",
1035
+ "UseIPv4",
1036
+ "ForceIP",
1037
+ "ForceIPv6v4",
1038
+ "ForceIPv6",
1039
+ "ForceIPv4v6",
1040
+ "ForceIPv4"
1041
+ ]).default("AsIs").optional(),
1042
+ proxySettings: z.object({
1043
+ tag: z.string().min(1),
1044
+ transportLayer: z.boolean().default(false).optional()
1045
+ }).optional(),
1046
+ mux: z.object({
1047
+ enabled: z.boolean().default(false).optional(),
1048
+ concurrency: z.int().optional(),
1049
+ xudpConcurrency: z.int().optional(),
1050
+ xudpProxyUDP443: z.enum([
1051
+ "reject",
1052
+ "allow",
1053
+ "skip"
1054
+ ]).default("reject").optional()
1055
+ }).optional()
1056
+ });
1057
+ //#endregion
1058
+ //#region src/outbounds/blackhole/blackhole.ts
1059
+ const blackhole = outboundSchemaBase.extend({
1060
+ protocol: z.literal("blackhole").or(z.literal("block")),
1061
+ settings: z.object({ response: z.object({ type: z.enum(["none", "http"]).default("none").optional() }).optional() }).optional()
1062
+ });
1063
+ //#endregion
1064
+ //#region src/outbounds/freedom/freedom.ts
1065
+ const fragment = z.object({
1066
+ length: z.int().or(z.string()),
1067
+ interval: z.int().or(z.string()),
1068
+ packets: z.literal("tlshello").or(z.string())
1069
+ });
1070
+ const noise = z.object({
1071
+ type: z.enum([
1072
+ "rand",
1073
+ "str",
1074
+ "base64"
1075
+ ]),
1076
+ packet: z.string(),
1077
+ delay: z.int().or(z.string()).optional()
1078
+ });
1079
+ const finalRule = z.object({
1080
+ action: z.enum(["allow", "block"]),
1081
+ network: z.enum([
1082
+ "tcp",
1083
+ "udp",
1084
+ "tcp,udp"
1085
+ ]),
1086
+ port: portLikeSchema,
1087
+ ip: z.array(z.string()).optional(),
1088
+ blockDelay: z.string().optional()
1089
+ });
1090
+ const freedom = outboundSchemaBase.extend({
1091
+ protocol: z.literal("freedom").or(z.literal("direct")),
1092
+ settings: z.object({
1093
+ domainStrategy: z.enum([
1094
+ "AsIs",
1095
+ "UseIP",
1096
+ "UseIPv6v4",
1097
+ "UseIPv6",
1098
+ "UseIPv4v6",
1099
+ "UseIPv4",
1100
+ "ForceIP",
1101
+ "ForceIPv6v4",
1102
+ "ForceIPv6",
1103
+ "ForceIPv4v6",
1104
+ "ForceIPv4"
1105
+ ]).default("AsIs").optional(),
1106
+ redirect: z.string().optional(),
1107
+ userLevel: z.int().default(0).optional(),
1108
+ fragment: fragment.optional(),
1109
+ noises: z.array(noise).optional(),
1110
+ proxyProtocol: z.literal(0).or(z.literal(1)).or(z.literal(2)).default(0).optional(),
1111
+ finalRules: z.array(finalRule).default([]).optional()
1112
+ }).optional()
1113
+ });
1114
+ //#endregion
1115
+ //#region src/outbounds/dns/dns.ts
1116
+ const dnsRule = z.object({
1117
+ action: z.enum([
1118
+ "direct",
1119
+ "hijack",
1120
+ "drop",
1121
+ "return"
1122
+ ]),
1123
+ qtype: z.number().or(z.string()).optional(),
1124
+ rCode: z.number().optional(),
1125
+ domain: z.array(z.string())
1126
+ });
1127
+ const dns = outboundSchemaBase.extend({
1128
+ protocol: z.literal("dns"),
1129
+ settings: z.object({
1130
+ rewriteNetwork: z.enum(["tcp", "udp"]).optional(),
1131
+ rewriteAddress: z.string().optional(),
1132
+ rewritePort: z.string().optional(),
1133
+ userLevel: z.int().default(0).optional(),
1134
+ rules: z.array(dnsRule).default([]).optional()
1135
+ })
1136
+ });
1137
+ //#endregion
1138
+ //#region src/outbounds/hysteria/hysteria.ts
1139
+ const hysteria = outboundSchemaBase.extend({
1140
+ protocol: z.literal("hysteria"),
1141
+ settings: z.object({
1142
+ version: z.literal(2),
1143
+ address: z.string(),
1144
+ port: portLikeSchema
1145
+ })
1146
+ });
1147
+ //#endregion
1148
+ //#region src/outbounds/loopback/loopback.ts
1149
+ const loopback = outboundSchemaBase.extend({
1150
+ protocol: z.literal("loopback"),
1151
+ settings: z.object({ inboundTag: z.string() })
1152
+ });
1153
+ //#endregion
1154
+ //#region src/outbounds/shadowsocks/shadowsocks.ts
1155
+ const shadowsocksServerSettings = z.object({
1156
+ address: z.string(),
1157
+ port: portLikeSchema,
1158
+ email: z.string().optional(),
1159
+ password: z.string().default(""),
1160
+ method: z.union([ss22Methods, ssMethods]),
1161
+ uot: z.boolean().default(true).optional(),
1162
+ UoTVersion: z.literal(1).or(z.literal(2)).default(2).optional(),
1163
+ level: z.int().default(0).optional()
1164
+ });
1165
+ const shadowsocks = outboundSchemaBase.extend({
1166
+ protocol: z.literal("shadowsocks"),
1167
+ settings: shadowsocksServerSettings.or(z.object({ servers: z.array(shadowsocksServerSettings) }))
1168
+ });
1169
+ //#endregion
1170
+ //#region src/outbounds/socks/socks.ts
1171
+ const socksServerSettings = z.object({
1172
+ address: z.string(),
1173
+ port: portLikeSchema,
1174
+ user: z.string().optional(),
1175
+ pass: z.string().optional(),
1176
+ level: z.int().default(0).optional(),
1177
+ email: z.string().optional()
1178
+ });
1179
+ const socks = outboundSchemaBase.extend({
1180
+ protocol: z.literal("socks"),
1181
+ settings: socksServerSettings.or(z.object({ servers: z.array(socksServerSettings) })).optional()
1182
+ });
1183
+ //#endregion
1184
+ //#region src/outbounds/trojan/trojan.ts
1185
+ const trojanServerSettings = z.object({
1186
+ address: z.string(),
1187
+ port: portLikeSchema.optional(),
1188
+ email: z.string().optional(),
1189
+ password: z.string(),
1190
+ level: z.int().default(0).optional()
1191
+ });
1192
+ const trojan = outboundSchemaBase.extend({
1193
+ protocol: z.literal("trojan"),
1194
+ settings: trojanServerSettings.or(z.object({ servers: z.array(trojanServerSettings) }))
1195
+ });
1196
+ //#endregion
1197
+ //#region src/outbounds/vless/vless.ts
1198
+ const vless = outboundSchemaBase.extend({
1199
+ protocol: z.literal("vless"),
1200
+ settings: z.object({
1201
+ address: z.string(),
1202
+ port: portLikeSchema,
1203
+ id: z.string(),
1204
+ encryption: z.string().default("none"),
1205
+ flow: z.enum([
1206
+ "",
1207
+ "xtls-rprx-vision",
1208
+ "xtls-rprx-vision-udp443"
1209
+ ]).optional(),
1210
+ level: z.int().default(0).optional(),
1211
+ reverse: z.object({
1212
+ tag: z.string(),
1213
+ sniffing: sniffingSchema.optional()
1214
+ }).optional()
1215
+ })
1216
+ });
1217
+ //#endregion
1218
+ //#region src/outbounds/vmess/vmess.ts
1219
+ const vmess = outboundSchemaBase.extend({
1220
+ protocol: z.literal("vmess"),
1221
+ settings: z.object({
1222
+ address: z.string(),
1223
+ port: portLikeSchema,
1224
+ id: z.string(),
1225
+ security: z.enum([
1226
+ "aes-128-gcm",
1227
+ "chacha20-poly1305",
1228
+ "auto",
1229
+ "none",
1230
+ "zero"
1231
+ ]).optional(),
1232
+ level: z.int().default(0).optional(),
1233
+ experiments: z.enum([
1234
+ "AuthenticatedLength",
1235
+ "NoTerminationSignal",
1236
+ "AuthenticatedLength|NoTerminationSignal"
1237
+ ]).optional()
1238
+ })
1239
+ });
1240
+ //#endregion
1241
+ //#region src/outbounds/wireguard/wireguard.ts
1242
+ const peer = z.object({
1243
+ endpoint: z.string(),
1244
+ publicKey: z.string(),
1245
+ preSharedKey: z.string().optional(),
1246
+ keepAlive: z.int().default(0).optional(),
1247
+ allowedIPs: z.array(z.string()).default(["0.0.0.0/0", "::/0"]).optional()
1248
+ });
1249
+ const wireguard = outboundSchemaBase.extend({
1250
+ protocol: z.literal("wireguard"),
1251
+ settings: z.object({
1252
+ secretKey: z.string(),
1253
+ address: z.array(z.string()).min(1),
1254
+ peers: z.array(peer).min(1),
1255
+ noKernelTun: z.boolean().default(false).optional(),
1256
+ mtu: z.int().default(1420),
1257
+ reserved: z.array(z.int()).default([]).optional(),
1258
+ workers: z.int().optional(),
1259
+ domainStrategy: z.enum([
1260
+ "ForceIPv6v4",
1261
+ "ForceIPv6",
1262
+ "ForceIPv4v6",
1263
+ "ForceIPv4",
1264
+ "ForceIP"
1265
+ ]).default("ForceIP").optional()
1266
+ })
1267
+ });
1268
+ //#endregion
1269
+ //#region src/outbounds/outbounds.ts
1270
+ const outbound = z.discriminatedUnion("protocol", [
1271
+ blackhole,
1272
+ freedom,
1273
+ dns,
1274
+ hysteria,
1275
+ loopback,
1276
+ shadowsocks,
1277
+ socks,
1278
+ trojan,
1279
+ vless,
1280
+ vmess,
1281
+ wireguard
1282
+ ]);
1283
+ //#endregion
1284
+ //#region src/fakedns/fakedns.ts
1285
+ const fakednsObject = z.object({
1286
+ ipPool: z.string(),
1287
+ poolSize: z.int().default(65535).optional()
1288
+ });
1289
+ const fakedns = fakednsObject.or(z.array(fakednsObject));
1290
+ //#endregion
1291
+ //#region src/schema.ts
1292
+ const xraySchema = z.object({
1293
+ version: versionSchema.optional(),
1294
+ log: logSchema.optional(),
1295
+ api: apiSchema.optional(),
1296
+ dns: dnsSchema.optional(),
1297
+ routing: routingSchema.optional(),
1298
+ fakedns: fakedns.optional(),
1299
+ policy: policySchema.optional(),
1300
+ stats: stats.optional(),
1301
+ metrics: metrics.optional(),
1302
+ observatory: observatory.optional(),
1303
+ burstObservatory: burstObservatory.optional(),
1304
+ reverse: reverse.optional(),
1305
+ inbounds: z.array(inbound).optional(),
1306
+ outbounds: z.array(outbound).optional()
1307
+ }).loose();
1308
+ //#endregion
1309
+ export { xraySchema };