All files / src/api/inventory/utils errorHandling.ts

100% Statements 57/57
100% Branches 17/17
100% Functions 1/1
100% Lines 57/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 581x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 14x 14x 8x 8x 8x 8x 7x 7x 7x 7x 5x 5x 8x 8x 8x 8x 1x 8x 14x 5x 5x  
/**
 * @file errorHandling.ts
 * @module api/inventory/utils/errorHandling
 *
 * @summary
 * Error extraction and user-friendly message handling.
 * Converts API errors into meaningful messages for UI display.
 *
 * @enterprise
 * - Extracts structured error info from Axios responses
 * - HTTP status-specific fallback messages
 * - User-friendly error messages (no technical jargon)
 * - Consistent error handling across all mutations
 */
 
import { isRecord } from './typeGuards';
import { pickString, pickNumber } from './fieldPickers';
 
/**
 * Extract user-friendly error message from network response or exception.
 * Handles Axios-like error shapes with structured response.data.
 * Provides HTTP status-specific fallback messages.
 *
 * @param e - Error from network call (Axios error or generic Error)
 * @returns User-friendly error message for UI display
 *
 * @example
 * ```typescript
 * try {
 *   await http.post('/api/items', data);
 * } catch (error) {
 *   const msg = errorMessage(error); // "Access denied - Admin permission required"
 * }
 * ```
 */
export const errorMessage = (e: unknown): string => {
  // Axios-like error shape with response.data.{message|error}
  if (isRecord(e) && isRecord(e.response)) {
    const resp = e.response as Record<string, unknown>;
    const status = pickNumber(resp, 'status');
 
    if (isRecord(resp.data)) {
      const d = resp.data as Record<string, unknown>;
      const msg = pickString(d, 'message') ?? pickString(d, 'error');
      if (msg) return msg;
    }
 
    // Fallback to HTTP status message if available
    if (status === 403) return 'Access denied - Admin permission required';
    if (status === 401) return 'Not authenticated - Please log in';
    if (status === 404) return 'Item not found';
    if (status === 409) return 'Conflict - Name already exists';
    if (status === 400) return 'Invalid input';
  }
  if (e instanceof Error) return e.message;
  return 'Request failed';
};