ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1/**
2 * Validation utilities using Zod schemas
3 */
4import { z } from "zod";
5
6export interface ValidationResult {
7 isValid: boolean;
8 error?: string;
9}
10
11/**
12 * Helper to convert Zod validation to ValidationResult
13 */
14function validateWithZod<T>(
15 schema: z.ZodSchema<T>,
16 value: unknown,
17): ValidationResult {
18 const result = schema.safeParse(value);
19 if (result.success) {
20 return { isValid: true };
21 }
22 return {
23 isValid: false,
24 error: result.error.errors[0]?.message || "Validation failed",
25 };
26}
27
28/**
29 * Zod Schemas
30 */
31const handleSchema = z
32 .string()
33 .trim()
34 .min(1, "Please enter your handle")
35 .transform((val) => (val.startsWith("@") ? val.slice(1) : val))
36 .pipe(
37 z
38 .string()
39 .min(3, "Handle is too short")
40 .regex(/^[a-zA-Z0-9.-]+$/, "Handle contains invalid characters")
41 .refine((val) => val.includes("."), {
42 message: "Handle must include a domain (e.g., username.bsky.social)",
43 })
44 .refine((val) => !/^[.-]|[.-]$/.test(val), {
45 message: "Handle cannot start or end with . or -",
46 }),
47 );
48
49const emailSchema = z
50 .string()
51 .trim()
52 .min(1, "Please enter your email")
53 .email("Please enter a valid email address");
54
55/**
56 * Validate AT Protocol handle
57 */
58export function validateHandle(handle: string): ValidationResult {
59 return validateWithZod(handleSchema, handle);
60}
61
62/**
63 * Validate email format
64 */
65export function validateEmail(email: string): ValidationResult {
66 return validateWithZod(emailSchema, email);
67}
68
69/**
70 * Validate required field
71 */
72export function validateRequired(
73 value: string,
74 fieldName: string = "This field",
75): ValidationResult {
76 const schema = z.string().trim().min(1, `${fieldName} is required`);
77 return validateWithZod(schema, value);
78}
79
80/**
81 * Validate minimum length
82 */
83export function validateMinLength(
84 value: string,
85 minLength: number,
86 fieldName: string = "This field",
87): ValidationResult {
88 const schema = z
89 .string()
90 .trim()
91 .min(minLength, `${fieldName} must be at least ${minLength} characters`);
92 return validateWithZod(schema, value);
93}
94
95/**
96 * Validate maximum length
97 */
98export function validateMaxLength(
99 value: string,
100 maxLength: number,
101 fieldName: string = "This field",
102): ValidationResult {
103 const schema = z
104 .string()
105 .max(maxLength, `${fieldName} must be ${maxLength} characters or less`);
106 return validateWithZod(schema, value);
107}
108
109/**
110 * Export schemas for advanced usage
111 */
112export const schemas = {
113 handle: handleSchema,
114 email: emailSchema,
115};