refactor: validate user state with zod
This commit is contained in:
+13
-29
@@ -1,38 +1,22 @@
|
||||
import { plainToClass } from "class-transformer";
|
||||
import { IsBoolean, IsString, validate } from "class-validator";
|
||||
import { z } from "zod";
|
||||
|
||||
export class UserStateUpdate {
|
||||
@IsString()
|
||||
userId!: string;
|
||||
const userStateUpdateSchema = z.object({
|
||||
userId: z.string(),
|
||||
username: z.string(),
|
||||
avatar: z.string(),
|
||||
speaking: z.boolean(),
|
||||
});
|
||||
|
||||
@IsString()
|
||||
username!: string;
|
||||
export type UserStateUpdate = z.infer<typeof userStateUpdateSchema>;
|
||||
|
||||
@IsString()
|
||||
avatar!: string;
|
||||
|
||||
@IsBoolean()
|
||||
speaking!: boolean;
|
||||
}
|
||||
|
||||
export class AudioMessage {
|
||||
data!: Buffer;
|
||||
userId!: string;
|
||||
export interface AudioMessage {
|
||||
data: Buffer;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export async function validateUserStateUpdate(
|
||||
data: unknown,
|
||||
): Promise<UserStateUpdate | null> {
|
||||
if (typeof data !== "object" || data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const obj = plainToClass(UserStateUpdate, data);
|
||||
const errors = await validate(obj);
|
||||
|
||||
if (errors.length > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return obj;
|
||||
const result = userStateUpdateSchema.safeParse(data);
|
||||
return result.success ? result.data : null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { validateUserStateUpdate } from "../src/validation";
|
||||
|
||||
describe("validateUserStateUpdate", () => {
|
||||
it("returns typed data for a valid user state update", async () => {
|
||||
const result = await validateUserStateUpdate({
|
||||
userId: "123",
|
||||
username: "aseph",
|
||||
avatar: "https://example.invalid/avatar.png",
|
||||
speaking: true,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
userId: "123",
|
||||
username: "aseph",
|
||||
avatar: "https://example.invalid/avatar.png",
|
||||
speaking: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns null for non-object input", async () => {
|
||||
await expect(validateUserStateUpdate("bad")).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for invalid field types", async () => {
|
||||
const result = await validateUserStateUpdate({
|
||||
userId: "123",
|
||||
username: "aseph",
|
||||
avatar: "https://example.invalid/avatar.png",
|
||||
speaking: "true",
|
||||
});
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user