79 lines
3.0 KiB
JavaScript
79 lines
3.0 KiB
JavaScript
(function (root, factory) {
|
|
const api = factory();
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
|
else root.liveDataStatus = api;
|
|
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
|
const feeds = [
|
|
['context', 'Work'],
|
|
['notifications', 'Updates'],
|
|
['events', 'Activity'],
|
|
];
|
|
|
|
function boundedSeconds(value) {
|
|
const seconds = Number(value);
|
|
return Number.isFinite(seconds) && seconds >= 0 ? Math.min(Math.round(seconds), 86400) : null;
|
|
}
|
|
|
|
function describe(freshness = {}) {
|
|
const sections = freshness.sections || {};
|
|
const hasSectionData = feeds.some(([key]) => Object.prototype.hasOwnProperty.call(sections, key));
|
|
const described = feeds.map(([key, label]) => {
|
|
const section = sections[key] || {};
|
|
const state = section.revalidating ? 'refreshing' :
|
|
(section.stale || section.degraded ? 'delayed' : 'live');
|
|
return { key, label, state, ageSeconds: boundedSeconds(section.age_seconds) };
|
|
});
|
|
const delayed = described.filter(feed => feed.state === 'delayed');
|
|
const refreshing = described.filter(feed => feed.state === 'refreshing');
|
|
let summary = hasSectionData ? 'Live' : 'Live data unavailable';
|
|
if (delayed.length === 1) summary = delayed[0].label + ' delayed';
|
|
else if (delayed.length > 1) summary = delayed.length + ' data feeds delayed';
|
|
else if (refreshing.length === 1) summary = refreshing[0].label + ' refreshing';
|
|
else if (refreshing.length > 1) summary = 'Refreshing live data';
|
|
const retryValues = described.map(feed => {
|
|
const section = sections[feed.key] || {};
|
|
return boundedSeconds(section.retry_in_seconds);
|
|
}).filter(value => value !== null && value > 0);
|
|
const aggregateRetry = boundedSeconds(freshness.retry_in_seconds);
|
|
if (aggregateRetry !== null && aggregateRetry > 0) retryValues.push(aggregateRetry);
|
|
return {
|
|
summary,
|
|
feeds: described,
|
|
nextRetrySeconds: retryValues.length ? Math.min(...retryValues) : null,
|
|
};
|
|
}
|
|
|
|
function createRefreshController({ button, output, refresh, onState = () => {} }) {
|
|
let pending = null;
|
|
function run() {
|
|
if (pending) return pending;
|
|
button.disabled = true;
|
|
output.textContent = 'Refreshing live data…';
|
|
onState('refreshing');
|
|
let request;
|
|
try {
|
|
request = refresh();
|
|
} catch (error) {
|
|
request = Promise.reject(error);
|
|
}
|
|
pending = Promise.resolve(request).then(result => {
|
|
if (!result) throw new Error('Live data remains unavailable.');
|
|
output.textContent = 'Live data refreshed.';
|
|
onState('success');
|
|
return result;
|
|
}).catch(error => {
|
|
output.textContent = error && error.message ? error.message : 'Live data refresh failed.';
|
|
onState('error');
|
|
return null;
|
|
}).finally(() => {
|
|
button.disabled = false;
|
|
pending = null;
|
|
});
|
|
return pending;
|
|
}
|
|
return { run };
|
|
}
|
|
|
|
return { describe, createRefreshController };
|
|
});
|