mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 08:31:13 -05:00
Refactor code structure and remove redundant changes
This commit is contained in:
240
src-old/lib/runtimeValidation.ts
Normal file
240
src-old/lib/runtimeValidation.ts
Normal file
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Runtime Type Validation
|
||||
*
|
||||
* Validates data from Supabase queries at runtime to ensure type safety.
|
||||
* Uses Zod schemas to parse and validate database responses.
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { Park, Ride, Company, RideModel } from '@/types/database';
|
||||
|
||||
// ============================================
|
||||
// RUNTIME SCHEMAS (Mirror Database Types)
|
||||
// ============================================
|
||||
|
||||
export const parkRuntimeSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
park_type: z.string(),
|
||||
status: z.enum(['operating', 'closed_permanently', 'closed_temporarily', 'under_construction', 'planned', 'abandoned']),
|
||||
opening_date: z.string().nullable().optional(),
|
||||
opening_date_precision: z.string().nullable().optional(),
|
||||
closing_date: z.string().nullable().optional(),
|
||||
closing_date_precision: z.string().nullable().optional(),
|
||||
location_id: z.string().uuid().nullable().optional(),
|
||||
operator_id: z.string().uuid().nullable().optional(),
|
||||
property_owner_id: z.string().uuid().nullable().optional(),
|
||||
website_url: z.string().nullable().optional(),
|
||||
phone: z.string().nullable().optional(),
|
||||
email: z.string().nullable().optional(),
|
||||
banner_image_url: z.string().nullable().optional(),
|
||||
banner_image_id: z.string().nullable().optional(),
|
||||
card_image_url: z.string().nullable().optional(),
|
||||
card_image_id: z.string().nullable().optional(),
|
||||
ride_count: z.number().optional(),
|
||||
coaster_count: z.number().optional(),
|
||||
average_rating: z.number().nullable().optional(),
|
||||
review_count: z.number().optional(),
|
||||
view_count_7d: z.number().optional(),
|
||||
view_count_30d: z.number().optional(),
|
||||
view_count_all: z.number().optional(),
|
||||
created_at: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
}).passthrough(); // Allow additional fields from joins
|
||||
|
||||
export const rideRuntimeSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
category: z.string(),
|
||||
ride_sub_type: z.string().nullable().optional(),
|
||||
status: z.enum(['operating', 'closed_permanently', 'closed_temporarily', 'under_construction', 'relocated', 'stored', 'demolished']),
|
||||
park_id: z.string().uuid().nullable().optional(),
|
||||
manufacturer_id: z.string().uuid().nullable().optional(),
|
||||
designer_id: z.string().uuid().nullable().optional(),
|
||||
ride_model_id: z.string().uuid().nullable().optional(),
|
||||
opening_date: z.string().nullable().optional(),
|
||||
opening_date_precision: z.string().nullable().optional(),
|
||||
closing_date: z.string().nullable().optional(),
|
||||
closing_date_precision: z.string().nullable().optional(),
|
||||
height_requirement_cm: z.number().nullable().optional(),
|
||||
age_requirement: z.number().nullable().optional(),
|
||||
max_speed_kmh: z.number().nullable().optional(),
|
||||
duration_seconds: z.number().nullable().optional(),
|
||||
capacity_per_hour: z.number().nullable().optional(),
|
||||
gforce_max: z.number().nullable().optional(),
|
||||
inversions_count: z.number().nullable().optional(),
|
||||
length_meters: z.number().nullable().optional(),
|
||||
height_meters: z.number().nullable().optional(),
|
||||
drop_meters: z.number().nullable().optional(),
|
||||
angle_degrees: z.number().nullable().optional(),
|
||||
coaster_type: z.string().nullable().optional(),
|
||||
seating_type: z.string().nullable().optional(),
|
||||
intensity_level: z.string().nullable().optional(),
|
||||
former_names: z.array(z.unknown()).nullable().optional(),
|
||||
banner_image_url: z.string().nullable().optional(),
|
||||
banner_image_id: z.string().nullable().optional(),
|
||||
card_image_url: z.string().nullable().optional(),
|
||||
card_image_id: z.string().nullable().optional(),
|
||||
average_rating: z.number().nullable().optional(),
|
||||
review_count: z.number().optional(),
|
||||
view_count_7d: z.number().optional(),
|
||||
view_count_30d: z.number().optional(),
|
||||
view_count_all: z.number().optional(),
|
||||
created_at: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
export const companyRuntimeSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
company_type: z.string(),
|
||||
person_type: z.string().nullable().optional(),
|
||||
founded_year: z.number().nullable().optional(),
|
||||
founded_date: z.string().nullable().optional(),
|
||||
founded_date_precision: z.string().nullable().optional(),
|
||||
headquarters_location: z.string().nullable().optional(),
|
||||
website_url: z.string().nullable().optional(),
|
||||
logo_url: z.string().nullable().optional(),
|
||||
banner_image_url: z.string().nullable().optional(),
|
||||
banner_image_id: z.string().nullable().optional(),
|
||||
card_image_url: z.string().nullable().optional(),
|
||||
card_image_id: z.string().nullable().optional(),
|
||||
average_rating: z.number().nullable().optional(),
|
||||
review_count: z.number().optional(),
|
||||
view_count_7d: z.number().optional(),
|
||||
view_count_30d: z.number().optional(),
|
||||
view_count_all: z.number().optional(),
|
||||
created_at: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
export const rideModelRuntimeSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
slug: z.string(),
|
||||
manufacturer_id: z.string().uuid().nullable().optional(),
|
||||
category: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
// Note: technical_specs deprecated - use ride_model_technical_specifications table
|
||||
created_at: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
// ============================================
|
||||
// VALIDATION HELPERS
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Validate a single park record
|
||||
*/
|
||||
export function validatePark(data: unknown): Park {
|
||||
return parkRuntimeSchema.parse(data) as Park;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of park records
|
||||
*/
|
||||
export function validateParks(data: unknown): Park[] {
|
||||
return z.array(parkRuntimeSchema).parse(data) as Park[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely validate parks (returns null on error)
|
||||
*/
|
||||
export function safeValidateParks(data: unknown): Park[] | null {
|
||||
const result = z.array(parkRuntimeSchema).safeParse(data);
|
||||
return result.success ? (result.data as Park[]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a single ride record
|
||||
*/
|
||||
export function validateRide(data: unknown): Ride {
|
||||
return rideRuntimeSchema.parse(data) as Ride;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of ride records
|
||||
*/
|
||||
export function validateRides(data: unknown): Ride[] {
|
||||
return z.array(rideRuntimeSchema).parse(data) as Ride[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely validate rides (returns null on error)
|
||||
*/
|
||||
export function safeValidateRides(data: unknown): Ride[] | null {
|
||||
const result = z.array(rideRuntimeSchema).safeParse(data);
|
||||
return result.success ? (result.data as Ride[]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a single company record
|
||||
*/
|
||||
export function validateCompany(data: unknown): Company {
|
||||
return companyRuntimeSchema.parse(data) as Company;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of company records
|
||||
*/
|
||||
export function validateCompanies(data: unknown): Company[] {
|
||||
return z.array(companyRuntimeSchema).parse(data) as Company[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely validate companies (returns null on error)
|
||||
*/
|
||||
export function safeValidateCompanies(data: unknown): Company[] | null {
|
||||
const result = z.array(companyRuntimeSchema).safeParse(data);
|
||||
return result.success ? (result.data as Company[]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a single ride model record
|
||||
*/
|
||||
export function validateRideModel(data: unknown): RideModel {
|
||||
return rideModelRuntimeSchema.parse(data) as RideModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array of ride model records
|
||||
*/
|
||||
export function validateRideModels(data: unknown): RideModel[] {
|
||||
return z.array(rideModelRuntimeSchema).parse(data) as RideModel[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely validate ride models (returns null on error)
|
||||
*/
|
||||
export function safeValidateRideModels(data: unknown): RideModel[] | null {
|
||||
const result = z.array(rideModelRuntimeSchema).safeParse(data);
|
||||
return result.success ? (result.data as RideModel[]) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic validator for any entity type
|
||||
*/
|
||||
export function validateEntity<T>(
|
||||
data: unknown,
|
||||
schema: z.ZodSchema<T>
|
||||
): T {
|
||||
return schema.parse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe generic validator (returns null on error)
|
||||
*/
|
||||
export function safeValidateEntity<T>(
|
||||
data: unknown,
|
||||
schema: z.ZodSchema<T>
|
||||
): T | null {
|
||||
const result = schema.safeParse(data);
|
||||
return result.success ? result.data : null;
|
||||
}
|
||||
Reference in New Issue
Block a user