File size: 3,796 Bytes
b190b45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
 * API Client Error Handling Fix
 * Add this to your api-client.js file
 */

class APIClient {
  constructor(baseURL = '') {
    this.baseURL = baseURL;
    this.errors = [];
  }

  /**
   * Fixed error handling with proper null checks
   */
  _getFallbackData(error) {
    // Ensure error is an object
    const safeError = error || {};
    
    return {
      data: [],
      success: false,
      error: true,
      message: safeError.message || 'Failed to fetch data',
      timestamp: Date.now(),
      details: {
        name: safeError.name || 'Error',
        stack: safeError.stack || 'No stack trace available'
      }
    };
  }

  /**
   * Fixed error logging with proper null checks
   */
  _logError(endpoint, method, error, duration = 0) {
    const errorLog = {
      endpoint: endpoint || 'unknown',
      method: method || 'GET',
      message: error?.message || 'Unknown error',
      duration: duration,
      timestamp: new Date().toISOString()
    };
    
    this.errors.push(errorLog);
    console.error('[APIClient] Error logged:', errorLog);
    
    // Keep only last 50 errors
    if (this.errors.length > 50) {
      this.errors = this.errors.slice(-50);
    }
  }

  /**
   * Fixed request method with comprehensive error handling
   */
  async request(endpoint, options = {}) {
    const startTime = Date.now();
    const method = options.method || 'GET';
    
    try {
      const url = endpoint.startsWith('http') 
        ? endpoint 
        : `${this.baseURL}${endpoint}`;
      
      const response = await fetch(url, {
        ...options,
        headers: {
          'Content-Type': 'application/json',
          ...options.headers
        }
      });

      const duration = Date.now() - startTime;

      if (!response.ok) {
        const errorText = await response.text().catch(() => 'No error message');
        const error = new Error(`HTTP ${response.status}: ${errorText}`);
        error.status = response.status;
        error.statusText = response.statusText;
        
        this._logError(endpoint, method, error, duration);
        
        // Return fallback data instead of throwing
        return this._getFallbackData(error);
      }

      const data = await response.json();
      return data;

    } catch (error) {
      const duration = Date.now() - startTime;
      
      // Handle different error types
      const safeError = error || new Error('Unknown error');
      
      if (safeError.name === 'AbortError') {
        safeError.message = 'Request timeout';
      } else if (!safeError.message) {
        safeError.message = 'Network error or invalid response';
      }
      
      this._logError(endpoint, method, safeError, duration);
      
      // Return fallback data instead of throwing
      return this._getFallbackData(safeError);
    }
  }

  /**
   * GET request wrapper
   */
  async get(endpoint, options = {}) {
    return this.request(endpoint, { ...options, method: 'GET' });
  }

  /**
   * POST request wrapper
   */
  async post(endpoint, data, options = {}) {
    return this.request(endpoint, {
      ...options,
      method: 'POST',
      body: JSON.stringify(data)
    });
  }

  /**
   * PUT request wrapper
   */
  async put(endpoint, data, options = {}) {
    return this.request(endpoint, {
      ...options,
      method: 'PUT',
      body: JSON.stringify(data)
    });
  }

  /**
   * DELETE request wrapper
   */
  async delete(endpoint, options = {}) {
    return this.request(endpoint, { ...options, method: 'DELETE' });
  }

  /**
   * Get error history
   */
  getErrors() {
    return [...this.errors];
  }

  /**
   * Clear error history
   */
  clearErrors() {
    this.errors = [];
  }
}

// Export singleton instance
export const api = new APIClient('/api');
export default api;