UNPKG

@antischematic/angular-state-library

Version:
1 lines 101 kB
{"version":3,"file":"antischematic-angular-state-library.mjs","sources":["../../../projects/core/src/interfaces.ts","../../../projects/core/src/metadata.ts","../../../projects/core/src/proxy.ts","../../../projects/core/src/utils.ts","../../../projects/core/src/providers.ts","../../../projects/core/src/hooks.ts","../../../projects/core/src/select.ts","../../../projects/core/src/core.ts","../../../projects/core/src/dispatch.ts","../../../projects/core/src/template-provider.ts","../../../projects/core/src/load-effect.ts","../../../projects/core/src/transition.ts","../../../projects/core/src/decorators.ts","../../../projects/core/src/data.ts","../../../projects/core/src/public-api.ts","../../../projects/core/src/antischematic-angular-state-library.ts"],"sourcesContent":["import {Observable} from \"rxjs\";\nimport {Provider} from \"@angular/core\";\n\ntype Changes = Map<object, Map<PropertyKey, any>>\n\nexport interface EventData<ActionName = string, ActionContext = unknown> {\n readonly id: number\n readonly name: ActionName\n readonly context: ActionContext\n readonly timestamp: number\n readonly changes: Changes\n}\n\nexport interface UnknownEvent extends EventData {\n type: EventType,\n value?: unknown\n}\n\nexport interface DispatchEvent<ActionName = string, ActionContext = unknown, ActionValue = unknown> extends EventData<ActionName, ActionContext> {\n readonly type: EventType.Dispatch\n readonly value: ActionValue\n}\n\nexport interface NextEvent<ActionName = string, ActionContext = unknown, ActionValue = unknown> extends EventData<ActionName, ActionContext> {\n readonly value: ActionValue extends Observable<infer R> ? R : never\n readonly type: EventType.Next\n}\n\nexport interface ErrorEvent<ActionName = string, ActionContext = unknown> extends EventData<ActionName, ActionContext> {\n readonly value: unknown\n readonly type: EventType.Error\n}\n\nexport interface CompleteEvent<ActionName = string, ActionContext = unknown> extends EventData<ActionName, ActionContext> {\n readonly type: EventType.Complete\n}\n\nexport type StoreEvent<ActionName = string, ActionContext = unknown, ActionType = unknown, EffectType = unknown> =\n | DispatchEvent<ActionName, ActionContext, ActionType>\n | NextEvent<ActionName, ActionContext, EffectType>\n | ErrorEvent<ActionName, ActionContext>\n | CompleteEvent<ActionName, ActionContext>\n\nexport enum EventType {\n Dispatch = \"dispatch\",\n Next = \"next\",\n Error = \"error\",\n Complete = \"complete\"\n}\n\nexport interface DispatchObserver<U> {\n next?(value: U): void\n error?(error: unknown): void\n complete?(): void\n finalize?(): void\n}\n\nexport interface TypedChange<T> {\n previousValue: T | undefined;\n currentValue: T;\n firstChange: boolean;\n isFirstChange(): boolean;\n}\n\nexport type TypedChanges<T> = {\n [key in keyof T]?: TypedChange<T[key]>\n}\n\nexport const enum Phase {\n DoCheck = \"ngDoCheck\",\n AfterContentChecked = \"ngAfterContentChecked\",\n AfterViewChecked = \"ngAfterViewChecked\"\n}\n\nexport interface ActionMetadata {\n immediate?: boolean;\n phase?: Phase\n track?: boolean\n catchError?: boolean\n}\n\nexport interface SelectMetadata {}\n\nexport interface CaughtMetadata {}\n\nexport type Metadata<T> = T & {\n key: string\n descriptor?: PropertyDescriptor\n}\n\nexport type ExtractEvents<T, U extends string> = {\n [key in U]: key extends keyof T ? T[key] extends (...params: infer P) => infer R ? StoreEvent<key, T, P, R> : never : never\n}[U]\n\nexport interface StoreConfig {\n root?: boolean\n actionProviders?: Provider[]\n}\n\nexport type DepMap = Map<Record<any, any>, Map<string, unknown>>\n\nexport interface ZoneCompatible {\n run(fn: Function, applyThis?: {}, applyArgs?: any[]): any\n runGuarded(fn: Function, applyThis?: {}, applyArgs?: any[]): any\n}\n","import {ChangeDetectorRef, Injector, ProviderToken} from \"@angular/core\";\nimport {\n ActionMetadata,\n CaughtMetadata,\n DepMap,\n Metadata,\n Phase,\n SelectMetadata,\n} from \"./interfaces\";\n\nexport const meta = new WeakMap()\n\nexport const action = Symbol(\"action\")\nexport const selector = Symbol(\"selector\")\nexport const tracked = Symbol(\"track\")\nexport const injector = Symbol(\"injector\")\nexport const caught = Symbol(\"caught\")\nexport const attach = Symbol(\"attach\")\n\nfunction ensureKey(target: WeakMap<any, any>, key: any) {\n return target.has(key) ? target.get(key)! : target.set(key, new Map()).get(key)!\n}\n\nexport function getMetaKeys<T>(metaKey: any, target: object): Map<unknown, Metadata<T>> {\n return ensureKey(ensureKey(meta, target), metaKey)\n}\n\nexport function getMeta<T>(metaKey: any, target: object, key?: PropertyKey): Metadata<T> | undefined {\n return getMetaKeys<any>(metaKey, target).get(key)\n}\n\nexport function setMeta(metaKey: any, value: any, target: object, key?: PropertyKey) {\n return ensureKey(ensureKey(meta, target), metaKey).set(key, value)\n}\n\nexport function getMetaValues<T>(metaKey: any, target: object): Metadata<T>[] {\n return Array.from(getMetaKeys<any>(metaKey, target).values())\n}\n\nexport function getActions(target: {}, phase?: Phase) {\n return getMetaValues<ActionMetadata>(action, target).filter(meta => phase ? meta.phase === phase : true)\n}\n\nexport function getSelectors<T>(target: {}, withDescriptor: boolean) {\n return getMetaValues<T>(selector, target).filter(selector => !!selector.descriptor === withDescriptor)\n}\n\nexport function getErrorHandlers(target: {}) {\n return getMetaValues<CaughtMetadata>(caught, target)\n}\n\nexport function getDeps(target: {}, key: PropertyKey): DepMap | undefined {\n return getMeta(tracked, target, key)\n}\n\nexport function getToken<T>(token: ProviderToken<T>, context: {}, key?: string): T {\n return getMeta<Injector>(injector, context, key)?.get(token)!\n}\n\nexport function markDirty(context: {}) {\n getToken(ChangeDetectorRef, context).markForCheck()\n}\n\nexport function getAttachments(target: {}) {\n return getMetaValues<{ token: ProviderToken<any> }>(attach, target)\n}\n","import {DepMap} from \"./interfaces\";\n\nconst cache = new WeakMap()\nconst proxies = new WeakMap()\n\nlet deps: Map<any, Map<any, any>>[] = []\n\nexport function pushStack(value: Map<any, any>) {\n deps.unshift(value)\n}\n\nexport function popStack() {\n deps.shift()\n}\n\nfunction isTracking() {\n return deps.length > 0\n}\n\nexport const changesMap = new WeakMap()\n\nexport function getChanges(deps: DepMap) {\n const changes = changesMap.get(deps) ?? new Map()\n changesMap.set(deps, changes)\n return changes\n}\n\nexport function addDep(object: object, key: PropertyKey, value: any, previous: any = value, update = false) {\n if (isTracking()) {\n let seen = false\n for (const dep of deps) {\n const keyValues = dep.get(object) ?? new Map\n dep.set(object, keyValues)\n if (!seen && update && !Object.is(value, previous)) {\n seen = true\n const changes = getChanges(dep)\n const change = changes.get(object) ?? new Map()\n changes.set(object, change)\n if (!change.has(key)) {\n change.set(key, untrack(previous))\n }\n }\n if (update && keyValues.has(key) || !update) {\n keyValues.set(key, value)\n }\n }\n }\n}\n\nfunction createObjectProxy(object: object) {\n return new Proxy(object, {\n get(target: object, p: string | symbol): any {\n const value = Reflect.get(target, p)\n addDep(target, p, value)\n return value\n },\n set(target: object, p: string | symbol, value: any, receiver: any): boolean {\n const previous = Reflect.get(target, p)\n const result = Reflect.set(target, p, value, receiver)\n addDep(target, p, value, previous, true)\n return result\n },\n deleteProperty(target: object, p: string | symbol): boolean {\n const previous = Reflect.get(target, p)\n const result = Reflect.deleteProperty(target, p)\n addDep(target, p, void 0, previous, true)\n return result\n }\n })\n}\n\nexport function createProxy(object: object) {\n if (!isObject(object)) return object\n if (cache.has(object)) {\n return cache.get(object)!\n }\n const proxy = createObjectProxy(object)\n cache.set(object, proxy)\n proxies.set(proxy, object)\n return proxy\n}\n\nexport function isTracked(object: any) {\n return proxies.has(object)\n}\n\nfunction isObject(value: any) {\n return typeof value === \"object\" && value !== null\n}\n\nexport function track<T>(object: T): T {\n return isObject(object) && !isTracked(object) ? createProxy(object as any) : object\n}\n\nexport function untrack<T>(object: T): T {\n return proxies.get(object as any) ?? object\n}\n","import {inject, InjectionToken, Injector, INJECTOR, ProviderToken} from \"@angular/core\";\nimport {defer, filter, map, Observable, OperatorFunction, tap} from \"rxjs\";\nimport {\n CompleteEvent,\n DispatchEvent, ErrorEvent,\n EventType,\n ExtractEvents, NextEvent,\n StoreConfig,\n StoreEvent,\n ZoneCompatible\n} from \"./interfaces\";\nimport {EVENTS, ROOT_CONFIG, STORE_CONFIG} from \"./providers\";\nimport {track, untrack} from \"./proxy\";\n\nexport function isPlainObject(obj: object) {\n const proto = Object.getPrototypeOf(obj)\n return proto === null || proto === Object.prototype\n}\n\nexport function call(target: Record<any, any>, key: string, ...args: any[]) {\n return target[key].apply(target, args)\n}\n\nexport function wrap(target: { [key: PropertyKey]: any }, property: PropertyKey, fn: (this: any, ...args: any[]) => any) {\n const descriptor = Object.getOwnPropertyDescriptor(target, property)!\n const object = descriptor ? descriptor : target\n const getOrValue = descriptor?.get ? \"get\" : \"value\"\n const originalFunction = (descriptor ? descriptor[getOrValue] : object[property]) ?? noop\n\n Object.defineProperty(target, property, {\n configurable: true,\n [getOrValue]: function (this: unknown, ...args: any[]) {\n return fn.call(untrack(this), originalFunction, ...args)\n }\n })\n\n return originalFunction === noop\n}\n\nexport function noop() {}\n\nexport const UID = new InjectionToken(\"UID\", {\n factory() {\n let id = 0\n return function getId() {\n return id++\n }\n }\n})\n\nexport function events<T>(token: ProviderToken<T>, injector?: Injector): Observable<ExtractEvents<T, Extract<keyof T, string>>>\nexport function events<T>(context: T): Observable<ExtractEvents<T, Extract<keyof T, string>>>\nexport function events<T>(token: ProviderToken<T> | T, injector = inject(INJECTOR)): Observable<ExtractEvents<T, Extract<keyof T, string>>> {\n return defer(() => {\n const context = typeof token === \"function\" ? injector.get(token) : token\n return injector.get(EVENTS).pipe(\n filter(event => event.context === context)\n )\n }) as Observable<ExtractEvents<T, Extract<keyof T, string>>>\n}\n\nexport function configureStore(config: StoreConfig) {\n return {\n provide: config.root ? ROOT_CONFIG : STORE_CONFIG,\n useValue: config\n }\n}\n\nexport function observeInZone<T>(source: Observable<T>, zone: ZoneCompatible): Observable<T> {\n return new Observable(subscriber => {\n return zone.run(() => {\n return source.subscribe(subscriber)\n })\n })\n}\n\nexport function get<T extends { value: unknown }>(token: ProviderToken<T>): T[\"value\"] {\n return track(inject(token).value)\n}\n\nexport function set<T extends { value: unknown, next: (value: T[\"value\"]) => void }>(token: ProviderToken<T>, value: T[\"value\"]): void {\n inject(token).next(value)\n}\n\ntype ActionParams<T> = T extends (...params: infer Params) => any ? Params extends { length: 1 } ? Params[0] : Params : never\n\nfunction filterByNameType<T extends StoreEvent>(name: PropertyKey, type: EventType): OperatorFunction<any, T> {\n return filter((event: StoreEvent): event is T => event.name === name && event.type === type)\n}\n\nexport function actionEvent<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<DispatchEvent> {\n return events(token, injector).pipe(\n filterByNameType<DispatchEvent<any, any, any[]>>(name, EventType.Dispatch),\n )\n}\n\nexport function action<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<ActionParams<T[TKey]>> {\n return actionEvent(token, name, injector).pipe(\n map((event: any) => event.value)\n )\n}\n\nexport function nextEvent<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<NextEvent> {\n return events(token, injector).pipe(\n filterByNameType<NextEvent>(name, EventType.Next)\n )\n}\n\nexport function next<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<T[TKey] extends () => infer R ? R extends Observable<infer S> ? S : never : never> {\n return nextEvent(token, name, injector).pipe(\n map((event) => event.value)\n )\n}\n\nexport function errorEvent<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<ErrorEvent> {\n return events(token, injector).pipe(\n filterByNameType<ErrorEvent>(name, EventType.Error)\n )\n}\n\nexport function error<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<unknown> {\n return errorEvent(token, name, injector).pipe(\n map((event) => event.value)\n )\n}\n\nexport function completeEvent<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<CompleteEvent> {\n return events(token, injector).pipe(\n filterByNameType<CompleteEvent>(name, EventType.Complete)\n )\n}\n\nexport function complete<T, TKey extends keyof T>(token: ProviderToken<T>, name: TKey, injector?: Injector): Observable<void> {\n return completeEvent(token, name, injector).pipe(\n filterByNameType<CompleteEvent>(name, EventType.Complete),\n map(() => undefined)\n )\n}\n","import {ErrorHandler, inject, Injectable, InjectionToken} from \"@angular/core\";\nimport {Observable, OperatorFunction, Subject, Subscription, switchAll} from \"rxjs\";\nimport {ActionMetadata, EventType, StoreConfig, StoreEvent} from \"./interfaces\";\nimport {getErrorHandlers} from \"./metadata\";\nimport {track} from \"./proxy\";\nimport {UID} from \"./utils\";\n\nexport const ACTION = new InjectionToken<ActionMetadata>(\"ACTION\")\nexport const CONTEXT = new InjectionToken<{ instance: unknown }>(\"CONTEXT\")\nexport const STORE_CONFIG = new InjectionToken<StoreConfig>(\"STORE_CONFIG\")\nexport const ROOT_CONFIG = new InjectionToken<StoreConfig>(\"ROOT_CONFIG\", {\n factory() {\n return {}\n }\n})\nexport const EVENTS = new InjectionToken(\"EVENTS\", {\n factory() {\n return new Subject<StoreEvent>()\n }\n})\n\nexport class EventScheduler {\n events: StoreEvent<any, any, any, any>[] = []\n dispatcher = inject(EVENTS)\n getId = inject(UID)\n\n schedule(type: EventType, name: string, value: unknown, changes: Map<any, any>) {\n this.events.push({\n id: this.getId(),\n timestamp: Date.now(),\n type,\n context: this.context,\n name,\n value,\n changes\n })\n }\n\n flush() {\n const events = this.events\n if (events.length) {\n let event\n this.events = []\n while (event = events.shift()) {\n this.dispatcher.next(event)\n }\n }\n return this.events.length > 0\n }\n\n constructor(private context: {}) {}\n}\n\n@Injectable()\nexport class EffectScheduler {\n source = new Subject<Observable<any>>()\n queue: any[] = []\n operator?: OperatorFunction<Observable<any>, any>\n connected = false\n subscription = Subscription.EMPTY\n pending = new Set\n closed = false\n\n next(source: Observable<any>) {\n this.connect()\n this.source.next(source)\n }\n\n enqueue(source: Observable<any>) {\n this.queue.push(source)\n }\n\n dequeue() {\n let effect: any\n if (this.pending.size === 0) {\n while (effect = this.queue.shift()) {\n this.next(effect)\n }\n }\n }\n\n connect() {\n if (!this.connected && !this.closed) {\n this.connected = true\n this.subscription = this.source.pipe(this.operator ?? switchAll()).subscribe()\n this.subscription.add(() => this.connected = false)\n }\n }\n\n addPending(promise: Promise<any>) {\n this.pending.add(promise)\n promise.finally(() => {\n this.pending.delete(promise)\n this.dequeue()\n })\n }\n\n ngOnDestroy() {\n this.closed = true\n this.source.complete()\n this.subscription.unsubscribe()\n }\n}\n\n@Injectable()\nexport class Teardown {\n subscriptions: Subscription[] = []\n\n unsubscribe() {\n let subscription\n while (subscription = this.subscriptions.shift()) {\n subscription.unsubscribe()\n }\n }\n\n ngOnDestroy() {\n this.unsubscribe()\n }\n}\n\nexport class Changes {\n get value() {\n return track(this.target.__ngSimpleChanges__?.previous) ?? {}\n }\n\n constructor(private target: any) {}\n}\n\nexport class StoreErrorHandler implements ErrorHandler {\n handleError(error: unknown) {\n const errorHandlers = getErrorHandlers(this.prototype)\n for (const handler of errorHandlers) {\n try {\n this.instance[handler.key].call(this.instance, error)\n break\n } catch (e) {\n error = e\n }\n }\n throw error\n }\n\n constructor(private prototype: any, private instance: any) {}\n}\n","import {inject} from \"@angular/core\";\nimport {\n concatAll,\n exhaustAll,\n mergeAll,\n MonoTypeOperatorFunction,\n Observable,\n OperatorFunction,\n pipe,\n Subscription,\n switchAll,\n TeardownLogic\n} from \"rxjs\";\nimport {TypedChanges} from \"./interfaces\";\nimport {Changes, EffectScheduler, Teardown} from \"./providers\";\n\nexport function useOperator<T extends OperatorFunction<Observable<unknown>, unknown>>(operator: T) {\n const effect = inject(EffectScheduler)\n if (!effect.operator) {\n effect.operator = operator\n }\n}\n\nexport function useSwitch(operator?: MonoTypeOperatorFunction<Observable<unknown>>) {\n useOperator(operator ? pipe(operator, switchAll()) : switchAll())\n}\n\nexport function useMerge(): void\nexport function useMerge(concurrent: number): void\nexport function useMerge(operator?: MonoTypeOperatorFunction<Observable<unknown>>, concurrent?: number): void\nexport function useMerge(operator?: MonoTypeOperatorFunction<Observable<unknown>> | number, concurrent: number = operator as number) {\n useOperator(typeof operator === \"function\" ? pipe(operator, mergeAll(concurrent)) : mergeAll(concurrent))\n}\n\nexport function useConcat(operator?: MonoTypeOperatorFunction<Observable<unknown>>) {\n useOperator(operator ? pipe(operator, concatAll()) : concatAll())\n}\n\nexport function useExhaust(operator?: MonoTypeOperatorFunction<Observable<unknown>>) {\n useOperator(operator ? pipe(operator, exhaustAll()) : exhaustAll())\n}\n\nexport function addTeardown(teardown: TeardownLogic) {\n const subscription = new Subscription()\n subscription.add(teardown)\n inject(Teardown).subscriptions.push(subscription)\n}\n\nexport function useInputs<T>(): TypedChanges<T> {\n return inject(Changes).value\n}\n","import {\n ChangeDetectorRef,\n ErrorHandler,\n inject,\n Injectable,\n Injector,\n INJECTOR,\n ProviderToken,\n Type,\n} from \"@angular/core\";\nimport {\n BehaviorSubject,\n defer,\n distinctUntilChanged,\n filter,\n isObservable,\n map,\n NEVER,\n observable,\n Observable,\n Observer,\n ReplaySubject,\n startWith,\n Subject,\n Subscription,\n} from \"rxjs\";\nimport {addTeardown} from \"./hooks\";\nimport {DispatchEvent, EventType, StoreEvent, TypedChanges} from \"./interfaces\";\nimport {EVENTS, EventScheduler} from \"./providers\";\nimport {track} from \"./proxy\";\nimport {events} from \"./utils\";\n\nfunction pick<T, U extends (keyof T)[]>(object: T, keys: U): Pick<T, U[number]>\nfunction pick<T, U extends keyof T>(object: T, keys: U): T[U]\nfunction pick(object: any, keys: PropertyKey | PropertyKey[]): unknown {\n if (Array.isArray(keys)) {\n return keys.reduce((acc, key) => {\n acc[key] = object[key]\n return acc\n }, {} as any)\n }\n return object[keys]\n}\n\nexport function slice<T extends {}, U extends keyof T>(token: ProviderToken<T>, key: U, injector?: Injector): Observable<T[U]>\nexport function slice<T extends {}, U extends (keyof T)[]>(token: ProviderToken<T>, key: U, injector?: Injector): Observable<Pick<T, U[number]>>\nexport function slice(token: ProviderToken<any>, keys: any, injector = inject(INJECTOR)): Observable<unknown> {\n return defer(() => {\n const context = injector.get(token)\n return store(token, injector).pipe(\n map((context) => pick(context, keys)),\n startWith(pick(context, keys)),\n distinctUntilChanged((a, b) => !Array.isArray(keys) ? Object.is(a, b) : keys.every(key => Object.is(a[key], b[key])))\n )\n })\n}\n\nexport function store<T extends {}>(token: ProviderToken<T>, injector = inject(INJECTOR)): Observable<T> {\n return defer(() => {\n const context = injector.get(token)\n return injector.get(EVENTS).pipe(\n filter(event => event.changes.has(context)),\n map(() => context)\n )\n })\n}\n\nexport function inputs<T>(token: ProviderToken<T>, injector = inject(INJECTOR)): Observable<TypedChanges<T>> {\n return defer(() => {\n return events(token, injector).pipe(\n filter((event: StoreEvent): event is DispatchEvent => event.name === \"ngOnChanges\"),\n map(event => event.value as TypedChanges<T>)\n )\n })\n}\n\nexport interface WithStateOptions<T> {\n from?: Observable<T>\n}\n\nexport interface WithState<T> {\n source: Observable<T>\n destination: BehaviorSubject<T>\n}\n\nexport interface Selector {\n new<T>(name: string, factory: (source: Observable<T>) => WithState<T>): Type<BehaviorSubject<T>>\n new<T>(name: string, factory: (source: Observable<T>) => Observable<T>): Type<BehaviorSubject<T> & { value: T | undefined }>\n}\n\nexport function withState<T>(initial: T, options: WithStateOptions<T> = {}): WithState<T> {\n const destination = new BehaviorSubject(initial)\n const source = options.from ?? NEVER\n\n return {\n destination,\n source,\n }\n}\n\nexport const Selector: Selector = function Selector(name: string, select: Function) {\n @Injectable()\n class Selector {\n source: Observable<any>\n destination: Subject<any>\n connected = false\n subscription = new Subscription()\n target: Subject<any>\n\n [observable]() {\n return this\n }\n\n value: any\n\n connect() {\n if (!this.connected) {\n this.connected = true\n this.subscription.add(this.source.subscribe(this.destination))\n }\n }\n\n next(value: any) {\n this.target.next(value)\n }\n\n pipe(...operators: any[]) {\n return new Observable(subscriber => {\n return this.subscribe(subscriber)\n }).pipe(...operators as [])\n }\n\n subscribe(observer: any) {\n try {\n return this.destination.subscribe(observer)\n } finally {\n this.connect()\n }\n }\n\n ngOnDestroy() {\n this.subscription.unsubscribe()\n }\n\n constructor() {\n const subject = new Subject()\n const selection = select(subject)\n if (isObservable(selection)) {\n this.source = selection\n this.destination = new ReplaySubject(1)\n } else {\n this.source = selection.source\n this.destination = selection.destination\n }\n this.target = select.length > 0 ? subject : this.destination\n this.subscription.add(this.destination.subscribe((value) => {\n this.value = value\n }))\n }\n\n static overriddenName = name\n }\n return Selector\n} as any\n\nclass SelectObserver {\n next(value: any) {\n const previous = this.target[this.key]\n this.target[this.key] = track(value)\n const changes = new Map([[this.target, new Map([[this.key, previous]])]])\n this.event.schedule(EventType.Dispatch, this.key, value, changes)\n this.cdr.markForCheck()\n }\n error(error: unknown) {\n console.error(\"Error thrown in Select\")\n console.error(\"Directive:\", this.target)\n console.error(\"Key:\", this.key)\n this.errorHandler.handleError(error)\n }\n complete() {}\n constructor(private target: any, private key: any, private event: EventScheduler, private cdr: ChangeDetectorRef, private errorHandler: ErrorHandler) {}\n}\n\nexport function subscribe<T extends {}>(token: ProviderToken<T> | undefined, directive: any, key: string): any {\n const instance = token ? inject(token) : directive[key]\n const observer = new SelectObserver(directive, key, inject(EventScheduler), inject(ChangeDetectorRef), inject(ErrorHandler))\n const subscription = instance.ngOnSelect?.(observer) ?? instance.subscribe?.(observer)\n if (!subscription) {\n console.error('Directive:', directive)\n console.error('Key:', key)\n console.error('Object:', instance)\n throw new Error(`Object does not implement OnSelect or Subscribable interfaces`)\n }\n directive[key] = track(directive[key])\n addTeardown(subscription)\n}\n\nexport interface OnSelect {\n ngOnSelect(observer: Observer<any>): Subscription\n}\n","import {\n createEnvironmentInjector,\n EnvironmentInjector,\n ErrorHandler,\n inject,\n INJECTOR,\n ProviderToken\n} from \"@angular/core\";\nimport {DepMap, EventType, Phase, SelectMetadata} from \"./interfaces\";\nimport {\n getActions,\n getDeps,\n getMeta,\n getMetaValues,\n getSelectors,\n getToken,\n injector,\n markDirty,\n setMeta,\n tracked\n} from \"./metadata\";\nimport {\n ACTION,\n Changes,\n CONTEXT,\n EffectScheduler,\n EventScheduler,\n ROOT_CONFIG,\n STORE_CONFIG,\n StoreErrorHandler,\n Teardown\n} from \"./providers\";\nimport {createProxy, getChanges, popStack, pushStack, untrack} from \"./proxy\";\nimport {store, subscribe} from \"./select\";\nimport {call, wrap} from \"./utils\";\n\nfunction checkDeps(deps: DepMap) {\n let dirty = false\n for (const [object, keyValues] of deps) {\n for (const [key, previous] of keyValues) {\n const current = object[key]\n if (!Object.is(current, previous)) {\n keyValues.set(key, current)\n dirty = true\n }\n }\n }\n return dirty\n}\n\nexport function decorateCheck(target: {}, name: Phase) {\n const actions = getActions(target, name)\n wrap(target, name, function check(fn) {\n const events = getToken(EventScheduler, this)\n for (const action of actions) {\n const deps = getDeps(this, action.key)\n const dirty = action.track && deps && checkDeps(deps)\n if (action.descriptor?.value.length === 0 && (!deps && action.immediate && action.phase === name || dirty)) {\n markDirty(this)\n call(this, action.key)\n }\n }\n for (const action of actions) {\n const effect = getToken(EffectScheduler, this, action.key)\n effect.dequeue()\n }\n if (events.flush()) {\n check.call(this, fn)\n } else {\n fn.apply(this)\n }\n })\n}\n\nfunction getConfig() {\n return inject(STORE_CONFIG, { self: true, optional: true }) ?? inject(ROOT_CONFIG)\n}\n\nfunction provideValue(provide: any, useValue: any) {\n return { provide, useValue}\n}\n\nexport function setup(target: any, factory: any, ...args: any[]) {\n const instance = factory(...args)\n const prototype = target.prototype\n const parent = inject(INJECTOR) as EnvironmentInjector\n const storeInjector = createEnvironmentInjector([\n provideValue(Changes, new Changes(instance)),\n provideValue(ErrorHandler, new StoreErrorHandler(prototype, instance)),\n provideValue(EventScheduler, new EventScheduler(instance)),\n Teardown\n ], parent)\n let storeConfig = getConfig()\n setMeta(injector, storeInjector, instance)\n for (const action of getActions(prototype)) {\n const actionInjector = createEnvironmentInjector([\n provideValue(ACTION, action),\n provideValue(CONTEXT, { instance }),\n EffectScheduler,\n Teardown,\n storeConfig?.actionProviders ?? []\n ], storeInjector)\n setMeta(injector, actionInjector, instance, action.key)\n }\n return instance\n}\n\nexport const stores = new Set<any>()\nconst decorated = new WeakSet()\n\nexport function decorateFactory(target: any, fn: (this: any, ...args: any[]) => any, ...additionalArgs: any[]) {\n const factory = target[\"ɵfac\"]\n if (factory) {\n Object.defineProperty(target, \"ɵfac\", {\n configurable: true,\n value: function (...args: any[]) {\n return fn(target, factory, ...additionalArgs, ...args)\n }\n })\n }\n}\n\nexport function runInContext<T extends (...args: any) => any>(deps: DepMap, fn: T, context = {}, catchError = true, key?: string, ...args: Parameters<T>) {\n const injector = getToken(EnvironmentInjector, untrack(context), key)\n const errorHandler = injector.get(ErrorHandler)\n pushStack(deps)\n try {\n return injector.runInContext(() => fn.apply(context, args))\n } catch (e) {\n if (catchError) {\n errorHandler.handleError(e)\n } else {\n throw e\n }\n } finally {\n popStack()\n }\n}\n\nfunction runAction(this: any, fn: any, key: any, deps: DepMap, args: any[]) {\n const event = inject(EventScheduler)\n event.schedule(EventType.Dispatch, key, args.length === 1 ? args[0] : args, getChanges(deps))\n return fn.apply(this, args)\n}\n\nexport function decorateActions(target: {}) {\n for (const { key, catchError } of getActions(target)) {\n wrap(target, key, function (fn, ...args) {\n const proxy = createProxy(this)\n const deps = new Map()\n setMeta(tracked, deps, this, key)\n teardown(this, key)\n return runInContext(deps, runAction, proxy, catchError, key, fn, key, deps, args)\n })\n }\n}\n\nexport function decorateSelect(target: any) {\n target.prototype.ngOnSelect ??= function (this: any, observer: any) {\n return store(target).subscribe(observer)\n }\n}\n\nexport function decorateSelectors(target: {}) {\n for (const { key } of getSelectors<SelectMetadata>(target, true)) {\n wrap(target, key, function (fn, ...args) {\n const cacheKey = key + JSON.stringify(args)\n const proxy = createProxy(this)\n const deps = getDeps(this, cacheKey)\n const dirty = deps ? checkDeps(deps) : true\n let result = getMeta(cacheKey, this, key)\n if (dirty) {\n const newDeps = new Map()\n result = runInContext(newDeps, fn, proxy, true, void 0, ...args)\n setMeta(cacheKey, result, this, key)\n setMeta(tracked, newDeps, this, cacheKey)\n }\n return result\n })\n }\n}\n\nexport function decorateChanges(target: {}) {\n wrap(target, \"ngOnChanges\", function (fn, value) {\n const events = getToken(EventScheduler, this)\n const changes = Object.entries(value).map(([key, change]) => [key, (change as any).previousValue]) as any[]\n events.schedule(EventType.Dispatch, \"ngOnChanges\", {...value}, new Map([[this, new Map(changes)]]))\n fn.call(this, value)\n })\n}\n\nexport function decorateOnInit(target: {}) {\n wrap(target, \"ngOnInit\", function (fn) {\n const injector = getToken(EnvironmentInjector, this)\n for (const attachment of getSelectors<{ token: ProviderToken<any> | undefined }>(target, false)) {\n injector.runInContext(() => {\n subscribe(attachment.token, this, attachment.key)\n })\n }\n fn.call(this)\n })\n}\n\nexport function decorateDestroy(target: {}) {\n wrap(target, \"ngOnDestroy\", function (fn) {\n for (const environmentInjector of getMetaValues<EnvironmentInjector>(injector, this)) {\n environmentInjector.destroy()\n }\n fn.apply(this)\n })\n}\n\nfunction teardown(context: {}, key: string) {\n getToken(Teardown, context, key)?.unsubscribe()\n}\n","import {ChangeDetectorRef, ErrorHandler, inject, ViewRef} from \"@angular/core\";\nimport {runInContext} from \"./core\";\nimport {ActionMetadata, DispatchObserver, EventType, Metadata, ZoneCompatible} from \"./interfaces\";\nimport {catchError, EMPTY, Observable, Subject, tap} from \"rxjs\";\nimport {getChanges} from \"./proxy\";\nimport {isPlainObject, observeInZone, wrap} from \"./utils\";\nimport {ACTION, CONTEXT, EffectScheduler, EventScheduler} from \"./providers\";\n\nconst observers = [EventType.Next, EventType.Error, EventType.Complete, \"finalize\"] as const\n\nexport interface DispatchOptions {\n zone?: \"noop\" | ZoneCompatible\n}\n\nfunction callObserver(fn: Function, applyThis: any, value: any) {\n fn.call(applyThis, value)\n}\n\nexport function dispatch<TValue>(source: Observable<TValue>, options?: DispatchOptions): Observable<TValue>\nexport function dispatch<TValue>(source: Observable<TValue>, observer: DispatchObserver<TValue>, options?: DispatchOptions): Observable<TValue>\nexport function dispatch<TValue>(source: Observable<TValue>, next: (value: TValue) => void, options?: DispatchOptions): Observable<TValue>\nexport function dispatch(source: Observable<any>, observerOrOptions: any = {}, options: DispatchOptions = observerOrOptions) {\n const action = inject(ACTION) as Metadata<ActionMetadata>\n const context = inject(CONTEXT).instance as any\n const applyThis = observerOrOptions && !isPlainObject(observerOrOptions) ? observerOrOptions : context\n const errorHandler = inject(ErrorHandler)\n const event = inject(EventScheduler)\n const effect = inject(EffectScheduler)\n const changeDetector = inject(ChangeDetectorRef) as ViewRef\n const signal = new Subject<any>()\n const zone = options.zone === \"noop\" ? Zone.root : options.zone ?? Zone.current\n const observer = typeof observerOrOptions === \"function\" ? { next: observerOrOptions } : { ...observerOrOptions }\n\n for (const key of observers) {\n wrap(observer!, key, function (fn, value) {\n const isAction = key !== \"finalize\"\n try {\n if (!changeDetector.destroyed) {\n const deps = new Map()\n isAction && event.schedule(key, action.key, value, getChanges(deps))\n changeDetector.markForCheck()\n runInContext(deps, callObserver, context, false, action.key, fn, applyThis, value)\n }\n } finally {\n if (isAction) {\n signal[key](value)\n } else {\n signal.complete()\n }\n }\n })\n }\n\n effect.enqueue(observeInZone(source.pipe(\n tap(observer),\n catchError(e => {\n zone.runGuarded(() => errorHandler.handleError(e))\n return EMPTY\n })\n ), zone))\n\n return signal as any\n}\n","import {Directive, ElementRef, inject, Input, OnInit} from \"@angular/core\";\nimport {Observer, ReplaySubject, Subscription} from \"rxjs\";\n\n@Directive()\nexport abstract class TemplateProvider extends ReplaySubject<unknown> implements OnInit {\n private _firstValue = false\n\n abstract value: unknown\n\n @Input(\"value\") set __value(value: this[\"value\"]) {\n this._firstValue = true\n this.next(value)\n }\n\n ngOnInit() {\n if (!this._firstValue) {\n this.next(this.value)\n }\n }\n\n override subscribe(next: (value: this['value']) => void): Subscription;\n override subscribe(observer?: Partial<Observer<this['value']>>): Subscription\n override subscribe(observer?: any): Subscription {\n return super.subscribe(observer);\n }\n\n constructor() {\n super(1)\n const style = inject(ElementRef).nativeElement?.style\n if (style) style.display = \"contents\"\n }\n}\n","import {Observable} from \"rxjs\";\nimport {EnvironmentInjector, inject} from \"@angular/core\";\nimport {EffectScheduler} from \"./providers\";\n\nexport function loadEffect<TArgs extends unknown[], TReturn extends Observable<unknown>>(load: () => Promise<{ default: (...args: TArgs) => TReturn }>): (...args: TArgs) => TReturn {\n return function (...args: any[]) {\n const injector = inject(EnvironmentInjector)\n const effect = inject(EffectScheduler)\n const promise = load().then((mod) => {\n return injector.runInContext(() => {\n return mod.default(...args as TArgs)\n })\n })\n\n effect.addPending(promise)\n\n return new Observable(subscriber => {\n promise\n .then(source => {\n subscriber.add(source.subscribe(subscriber))\n })\n .catch(e => {\n subscriber.error(e)\n })\n return subscriber\n }) as TReturn\n }\n}\n","/// <reference path=\"../../../node_modules/zone.js/zone.d.ts\" />\n\nimport {EventEmitter, InjectionToken} from \"@angular/core\";\nimport {\n BehaviorSubject,\n map, merge,\n MonoTypeOperatorFunction,\n Observable, Observer,\n PartialObserver,\n Subject, Subscription,\n takeWhile\n} from \"rxjs\";\nimport {OnSelect} from \"./select\";\n\ninterface TransitionOptions {\n async?: boolean\n slowMs?: number\n timeoutMs?: number\n resetOnSuccess?: boolean\n cancelPrevious?: boolean\n}\n\nfunction handleError(transition: Transition) {\n if (transition.failed) {\n transition.onError.next(transition.thrownError)\n } else if (transition.resetOnSuccess) {\n transition.retryCount = 0\n }\n}\n\nfunction checkStable({ transition, microtasks, macroTasks, parentZone, timeout }: TransitionSpec) {\n const { isUnstable } = transition\n const { slowMs, timeoutMs, slow, isSlow } = transition\n if (!microtasks && !macroTasks && !transition.stable) {\n clearTimeout(timeout.timeoutId)\n clearTimeout(timeout.slowId)\n parentZone.run(() => {\n handleError(transition)\n if (slow) {\n isSlow.next(false)\n }\n isUnstable.next(false)\n })\n }\n if ((microtasks || macroTasks) && transition.stable) {\n if (transition.failed) {\n transition.retryCount++\n }\n transition.failed = false\n transition.timeout = false\n transition.thrownError = null\n parentZone.run(() => {\n isUnstable.next(true)\n if (slowMs) {\n timeout.slowId = setTimeout(() => {\n transition.isSlow.next(true)\n }, slowMs)\n }\n if (timeoutMs) {\n timeout.timeoutId = setTimeout(() => {\n transition.failed = true\n transition.timeout = true\n transition.thrownError = new Error(`Transition timed out after ${timeoutMs}ms`)\n transition.cancel()\n }, timeoutMs)\n }\n })\n }\n}\n\nlet id = 0\n\nexport class TransitionSpec implements ZoneSpec {\n microtasks = 0\n macroTasks = 0\n parentZone = Zone.current\n tasks = new Set<Task>()\n timeout = {} as any\n properties = {\n id: id++\n }\n\n onScheduleTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) {\n this.tasks.add(task)\n return parentZoneDelegate.scheduleTask(targetZone, task)\n }\n\n onInvokeTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, applyThis: any, applyArgs?: any[]) {\n this.tasks.delete(task)\n return parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs)\n }\n\n onCancelTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) {\n this.tasks.delete(task)\n return parentZoneDelegate.cancelTask(targetZone, task)\n }\n\n onHasTask(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, hasTaskState: HasTaskState) {\n if (currentZone === targetZone) {\n if (hasTaskState.change === \"microTask\") {\n this.microtasks += hasTaskState.microTask ? 1 : -1\n checkStable(this)\n } else if (hasTaskState.change === \"macroTask\") {\n this.macroTasks += hasTaskState.macroTask ? 1 : -1\n checkStable(this)\n }\n }\n return parentZoneDelegate.hasTask(targetZone, hasTaskState)\n }\n\n onHandleError(parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any) {\n this.transition.failed = true\n this.transition.thrownError = error\n return parentZoneDelegate.handleError(targetZone, error)\n }\n\n cancelTasks() {\n for (const task of this.tasks) {\n task.zone.cancelTask(task)\n }\n }\n\n constructor(public name: string, public transition: Transition<any>) {}\n}\n\nexport class Transition<T = unknown> implements OnSelect {\n private readonly spec: TransitionSpec = new TransitionSpec(\"transition\", this)\n private readonly emitter: EventEmitter<T>\n\n readonly timeoutMs: number\n readonly slowMs: number\n readonly resetOnSuccess: boolean\n readonly isUnstable = new BehaviorSubject<boolean>(false)\n readonly isSlow = new BehaviorSubject<boolean>(false)\n readonly onError = new Subject<unknown>()\n\n timeout = false\n failed = false\n retryCount = 0\n thrownError: unknown = null\n\n get stable() {\n return !this.unstable\n }\n\n get unstable() {\n return this.isUnstable.value\n }\n\n get slow() {\n return this.isSlow.value\n }\n\n next(value: T) {\n this.run(this.emitter.next, this.emitter, value)\n }\n\n error(error: unknown) {\n this.run(this.emitter.error, this.emitter, error)\n }\n\n complete() {\n this.run(this.emitter.complete, this.emitter)\n }\n\n emit(value: T) {\n this.run(this.emitter.emit, this.emitter, value)\n return this.isUnstable.pipe(\n takeWhile(Boolean)\n )\n }\n\n cancel() {\n this.spec.cancelTasks()\n }\n\n subscribe(next: (value: T) => void): Subscription;\n subscribe(observer?: Partial<Observer<T>>): Subscription\n subscribe(observer?: any): Subscription {\n return this.emitter.subscribe(observer);\n }\n\n run<T extends (...args: any[]) => any>(fn: Function, applyThis?: {}, ...applyArgs: Parameters<T>): ReturnType<T> {\n if (Zone.current.get(\"id\") === this.spec.properties.id) {\n return fn.apply(this, applyArgs)\n } else {\n const zone = Zone.current.fork(this.spec)\n if (this.options.cancelPrevious) {\n this.cancel()\n }\n return zone.runGuarded(fn, applyThis, applyArgs)\n }\n }\n\n ngOnSelect(observer: PartialObserver<any>) {\n return merge(this.isUnstable, this.isSlow).pipe(map(() => this)).subscribe(observer)\n }\n\n constructor(private options: TransitionOptions = {}) {\n this.emitter = new EventEmitter<T>(options.async)\n this.slowMs = options.slowMs ?? 0\n this.timeoutMs = options.timeoutMs ?? 0\n this.resetOnSuccess = options.resetOnSuccess ?? false\n }\n}\n\nexport interface UseTransitionOptions {\n emit: boolean\n}\n\nexport function useTransition<T>(transition?: Transition<T>, options?: { emit: true }): MonoTypeOperatorFunction<T>\nexport function useTransition<T>(transition?: Transition, options?: { emit: false }): MonoTypeOperatorFunction<T>\nexport function useTransition<T>(transition?: Transition, options: UseTransitionOptions = { emit: false }): MonoTypeOperatorFunction<T> {\n return source => transition ? new Observable<any>(subscriber => {\n return transition.run(() => {\n if (options.emit) {\n subscriber.add(transition.subscribe(subscriber))\n }\n subscriber.add(source.subscribe(subscriber))\n return subscriber\n })\n }) : source\n}\n\ninterface TransitionToken {\n new<T>(name: string, options?: TransitionOptions): InjectionToken<Transition<T>>\n}\n\nexport const TransitionToken: TransitionToken = class TransitionToken<T> extends InjectionToken<Transition<T>> {\n constructor(name: string, options?: TransitionOptions) {\n super(name, {\n factory() {\n return new Transition(options)\n }\n })\n }\n}\n","import {ProviderToken} from \"@angular/core\";\nimport {Observable} from \"rxjs\";\nimport {\n decorateActions,\n decorateChanges,\n decorateCheck,\n decorateDestroy,\n decorateFactory,\n decorateSelectors,\n decorateSelect,\n setup, decorateOnInit\n} from \"./core\";\nimport {ActionMetadata, Phase} from \"./interfaces\";\nimport {action, caught, selector, setMeta} from \"./metadata\";\n\nconst defaults = {track: true, immediate: true}\n\nexport function createDecorator<T extends {}>(symbol: symbol, defaults: {}) {\n return function decorate(options?: T) {\n return function (target: {}, key: PropertyKey, descriptor?: PropertyDescriptor) {\n setMeta(symbol, {...defaults, ...options, key, descriptor}, target, key)\n }\n }\n}\n\nexport function Store() {\n return function (target: Function) {\n const {prototype} = target\n\n decorateFactory(target, setup)\n decorateChanges(prototype)\n decorateOnInit(prototype)\n decorateDestroy(prototype)\n\n decorateCheck(prototype, Phase.DoCheck)\n decorateCheck(prototype, Phase.AfterContentChecked)\n decorateCheck(prototype, Phase.AfterViewChecked)\n\n decorateActions(prototype)\n decorateSelectors(prototype)\n decorateSelect(target)\n }\n}\n\nexport const Action = createDecorator<ActionMetadata>(action, {phase: Phase.DoCheck})\nexport const Invoke = createDecorator<ActionMetadata>(action, {...defaults, phase: Phase.DoCheck})\nexport const Before = createDecorator<ActionMetadata>(action, {...defaults, phase: Phase.AfterContentChecked})\nexport const Layout = createDecorator<ActionMetadata>(action, {...defaults, phase: Phase.AfterViewChecked})\n\nexport function Caught() {\n return function (target: {}, key: PropertyKey, descriptor: PropertyDescriptor) {\n setMeta(action, { key, descriptor, phase: Phase.DoCheck, catchError: false }, target, key)\n setMeta(caught, { key, descriptor }, target, key)\n }\n}\n\nexport function Select(): (target: {}, key: PropertyKey, descriptor?: PropertyDescriptor) => void\nexport function Select(token: ProviderToken<any>): (target: {}, key: PropertyKey, descriptor: void) => void\nexport function Select(token?: ProviderToken<any>) {\n return function (target: {}, key: PropertyKey, descriptor: any) {\n setMeta(selector, { key, token, descriptor }, target, key)\n }\n}\n\nexport type Action<TFunction extends (...params: any[]) => void = () => void> = TFunction\n\nexport type Select<T> = {\n [key in keyof T]: Observable<T[key]>\n}\n","import {DOCUMENT} from \"@angular/common\";\nimport {inject, Injectable} from \"@angular/core\";\nimport {\n BehaviorSubject,\n debounce,\n EMPTY,\n filter,\n finalize,\n fromEvent,\n interval,\n merge,\n MonoTypeOperatorFunction,\n Observable,\n of,\n ReplaySubject,\n retry,\n share,\n startWith,\n Subject,\n switchAll,\n switchMap,\n takeUntil,\n tap,\n throttle,\n timer,\n} from \"rxjs\";\nimport {observeInZone} from \"./utils\";\n\nexport interface QueryOptions<T = any> {\n key: unknown[]\n refreshInterval?: number\n refreshOnFocus?: boolean\n refreshOnReconnect?: boolean\n refreshIfStale?: boolean\n staleTime?: number\n cacheTime?: number\n resource?: ResourceManager\n}\n\nexport interface MutateOptions {\n invalidate?: unknown[] | unknown[][]\n resource?: ResourceManager\n}\n\nfunction onVisible(document: Document, refCount: BehaviorSubject<any>) {\n return toggle(refCount, fromEvent(document, \"visibilitychange\").pipe(\n filter(() => document.visibilityState === \"visible\")\n ))\n}\n\nfunction onReconnect(document: Document, refCount: BehaviorSubject<any>) {\n const window = document.defaultView\n if (window) {\n return toggle(refCount, fromEvent(window, \"online\"))\n } else {\n return EMPTY\n }\n}\n\nfunction toggle(refCount: BehaviorSubject<number>, source: Observable<any>) {\n const delay = refCount.pipe(\n filter((count) => count > 0)\n )\n const resume = of(null)\n return source.pipe(\n debounce(() => refCount.value > 0 ? resume : delay)\n )\n}\n\n@Injectable({ providedIn: \"root\" })\nexport class ResourceManager {\n cache = new Map()\n document = inject(DOCUMENT)\n\n query<T>(source: Observable<T>, options: QueryOptions): Observable<T> {\n const key = this.keygen(options.key)\n const { cache, document } = this\n\n if (cache.has(key)) {\n const { resource, fetch, errors } = cache.get(key)\n if (options.refreshIfStale !== false) {\n fetch.next(source)\n