{"version":3,"file":"response-normalizer.mjs","sources":["../../../../src/lib/api/advanced/response-normalizer.ts"],"sourcesContent":["/**\n * Response Normalizer\n *\n * Normalizes diverse API responses into consistent formats.\n * Handles different API conventions, pagination styles, and error formats.\n *\n * @module api/advanced/response-normalizer\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Normalized response structure.\n */\nexport interface NormalizedResponse<T = unknown> {\n  /** Response data */\n  data: T;\n  /** Pagination information */\n  pagination?: NormalizedPagination;\n  /** Response metadata */\n  meta?: Record<string, unknown>;\n  /** Links for HATEOAS */\n  links?: NormalizedLinks;\n  /** Included/embedded resources */\n  included?: Record<string, unknown[]>;\n}\n\n/**\n * Normalized pagination structure.\n */\nexport interface NormalizedPagination {\n  /** Current page number (1-indexed) */\n  currentPage: number;\n  /** Total number of pages */\n  totalPages: number;\n  /** Items per page */\n  pageSize: number;\n  /** Total number of items */\n  totalItems: number;\n  /** Whether there's a next page */\n  hasNextPage: boolean;\n  /** Whether there's a previous page */\n  hasPrevPage: boolean;\n  /** Cursor for cursor-based pagination */\n  cursor?: string;\n  /** Next cursor */\n  nextCursor?: string;\n  /** Previous cursor */\n  prevCursor?: string;\n}\n\n/**\n * Normalized links structure.\n */\nexport interface NormalizedLinks {\n  /** Link to self */\n  self?: string;\n  /** Link to first page */\n  first?: string;\n  /** Link to last page */\n  last?: string;\n  /** Link to next page */\n  next?: string;\n  /** Link to previous page */\n  prev?: string;\n  /** Additional links */\n  [key: string]: string | undefined;\n}\n\n/**\n * Normalized error structure.\n */\nexport interface NormalizedError {\n  /** Error code */\n  code: string;\n  /** Error message */\n  message: string;\n  /** Field that caused the error */\n  field?: string;\n  /** Detailed error description */\n  details?: string;\n  /** HTTP status code */\n  status?: number;\n  /** Additional error context */\n  context?: Record<string, unknown>;\n}\n\n/**\n * Response format configuration.\n */\nexport interface ResponseFormatConfig {\n  /** Path to data in response */\n  dataPath?: string | string[];\n  /** Path to pagination info */\n  paginationPath?: string;\n  /** Path to meta info */\n  metaPath?: string;\n  /** Path to links */\n  linksPath?: string;\n  /** Path to included resources */\n  includedPath?: string;\n  /** Pagination field mapping */\n  paginationMapping?: {\n    currentPage?: string;\n    totalPages?: string;\n    pageSize?: string;\n    totalItems?: string;\n    hasNext?: string;\n    hasPrev?: string;\n    cursor?: string;\n    nextCursor?: string;\n    prevCursor?: string;\n  };\n  /** Error field mapping */\n  errorMapping?: {\n    code?: string;\n    message?: string;\n    field?: string;\n    details?: string;\n  };\n}\n\n/**\n * Predefined API response formats.\n */\nexport type ResponseFormat =\n  | 'standard'\n  | 'json-api'\n  | 'hal'\n  | 'spring'\n  | 'laravel'\n  | 'django'\n  | 'graphql'\n  | 'custom';\n\n// =============================================================================\n// Format Configurations\n// =============================================================================\n\n/**\n * Standard format configuration.\n */\nconst STANDARD_FORMAT: ResponseFormatConfig = {\n  dataPath: 'data',\n  paginationPath: 'pagination',\n  metaPath: 'meta',\n  linksPath: 'links',\n  paginationMapping: {\n    currentPage: 'page',\n    totalPages: 'totalPages',\n    pageSize: 'pageSize',\n    totalItems: 'total',\n    hasNext: 'hasNext',\n    hasPrev: 'hasPrev',\n  },\n};\n\n/**\n * JSON:API format configuration.\n */\nconst JSON_API_FORMAT: ResponseFormatConfig = {\n  dataPath: 'data',\n  paginationPath: 'meta',\n  metaPath: 'meta',\n  linksPath: 'links',\n  includedPath: 'included',\n  paginationMapping: {\n    currentPage: 'meta.page.number',\n    totalPages: 'meta.page.totalPages',\n    pageSize: 'meta.page.size',\n    totalItems: 'meta.page.totalElements',\n  },\n};\n\n/**\n * HAL format configuration.\n */\nconst HAL_FORMAT: ResponseFormatConfig = {\n  dataPath: '_embedded',\n  linksPath: '_links',\n  metaPath: 'page',\n  paginationMapping: {\n    currentPage: 'page.number',\n    totalPages: 'page.totalPages',\n    pageSize: 'page.size',\n    totalItems: 'page.totalElements',\n  },\n};\n\n/**\n * Spring Data format configuration.\n */\nconst SPRING_FORMAT: ResponseFormatConfig = {\n  dataPath: 'content',\n  paginationPath: '',\n  paginationMapping: {\n    currentPage: 'number',\n    totalPages: 'totalPages',\n    pageSize: 'size',\n    totalItems: 'totalElements',\n    hasNext: 'last',\n    hasPrev: 'first',\n  },\n};\n\n/**\n * Laravel format configuration.\n */\nconst LARAVEL_FORMAT: ResponseFormatConfig = {\n  dataPath: 'data',\n  paginationPath: '',\n  linksPath: 'links',\n  metaPath: 'meta',\n  paginationMapping: {\n    currentPage: 'current_page',\n    totalPages: 'last_page',\n    pageSize: 'per_page',\n    totalItems: 'total',\n  },\n};\n\n/**\n * Django REST Framework format configuration.\n */\nconst DJANGO_FORMAT: ResponseFormatConfig = {\n  dataPath: 'results',\n  paginationPath: '',\n  paginationMapping: {\n    totalItems: 'count',\n    nextCursor: 'next',\n    prevCursor: 'previous',\n  },\n};\n\n/**\n * GraphQL format configuration.\n */\nconst GRAPHQL_FORMAT: ResponseFormatConfig = {\n  dataPath: 'data',\n  errorMapping: {\n    code: 'extensions.code',\n    message: 'message',\n    field: 'path',\n  },\n};\n\nconst FORMAT_CONFIGS: Record<ResponseFormat, ResponseFormatConfig> = {\n  standard: STANDARD_FORMAT,\n  'json-api': JSON_API_FORMAT,\n  hal: HAL_FORMAT,\n  spring: SPRING_FORMAT,\n  laravel: LARAVEL_FORMAT,\n  django: DJANGO_FORMAT,\n  graphql: GRAPHQL_FORMAT,\n  custom: {},\n};\n\n// =============================================================================\n// Response Normalizer Class\n// =============================================================================\n\n/**\n * Response Normalizer for consistent API responses.\n *\n * @example\n * ```typescript\n * const normalizer = new ResponseNormalizer('json-api');\n *\n * // Normalize a JSON:API response\n * const normalized = normalizer.normalize(response);\n * console.log(normalized.data);\n * console.log(normalized.pagination);\n *\n * // Normalize errors\n * const errors = normalizer.normalizeErrors(errorResponse);\n * ```\n */\nexport class ResponseNormalizer {\n  private config: ResponseFormatConfig;\n\n  /**\n   * Create a new response normalizer.\n   *\n   * @param format - Response format or custom config\n   */\n  constructor(format: ResponseFormat | ResponseFormatConfig = 'standard') {\n    if (typeof format === 'string') {\n      this.config = FORMAT_CONFIGS[format];\n    } else {\n      this.config = format;\n    }\n  }\n\n  // ===========================================================================\n  // Normalization Methods\n  // ===========================================================================\n\n  /**\n   * Normalize a response to standard format.\n   *\n   * @param response - Raw API response\n   * @returns Normalized response\n   */\n  normalize<T = unknown>(response: unknown): NormalizedResponse<T> {\n    const data = this.extractData<T>(response);\n    const pagination = this.extractPagination(response);\n    const meta = this.extractMeta(response);\n    const links = this.extractLinks(response);\n    const included = this.extractIncluded(response);\n\n    return {\n      data,\n      ...(pagination && { pagination }),\n      ...(meta && { meta }),\n      ...(links && { links }),\n      ...(included && { included }),\n    };\n  }\n\n  /**\n   * Normalize error response.\n   *\n   * @param response - Error response\n   * @returns Normalized errors\n   */\n  normalizeErrors(response: unknown): NormalizedError[] {\n    // Handle array of errors\n    if (Array.isArray(response)) {\n      return response.map(err => this.normalizeError(err));\n    }\n\n    // Handle single error\n    if (this.isErrorObject(response)) {\n      return [this.normalizeError(response)];\n    }\n\n    // Handle nested errors\n    const errorsPath = ['errors', 'error', 'message'];\n    for (const path of errorsPath) {\n      const extracted = this.getNestedValue(response, path);\n      if (extracted !== null && extracted !== undefined) {\n        if (Array.isArray(extracted)) {\n          return extracted.map(err => this.normalizeError(err));\n        }\n        return [this.normalizeError(extracted)];\n      }\n    }\n\n    // Fallback to generic error\n    return [\n      {\n        code: 'UNKNOWN_ERROR',\n        message: String(response),\n      },\n    ];\n  }\n\n  /**\n   * Update configuration.\n   */\n  setConfig(config: Partial<ResponseFormatConfig>): void {\n    this.config = { ...this.config, ...config };\n  }\n\n  // ===========================================================================\n  // Extraction Methods\n  // ===========================================================================\n\n  /**\n   * Get current configuration.\n   */\n  getConfig(): ResponseFormatConfig {\n    return { ...this.config };\n  }\n\n  /**\n   * Normalize a single error.\n   */\n  private normalizeError(error: unknown): NormalizedError {\n    if (typeof error === 'string') {\n      return { code: 'ERROR', message: error };\n    }\n\n    if (!this.isObject(error)) {\n      return { code: 'ERROR', message: String(error) };\n    }\n\n    const mapping = this.config.errorMapping ?? {};\n\n    return {\n      code:\n        (this.getNestedValue(error, mapping.code ?? 'code') as string) ??\n        (this.getNestedValue(error, 'status') as string) ??\n        'ERROR',\n      message:\n        (this.getNestedValue(error, mapping.message ?? 'message') as string) ??\n        (this.getNestedValue(error, 'error') as string) ??\n        'Unknown error',\n      field: this.getNestedValue(error, mapping.field ?? 'field') as string | undefined,\n      details: this.getNestedValue(error, mapping.details ?? 'details') as string | undefined,\n      status: this.getNestedValue(error, 'status') as number | undefined,\n      context: this.extractErrorContext(error),\n    };\n  }\n\n  /**\n   * Extract data from response.\n   */\n  private extractData<T>(response: unknown): T {\n    const paths = this.config.dataPath;\n\n    if (paths === undefined || paths === null) {\n      return response as T;\n    }\n\n    const pathArray = Array.isArray(paths) ? paths : [paths];\n\n    for (const path of pathArray) {\n      const data = this.getNestedValue(response, path);\n      if (data !== undefined) {\n        return data as T;\n      }\n    }\n\n    return response as T;\n  }\n\n  /**\n   * Extract pagination from response.\n   */\n  private extractPagination(response: unknown): NormalizedPagination | undefined {\n    const mapping = this.config.paginationMapping;\n    if (!mapping) return undefined;\n\n    const paginationSource = (this.config.paginationPath != null && this.config.paginationPath !== '')\n      ? this.getNestedValue(response, this.config.paginationPath) ?? response\n      : response;\n\n    const currentPage = this.getNestedValue(\n      paginationSource,\n      mapping.currentPage ?? 'currentPage'\n    );\n    const totalItems = this.getNestedValue(\n      paginationSource,\n      mapping.totalItems ?? 'total'\n    );\n\n    // If no pagination info found, return undefined\n    if (currentPage === undefined && totalItems === undefined) {\n      return undefined;\n    }\n\n    const pageSize =\n      (this.getNestedValue(paginationSource, mapping.pageSize ?? 'pageSize') as number) ?? 20;\n    const totalItemsCount = this.getNestedValue(paginationSource, mapping.totalItems ?? 'totalItems') as number | undefined;\n    const totalPages =\n      (this.getNestedValue(paginationSource, mapping.totalPages ?? 'totalPages') as number) ??\n      (totalItemsCount !== undefined && totalItemsCount > 0 && pageSize > 0 ? Math.ceil(totalItemsCount / pageSize) : 1);\n\n    let hasNextPage: boolean;\n    let hasPrevPage: boolean;\n\n    if (mapping.hasNext !== undefined && mapping.hasNext !== null && mapping.hasNext !== '') {\n      const hasNextValue = this.getNestedValue(paginationSource, mapping.hasNext);\n      // Handle Spring's 'last' field (inverted)\n      hasNextPage = mapping.hasNext === 'last' ? (hasNextValue !== true) : (hasNextValue === true);\n    } else {\n      hasNextPage = ((currentPage as number) ?? 1) < totalPages;\n    }\n\n    if (mapping.hasPrev !== undefined && mapping.hasPrev !== null && mapping.hasPrev !== '') {\n      const hasPrevValue = this.getNestedValue(paginationSource, mapping.hasPrev);\n      // Handle Spring's 'first' field (inverted)\n      hasPrevPage = mapping.hasPrev === 'first' ? (hasPrevValue !== true) : (hasPrevValue === true);\n    } else {\n      hasPrevPage = ((currentPage as number) ?? 1) > 1;\n    }\n\n    return {\n      currentPage: (currentPage as number) ?? 1,\n      totalPages: (totalPages) ?? 1,\n      pageSize: (pageSize) ?? 20,\n      totalItems: (totalItems as number) ?? 0,\n      hasNextPage,\n      hasPrevPage,\n      cursor: this.getNestedValue(paginationSource, mapping.cursor ?? 'cursor') as string | undefined,\n      nextCursor: this.getNestedValue(\n        paginationSource,\n        mapping.nextCursor ?? 'nextCursor'\n      ) as string | undefined,\n      prevCursor: this.getNestedValue(\n        paginationSource,\n        mapping.prevCursor ?? 'prevCursor'\n      ) as string | undefined,\n    };\n  }\n\n  /**\n   * Extract meta information from response.\n   */\n  private extractMeta(response: unknown): Record<string, unknown> | undefined {\n    if (this.config.metaPath === undefined || this.config.metaPath === null || this.config.metaPath === '') return undefined;\n\n    const meta = this.getNestedValue(response, this.config.metaPath);\n\n    if (meta !== undefined && meta !== null && this.isObject(meta)) {\n      // Filter out pagination fields that are handled separately\n      const { page: _page, number: _number, size: _size, totalElements: _totalElements, totalPages: _totalPages, ...rest } = meta;\n      return Object.keys(rest).length > 0 ? rest : undefined;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Extract links from response.\n   */\n  private extractLinks(response: unknown): NormalizedLinks | undefined {\n    if (this.config.linksPath === undefined || this.config.linksPath === null || this.config.linksPath === '') return undefined;\n\n    const links = this.getNestedValue(response, this.config.linksPath);\n\n    if (links === undefined || links === null || !this.isObject(links)) return undefined;\n\n    // Normalize HAL links\n    const normalizedLinks: NormalizedLinks = {};\n\n    for (const [key, value] of Object.entries(links)) {\n      if (typeof value === 'string') {\n        normalizedLinks[key] = value;\n      } else if (this.isObject(value) && 'href' in value) {\n        normalizedLinks[key] = (value as { href: string }).href;\n      }\n    }\n\n    return Object.keys(normalizedLinks).length > 0 ? normalizedLinks : undefined;\n  }\n\n  // ===========================================================================\n  // Utility Methods\n  // ===========================================================================\n\n  /**\n   * Extract included/embedded resources.\n   */\n  private extractIncluded(\n    response: unknown\n  ): Record<string, unknown[]> | undefined {\n    if (this.config.includedPath === undefined || this.config.includedPath === null || this.config.includedPath === '') return undefined;\n\n    const included = this.getNestedValue(response, this.config.includedPath);\n\n    if (included === undefined || included === null) return undefined;\n\n    // Handle JSON:API included format (array of resources)\n    if (Array.isArray(included)) {\n      const grouped: Record<string, unknown[]> = {};\n\n      for (const item of included) {\n        if (this.isObject(item) && 'type' in item) {\n          const {type} = (item as { type: string });\n          grouped[type] ??= [];\n          grouped[type].push(item);\n        }\n      }\n\n      return Object.keys(grouped).length > 0 ? grouped : undefined;\n    }\n\n    // Handle HAL _embedded format (object with arrays)\n    if (this.isObject(included)) {\n      return included as Record<string, unknown[]>;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Extract additional context from error.\n   */\n  private extractErrorContext(error: Record<string, unknown>): Record<string, unknown> | undefined {\n    const contextFields = [\n      'extensions',\n      'context',\n      'metadata',\n      'trace',\n      'stack',\n    ];\n    const context: Record<string, unknown> = {};\n\n    for (const field of contextFields) {\n      const value = error[field];\n      if (value !== undefined) {\n        context[field] = value;\n      }\n    }\n\n    return Object.keys(context).length > 0 ? context : undefined;\n  }\n\n  /**\n   * Get nested value from object using dot notation.\n   */\n  private getNestedValue(obj: unknown, path: string): unknown {\n    if (!path || !this.isObject(obj)) return undefined;\n\n    const keys = path.split('.');\n    let current: unknown = obj;\n\n    for (const key of keys) {\n      if (!this.isObject(current)) return undefined;\n      current = (current)[key];\n    }\n\n    return current;\n  }\n\n  /**\n   * Check if value is a plain object.\n   */\n  private isObject(value: unknown): value is Record<string, unknown> {\n    return typeof value === 'object' && value !== null && !Array.isArray(value);\n  }\n\n  /**\n   * Check if value is an error object.\n   */\n  private isErrorObject(value: unknown): boolean {\n    if (!this.isObject(value)) return false;\n    return 'message' in value || 'error' in value || 'code' in value;\n  }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a new response normalizer.\n *\n * @param format - Response format or custom config\n * @returns ResponseNormalizer instance\n */\nexport function createResponseNormalizer(\n  format: ResponseFormat | ResponseFormatConfig = 'standard'\n): ResponseNormalizer {\n  return new ResponseNormalizer(format);\n}\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Quick normalize function for one-off use.\n */\nexport function normalizeResponse<T = unknown>(\n  response: unknown,\n  format: ResponseFormat = 'standard'\n): NormalizedResponse<T> {\n  const normalizer = new ResponseNormalizer(format);\n  return normalizer.normalize<T>(response);\n}\n\n/**\n * Quick normalize errors function.\n */\nexport function normalizeErrors(\n  response: unknown,\n  format: ResponseFormat = 'standard'\n): NormalizedError[] {\n  const normalizer = new ResponseNormalizer(format);\n  return normalizer.normalizeErrors(response);\n}\n"],"names":["STANDARD_FORMAT","JSON_API_FORMAT","HAL_FORMAT","SPRING_FORMAT","LARAVEL_FORMAT","DJANGO_FORMAT","GRAPHQL_FORMAT","FORMAT_CONFIGS","ResponseNormalizer","format","response","data","pagination","meta","links","included","err","errorsPath","path","extracted","config","error","mapping","paths","pathArray","paginationSource","currentPage","totalItems","pageSize","totalItemsCount","totalPages","hasNextPage","hasPrevPage","hasNextValue","hasPrevValue","_page","_number","_size","_totalElements","_totalPages","rest","normalizedLinks","key","value","grouped","item","type","contextFields","context","field","obj","keys","current","createResponseNormalizer","normalizeResponse","normalizeErrors"],"mappings":"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"}