_wrapperVersion = '1.0.0'; _minApiVersion = '1.0.0'; _maxApiVersion = '1.0.0'; _defaultTTL = 60000; _apiConfig = { basePath: '/api/v1/' }; if (!window.localStorage) { console.warn('Local Storage is not available, some features may not work'); } // Generic driver functions let _api = { get: async function (path) { const options = { headers: new Headers({ 'content-type': 'application/json' }) }; const response = await fetch(_apiConfig.basePath + path, options); // Handle the response if (!response.ok) { _testPageFail(response.statusText); return; } const result = await response.json(); // Handle the result, was json valid? if (!result) { _testPageFail('Invalid JSON response'); return; } return result; }, post: async function (path, data) { const options = { method: 'POST', headers: new Headers({ 'content-type': 'application/json' }), body: JSON.stringify(data) }; const response = await fetch(_apiConfig.basePath + path, options); // Handle the response if (!response.ok) { _testPageFail(response.statusText); return; } const result = await response.json(); // Handle the result, was json valid? if (!result) { _testPageFail('Invalid JSON response'); return; } return result; }, getAsync: function (path, callback) { const options = { headers: new Headers({ 'content-type': 'application/json' }) }; fetch(_apiConfig.basePath + path, options) .then((response) => response.json()) .then((data) => callback(data)) .catch((error) => _testPageFail(error)); } }; function getApiDescriptionByTable(tableName) { const keyDesc = `desc:${tableName}`; const keyTime = `${keyDesc}:time`; const keyTTL = `${keyDesc}:ttl`; // Retrieve cached data const description = JSON.parse(localStorage.getItem(keyDesc)); const timeCreated = parseInt(localStorage.getItem(keyTime)); const ttl = parseInt(localStorage.getItem(keyTTL)); // Check if valid cached data exists if (description && timeCreated && ttl) { const currentTime = Date.now(); const age = currentTime - parseInt(timeCreated, 10); if (age < parseInt(ttl, 10)) { // Return cached data immediately return Promise.resolve(description); } else { console.warn('Cached description expired; fetching new data'); // Fetch new data, update cache, and return it return fetchAndUpdateCache(tableName); } } else { console.warn('No cached description; fetching from server'); // Fetch data, update cache, and return it return fetchAndUpdateCache(tableName); } function fetchAndUpdateCache(tableName) { return _api .get(`${tableName}/describe`) .then((data) => { if (data) { // Update local storage with new data localStorage.setItem(keyDesc, JSON.stringify(data)); localStorage.setItem(keyTime, Date.now().toString()); localStorage.setItem(keyTTL, '60000'); // 60 seconds TTL } return data; // Return the fetched data }) .catch((error) => { console.error('Failed to fetch description:', error); // Fallback to cached data if available (even if expired) return description || null; }); } } function returnTableDataByTableName(tableName) { return _api.get(tableName); } function returnTableDataByTableNameWithSearch(tableName, search) { return _api.get(tableName + '?search=' + search); } function returnTableDataByTableNameAsync(tableName, callback) { _api.getAsync(tableName, callback); } async function getCountByTable(tableName) { // Stored in `data:count:${tableName}` let result = await _api.get(tableName + '?count=true'); if (typeof result !== 'number') { _testPageWarn('Count was not a number, was: ' + result); console.warn('Count was not a number, was: ' + result); return -1; } return result; } function getRowsByTableAndColumnList(tableName, columnList) { //return _api.get(tableName + '/rows/' + columnList.join(',')) return undefined; } function _testPageFail(reason) { document.getElementById('heroStatus').classList.remove('is-success'); document.getElementById('heroStatus').classList.add('is-danger'); document.getElementById('heroExplainer').innerHTML = 'API Wrapper Test Failed, reason: ' + reason; } function _testPageWarn(reason) { document.getElementById('heroStatus').classList.remove('is-success'); document.getElementById('heroStatus').classList.add('is-warning'); document.getElementById('heroExplainer').innerHTML = 'API Wrapper Test Warning, reason: ' + reason; } function getServerVersion() { return _api.get('version'); } function createEntry(tableName, data) { invalidateCache(tableName); return _api.post(tableName, data); } function invalidateCache(tableName) { const keyDesc = `desc:${tableName}`; const keyTime = `${keyDesc}:time`; const keyTTL = `${keyDesc}:ttl`; localStorage.removeItem(keyDesc); localStorage.removeItem(keyTime); localStorage.removeItem(keyTTL); }