Files
SkyArtShop/website/public/assets/js/archive/api-enhanced.js

161 lines
4.0 KiB
JavaScript
Raw Normal View History

2026-01-04 17:52:37 -06:00
/**
* API Integration Improvements
* Enhanced API client with retry logic and better error handling
*/
(function () {
"use strict";
class EnhancedAPIClient {
constructor(baseURL = "") {
this.baseURL = baseURL;
this.retryAttempts = 3;
this.retryDelay = 1000;
this.cache = new Map();
this.cacheTimeout = 5 * 60 * 1000; // 5 minutes
}
async requestWithRetry(endpoint, options = {}, attempt = 1) {
try {
const response = await fetch(this.baseURL + endpoint, {
...options,
headers: {
"Content-Type": "application/json",
...options.headers,
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const contentType = response.headers.get("content-type");
if (contentType?.includes("application/json")) {
return await response.json();
}
return await response.text();
} catch (error) {
// Retry logic for network errors
if (attempt < this.retryAttempts && this.isRetryableError(error)) {
await this.delay(this.retryDelay * attempt);
return this.requestWithRetry(endpoint, options, attempt + 1);
}
throw error;
}
}
isRetryableError(error) {
// Retry on network errors or 5xx server errors
return (
error.message.includes("Failed to fetch") ||
error.message.includes("NetworkError") ||
error.message.includes("500") ||
error.message.includes("502") ||
error.message.includes("503")
);
}
delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
getCacheKey(endpoint, params) {
return endpoint + JSON.stringify(params || {});
}
getFromCache(key) {
const cached = this.cache.get(key);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data;
}
this.cache.delete(key);
return null;
}
setCache(key, data) {
this.cache.set(key, {
data,
timestamp: Date.now(),
});
}
clearCache() {
this.cache.clear();
}
async get(endpoint, params = {}, useCache = true) {
const cacheKey = this.getCacheKey(endpoint, params);
if (useCache) {
const cached = this.getFromCache(cacheKey);
if (cached) return cached;
}
const queryString = new URLSearchParams(params).toString();
const url = queryString ? `${endpoint}?${queryString}` : endpoint;
const data = await this.requestWithRetry(url, { method: "GET" });
if (useCache) {
this.setCache(cacheKey, data);
}
return data;
}
async post(endpoint, body = {}) {
return this.requestWithRetry(endpoint, {
method: "POST",
body: JSON.stringify(body),
});
}
async put(endpoint, body = {}) {
return this.requestWithRetry(endpoint, {
method: "PUT",
body: JSON.stringify(body),
});
}
async delete(endpoint) {
return this.requestWithRetry(endpoint, { method: "DELETE" });
}
// Product methods with caching
async getProducts(params = {}) {
return this.get("/api/products", params, true);
}
async getProduct(id) {
return this.get(`/api/products/${id}`, {}, true);
}
async getFeaturedProducts(limit = 4) {
return this.get("/api/products/featured", { limit }, true);
}
// Pages methods
async getPages() {
return this.get("/api/pages", {}, true);
}
async getPage(slug) {
return this.get(`/api/pages/${slug}`, {}, true);
}
// Menu methods
async getMenu() {
return this.get("/api/menu", {}, true);
}
}
// Replace global API client if it exists
if (window.API) {
const oldAPI = window.API;
window.API = new EnhancedAPIClient(oldAPI.baseURL || "");
} else {
window.API = new EnhancedAPIClient();
}
})();