import { z } from "zod"; const isoDateTimeSchema = z.iso.datetime({ offset: true }); const minecraftUuidSchema = z .string() .regex(/^[0-9a-f]{32}$/i, "Expected a compact Java Edition UUID"); const minecraftUsernameSchema = z .string() .regex(/^[A-Za-z0-9_]{3,16}$/, "Expected a valid Java Edition username"); export const cloudEventSchema = z.object({ id: z.uuid(), specversion: z.literal("1.0"), source: z.string().startsWith("/"), type: z.string().min(1), subject: z.string().min(1).optional(), time: isoDateTimeSchema, datacontenttype: z.literal("application/json").default("application/json"), dataschema: z.url().optional(), data: z.record(z.string(), z.unknown()), }); export type CloudEvent = z.infer; export const velocityAccessRequestSchema = z.object({ requestId: z.uuid(), serverId: z.string().min(1).max(100), minecraftUuid: minecraftUuidSchema, username: minecraftUsernameSchema, ipAddress: z.union([z.ipv4(), z.ipv6()]), occurredAt: isoDateTimeSchema, }); export type VelocityAccessRequest = z.infer; export const velocityConnectionRequestSchema = z.object({ requestId: z.uuid(), serverId: z.string().min(1).max(100), minecraftUuid: minecraftUuidSchema, username: minecraftUsernameSchema, occurredAt: isoDateTimeSchema, }); export type VelocityConnectionRequest = z.infer; export const velocityAccessResponseSchema = z.discriminatedUnion("allowed", [ z.object({ allowed: z.literal(true), message: z.string().min(1).optional(), }), z.object({ allowed: z.literal(false), message: z.string().min(1), }), ]); export type VelocityAccessResponse = z.infer; export const problemDetailsSchema = z.object({ type: z.string().min(1), title: z.string().min(1), status: z.number().int().min(100).max(599), detail: z.string().min(1).optional(), instance: z.string().min(1).optional(), extensions: z.record(z.string(), z.unknown()).optional(), }); export type ProblemDetails = z.infer; export function problemDetails( type: string, title: string, status: number, detail?: string, instance?: string, extensions?: Record, ): ProblemDetails { return { type, title, status, ...(detail ? { detail } : {}), ...(instance ? { instance } : {}), ...(extensions ? { extensions } : {}), }; }