Barazo AppView backend barazo.forum
at main 93 lines 3.4 kB view raw
1import { z } from 'zod/v4' 2import { maturityRatingSchema } from './categories.js' 3import { reactionSetSchema } from './reactions.js' 4 5// --------------------------------------------------------------------------- 6// Request schemas 7// --------------------------------------------------------------------------- 8 9/** Hex color code pattern: # followed by 3, 4, 6, or 8 hex digits. */ 10const hexColorPattern = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/ 11 12/** Schema for updating community settings (all fields optional). */ 13export const updateSettingsSchema = z.object({ 14 communityName: z 15 .string() 16 .trim() 17 .min(1, 'Community name is required') 18 .max(100, 'Community name must be at most 100 characters') 19 .optional(), 20 maturityRating: maturityRatingSchema.optional(), 21 reactionSet: reactionSetSchema.optional(), 22 communityDescription: z 23 .string() 24 .trim() 25 .max(500, 'Community description must be at most 500 characters') 26 .nullable() 27 .optional(), 28 communityLogoUrl: z.url('Community logo must be a valid URL').nullable().optional(), 29 faviconUrl: z.url('Favicon must be a valid URL').nullable().optional(), 30 headerLogoUrl: z.url('Header logo must be a valid URL').nullable().optional(), 31 showCommunityName: z.boolean().optional(), 32 primaryColor: z 33 .string() 34 .regex(hexColorPattern, 'Primary color must be a valid hex color (e.g., #ff0000)') 35 .nullable() 36 .optional(), 37 accentColor: z 38 .string() 39 .regex(hexColorPattern, 'Accent color must be a valid hex color (e.g., #00ff00)') 40 .nullable() 41 .optional(), 42 jurisdictionCountry: z 43 .string() 44 .length(2, 'Jurisdiction country must be a 2-letter ISO 3166-1 alpha-2 code') 45 .regex(/^[A-Z]{2}$/, 'Jurisdiction country must be uppercase letters') 46 .nullable() 47 .optional(), 48 ageThreshold: z 49 .number() 50 .int('Age threshold must be an integer') 51 .min(13, 'Age threshold must be at least 13') 52 .max(18, 'Age threshold must be at most 18') 53 .optional(), 54 requireLoginForMature: z.boolean().optional(), 55 maxReplyDepth: z 56 .number() 57 .int('Max reply depth must be an integer') 58 .min(1, 'Max reply depth must be at least 1') 59 .max(9999, 'Max reply depth must be at most 9999') 60 .optional(), 61}) 62 63export type UpdateSettingsInput = z.infer<typeof updateSettingsSchema> 64 65// --------------------------------------------------------------------------- 66// Response schemas (for OpenAPI documentation) 67// --------------------------------------------------------------------------- 68 69/** Schema describing community settings in API responses. */ 70export const settingsResponseSchema = z.object({ 71 id: z.string(), 72 initialized: z.boolean(), 73 communityDid: z.string().nullable(), 74 adminDid: z.string().nullable(), 75 communityName: z.string(), 76 maturityRating: maturityRatingSchema, 77 reactionSet: z.array(z.string()), 78 communityDescription: z.string().nullable(), 79 communityLogoUrl: z.string().nullable(), 80 faviconUrl: z.string().nullable(), 81 headerLogoUrl: z.string().nullable(), 82 showCommunityName: z.boolean(), 83 primaryColor: z.string().nullable(), 84 accentColor: z.string().nullable(), 85 jurisdictionCountry: z.string().nullable(), 86 ageThreshold: z.number(), 87 maxReplyDepth: z.number(), 88 requireLoginForMature: z.boolean(), 89 createdAt: z.string(), 90 updatedAt: z.string(), 91}) 92 93export type SettingsResponse = z.infer<typeof settingsResponseSchema>