ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { z } from "zod";
2import { ValidationError } from "../core/errors";
3
4/**
5 * Validation utility schemas using Zod
6 * Provides type-safe validation with clear error messages
7 */
8
9/**
10 * Generic array validation schema factory
11 * @param itemSchema - Zod schema for array items
12 * @param maxLength - Maximum array length
13 * @param fieldName - Name of field for error messages
14 */
15export function createArraySchema<T extends z.ZodTypeAny>(
16 itemSchema: T,
17 maxLength: number,
18 fieldName: string = "items",
19) {
20 return z
21 .array(itemSchema)
22 .min(1, `${fieldName} array is required and must not be empty`)
23 .max(maxLength, `Maximum ${maxLength} ${fieldName} per batch`);
24}
25
26/**
27 * Common validation schemas
28 */
29export const ValidationSchemas = {
30 // DIDs array (max 100)
31 didsArray: createArraySchema(z.string(), 100, "DIDs"),
32
33 // Usernames array (max 50)
34 usernamesArray: createArraySchema(z.string(), 50, "usernames"),
35
36 // Generic string array with custom max
37 stringArray: (maxLength: number, fieldName: string = "items") =>
38 createArraySchema(z.string(), maxLength, fieldName),
39};
40
41/**
42 * Validates input against a Zod schema and throws ValidationError on failure
43 * @param schema - Zod schema to validate against
44 * @param data - Data to validate
45 * @returns Parsed and validated data
46 * @throws ValidationError if validation fails
47 */
48export function validateInput<T>(schema: z.ZodSchema<T>, data: unknown): T {
49 const result = schema.safeParse(data);
50
51 if (!result.success) {
52 // Extract first error message for cleaner API responses
53 const firstError = result.error.issues[0];
54 const message = firstError.message;
55 throw new ValidationError(message);
56 }
57
58 return result.data;
59}
60
61/**
62 * Parses request body and validates array input
63 * Common pattern: JSON.parse(body) -> extract array -> validate
64 */
65export function validateArrayInput<T>(
66 body: string | null,
67 fieldName: string,
68 schema: z.ZodArray<any>,
69): T[] {
70 const parsed = JSON.parse(body || "{}");
71 const data = parsed[fieldName];
72
73 return validateInput(schema, data);
74}