pummmp.fun/lib/validations.ts
2026-07-04 12:49:09 -07:00

56 lines
2.2 KiB
TypeScript

import { z } from 'zod'
import DOMPurify from 'isomorphic-dompurify'
const sanitizeString = (str: string) => DOMPurify.sanitize(str).trim()
const urlSchema = z.string().url("Invalid URL").refine((val) => val.startsWith("http://") || val.startsWith("https://"), {
message: "URL must start with http:// or https://",
})
export const coinSchema = z.object({
name: z.string()
.min(1, "Name is required")
.max(50, "Name too long")
.regex(/^[\x20-\x7E]+$/, "Name can only contain standard characters")
.transform(sanitizeString),
ticker: z.string()
.min(3, "Ticker must be at least 3 characters")
.max(10, "Ticker cannot exceed 10 characters")
.regex(/^[a-zA-Z0-9]+$/, "Ticker can only contain letters and numbers")
.toUpperCase()
.transform(sanitizeString),
description: z.string()
.max(500, "Description too long")
.regex(/^[\x20-\x7E\n\r]*$/, "Description can only contain standard characters")
.optional()
.transform(val => sanitizeString(val || '')),
image: urlSchema.optional().or(z.literal('')),
website: urlSchema.optional().or(z.literal('')),
twitter: urlSchema.optional().or(z.literal('')),
telegram: urlSchema.optional().or(z.literal('')),
initialBuy: z.number().min(0).max(100, "Initial buy cannot exceed 100 SOL").optional().default(0),
useUserImage: z.boolean().optional(),
verified: z.boolean().optional().default(false),
boosted: z.boolean().optional().default(false),
})
export const commentSchema = z.object({
coinId: z.string().min(1, "Coin ID required"),
text: z.string()
.min(1)
.max(280, "Comment too long")
.regex(/^[\x20-\x7E\n\r]+$/, "Comment can only contain standard characters")
.transform(sanitizeString),
})
export type CreateCoinInput = z.infer<typeof coinSchema>
export type CreateCommentInput = z.infer<typeof commentSchema>
export const RESERVED_USERNAMES = [
'api', 'coin', 'create', 'dashboard', 'login', 'onboarding', 'privacy', 'terms', 'u',
'admin', 'administrator', 'mod', 'moderator', 'support', 'help', 'system', 'sys',
'bot', 'pummmp', 'null', 'undefined', 'void', 'root', 'webmaster', '404', '500'
]
export const isReservedUsername = (username: string) => {
return RESERVED_USERNAMES.includes(username.toLowerCase());
}