@antischematic/angular-state-library
Version:
Reactive state without boilerplate
133 lines • 20.2 kB
JavaScript
import { DOCUMENT } from "@angular/common";
import { inject, Injectable } from "@angular/core";
import { BehaviorSubject, debounce, EMPTY, filter, finalize, fromEvent, interval, merge, of, ReplaySubject, retry, share, startWith, Subject, switchAll, switchMap, takeUntil, tap, throttle, timer, } from "rxjs";
import { observeInZone } from "./utils";
import * as i0 from "@angular/core";
function onVisible(document, refCount) {
return toggle(refCount, fromEvent(document, "visibilitychange").pipe(filter(() => document.visibilityState === "visible")));
}
function onReconnect(document, refCount) {
const window = document.defaultView;
if (window) {
return toggle(refCount, fromEvent(window, "online"));
}
else {
return EMPTY;
}
}
function toggle(refCount, source) {
const delay = refCount.pipe(filter((count) => count > 0));
const resume = of(null);
return source.pipe(debounce(() => refCount.value > 0 ? resume : delay));
}
export class ResourceManager {
constructor() {
this.cache = new Map();
this.document = inject(DOCUMENT);
}
query(source, options) {
const key = this.keygen(options.key);
const { cache, document } = this;
if (cache.has(key)) {
const { resource, fetch, errors } = cache.get(key);
if (options.refreshIfStale !== false) {
fetch.next(source);
}
return merge(resource, errors);
}
const cancel = new Subject();
const invalidate = new Subject();
const fetch = new BehaviorSubject(source);
const refCount = new BehaviorSubject(0);
const invalidators = [fetch];
if (options.refreshOnFocus) {
invalidators.push(onVisible(document, refCount));
}
if (options.refreshOnReconnect) {
invalidators.push(onReconnect(document, refCount));
}
if (options.refreshInterval) {
const nativeInterval = observeInZone(interval(options.refreshInterval), Zone.root);
invalidators.push(toggle(refCount, nativeInterval));
}
const errors = new Subject();
const reload = merge(...invalidators).pipe(switchMap(() => fetch.pipe(takeUntil(cancel))), takeUntil(cancel), throttle(() => observeInZone(timer(options.staleTime ?? 0), Zone.root)));
const resource = invalidate.pipe(startWith(null), switchMap(() => reload), switchAll(), retry({
resetOnSuccess: true,
delay: (error, retryCount) => {
fetch.next(void 0);
errors.error(new QueryError(error, retryCount));
return resource;
}
}), share({
connector: () => new ReplaySubject(1, options.cacheTime ?? Infinity),
resetOnError: false,
resetOnComplete: false,
resetOnRefCountZero: false
}), tap({
subscribe: () => refCount.next(refCount.value + 1),
unsubscribe: () => refCount.next(refCount.value - 1)
}));
cache.set(key, {
resource,
errors,
fetch,
cancel,
invalidate,
source,
options
});
return merge(resource, errors);
}
mutate(source, options) {
const keys = options.invalidate ? Array.isArray(options.invalidate[0]) ? options.invalidate.map(this.keygen) : [this.keygen(options.invalidate)] : [];
for (const key of keys) {
this.invalidate(key, true);
}
return source.pipe(finalize(() => {
for (const key of keys) {
this.invalidate(key, false);
}
}));
}
revalidate(key) {
this.invalidate(this.keygen(key), true);
this.invalidate(this.keygen(key), false);
}
keygen(seed) {
return JSON.stringify(seed);
}
invalidate(key, doCancel) {
for (const [matchKey, { invalidate, cancel }] of this.cache) {
if (matchKey.startsWith(key.slice(0, key.length - 2))) {
if (doCancel) {
cancel.next();
}
else {
invalidate.next();
}
}
}
}
}
ResourceManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ResourceManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
ResourceManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ResourceManager, providedIn: "root" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ResourceManager, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}] });
export function useQuery(options) {
const resource = options.resource ?? inject(ResourceManager);
return source => resource.query(source, options);
}
export function useMutation(options) {
const resource = options.resource ?? inject(ResourceManager);
return source => resource.mutate(source, options);
}
export class QueryError {
constructor(error, retryCount) {
this.error = error;
this.retryCount = retryCount;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2NvcmUvc3JjL2RhdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ2pELE9BQU8sRUFDSixlQUFlLEVBQ2YsUUFBUSxFQUNSLEtBQUssRUFDTCxNQUFNLEVBQ04sUUFBUSxFQUNSLFNBQVMsRUFDVCxRQUFRLEVBQ1IsS0FBSyxFQUdMLEVBQUUsRUFDRixhQUFhLEVBQ2IsS0FBSyxFQUNMLEtBQUssRUFDTCxTQUFTLEVBQ1QsT0FBTyxFQUNQLFNBQVMsRUFDVCxTQUFTLEVBQ1QsU0FBUyxFQUNULEdBQUcsRUFDSCxRQUFRLEVBQ1IsS0FBSyxHQUNQLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLFNBQVMsQ0FBQzs7QUFrQnRDLFNBQVMsU0FBUyxDQUFDLFFBQWtCLEVBQUUsUUFBOEI7SUFDbEUsT0FBTyxNQUFNLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxJQUFJLENBQ2pFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsZUFBZSxLQUFLLFNBQVMsQ0FBQyxDQUN0RCxDQUFDLENBQUE7QUFDTCxDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsUUFBa0IsRUFBRSxRQUE4QjtJQUNwRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFBO0lBQ25DLElBQUksTUFBTSxFQUFFO1FBQ1QsT0FBTyxNQUFNLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQTtLQUN0RDtTQUFNO1FBQ0osT0FBTyxLQUFLLENBQUE7S0FDZDtBQUNKLENBQUM7QUFF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Q1VNRU5UfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQge2luamVjdCwgSW5qZWN0YWJsZX0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7XG4gICBCZWhhdmlvclN1YmplY3QsXG4gICBkZWJvdW5jZSxcbiAgIEVNUFRZLFxuICAgZmlsdGVyLFxuICAgZmluYWxpemUsXG4gICBmcm9tRXZlbnQsXG4gICBpbnRlcnZhbCxcbiAgIG1lcmdlLFxuICAgTW9ub1R5cGVPcGVyYXRvckZ1bmN0aW9uLFxuICAgT2JzZXJ2YWJsZSxcbiAgIG9mLFxuICAgUmVwbGF5U3ViamVjdCxcbiAgIHJldHJ5LFxuICAgc2hhcmUsXG4gICBzdGFydFdpdGgsXG4gICBTdWJqZWN0LFxuICAgc3dpdGNoQWxsLFxuICAgc3dpdGNoTWFwLFxuICAgdGFrZVVudGlsLFxuICAgdGFwLFxuICAgdGhyb3R0bGUsXG4gICB0aW1lcixcbn0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7b2JzZXJ2ZUluWm9uZX0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBRdWVyeU9wdGlvbnM8VCA9IGFueT4ge1xuICAga2V5OiB1bmtub3duW11cbiAgIHJlZnJlc2hJbnRlcnZhbD86IG51bWJlclxuICAgcmVmcmVzaE9uRm9jdXM/OiBib29sZWFuXG4gICByZWZyZXNoT25SZWNvbm5lY3Q/OiBib29sZWFuXG4gICByZWZyZXNoSWZTdGFsZT86IGJvb2xlYW5cbiAgIHN0YWxlVGltZT86IG51bWJlclxuICAgY2FjaGVUaW1lPzogbnVtYmVyXG4gICByZXNvdXJjZT86IFJlc291cmNlTWFuYWdlclxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE11dGF0ZU9wdGlvbnMge1xuICAgaW52YWxpZGF0ZT86IHVua25vd25bXSB8IHVua25vd25bXVtdXG4gICByZXNvdXJjZT86IFJlc291cmNlTWFuYWdlclxufVxuXG5mdW5jdGlvbiBvblZpc2libGUoZG9jdW1lbnQ6IERvY3VtZW50LCByZWZDb3VudDogQmVoYXZpb3JTdWJqZWN0PGFueT4pIHtcbiAgIHJldHVybiB0b2dnbGUocmVmQ291bnQsIGZyb21FdmVudChkb2N1bWVudCwgXCJ2aXNpYmlsaXR5Y2hhbmdlXCIpLnBpcGUoXG4gICAgICBmaWx0ZXIoKCkgPT4gZG9jdW1lbnQudmlzaWJpbGl0eVN0YXRlID09PSBcInZpc2libGVcIilcbiAgICkpXG59XG5cbmZ1bmN0aW9uIG9uUmVjb25uZWN0KGRvY3VtZW50OiBEb2N1bWVudCwgcmVmQ291bnQ6IEJlaGF2aW9yU3ViamVjdDxhbnk+KSB7XG4gICBjb25zdCB3aW5kb3cgPSBkb2N1bWVudC5kZWZhdWx0Vmlld1xuICAgaWYgKHdpbmRvdykge1xuICAgICAgcmV0dXJuIHRvZ2dsZShyZWZDb3VudCwgZnJvbUV2ZW50KHdpbmRvdywgXCJvbmxpbmVcIikpXG4gICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIEVNUFRZXG4gICB9XG59XG5cbmZ1bmN0aW9uIHRvZ2dsZShyZWZDb3VudDogQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4sIHNvdXJjZTogT2JzZXJ2YWJsZTxhbnk+KSB7XG4gICBjb25zdCBkZWxheSA9IHJlZkNvdW50LnBpcGUoXG4gICAgICBmaWx0ZXIoKGNvdW50KSA9PiBjb3VudCA+IDApXG4gICApXG4gICBjb25zdCByZXN1bWUgPSBvZihudWxsKVxuICAgcmV0dXJuIHNvdXJjZS5waXBlKFxuICAgICAgZGVib3VuY2UoKCkgPT4gcmVmQ291bnQudmFsdWUgPiAwID8gcmVzdW1lIDogZGVsYXkpXG4gICApXG59XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogXCJyb290XCIgfSlcbmV4cG9ydCBjbGFzcyBSZXNvdXJjZU1hbmFnZXIge1xuICAgY2FjaGUgPSBuZXcgTWFwKClcbiAgIGRvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKVxuXG4gICBxdWVyeTxUPihzb3VyY2U6IE9ic2VydmFibGU8VD4sIG9wdGlvbnM6IFF1ZXJ5T3B0aW9ucyk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5rZXlnZW4ob3B0aW9ucy5rZXkpXG4gICAgICBjb25zdCB7IGNhY2hlLCBkb2N1bWVudCB9ID0gdGhpc1xuXG4gICAgICBpZiAoY2FjaGUuaGFzKGtleSkpIHtcbiAgICAgICAgIGNvbnN0IHsgcmVzb3VyY2UsIGZldGNoLCBlcnJvcnMgfSA9IGNhY2hlLmdldChrZXkpXG4gICAgICAgICBpZiAob3B0aW9ucy5yZWZyZXNoSWZTdGFsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGZldGNoLm5leHQoc291cmNlKVxuICAgICAgICAgfVxuICAgICAgICAgcmV0dXJuIG1lcmdlKHJlc291cmNlLCBlcnJvcnMpIGFzIE9ic2VydmFibGU8VD5cbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FuY2VsID0gbmV3IFN1YmplY3Q8dm9pZD4oKVxuICAgICAgY29uc3QgaW52YWxpZGF0ZSA9IG5ldyBTdWJqZWN0PE9ic2VydmFibGU8VD4+KClcbiAgICAgIGNvbnN0IGZldGNoID0gbmV3IEJlaGF2aW9yU3ViamVjdDxPYnNlcnZhYmxlPFQ+Pihzb3VyY2UpXG4gICAgICBjb25zdCByZWZDb3VudCA9IG5ldyBCZWhhdmlvclN1YmplY3QoMClcbiAgICAgIGNvbnN0IGludmFsaWRhdG9ycyA9IFtmZXRjaF0gYXMgT2JzZXJ2YWJsZTxhbnk+W11cblxuICAgICAgaWYgKG9wdGlvbnMucmVmcmVzaE9uRm9jdXMpIHtcbiAgICAgICAgIGludmFsaWRhdG9ycy5wdXNoKG9uVmlzaWJsZShkb2N1bWVudCwgcmVmQ291bnQpKVxuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5yZWZyZXNoT25SZWNvbm5lY3QpIHtcbiAgICAgICAgIGludmFsaWRhdG9ycy5wdXNoKG9uUmVjb25uZWN0KGRvY3VtZW50LCByZWZDb3VudCkpXG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnJlZnJlc2hJbnRlcnZhbCkge1xuICAgICAgICAgY29uc3QgbmF0aXZlSW50ZXJ2YWwgPSBvYnNlcnZlSW5ab25lKGludGVydmFsKG9wdGlvbnMucmVmcmVzaEludGVydmFsKSwgWm9uZS5yb290KVxuICAgICAgICAgaW52YWxpZGF0b3JzLnB1c2godG9nZ2xlKHJlZkNvdW50LCBuYXRpdmVJbnRlcnZhbCkpXG4gICAgICB9XG4gICAgICBjb25zdCBlcnJvcnMgPSBuZXcgU3ViamVjdDxuZXZlcj4oKVxuXG4gICAgICBjb25zdCByZWxvYWQgPSBtZXJnZSguLi5pbnZhbGlkYXRvcnMpLnBpcGUoXG4gICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gZmV0Y2gucGlwZShcbiAgICAgICAgICAgIHRha2VVbnRpbChjYW5jZWwpXG4gICAgICAgICApKSxcbiAgICAgICAgIHRha2VVbnRpbChjYW5jZWwpLFxuICAgICAgICAgdGhyb3R0bGUoKCkgPT4gb2JzZXJ2ZUluWm9uZSh0aW1lcihvcHRpb25zLnN0YWxlVGltZSA/PyAwKSwgWm9uZS5yb290KSksXG4gICAgICApXG5cbiAgICAgIGNvbnN0IHJlc291cmNlOiBPYnNlcnZhYmxlPFQ+ID0gaW52YWxpZGF0ZS5waXBlKFxuICAgICAgICAgc3RhcnRXaXRoKG51bGwpLFxuICAgICAgICAgc3dpdGNoTWFwKCgpID0+IHJlbG9hZCksXG4gICAgICAgICBzd2l0Y2hBbGwoKSxcbiAgICAgICAgIHJldHJ5KHtcbiAgICAgICAgICAgIHJlc2V0T25TdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgZGVsYXk6IChlcnJvciwgcmV0cnlDb3VudCkgPT4ge1xuICAgICAgICAgICAgICAgZmV0Y2gubmV4dCh2b2lkIDAgYXMgYW55KVxuICAgICAgICAgICAgICAgZXJyb3JzLmVycm9yKG5ldyBRdWVyeUVycm9yKGVycm9yLCByZXRyeUNvdW50KSlcbiAgICAgICAgICAgICAgIHJldHVybiByZXNvdXJjZVxuICAgICAgICAgICAgfVxuICAgICAgICAgfSksXG4gICAgICAgICBzaGFyZSh7XG4gICAgICAgICAgICBjb25uZWN0b3I6ICgpID0+IG5ldyBSZXBsYXlTdWJqZWN0KDEsIG9wdGlvbnMuY2FjaGVUaW1lID8/IEluZmluaXR5KSxcbiAgICAgICAgICAgIHJlc2V0T25FcnJvcjogZmFsc2UsXG4gICAgICAgICAgICByZXNldE9uQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgICAgcmVzZXRPblJlZkNvdW50WmVybzogZmFsc2VcbiAgICAgICAgIH0pLFxuICAgICAgICAgdGFwKHtcbiAgICAgICAgICAgIHN1YnNjcmliZTogKCkgPT4gcmVmQ291bnQubmV4dChyZWZDb3VudC52YWx1ZSArIDEpLFxuICAgICAgICAgICAgdW5zdWJzY3JpYmU6ICgpID0+IHJlZkNvdW50Lm5leHQocmVmQ291bnQudmFsdWUgLSAxKVxuICAgICAgICAgfSlcbiAgICAgIClcblxuICAgICAgY2FjaGUuc2V0KGtleSwge1xuICAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgICBlcnJvcnMsXG4gICAgICAgICBmZXRjaCxcbiAgICAgICAgIGNhbmNlbCxcbiAgICAgICAgIGludmFsaWRhdGUsXG4gICAgICAgICBzb3VyY2UsXG4gICAgICAgICBvcHRpb25zXG4gICAgICB9KVxuXG4gICAgICByZXR1cm4gbWVyZ2UocmVzb3VyY2UsIGVycm9ycylcbiAgIH1cblxuICAgbXV0YXRlPFQ+KHNvdXJjZTogT2JzZXJ2YWJsZTxUPiwgb3B0aW9uczogTXV0YXRlT3B0aW9ucykge1xuICAgICAgY29uc3Qga2V5cyA9IG9wdGlvbnMuaW52YWxpZGF0ZSA/IEFycmF5LmlzQXJyYXkob3B0aW9ucy5pbnZhbGlkYXRlWzBdKSA/IChvcHRpb25zLmludmFsaWRhdGUgYXMgdW5rbm93bltdW10pLm1hcCh0aGlzLmtleWdlbikgOiBbdGhpcy5rZXlnZW4ob3B0aW9ucy5pbnZhbGlkYXRlKV0gOiBbXVxuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgICAgdGhpcy5pbnZhbGlkYXRlKGtleSwgdHJ1ZSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBzb3VyY2UucGlwZShcbiAgICAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICAgICAgICAgICAgIHRoaXMuaW52YWxpZGF0ZShrZXksIGZhbHNlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgfSksXG4gICAgICApXG4gICB9XG5cbiAgIHJldmFsaWRhdGUoa2V5OiBhbnlbXSkge1xuICAgICAgdGhpcy5pbnZhbGlkYXRlKHRoaXMua2V5Z2VuKGtleSksIHRydWUpXG4gICAgICB0aGlzLmludmFsaWRhdGUodGhpcy5rZXlnZW4oa2V5KSwgZmFsc2UpXG4gICB9XG5cbiAgIHByaXZhdGUga2V5Z2VuKHNlZWQ6IHVua25vd25bXSkge1xuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHNlZWQpXG4gICB9XG5cbiAgIHByaXZhdGUgaW52YWxpZGF0ZShrZXk6IHN0cmluZywgZG9DYW5jZWw6IGJvb2xlYW4pIHtcbiAgICAgIGZvciAoY29uc3QgW21hdGNoS2V5LCB7IGludmFsaWRhdGUsIGNhbmNlbCB9XSBvZiB0aGlzLmNhY2hlKSB7XG4gICAgICAgICBpZiAobWF0Y2hLZXkuc3RhcnRzV2l0aChrZXkuc2xpY2UoMCwga2V5Lmxlbmd0aCAtIDIpKSkge1xuICAgICAgICAgICAgaWYgKGRvQ2FuY2VsKSB7XG4gICAgICAgICAgICAgICBjYW5jZWwubmV4dCgpXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgaW52YWxpZGF0ZS5uZXh0KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgIH1cbiAgICAgIH1cbiAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZVF1ZXJ5PFQ+KG9wdGlvbnM6IFF1ZXJ5T3B0aW9uczxUPik6IE1vbm9UeXBlT3BlcmF0b3JGdW5jdGlvbjxUPiB7XG4gICBjb25zdCByZXNvdXJjZSA9IG9wdGlvbnMucmVzb3VyY2UgPz8gaW5qZWN0KFJlc291cmNlTWFuYWdlcilcbiAgIHJldHVybiBzb3VyY2UgPT4gcmVzb3VyY2UucXVlcnkoc291cmNlLCBvcHRpb25zKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlTXV0YXRpb248VD4ob3B0aW9uczogTXV0YXRlT3B0aW9ucyk6IE1vbm9UeXBlT3BlcmF0b3JGdW5jdGlvbjxUPiB7XG4gICBjb25zdCByZXNvdXJjZSA9IG9wdGlvbnMucmVzb3VyY2UgPz8gaW5qZWN0KFJlc291cmNlTWFuYWdlcilcbiAgIHJldHVybiBzb3VyY2UgPT4gcmVzb3VyY2UubXV0YXRlKHNvdXJjZSwgb3B0aW9ucylcbn1cblxuZXhwb3J0IGNsYXNzIFF1ZXJ5RXJyb3Ige1xuICAgY29uc3RydWN0b3IocHVibGljIGVycm9yOiB1bmtub3duLCBwdWJsaWMgcmV0cnlDb3VudDogdW5rbm93bikge31cbn1cbiJdfQ==