mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 10:11:13 -05:00
feat: Implement comprehensive validation error handling
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import { handleNonCriticalError, getErrorMessage } from '@/lib/errorHandler';
|
||||
import { logger } from '@/lib/logger';
|
||||
|
||||
// ============================================
|
||||
// CENTRALIZED VALIDATION SCHEMAS
|
||||
@@ -452,35 +454,71 @@ export async function validateEntityData(
|
||||
entityType: keyof typeof entitySchemas,
|
||||
data: unknown
|
||||
): Promise<ValidationResult> {
|
||||
const schema = entitySchemas[entityType];
|
||||
|
||||
if (!schema) {
|
||||
return {
|
||||
isValid: false,
|
||||
blockingErrors: [{ field: 'entity_type', message: `Unknown entity type: ${entityType}`, severity: 'blocking' }],
|
||||
warnings: [],
|
||||
suggestions: [],
|
||||
allErrors: [{ field: 'entity_type', message: `Unknown entity type: ${entityType}`, severity: 'blocking' }],
|
||||
};
|
||||
}
|
||||
|
||||
const result = schema.safeParse(data);
|
||||
const blockingErrors: ValidationError[] = [];
|
||||
const warnings: ValidationError[] = [];
|
||||
const suggestions: ValidationError[] = [];
|
||||
|
||||
// Process Zod errors
|
||||
if (!result.success) {
|
||||
const zodError = result.error as z.ZodError;
|
||||
zodError.issues.forEach((issue) => {
|
||||
const field = issue.path.join('.');
|
||||
blockingErrors.push({
|
||||
field: field || 'unknown',
|
||||
message: issue.message,
|
||||
severity: 'blocking',
|
||||
try {
|
||||
// Debug logging for operator entity
|
||||
if (entityType === 'operator') {
|
||||
logger.log('Validating operator entity', {
|
||||
dataKeys: data ? Object.keys(data as object) : [],
|
||||
dataTypes: data ? Object.entries(data as object).reduce((acc, [key, val]) => {
|
||||
acc[key] = typeof val;
|
||||
return acc;
|
||||
}, {} as Record<string, string>) : {},
|
||||
rawData: JSON.stringify(data).substring(0, 500)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const schema = entitySchemas[entityType];
|
||||
|
||||
if (!schema) {
|
||||
const error = {
|
||||
field: 'entity_type',
|
||||
message: `Unknown entity type: ${entityType}`,
|
||||
severity: 'blocking' as const
|
||||
};
|
||||
|
||||
handleNonCriticalError(new Error(`Unknown entity type: ${entityType}`), {
|
||||
action: 'Entity Validation',
|
||||
metadata: { entityType, providedData: data }
|
||||
});
|
||||
|
||||
return {
|
||||
isValid: false,
|
||||
blockingErrors: [error],
|
||||
warnings: [],
|
||||
suggestions: [],
|
||||
allErrors: [error],
|
||||
};
|
||||
}
|
||||
|
||||
const result = schema.safeParse(data);
|
||||
const blockingErrors: ValidationError[] = [];
|
||||
const warnings: ValidationError[] = [];
|
||||
const suggestions: ValidationError[] = [];
|
||||
|
||||
// Process Zod errors
|
||||
if (!result.success) {
|
||||
const zodError = result.error as z.ZodError;
|
||||
|
||||
// Log detailed validation failure
|
||||
handleNonCriticalError(zodError, {
|
||||
action: 'Zod Validation Failed',
|
||||
metadata: {
|
||||
entityType,
|
||||
issues: zodError.issues,
|
||||
providedData: JSON.stringify(data).substring(0, 500),
|
||||
issueCount: zodError.issues.length
|
||||
}
|
||||
});
|
||||
|
||||
zodError.issues.forEach((issue) => {
|
||||
const field = issue.path.join('.') || entityType;
|
||||
blockingErrors.push({
|
||||
field,
|
||||
message: `${issue.message} (code: ${issue.code})`,
|
||||
severity: 'blocking',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add warnings for optional but recommended fields
|
||||
const validData = data as Record<string, unknown>;
|
||||
@@ -585,16 +623,43 @@ export async function validateEntityData(
|
||||
}
|
||||
}
|
||||
|
||||
const allErrors = [...blockingErrors, ...warnings, ...suggestions];
|
||||
const isValid = blockingErrors.length === 0;
|
||||
const allErrors = [...blockingErrors, ...warnings, ...suggestions];
|
||||
const isValid = blockingErrors.length === 0;
|
||||
|
||||
return {
|
||||
isValid,
|
||||
blockingErrors,
|
||||
warnings,
|
||||
suggestions,
|
||||
allErrors,
|
||||
};
|
||||
return {
|
||||
isValid,
|
||||
blockingErrors,
|
||||
warnings,
|
||||
suggestions,
|
||||
allErrors,
|
||||
};
|
||||
} catch (error) {
|
||||
// Catch any unexpected errors during validation
|
||||
const errorId = handleNonCriticalError(error, {
|
||||
action: 'Entity Validation Unexpected Error',
|
||||
metadata: {
|
||||
entityType,
|
||||
dataType: typeof data,
|
||||
hasData: !!data
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
isValid: false,
|
||||
blockingErrors: [{
|
||||
field: entityType,
|
||||
message: `Validation error: ${getErrorMessage(error)} (ref: ${errorId.slice(0, 8)})`,
|
||||
severity: 'blocking'
|
||||
}],
|
||||
warnings: [],
|
||||
suggestions: [],
|
||||
allErrors: [{
|
||||
field: entityType,
|
||||
message: `Validation error: ${getErrorMessage(error)} (ref: ${errorId.slice(0, 8)})`,
|
||||
severity: 'blocking'
|
||||
}],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user