/** * @ai-summary Request validation schemas for vehicles API * @ai-context Uses Zod for runtime validation and type safety */ import { z } from 'zod'; import { isValidVIN } from '../../../shared-minimal/utils/validators'; // Cost interval enum for TCO recurring costs const costIntervalSchema = z.enum(['monthly', 'semi_annual', 'annual']); export const createVehicleSchema = z.object({ vin: z.string() .length(17, 'VIN must be exactly 17 characters') .refine(isValidVIN, 'Invalid VIN format'), nickname: z.string().min(1).max(100).optional(), color: z.string().min(1).max(50).optional(), licensePlate: z.string().min(1).max(20).optional(), odometerReading: z.number().min(0).max(9999999).optional(), // TCO fields purchasePrice: z.number().min(0).max(99999999.99).optional(), purchaseDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD').optional(), insuranceCost: z.number().min(0).max(9999999.99).optional(), insuranceInterval: costIntervalSchema.optional(), registrationCost: z.number().min(0).max(9999999.99).optional(), registrationInterval: costIntervalSchema.optional(), tcoEnabled: z.boolean().optional(), }); export const updateVehicleSchema = z.object({ vin: z.string().max(17).optional(), year: z.number().min(1900).max(new Date().getFullYear() + 1).optional(), make: z.string().max(100).optional(), model: z.string().max(100).optional(), engine: z.string().max(100).optional(), transmission: z.string().max(100).optional(), trimLevel: z.string().max(100).optional(), driveType: z.string().max(50).optional(), fuelType: z.string().max(50).optional(), nickname: z.string().min(1).max(100).optional(), color: z.string().min(1).max(50).optional(), licensePlate: z.string().min(1).max(20).optional(), odometerReading: z.number().min(0).max(9999999).optional(), // TCO fields purchasePrice: z.number().min(0).max(99999999.99).optional().nullable(), purchaseDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD').optional().nullable(), insuranceCost: z.number().min(0).max(9999999.99).optional().nullable(), insuranceInterval: costIntervalSchema.optional().nullable(), registrationCost: z.number().min(0).max(9999999.99).optional().nullable(), registrationInterval: costIntervalSchema.optional().nullable(), tcoEnabled: z.boolean().optional(), }); export const vehicleIdSchema = z.object({ id: z.string().uuid('Invalid vehicle ID format'), }); export type CreateVehicleInput = z.infer; export type UpdateVehicleInput = z.infer; export type VehicleIdInput = z.infer;