refactor(validation): restucture api input and output validation
This commit is contained in:
parent
485a95f99a
commit
eef17c5360
34 changed files with 1891 additions and 1802 deletions
168
src/app/api/event/validation.ts
Normal file
168
src/app/api/event/validation.ts
Normal file
|
@ -0,0 +1,168 @@
|
|||
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({
|
||||
id: eventIdSchema,
|
||||
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),
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue