@hazae41/glacier
Version:
Yet another React data (re)fetching library
132 lines (129 loc) • 5.39 kB
JavaScript
import { Some } from '@hazae41/option';
import { Err, Ok } from '@hazae41/result';
import { Arrays } from '../../../libs/arrays/arrays.mjs';
import { shouldUseCacheIfFresh, shouldUseCacheIfStale, shouldUseNetwork } from '../../../libs/request/index.mjs';
import { AbortSignals } from '../../../libs/signals/index.mjs';
import { Time } from '../../../libs/time/time.mjs';
import { core, MissingFetcherError } from '../../core/core.mjs';
import { Scrollable } from './helper.mjs';
function createScrollableQuery(settings) {
if (settings.fetcher == null)
return new ScrollableFetcherlessQuery(settings);
return new ScrollableFetcherfulQuery(settings);
}
class ScrollableFetcherfulQuery {
settings;
cacheKey;
constructor(settings) {
this.settings = settings;
this.cacheKey = Scrollable.getCacheKey(settings.key);
}
get state() {
return core.getOrThrow(this.cacheKey, this.settings);
}
get aborter() {
return core.getAborterSync(this.cacheKey);
}
async mutateOrThrow(mutator) {
return await core.mutateOrThrow(this.cacheKey, mutator, this.settings);
}
async deleteOrThrow() {
return await core.deleteOrThrow(this.cacheKey, this.settings);
}
async normalizeOrThrow(fetched, more) {
if (more.shallow)
return;
await this.mutateOrThrow(() => new Some(fetched));
}
async fetchOrThrow(init) {
const { cacheKey, settings } = this;
const state = await this.state;
if (shouldUseCacheIfFresh(init?.cache) && Time.isAfterNow(state.real?.current.cooldown))
return new Err(state);
if (shouldUseCacheIfStale(init?.cache) && Time.isAfterNow(state.real?.current.expiration))
return new Err(state);
if (!shouldUseNetwork(init?.cache))
throw new Error(`Could not fetch using the provided cache directive`);
const aborter = new AbortController();
const signal = AbortSignal.any([aborter.signal, AbortSignals.getOrNever(init?.signal)]);
return new Ok(await core.runOrJoin(cacheKey, aborter, () => Scrollable.fetchOrThrow(cacheKey, signal, settings)));
}
async refetchOrThrow(init) {
const { cacheKey, settings } = this;
const state = await this.state;
if (shouldUseCacheIfFresh(init?.cache) && Time.isAfterNow(state.real?.current.cooldown))
return new Err(state);
if (shouldUseCacheIfStale(init?.cache) && Time.isAfterNow(state.real?.current.expiration))
return new Err(state);
if (!shouldUseNetwork(init?.cache))
throw new Error(`Could not fetch using the provided cache directive`);
const aborter = new AbortController();
const signal = AbortSignal.any([aborter.signal, AbortSignals.getOrNever(init?.signal)]);
return new Ok(await core.runOrReplace(cacheKey, aborter, () => Scrollable.fetchOrThrow(cacheKey, signal, settings)));
}
async scrollOrThrow(init) {
const { cacheKey, settings } = this;
const state = await this.state;
if (shouldUseCacheIfFresh(init?.cache) && Time.isAfterNow(state.real?.current.cooldown))
return new Err(state);
if (shouldUseCacheIfStale(init?.cache) && Time.isAfterNow(state.real?.current.expiration))
return new Err(state);
if (!shouldUseNetwork(init?.cache))
throw new Error(`Could not fetch using the provided cache directive`);
const aborter = new AbortController();
const signal = AbortSignal.any([aborter.signal, AbortSignals.getOrNever(init?.signal)]);
return new Ok(await core.runOrReplace(cacheKey, aborter, () => Scrollable.scrollOrThrow(cacheKey, signal, settings)));
}
async peekOrNull() {
const { settings } = this;
const state = await this.state;
const pages = state.real?.data?.get();
if (pages == null)
return undefined;
return settings.scroller(Arrays.last(pages));
}
}
class ScrollableFetcherlessQuery {
settings;
cacheKey;
constructor(settings) {
this.settings = settings;
this.cacheKey = Scrollable.getCacheKey(settings.key);
}
get state() {
return core.getOrThrow(this.cacheKey, this.settings);
}
get aborter() {
return core.getAborterSync(this.cacheKey);
}
async mutateOrThrow(mutator) {
return await core.mutateOrThrow(this.cacheKey, mutator, this.settings);
}
async deleteOrThrow() {
return await core.deleteOrThrow(this.cacheKey, this.settings);
}
async normalizeOrThrow(fetched, more) {
if (more.shallow)
return;
await this.mutateOrThrow(() => new Some(fetched));
}
async fetchOrThrow(init) {
throw new MissingFetcherError();
}
async refetchOrThrow(init) {
throw new MissingFetcherError();
}
async scrollOrThrow(init) {
throw new MissingFetcherError();
}
async peekOrNull() {
const { settings } = this;
const state = await this.state;
const pages = state.real?.data?.get();
if (pages == null)
return undefined;
return settings.scroller(Arrays.last(pages));
}
}
export { ScrollableFetcherfulQuery, ScrollableFetcherlessQuery, createScrollableQuery };
//# sourceMappingURL=query.mjs.map