mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 20:09:34 +00:00
feat(frontend): add Zod runtime validation at API boundary
Introduces Zod 4 schemas for response validation on the three highest-traffic endpoints (server/status, nodes/list, setting/all) and a Zod->AntD form rule adapter, replacing the duplicated per-file ApiMsg<T> interfaces. Validation runs safeParse with console.warn + raw-payload fallback so backend drift never breaks the UI for users. Login form switches to schema-driven rules as the proof-of-life for the adapter. Class-based models stay untouched; remaining query/mutation hooks and form modals will migrate in follow-ups.
This commit is contained in:
15
frontend/src/utils/zodForm.ts
Normal file
15
frontend/src/utils/zodForm.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { Rule } from 'antd/es/form';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { z } from 'zod';
|
||||
|
||||
export function antdRule<T extends z.ZodTypeAny>(schema: T, t: TFunction): Rule {
|
||||
return {
|
||||
validator: async (_rule, value) => {
|
||||
const result = schema.safeParse(value);
|
||||
if (result.success) return;
|
||||
const issue = result.error.issues[0];
|
||||
const key = issue?.message ?? 'validation.invalid';
|
||||
throw new Error(t(key, { defaultValue: key }));
|
||||
},
|
||||
};
|
||||
}
|
||||
18
frontend/src/utils/zodValidate.ts
Normal file
18
frontend/src/utils/zodValidate.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { z } from 'zod';
|
||||
import { Msg } from '@/utils';
|
||||
|
||||
export function parseMsg<T extends z.ZodTypeAny>(
|
||||
msg: Msg<unknown>,
|
||||
schema: T,
|
||||
context: string,
|
||||
): Msg<z.infer<T>> {
|
||||
if (!msg.success || msg.obj == null) {
|
||||
return msg as Msg<z.infer<T>>;
|
||||
}
|
||||
const result = schema.safeParse(msg.obj);
|
||||
if (!result.success) {
|
||||
console.warn(`[zod] ${context} response failed validation`, result.error.issues);
|
||||
return msg as Msg<z.infer<T>>;
|
||||
}
|
||||
return new Msg<z.infer<T>>(msg.success, msg.msg, result.data);
|
||||
}
|
||||
Reference in New Issue
Block a user