mirror of
https://github.com/Chewbaccalakis/rfid-database.git
synced 2026-09-10 00:11:56 -07:00
Add Next.js app with SQLite/Drizzle storage for sites and LF/HF tag dumps, multi-user Auth.js (credentials + optional OIDC), personal API tokens in Settings, versioned /api/v1 for UI and future CLI use, MCT/Proxmark/JSON import-export, PWA offline shell, Vitest tests, and GitHub Actions CI. Co-authored-by: Cursor Agent <[email protected]>
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
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<typeof mifareClassicDumpSchema>;
|
|
export type NtagDump = z.infer<typeof ntagDumpSchema>;
|
|
export type LfDump = z.infer<typeof lfDumpSchema>;
|
|
export type DumpData = z.infer<typeof dumpDataSchema>;
|
|
export type TagKeys = z.infer<typeof keysSchema>;
|