82 lines
2.1 KiB
JavaScript
82 lines
2.1 KiB
JavaScript
export const ASYNC_BASE_STATES = Object.freeze([
|
|
"initial-loading",
|
|
"success",
|
|
"empty",
|
|
"terminal-error",
|
|
]);
|
|
|
|
export const ASYNC_OVERLAYS = Object.freeze([
|
|
"refreshing",
|
|
"stale-degraded",
|
|
"mutation-pending",
|
|
"mutation-conflict",
|
|
]);
|
|
|
|
/**
|
|
* @typedef {{
|
|
* data?: unknown,
|
|
* isInitialLoading?: boolean,
|
|
* failure?: import("../../contracts/errors.js").ApiFailure,
|
|
* isFetching?: boolean,
|
|
* isStale?: boolean,
|
|
* isDegraded?: boolean,
|
|
* isMutationPending?: boolean,
|
|
* hasMutationConflict?: boolean
|
|
* }} AsyncSignals
|
|
*/
|
|
|
|
/** @param {AsyncSignals} signals */
|
|
export function deriveAsyncState(signals) {
|
|
const hasData = signals.data !== undefined && signals.data !== null;
|
|
const empty =
|
|
hasData &&
|
|
((Array.isArray(signals.data) && signals.data.length === 0) ||
|
|
signals.data === "");
|
|
|
|
let base;
|
|
if (signals.isInitialLoading && !hasData) {
|
|
base = "initial-loading";
|
|
} else if (signals.failure && !hasData) {
|
|
base = "terminal-error";
|
|
} else if (empty) {
|
|
base = "empty";
|
|
} else if (hasData) {
|
|
base = "success";
|
|
} else {
|
|
base = "initial-loading";
|
|
}
|
|
|
|
const overlay = Object.freeze({
|
|
refreshing: Boolean(signals.isFetching && hasData),
|
|
staleDegraded: Boolean(signals.isStale && signals.isDegraded && hasData),
|
|
mutationPending: Boolean(signals.isMutationPending && hasData),
|
|
mutationConflict: Boolean(signals.hasMutationConflict && hasData),
|
|
});
|
|
|
|
const state = {
|
|
base,
|
|
data: base === "success" || base === "empty" ? signals.data : undefined,
|
|
failure: base === "terminal-error" ? signals.failure : undefined,
|
|
overlay,
|
|
indicator: selectOverlayIndicator(overlay),
|
|
};
|
|
|
|
return Object.freeze(state);
|
|
}
|
|
|
|
/**
|
|
* @param {{
|
|
* refreshing: boolean,
|
|
* staleDegraded: boolean,
|
|
* mutationPending: boolean,
|
|
* mutationConflict: boolean
|
|
* }} overlay
|
|
*/
|
|
export function selectOverlayIndicator(overlay) {
|
|
if (overlay.mutationConflict) return "mutation-conflict";
|
|
if (overlay.mutationPending) return "mutation-pending";
|
|
if (overlay.staleDegraded) return "stale-degraded";
|
|
if (overlay.refreshing) return "refreshing";
|
|
return null;
|
|
}
|