{"version":3,"file":"response-handler.mjs","sources":["../../../src/lib/api/response-handler.ts"],"sourcesContent":["/**\n * @file Response Handler\n * @description Comprehensive response handling utilities for API responses including\n * typed parsing, error normalization, caching hints, streaming support, and pagination.\n *\n * This module provides:\n * - Type-safe response parsing with validation\n * - Error normalization from various API error formats\n * - Response caching hint extraction and management\n * - Streaming response handling (SSE, NDJSON)\n * - Pagination helpers for cursor and offset-based APIs\n * - Response transformation pipelines\n *\n * @example\n * ```typescript\n * import {\n *   parseResponse,\n *   normalizeError,\n *   extractCacheHints,\n *   streamResponse,\n *   paginateResponse,\n * } from '@/lib/api';\n *\n * // Parse and validate response\n * const user = await parseResponse<User>(response, userSchema);\n *\n * // Handle streaming data\n * const stream = streamResponse<Message>(response, { sse: true });\n * stream.subscribe((event) => console.log(event.data));\n * ```\n */\n\nimport type { ApiResponse, ApiError } from './types';\n\n// Re-export extracted utilities\nexport { normalizeError, isApiError, type ErrorNormalizationConfig } from './error-normalizer';\n\nexport {\n  extractCacheHints,\n  buildCacheInfo,\n  generateCacheControl,\n  type CacheHints,\n} from './cache-hints';\n\nexport { streamResponse } from './stream-handler';\n\nexport {\n  extractPagination,\n  createPaginatedResponse,\n  mergePaginatedResponses,\n  type PaginationConfig,\n} from './pagination-helpers';\n\n// =============================================================================\n// RESPONSE PARSING\n// =============================================================================\n\n/**\n * Response parser configuration\n */\nexport interface ResponseParserConfig<T> {\n  /** Schema validator (e.g., Zod schema) */\n  schema?: { parse: (data: unknown) => T };\n  /** Transform function applied after parsing */\n  transform?: (data: T) => T;\n  /** Default value if response is empty */\n  defaultValue?: T;\n  /** Whether to throw on validation errors */\n  throwOnValidationError?: boolean;\n  /** Custom error message for validation failures */\n  validationErrorMessage?: string;\n}\n\n/**\n * Parse and optionally validate an API response\n *\n * @typeParam T - Expected response data type\n * @param response - Raw API response\n * @param config - Parser configuration\n * @returns Parsed and validated data\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const userSchema = z.object({\n *   id: z.string(),\n *   name: z.string(),\n *   email: z.string().email(),\n * });\n *\n * const user = parseResponse<User>(response, {\n *   schema: userSchema,\n *   transform: (u) => ({ ...u, displayName: u.name.toUpperCase() }),\n * });\n * ```\n */\nexport function parseResponse<T>(response: ApiResponse, config: ResponseParserConfig<T> = {}): T {\n  let data = response.data as T;\n\n  // Handle empty responses\n  if (data === null || data === undefined) {\n    if (config.defaultValue !== undefined) {\n      return config.defaultValue;\n    }\n    // Return empty data as-is for void responses\n    return data;\n  }\n\n  // Validate with schema if provided\n  if (config.schema) {\n    try {\n      data = config.schema.parse(data);\n    } catch (error) {\n      if (config.throwOnValidationError !== false) {\n        const message =\n          config.validationErrorMessage ??\n          `Response validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`;\n        throw createValidationError(message, error);\n      }\n      // Return raw data if validation fails and throwing is disabled\n      console.warn('[ResponseHandler] Validation failed:', error);\n    }\n  }\n\n  // Apply transformation\n  if (config.transform) {\n    data = config.transform(data);\n  }\n\n  return data;\n}\n\n/**\n * Create a response parser for a specific type\n *\n * @example\n * ```typescript\n * const parseUser = createResponseParser<User>({\n *   schema: userSchema,\n * });\n *\n * const user = parseUser(response);\n * ```\n */\nexport function createResponseParser<T>(\n  config: ResponseParserConfig<T>\n): (response: ApiResponse) => T {\n  return (response) => parseResponse<T>(response, config);\n}\n\n/**\n * Create validation error helper\n */\nfunction createValidationError(message: string, cause?: unknown): ApiError {\n  const error = new Error(message) as ApiError;\n  error.name = 'ApiError';\n  error.status = 422;\n  error.code = 'VALIDATION_ERROR';\n  error.message = message;\n  error.category = 'validation';\n  error.severity = 'warning';\n  error.cause = cause instanceof Error ? cause : undefined;\n  error.retryable = false;\n  error.timestamp = Date.now();\n  return error;\n}\n\n// =============================================================================\n// RESPONSE TRANSFORMERS\n// =============================================================================\n\n/**\n * Response transformer function type\n */\nexport type ResponseTransformer<TInput, TOutput> = (data: TInput) => TOutput;\n\n/**\n * Create a transformation pipeline for responses\n *\n * @example\n * ```typescript\n * const pipeline = createTransformPipeline(\n *   (data: ApiUser[]) => data.map(normalizeUser),\n *   (users) => users.filter(u => u.active),\n *   (users) => users.sort((a, b) => a.name.localeCompare(b.name)),\n * );\n *\n * const users = pipeline(response.data);\n * ```\n */\nexport function createTransformPipeline<T, U = T>(\n  fn?: ResponseTransformer<T, U>\n): {\n  pipe: <V>(nextFn: ResponseTransformer<U, V>) => {\n    pipe: <W>(\n      nextFn: ResponseTransformer<V, W>\n    ) => ReturnType<typeof createTransformPipeline<T, W>>;\n    execute: (data: T) => V;\n  };\n  execute: (data: T) => U;\n} {\n  const transform = fn ?? ((data: T) => data as unknown as U);\n\n  return {\n    pipe: <V>(nextFn: ResponseTransformer<U, V>) => {\n      const combined = (data: T): V => nextFn(transform(data));\n      return createTransformPipeline(combined);\n    },\n    execute: (data: T) => transform(data),\n  };\n}\n\n/**\n * Common transformers\n */\nexport const transformers = {\n  /**\n   * Normalize dates in response (ISO string to Date)\n   */\n  normalizeDates: <T extends Record<string, unknown>>(\n    fields: string[]\n  ): ResponseTransformer<T, T> => {\n    return (data: T) => {\n      const result: Record<string, unknown> = { ...data };\n      for (const field of fields) {\n        if (field in result && typeof result[field] === 'string') {\n          result[field] = new Date(result[field]);\n        }\n      }\n      return result as T;\n    };\n  },\n\n  /**\n   * Rename fields in response\n   */\n  renameFields: <T extends Record<string, unknown>>(\n    mapping: Record<string, string>\n  ): ResponseTransformer<T, T> => {\n    return (data: T) => {\n      const result = { ...data };\n      for (const [from, to] of Object.entries(mapping)) {\n        if (from in result) {\n          result[to as keyof T] = result[from as keyof T];\n          delete result[from as keyof T];\n        }\n      }\n      return result;\n    };\n  },\n\n  /**\n   * Pick specific fields from response\n   */\n  pickFields: <T extends Record<string, unknown>, K extends keyof T>(\n    fields: K[]\n  ): ResponseTransformer<T, Pick<T, K>> => {\n    return (data: T) => {\n      const result = {} as Pick<T, K>;\n      for (const field of fields) {\n        if (field in data) {\n          result[field] = data[field];\n        }\n      }\n      return result;\n    };\n  },\n\n  /**\n   * Omit specific fields from response\n   */\n  omitFields: <T extends Record<string, unknown>, K extends keyof T>(\n    fields: K[]\n  ): ResponseTransformer<T, Omit<T, K>> => {\n    return (data: T) => {\n      const result = { ...data };\n      for (const field of fields) {\n        delete result[field];\n      }\n      return result as Omit<T, K>;\n    };\n  },\n\n  /**\n   * Apply default values to missing fields\n   */\n  withDefaults: <T extends Record<string, unknown>>(\n    defaults: Partial<T>\n  ): ResponseTransformer<T, T> => {\n    return (data: T) => ({ ...defaults, ...data });\n  },\n};\n"],"names":["parseResponse","response","config","data","error","message","createValidationError","createResponseParser","cause","createTransformPipeline","fn","transform","nextFn","transformers","fields","result","field","mapping","from","to","defaults"],"mappings":"AAiGO,SAASA,EAAiBC,GAAuBC,IAAkC,IAAO;AAC/F,MAAIC,IAAOF,EAAS;AAGpB,MAAIE,KAAS;AACX,WAAID,EAAO,iBAAiB,SACnBA,EAAO,eAGTC;AAIT,MAAID,EAAO;AACT,QAAI;AACF,MAAAC,IAAOD,EAAO,OAAO,MAAMC,CAAI;AAAA,IACjC,SAASC,GAAO;AACd,UAAIF,EAAO,2BAA2B,IAAO;AAC3C,cAAMG,IACJH,EAAO,0BACP,+BAA+BE,aAAiB,QAAQA,EAAM,UAAU,eAAe;AACzF,cAAME,EAAsBD,GAASD,CAAK;AAAA,MAC5C;AAEA,cAAQ,KAAK,wCAAwCA,CAAK;AAAA,IAC5D;AAIF,SAAIF,EAAO,cACTC,IAAOD,EAAO,UAAUC,CAAI,IAGvBA;AACT;AAcO,SAASI,EACdL,GAC8B;AAC9B,SAAO,CAACD,MAAaD,EAAiBC,GAAUC,CAAM;AACxD;AAKA,SAASI,EAAsBD,GAAiBG,GAA2B;AACzE,QAAMJ,IAAQ,IAAI,MAAMC,CAAO;AAC/B,SAAAD,EAAM,OAAO,YACbA,EAAM,SAAS,KACfA,EAAM,OAAO,oBACbA,EAAM,UAAUC,GAChBD,EAAM,WAAW,cACjBA,EAAM,WAAW,WACjBA,EAAM,QAAQI,aAAiB,QAAQA,IAAQ,QAC/CJ,EAAM,YAAY,IAClBA,EAAM,YAAY,KAAK,IAAA,GAChBA;AACT;AAyBO,SAASK,EACdC,GASA;AACA,QAAMC,IAAYD,MAAO,CAACP,MAAYA;AAEtC,SAAO;AAAA,IACL,MAAM,CAAIS,MAEDH,EADU,CAACN,MAAeS,EAAOD,EAAUR,CAAI,CAAC,CAChB;AAAA,IAEzC,SAAS,CAACA,MAAYQ,EAAUR,CAAI;AAAA,EAAA;AAExC;AAKO,MAAMU,IAAe;AAAA;AAAA;AAAA;AAAA,EAI1B,gBAAgB,CACdC,MAEO,CAACX,MAAY;AAClB,UAAMY,IAAkC,EAAE,GAAGZ,EAAA;AAC7C,eAAWa,KAASF;AAClB,MAAIE,KAASD,KAAU,OAAOA,EAAOC,CAAK,KAAM,aAC9CD,EAAOC,CAAK,IAAI,IAAI,KAAKD,EAAOC,CAAK,CAAC;AAG1C,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMF,cAAc,CACZE,MAEO,CAACd,MAAY;AAClB,UAAMY,IAAS,EAAE,GAAGZ,EAAA;AACpB,eAAW,CAACe,GAAMC,CAAE,KAAK,OAAO,QAAQF,CAAO;AAC7C,MAAIC,KAAQH,MACVA,EAAOI,CAAa,IAAIJ,EAAOG,CAAe,GAC9C,OAAOH,EAAOG,CAAe;AAGjC,WAAOH;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMF,YAAY,CACVD,MAEO,CAACX,MAAY;AAClB,UAAMY,IAAS,CAAA;AACf,eAAWC,KAASF;AAClB,MAAIE,KAASb,MACXY,EAAOC,CAAK,IAAIb,EAAKa,CAAK;AAG9B,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMF,YAAY,CACVD,MAEO,CAACX,MAAY;AAClB,UAAMY,IAAS,EAAE,GAAGZ,EAAA;AACpB,eAAWa,KAASF;AAClB,aAAOC,EAAOC,CAAK;AAErB,WAAOD;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMF,cAAc,CACZK,MAEO,CAACjB,OAAa,EAAE,GAAGiB,GAAU,GAAGjB,EAAA;AAE3C;"}