/** * @fileoverview CON-04 Runtime Validation - Envelope Validation * @description Validation functions for API response envelopes * @version 0.18.4 */ import { z, ZodSchema } from "zod"; import { ApiEnvelopeSchema, EnhancedApiEnvelopeSchema, ErrorEnvelopeSchema } from "../envelopes/standard"; import { EnvelopeValidationError } from "../utils/errors"; /** * Validates that a response follows the standard API envelope format * * @param response - Unknown response to validate * @throws {EnvelopeValidationError} if response doesn't match envelope format * * @example * ```typescript * const response = { success: true, data: { id: "123" }, meta: {} }; * validateStandardEnvelope(response); * // Throws if response doesn't match standard envelope format * ``` */ export function validateStandardEnvelope( response: unknown ): asserts response is { success: boolean; data?: any; error?: any; meta?: Record } { try { ApiEnvelopeSchema.parse(response); } catch (err) { if (err instanceof z.ZodError) { throw new EnvelopeValidationError( "Response does not match standard envelope format", "ENVELOPE_VALIDATION_ERROR", err, { zodError: err.format(), expectedSchema: 'ApiEnvelopeSchema' } ); } throw new EnvelopeValidationError( "Response validation failed with unknown error", "ENVELOPE_VALIDATION_ERROR", err instanceof Error ? err : undefined, { expectedSchema: 'ApiEnvelopeSchema', originalError: err } ); } } /** * Validates that a response follows the enhanced API envelope format * * @param response - Unknown response to validate * @throws {EnvelopeValidationError} if response doesn't match enhanced envelope format */ export function validateEnhancedEnvelope( response: unknown ): asserts response is { success: boolean; data?: any; error?: any; requestId: string; timestamp: string; meta?: { contractsVersion: string; traceId?: string; latencyMs?: number; source?: string } } { try { EnhancedApiEnvelopeSchema.parse(response); } catch (err) { if (err instanceof z.ZodError) { throw new EnvelopeValidationError( "Response does not match enhanced envelope format", "ENVELOPE_VALIDATION_ERROR", err, { zodError: err.format(), expectedSchema: 'EnhancedApiEnvelopeSchema' } ); } throw new EnvelopeValidationError( "Response validation failed with unknown error", "ENVELOPE_VALIDATION_ERROR", err instanceof Error ? err : undefined, { expectedSchema: 'EnhancedApiEnvelopeSchema', originalError: err } ); } } /** * Creates a combined schema that validates both envelope and data structure * This is the primary function for validating API responses with data * * @param dataSchema - Zod schema for the expected data structure * @returns Zod schema that validates envelope + data * * @example * ```typescript * const userSchema = z.object({ * id: z.string(), * email: z.string().email() * }); * * const envelopeWithUser = validateEnvelope(userSchema); * const response = { * success: true, * data: { id: "123", email: "user@example.com" } * }; * * const result = envelopeWithUser.parse(response); * // result.data is now typed as { id: string, email: string } * ``` */ export function validateEnvelope(dataSchema: ZodSchema) { return ApiEnvelopeSchema.extend({ data: dataSchema }); } /** * Validates an error response according to the standard error envelope format * * @param response - Unknown error response to validate * @throws {EnvelopeValidationError} if error response doesn't match expected format */ export function validateErrorEnvelope( response: unknown ): asserts response is { success: false; error: { code: string; message: string; details?: Record; timestamp: string }; meta?: Record } { try { const errorEnvelopeSchema = ApiEnvelopeSchema.extend({ success: z.literal(false), error: ErrorEnvelopeSchema, data: z.undefined() }); errorEnvelopeSchema.parse(response); } catch (err) { if (err instanceof z.ZodError) { throw new EnvelopeValidationError( "Error response does not match expected error envelope format", "ENVELOPE_VALIDATION_ERROR", err, { zodError: err.format(), expectedSchema: 'ErrorEnvelopeSchema' } ); } throw new EnvelopeValidationError( "Error response validation failed with unknown error", "ENVELOPE_VALIDATION_ERROR", err instanceof Error ? err : undefined, { expectedSchema: 'ErrorEnvelopeSchema', originalError: err } ); } } /** * Safely validates an envelope without throwing * Useful for graceful error handling * * @param dataSchema - Zod schema for the expected data structure * @param response - Unknown response to validate * @returns Validation result with success flag and data/error */ export function safeValidateEnvelope( dataSchema: ZodSchema, response: unknown ): { success: true; data: T } | { success: false; error: z.ZodError } { const schema = validateEnvelope(dataSchema); const result = schema.safeParse(response); if (result.success) { return { success: true, data: result.data.data as T }; } return { success: false, error: result.error }; }