// JSON Schemas for auth payloads — the single source of truth. The backend // validates requests against these (Fastify), and the payload TS types are // derived from them via `FromSchema` (see ./types), so there is no drift. import type { FromSchema } from 'json-schema-to-ts'; // Username: public handle, case-insensitive-unique. Letters/digits/underscore. const USERNAME_PATTERN = '^[a-zA-Z0-9_]{3,32}$'; // E.164 phone, e.g. +14155552671. const PHONE_PATTERN = '^\\+[1-9]\\d{1,14}$'; export const registerBodySchema = { type: 'object', additionalProperties: false, required: ['username', 'displayName', 'password'], properties: { username: { type: 'string', pattern: USERNAME_PATTERN }, displayName: { type: 'string', minLength: 1, maxLength: 64 }, password: { type: 'string', minLength: 8, maxLength: 128 }, email: { type: 'string', format: 'email', maxLength: 254 }, phone: { type: 'string', pattern: PHONE_PATTERN }, }, } as const; export const loginBodySchema = { type: 'object', additionalProperties: false, required: ['username', 'password'], properties: { username: { type: 'string', pattern: USERNAME_PATTERN }, password: { type: 'string', minLength: 1, maxLength: 128 }, }, } as const; export const refreshBodySchema = { type: 'object', additionalProperties: false, required: ['refreshToken'], properties: { refreshToken: { type: 'string', minLength: 1 }, }, } as const; export const logoutBodySchema = { type: 'object', additionalProperties: false, required: ['refreshToken'], properties: { refreshToken: { type: 'string', minLength: 1 }, }, } as const; export const updateMeBodySchema = { type: 'object', additionalProperties: false, minProperties: 1, properties: { displayName: { type: 'string', minLength: 1, maxLength: 64 }, // `null` clears the value; a string sets it. email: { type: ['string', 'null'], format: 'email', maxLength: 254 }, phone: { type: ['string', 'null'], pattern: PHONE_PATTERN }, }, } as const; export type RegisterBody = FromSchema; export type LoginBody = FromSchema; export type RefreshBody = FromSchema; export type LogoutBody = FromSchema; export type UpdateMeBody = FromSchema;