mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 12:44:22 +00:00
fix(frontend): allow null slices in client/summary schemas
Go's encoding/json emits nil []T as null, not []. The initial ClientPageResponseSchema and ClientHydrateSchema rejected null inboundIds / summary.online / summary.depleted / etc., causing [zod] warnings on every empty list. Add nullableStringArray / nullableNumberArray helpers that accept null and transform to [] so consuming code keeps seeing arrays. Mark ClientRecord.traffic and .reverse nullable too (reverse is explicitly null in MarshalJSON when storage is empty).
This commit is contained in:
parent
d00ddc3f58
commit
c16fb93899
1 changed files with 19 additions and 11 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const nullableStringArray = z.array(z.string()).nullable().transform((v) => v ?? []);
|
||||||
|
const nullableNumberArray = z.array(z.number()).nullable().transform((v) => v ?? []);
|
||||||
|
|
||||||
export const ClientTrafficSchema = z.object({
|
export const ClientTrafficSchema = z.object({
|
||||||
up: z.number().optional(),
|
up: z.number().optional(),
|
||||||
down: z.number().optional(),
|
down: z.number().optional(),
|
||||||
|
|
@ -10,21 +13,24 @@ export const ClientTrafficSchema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ClientRecordSchema = z.object({
|
export const ClientRecordSchema = z.object({
|
||||||
|
id: z.number().optional(),
|
||||||
email: z.string(),
|
email: z.string(),
|
||||||
subId: z.string().optional(),
|
subId: z.string().optional(),
|
||||||
uuid: z.string().optional(),
|
uuid: z.string().optional(),
|
||||||
password: z.string().optional(),
|
password: z.string().optional(),
|
||||||
auth: z.string().optional(),
|
auth: z.string().optional(),
|
||||||
flow: z.string().optional(),
|
flow: z.string().optional(),
|
||||||
|
security: z.string().optional(),
|
||||||
totalGB: z.number().optional(),
|
totalGB: z.number().optional(),
|
||||||
expiryTime: z.number().optional(),
|
expiryTime: z.number().optional(),
|
||||||
limitIp: z.number().optional(),
|
limitIp: z.number().optional(),
|
||||||
tgId: z.union([z.number(), z.string()]).optional(),
|
tgId: z.union([z.number(), z.string()]).optional(),
|
||||||
comment: z.string().optional(),
|
comment: z.string().optional(),
|
||||||
enable: z.boolean().optional(),
|
enable: z.boolean().optional(),
|
||||||
inboundIds: z.array(z.number()).optional(),
|
reset: z.number().optional(),
|
||||||
traffic: ClientTrafficSchema.optional(),
|
inboundIds: nullableNumberArray.optional(),
|
||||||
reverse: z.object({ tag: z.string().optional() }).loose().optional(),
|
traffic: ClientTrafficSchema.nullable().optional(),
|
||||||
|
reverse: z.object({ tag: z.string().optional() }).loose().nullable().optional(),
|
||||||
createdAt: z.number().optional(),
|
createdAt: z.number().optional(),
|
||||||
updatedAt: z.number().optional(),
|
updatedAt: z.number().optional(),
|
||||||
}).loose();
|
}).loose();
|
||||||
|
|
@ -42,24 +48,26 @@ export const InboundOptionsSchema = z.array(InboundOptionSchema);
|
||||||
export const ClientsSummarySchema = z.object({
|
export const ClientsSummarySchema = z.object({
|
||||||
total: z.number(),
|
total: z.number(),
|
||||||
active: z.number(),
|
active: z.number(),
|
||||||
online: z.array(z.string()),
|
online: nullableStringArray,
|
||||||
depleted: z.array(z.string()),
|
depleted: nullableStringArray,
|
||||||
expiring: z.array(z.string()),
|
expiring: nullableStringArray,
|
||||||
deactive: z.array(z.string()),
|
deactive: nullableStringArray,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const nullableClientArray = z.array(ClientRecordSchema).nullable().transform((v) => v ?? []);
|
||||||
|
|
||||||
export const ClientPageResponseSchema = z.object({
|
export const ClientPageResponseSchema = z.object({
|
||||||
items: z.array(ClientRecordSchema),
|
items: nullableClientArray,
|
||||||
total: z.number(),
|
total: z.number(),
|
||||||
filtered: z.number(),
|
filtered: z.number(),
|
||||||
page: z.number(),
|
page: z.number(),
|
||||||
pageSize: z.number(),
|
pageSize: z.number(),
|
||||||
summary: ClientsSummarySchema.optional(),
|
summary: ClientsSummarySchema.nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ClientHydrateSchema = z.object({
|
export const ClientHydrateSchema = z.object({
|
||||||
client: ClientRecordSchema,
|
client: ClientRecordSchema,
|
||||||
inboundIds: z.array(z.number()),
|
inboundIds: nullableNumberArray,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const BulkAdjustResultSchema = z.object({
|
export const BulkAdjustResultSchema = z.object({
|
||||||
|
|
@ -73,7 +81,7 @@ export const DelDepletedResultSchema = z.object({
|
||||||
deleted: z.number().optional(),
|
deleted: z.number().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const OnlinesSchema = z.array(z.string());
|
export const OnlinesSchema = nullableStringArray;
|
||||||
|
|
||||||
export type ClientRecord = z.infer<typeof ClientRecordSchema>;
|
export type ClientRecord = z.infer<typeof ClientRecordSchema>;
|
||||||
export type ClientTraffic = z.infer<typeof ClientTrafficSchema>;
|
export type ClientTraffic = z.infer<typeof ClientTrafficSchema>;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue