diff --git a/src/validation.ts b/src/validation.ts index 3fb2bd6..c599795 100644 --- a/src/validation.ts +++ b/src/validation.ts @@ -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; - @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 { - 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; } diff --git a/tests/validation.test.ts b/tests/validation.test.ts new file mode 100644 index 0000000..7a19d45 --- /dev/null +++ b/tests/validation.test.ts @@ -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(); + }); +});