238 lines
6.2 KiB
JavaScript
238 lines
6.2 KiB
JavaScript
|
_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) {
|
||
|
console.error('Failed to fetch:', response.statusText);
|
||
|
_testPageFail(response.statusText);
|
||
|
return;
|
||
|
}
|
||
|
const result = await response.json();
|
||
|
// Handle the result, was json valid?
|
||
|
if (!result) {
|
||
|
// Is it a number instead?
|
||
|
if (typeof result === 'number') {
|
||
|
return result;
|
||
|
}
|
||
|
console.error('Invalid JSON response');
|
||
|
_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;
|
||
|
},
|
||
|
delete: async function (path, data) {
|
||
|
const options = {
|
||
|
method: 'DELETE',
|
||
|
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;
|
||
|
},
|
||
|
patch: async function (path, data) {
|
||
|
const options = {
|
||
|
method: 'PATCH',
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
function updateRow(tableName, id, data) {
|
||
|
invalidateCache(tableName);
|
||
|
return _api.patch(`${tableName}`, { id: id, ...data });
|
||
|
}
|
||
|
|
||
|
function deleteRow(tableName, id) {
|
||
|
invalidateCache(tableName);
|
||
|
return _api.delete(`${tableName}`, { id: id });
|
||
|
}
|
||
|
|
||
|
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, search="", orderBy="asc", sort="", take=-1, skip=0) {
|
||
|
var orderBy = orderBy.toLowerCase();
|
||
|
if(orderBy == "") {
|
||
|
orderBy = "asc";
|
||
|
}
|
||
|
var baseString = tableName + "?order=" + orderBy;
|
||
|
if(sort && sort.length > 0) {
|
||
|
baseString += "&sort=" + sort;
|
||
|
}
|
||
|
if(take > 0) {
|
||
|
baseString += "&take=" + take;
|
||
|
}
|
||
|
if(skip > 0) {
|
||
|
baseString += "&skip=" + skip;
|
||
|
}
|
||
|
|
||
|
if (search && search.length > 0) {
|
||
|
return _api.get(baseString + '&search=' + search);
|
||
|
} else {
|
||
|
return _api.get(baseString);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function getCountByTable(tableName, search="") {
|
||
|
let baseString = tableName + '?count=true';
|
||
|
if (search && search.length > 0) {
|
||
|
baseString += '&search=' + search;
|
||
|
}
|
||
|
// Stored in `data:count:${tableName}`
|
||
|
let result = await _api.get(baseString);
|
||
|
console.debug('Count result:', result);
|
||
|
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 _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);
|
||
|
}
|