import { z } from "zod"; import { FREQUENCIES, PROTOCOLS } from "@/lib/rfid/protocols"; export const mifareClassicDumpSchema = z.object({ size: z.enum(["1K", "4K"]), sectors: z.array( z.object({ index: z.number().int().min(0), blocks: z.array(z.string().regex(/^[0-9A-Fa-f]+$/)).min(1), }) ), }); export const ntagDumpSchema = z.object({ pages: z.array( z.object({ index: z.number().int().min(0), data: z.string().regex(/^[0-9A-Fa-f]+$/), }) ), }); export const lfDumpSchema = z.object({ uidBytes: z.string().regex(/^[0-9A-Fa-f]+$/), format: z.string().min(1), }); export const dumpDataSchema = z.union([ mifareClassicDumpSchema, ntagDumpSchema, lfDumpSchema, z.record(z.string(), z.unknown()), ]); export const keysSchema = z .object({ A: z.array(z.string()).optional(), B: z.array(z.string()).optional(), }) .passthrough() .nullable() .optional(); export const siteCreateSchema = z.object({ name: z.string().min(1).max(200), code: z .string() .min(1) .max(32) .regex(/^[A-Za-z0-9_-]+$/, "Code must be alphanumeric"), notes: z.string().max(5000).nullable().optional(), }); export const siteUpdateSchema = siteCreateSchema.partial(); export const tagCreateSchema = z.object({ siteId: z.string().uuid(), label: z.string().min(1).max(200), frequency: z.enum(FREQUENCIES), protocol: z.enum(PROTOCOLS), uid: z.string().min(1), dumpData: dumpDataSchema, keys: keysSchema, notes: z.string().max(5000).nullable().optional(), lastWrittenAt: z.string().datetime().nullable().optional(), }); export const tagUpdateSchema = tagCreateSchema.partial().omit({ siteId: true }).extend({ siteId: z.string().uuid().optional(), }); export const tagUpsertSchema = tagCreateSchema; export const tokenCreateSchema = z.object({ name: z.string().min(1).max(100), expiresAt: z.string().datetime().nullable().optional(), }); export const exportFormatSchema = z.enum(["json", "proxmark", "mct", "hex"]); export type MifareClassicDump = z.infer; export type NtagDump = z.infer; export type LfDump = z.infer; export type DumpData = z.infer; export type TagKeys = z.infer;