@remcostoeten/fync
Version:
A unified TypeScript library for easy access to popular APIs (GitHub, Spotify, GitLab, etc.)
119 lines (118 loc) • 3.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createHttpClient = createHttpClient;
var _exports = require("../../core/errors/exports");
function createHttpClient(config) {
// Initialize error handling system
(0, _exports.initializeErrorHandling)();
// Create error handler with Spotify-specific retry config
const errorHandler = new _exports.HttpErrorHandler({
maxAttempts: 3,
baseDelay: 1000,
maxDelay: 30000,
backoffMultiplier: 2,
retryableStatuses: [408, 429, 500, 502, 503, 504]
});
const cache = new Map();
function getCacheKey(url, options = {}) {
return `${url}:${JSON.stringify(options)}`;
}
function isExpired(timestamp, ttl) {
return Date.now() - timestamp > ttl;
}
function getFromCache(key) {
const cached = cache.get(key);
if (!cached) return null;
if (isExpired(cached.timestamp, cached.ttl)) {
cache.delete(key);
return null;
}
return cached.data;
}
function setCache(key, data, ttl) {
cache.set(key, {
data,
timestamp: Date.now(),
ttl
});
}
async function makeRequest(url, method, data, options = {}) {
const shouldCache = options.cache !== false && config.cache !== false;
const cacheTTL = options.cacheTTL || config.cacheTTL || 300000;
// Check cache for GET requests
if (shouldCache && method === "GET") {
const cacheKey = getCacheKey(url, options);
const cached = getFromCache(cacheKey);
if (cached) return cached;
}
// Use error handler to execute the request with retry logic
const result = await errorHandler.execute(async () => {
const fetchOptions = {
method,
headers: {
...(config.accessToken && {
"Authorization": `Bearer ${config.accessToken}`
}),
"Content-Type": "application/json",
...options.headers
}
};
if (data && (method === "POST" || method === "PUT" || method === "DELETE")) {
fetchOptions.body = JSON.stringify(data);
}
const response = await fetch(url, fetchOptions);
if (!response.ok) {
// Create a structured error message that our transformers can understand
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
try {
const errorData = await response.json();
if (errorData.error) {
if (typeof errorData.error === "string") {
errorMessage = errorData.error;
} else {
errorMessage = errorData.error.message || errorMessage;
}
}
} catch {
// Use the HTTP status error message
}
throw new Error(errorMessage);
}
if (response.status === 204) {
return undefined;
}
return await response.json();
}, {
service: "spotify",
endpoint: url,
method,
userAgent: config.userAgent || `@remcostoeten/fync/3.3.0`
});
// Cache successful GET requests
if (shouldCache && method === "GET") {
const cacheKey = getCacheKey(url, options);
setCache(cacheKey, result, cacheTTL);
}
return result;
}
function get(url, options) {
return makeRequest(url, "GET", undefined, options);
}
function post(url, data, options) {
return makeRequest(url, "POST", data, options);
}
function put(url, data, options) {
return makeRequest(url, "PUT", data, options);
}
function deleteRequest(url, data, options) {
return makeRequest(url, "DELETE", data, options);
}
return {
get,
post,
put,
delete: deleteRequest
};
}