shelving
Version:
Toolkit for using data in JavaScript.
52 lines (51 loc) • 2.02 kB
JavaScript
import { AVOID_REFRESH } from "../../store/FetchStore.js";
import { awaitDispose } from "../../util/dispose.js";
import { setMapItem } from "../../util/map.js";
import { EndpointCache } from "./EndpointCache.js";
/**
* Cache of `EndpointCache` objects for multiple endpoints.
* - Use `get(endpoint)` to retrieve or create the `EndpointCache` for a given endpoint, then `get(payload)` on that to get a specific `EndpointStore`.
*/
export class APICache {
_endpoints = new Map();
provider;
constructor(provider) {
this.provider = provider;
}
_get(endpoint) {
return this._endpoints.get(endpoint);
}
get(endpoint) {
return this._get(endpoint) || setMapItem(this._endpoints, endpoint, new EndpointCache(endpoint, this.provider));
}
/**
* Fetch (or return a cached result) for the given endpoint and payload.
* - Returns the cached value immediately if one exists.
* - Waits for the in-flight fetch if the store is loading.
* - Throws if the fetch fails, matching `APIProvider.call` behaviour.
*/
async call(endpoint, payload, maxAge = AVOID_REFRESH, caller = this.call) {
return this.get(endpoint).call(payload, maxAge, caller);
}
/** Invalidate a specific store for an endpoint. */
invalidate(endpoint, payload) {
this._get(endpoint)?.invalidate(payload);
}
/** Invalidate all stores for an endpoint. */
invalidateAll(endpoint) {
this._get(endpoint)?.invalidateAll();
}
/** Trigger a refetch on a specific store for an endpoint. */
refresh(endpoint, payload, maxAge) {
this._get(endpoint)?.refresh(payload, maxAge);
}
/** Trigger a refetch on all stores for an endpoint. */
refreshAll(endpoint, maxAge) {
this._get(endpoint)?.refreshAll(maxAge);
}
// Implement `AsyncDisposable`
[Symbol.asyncDispose]() {
return awaitDispose(...this._endpoints.values(), // Dispose all endpoints.
() => this._endpoints.clear());
}
}