MeetUp/src/app/api/event/validation.ts
Dominik Stahl 5e9f8b59a4
All checks were successful
container-scan / Container Scan (pull_request) Successful in 2m54s
docker-build / docker (pull_request) Successful in 6m5s
fix(api): update paths in Swagger documentation to include '/api' prefix
2025-06-19 20:47:10 +02:00

167 lines
4.5 KiB
TypeScript

import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
import zod from 'zod/v4';
import {
existingUserIdServerSchema,
PublicUserSchema,
} from '../user/validation';
import { ParticipantSchema } from './[eventID]/participant/validation';
extendZodWithOpenApi(zod);
// ----------------------------------------
//
// Event ID Validation
//
// ----------------------------------------
export const eventIdSchema = zod.string().min(1, 'Event ID is required');
// ----------------------------------------
//
// Event Title Validation
//
// ----------------------------------------
export const eventTitleSchema = zod
.string()
.min(1, 'Title is required')
.max(100, 'Title must be at most 100 characters long');
// ----------------------------------------
//
// Event Description Validation
//
// ----------------------------------------
export const eventDescriptionSchema = zod
.string()
.max(500, 'Description must be at most 500 characters long');
// ----------------------------------------
//
// Event start time Validation
//
// ----------------------------------------
export const eventStartTimeSchema = zod.iso
.datetime()
.or(zod.date().transform((date) => date.toISOString()))
.refine((date) => !isNaN(new Date(date).getTime()), {
message: 'Invalid start time',
});
// ----------------------------------------
//
// Event end time Validation
//
// ----------------------------------------
export const eventEndTimeSchema = zod.iso.datetime().or(
zod
.date()
.transform((date) => date.toISOString())
.refine((date) => !isNaN(new Date(date).getTime()), {
message: 'Invalid end time',
}),
);
// ----------------------------------------
//
// Event Location Validation
//
// ----------------------------------------
export const eventLocationSchema = zod
.string()
.max(200, 'Location must be at most 200 characters long');
// ----------------------------------------
//
// Event Participants Validation
//
// ----------------------------------------
export const eventParticipantsSchema = zod.array(existingUserIdServerSchema);
// ----------------------------------------
//
// Event Status Validation
//
// ----------------------------------------
export const eventStatusSchema = zod.enum([
'TENTATIVE',
'CONFIRMED',
'CANCELLED',
]);
// ----------------------------------------
//
// Create Event Schema
//
// ----------------------------------------
export const createEventSchema = zod
.object({
title: eventTitleSchema,
description: eventDescriptionSchema.optional(),
start_time: eventStartTimeSchema,
end_time: eventEndTimeSchema,
location: eventLocationSchema.optional().default(''),
participants: eventParticipantsSchema.optional(),
status: eventStatusSchema.optional().default('TENTATIVE'),
})
.refine((data) => new Date(data.start_time) < new Date(data.end_time), {
message: 'Start time must be before end time',
});
// ----------------------------------------
//
// Update Event Schema
//
// ----------------------------------------
export const updateEventSchema = zod
.object({
title: eventTitleSchema.optional(),
description: eventDescriptionSchema.optional(),
start_time: eventStartTimeSchema.optional(),
end_time: eventEndTimeSchema.optional(),
location: eventLocationSchema.optional().default(''),
participants: eventParticipantsSchema.optional(),
status: eventStatusSchema.optional(),
})
.refine(
(data) => {
if (data.start_time && data.end_time) {
return new Date(data.start_time) < new Date(data.end_time);
}
return true;
},
{
message: 'Start time must be before end time',
},
);
// ----------------------------------------
//
// Event Schema Validation (for API responses)
//
// ----------------------------------------
export const EventSchema = zod
.object({
id: eventIdSchema,
title: eventTitleSchema,
description: eventDescriptionSchema.nullish(),
start_time: eventStartTimeSchema,
end_time: eventEndTimeSchema,
location: eventLocationSchema.nullish(),
status: eventStatusSchema,
created_at: zod.date(),
updated_at: zod.date(),
organizer: PublicUserSchema,
participants: zod.array(ParticipantSchema).nullish(),
})
.openapi('Event', {
description: 'Event information including all fields',
});
export const EventResponseSchema = zod.object({
success: zod.boolean(),
event: EventSchema,
});
export const EventsResponseSchema = zod.object({
success: zod.boolean(),
events: zod.array(EventSchema),
});