@ethlete/query 5.19.0 → 5.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +3 -3
  3. package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +3 -3
  4. package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +3 -3
  5. package/esm2022/lib/directives/infinity-query.directive.mjs +3 -3
  6. package/esm2022/lib/directives/query.directive.mjs +3 -3
  7. package/esm2022/lib/experimental/bearer-auth-provider-config.mjs +2 -2
  8. package/esm2022/lib/experimental/bearer-auth-provider.mjs +2 -2
  9. package/esm2022/lib/experimental/http-request.mjs +10 -9
  10. package/esm2022/lib/experimental/index.mjs +2 -1
  11. package/esm2022/lib/experimental/query-dependencies.mjs +6 -6
  12. package/esm2022/lib/experimental/query-errors.mjs +7 -1
  13. package/esm2022/lib/experimental/query-execute-utils.mjs +19 -22
  14. package/esm2022/lib/experimental/query-execute.mjs +9 -7
  15. package/esm2022/lib/experimental/query-features.mjs +13 -13
  16. package/esm2022/lib/experimental/query-repository.mjs +28 -22
  17. package/esm2022/lib/experimental/query-snapshot.mjs +2 -1
  18. package/esm2022/lib/experimental/query-stack.mjs +65 -0
  19. package/esm2022/lib/experimental/query-utils.mjs +32 -4
  20. package/esm2022/lib/experimental/query.mjs +6 -14
  21. package/esm2022/lib/experimental/secure-query-execute.mjs +9 -6
  22. package/esm2022/lib/experimental/secure-query.mjs +6 -14
  23. package/esm2022/lib/query-form/query-form.mjs +15 -6
  24. package/esm2022/lib/query-form/query-form.types.mjs +1 -1
  25. package/esm2022/lib/utils/data.utils.mjs +2 -2
  26. package/fesm2022/ethlete-query.mjs +230 -124
  27. package/fesm2022/ethlete-query.mjs.map +1 -1
  28. package/lib/experimental/http-request.d.ts +72 -14
  29. package/lib/experimental/index.d.ts +1 -0
  30. package/lib/experimental/query-dependencies.d.ts +2 -2
  31. package/lib/experimental/query-errors.d.ts +5 -1
  32. package/lib/experimental/query-execute-utils.d.ts +12 -4
  33. package/lib/experimental/query-execute.d.ts +9 -2
  34. package/lib/experimental/query-features.d.ts +4 -1
  35. package/lib/experimental/query-repository.d.ts +41 -20
  36. package/lib/experimental/query-snapshot.d.ts +2 -0
  37. package/lib/experimental/query-stack.d.ts +46 -0
  38. package/lib/experimental/query-utils.d.ts +10 -2
  39. package/lib/experimental/query.d.ts +8 -5
  40. package/lib/experimental/secure-query.d.ts +2 -2
  41. package/lib/query-form/query-form.types.d.ts +8 -0
  42. package/package.json +1 -1
@@ -2,7 +2,7 @@ import * as i1 from '@ethlete/core';
2
2
  import { createDestroy, computedTillTruthy, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, getDomain, syncSignal, injectQueryParamChanges, injectQueryParams, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
3
3
  import { Observable, takeUntil, startWith, pairwise, tap, switchMap, of, BehaviorSubject, Subject, fromEvent, timer, take, filter, takeWhile, map, shareReplay, ReplaySubject, combineLatest, interval, skip, withLatestFrom, debounceTime, Subscription, retry, throwError, catchError, merge } from 'rxjs';
4
4
  import * as i0 from '@angular/core';
5
- import { assertInInjectionContext, inject, Injector, computed, signal, isDevMode, untracked, TemplateRef, ViewContainerRef, ErrorHandler, ChangeDetectorRef, Directive, Input, InjectionToken, ElementRef, Pipe, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, DestroyRef, runInInjectionContext, NgZone } from '@angular/core';
5
+ import { assertInInjectionContext, inject, Injector, computed, signal, isDevMode, untracked, TemplateRef, ViewContainerRef, ErrorHandler, ChangeDetectorRef, Directive, Input, InjectionToken, ElementRef, Pipe, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, runInInjectionContext, EnvironmentInjector, createEnvironmentInjector, DestroyRef, NgZone } from '@angular/core';
6
6
  import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
7
  import { AsyncPipe, JsonPipe, NgClass } from '@angular/common';
8
8
  import * as i1$1 from '@angular/forms';
@@ -632,7 +632,7 @@ function queryStateSignal(source, options) {
632
632
  const { cacheResponse } = options ?? {};
633
633
  return toSignal(toObservable(source).pipe(switchMap((q) => extractQuery(q)?.state$ ?? of(null)), switchMap((state) => {
634
634
  if (cacheResponse) {
635
- return of(state).pipe(filterQueryStates(["SUCCESS" /* QueryStateType.Success */, "FAILURE" /* QueryStateType.Failure */, "CANCELLED" /* QueryStateType.Cancelled */]));
635
+ return of(state).pipe(filterQueryStates(["SUCCESS" /* QueryStateType.Success */, "FAILURE" /* QueryStateType.Failure */]));
636
636
  }
637
637
  return of(state);
638
638
  })), {
@@ -1959,10 +1959,10 @@ class QueryDirective {
1959
1959
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
1960
1960
  }
1961
1961
  }
1962
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1963
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.4", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1962
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1963
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.6", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1964
1964
  }
1965
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryDirective, decorators: [{
1965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryDirective, decorators: [{
1966
1966
  type: Directive,
1967
1967
  args: [{
1968
1968
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -2270,10 +2270,10 @@ class InfinityQueryDirective {
2270
2270
  this._viewContext.currentQuery = null;
2271
2271
  this._data$.next([]);
2272
2272
  }
2273
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2274
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.4", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 }); }
2273
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2274
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.6", type: InfinityQueryDirective, isStandalone: true, selector: "[etInfinityQuery]", inputs: { infinityQuery: ["etInfinityQuery", "infinityQuery"] }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }], exportAs: ["etInfinityQuery"], hostDirectives: [{ directive: i1.DelayableDirective }], ngImport: i0 }); }
2275
2275
  }
2276
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2276
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2277
2277
  type: Directive,
2278
2278
  args: [{
2279
2279
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -2326,10 +2326,10 @@ class InfinityQueryTriggerDirective {
2326
2326
  });
2327
2327
  this._observer.observe(this._elementRef.nativeElement);
2328
2328
  }
2329
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2330
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.4", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
2329
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2330
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.6", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
2331
2331
  }
2332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2332
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2333
2333
  type: Directive,
2334
2334
  args: [{
2335
2335
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -2354,10 +2354,10 @@ class QueryShortNamePipe {
2354
2354
  }
2355
2355
  return route;
2356
2356
  }
2357
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2358
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.1.4", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
2357
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2358
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.6", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
2359
2359
  }
2360
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2360
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2361
2361
  type: Pipe,
2362
2362
  args: [{ name: 'queryShortName', standalone: true }]
2363
2363
  }] });
@@ -2648,10 +2648,10 @@ class QueryDevtoolsComponent {
2648
2648
  clearQueryHistory() {
2649
2649
  this.queryHistory$.next([]);
2650
2650
  }
2651
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2652
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.4", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid #3c424a;padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid #3c424a;margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }, { kind: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
2651
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2652
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.6", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "@if (!isOpen()) {\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn et-qd-chip\">Query Devtools</button>\n}\n\n@if (isOpen()) {\n <div\n [class.et-query-devtools-container--transparent]=\"isTranslucent()\"\n class=\"et-query-devtools-container et-query-devtools-container--snap-{{ snapLayout() }}\"\n >\n <header class=\"et-qd-header\">\n <h3 class=\"et-qd-header__title\">Query Devtools</h3>\n\n <div class=\"et-qd-header__select\">\n <label for=\"et-query-client-instance\">Client instance</label>\n <select [formControl]=\"selectedClientIdCtrl\" id=\"et-query-client-instance\">\n @for (clientConfig of queryClientConfigs; track trackByClient(i, clientConfig); let i = $index) {\n <option [value]=\"i\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </option>\n }\n </select>\n </div>\n\n <button (click)=\"toggleOpen()\" class=\"et-qd-btn et-qd-btn-secondary\">Close</button>\n </header>\n\n <div class=\"et-qd-sub-header\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !isTranslucent() }\"\n (click)=\"toggleTranslucent()\"\n class=\"et-qd-chip et-qd-translucent-clickable\"\n >\n Translucent\n </button>\n <div class=\"et-qd-sub-header__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'full' }\"\n (click)=\"selectSnapLayout('full')\"\n class=\"et-qd-chip\"\n >\n Fullscreen\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'top' }\"\n (click)=\"selectSnapLayout('top')\"\n class=\"et-qd-chip\"\n >\n Top\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'bottom' }\"\n (click)=\"selectSnapLayout('bottom')\"\n class=\"et-qd-chip\"\n >\n Bottom\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'left' }\"\n (click)=\"selectSnapLayout('left')\"\n class=\"et-qd-chip\"\n >\n Left\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': snapLayout() !== 'right' }\"\n (click)=\"selectSnapLayout('right')\"\n class=\"et-qd-chip\"\n >\n Right\n </button>\n </div>\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-client\">\n <p class=\"et-qd-client__title\">{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <div class=\"et-qd-client__actions\">\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\" class=\"et-qd-chip\">Refresh all</button>\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\" class=\"et-qd-chip\">\n Refresh all (ignore caches)\n </button>\n <button\n (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\"\n class=\"et-qd-chip\"\n >\n Refresh all (ignore caches & purge unused)\n </button>\n </div>\n </div>\n }\n\n @if (selectedClientConfig(); as cfg) {\n <div class=\"et-qd-queries\">\n <p class=\"et-qd-queries__title\">Inspector</p>\n <div class=\"et-qd-queries__actions\">\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'live' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('live'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Live Queries ({{ queries()?.length ?? 0 }})\n </button>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': queryListMode() !== 'history' || viewMode() !== 'query' }\"\n (click)=\"selectQueryListMode('history'); selectViewMode('query')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Query History ({{ (queryHistory$ | async)?.length ?? 0 }}/50)\n </button>\n @if (queryListMode() === 'history' && viewMode() === 'query') {\n <div class=\"et-qd-queries__divider\"></div>\n <button (click)=\"clearQueryHistory()\" class=\"et-qd-chip et-qd-chip-bordered\">Clear history</button>\n }\n\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': viewMode() !== 'authProvider' }\"\n (click)=\"selectViewMode('authProvider')\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Auth Provider\n </button>\n </div>\n\n @if (viewMode() === 'query') {\n <div class=\"et-qd-queries__browser\">\n @if (queryListMode() === 'live') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queries(); track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n @if (queryListMode() === 'history') {\n <ul class=\"et-qd-queries__browser-list\">\n @for (query of queryHistory$ | async; track trackByQuery($index, query)) {\n <li>\n <button\n [class.et-qd-query--active]=\"selectedQuery()?._id === query._id\"\n (click)=\"selectQuery(query)\"\n >\n <span> {{ query._queryConfig.method }}</span>\n <span> {{ query | queryShortName }}</span>\n </button>\n </li>\n }\n </ul>\n }\n <div class=\"et-qd-queries__browser-detail\">\n @if (selectedQuery(); as query) {\n <p class=\"et-qd-queries__browser-detail__title\">\n {{ query._queryConfig.method }} {{ query._routeWithParams }}\n </p>\n\n <div class=\"et-qd-queries__actions\">\n <button (click)=\"query.execute()\" class=\"et-qd-chip et-qd-chip-bordered\">Execute</button>\n <button (click)=\"query.execute({ skipCache: true })\" class=\"et-qd-chip et-qd-chip-bordered\">\n Execute (ignore cache)\n </button>\n\n <button (click)=\"query.abort()\" class=\"et-qd-chip et-qd-chip-bordered\">Abort</button>\n <div class=\"et-qd-queries__divider\"></div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !query.isPolling }\"\n (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Poll\n </button>\n\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': query.isPolling }\"\n (click)=\"query.stopPolling()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Stop polling\n </button>\n @if (query.isPolling || query._isPollingPaused) {\n <button (click)=\"query.pausePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Pause polling\n </button>\n <button (click)=\"query.resumePolling()\" class=\"et-qd-chip et-qd-chip-secondary et-qd-chip-bordered\">\n Resume polling\n </button>\n }\n </div>\n\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>State type</p>\n <pre>{{ query.rawState.type }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Dependents</p>\n <pre>{{ query._dependents | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is expired</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is in use</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Subscriber count</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Is polling paused</p>\n <pre>{{ query._isPollingPaused }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Enable smart polling</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query store key</p>\n <pre>{{ query._queryStoreKey }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Arguments</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showArguments() }\"\n (click)=\"toggleShowArguments()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showArguments()) {\n <pre>{{ query._arguments | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <p><i> Warning, this will cause a subscription if shown!</i></p>\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showResponse() }\"\n (click)=\"toggleShowResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showResponse()) {\n <pre>{{ query.state$ | async | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Raw state</p>\n <p><i> The query state unaffected by entity stores</i></p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showRawResponse() }\"\n (click)=\"toggleShowRawResponse()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showRawResponse()) {\n <pre>{{ query.rawState | json }}</pre>\n }\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Query config</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showQueryConfig() }\"\n (click)=\"toggleShowQueryConfig()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showQueryConfig()) {\n <pre>{{ stringifiedQueryConfig() | json }}</pre>\n }\n </div>\n\n @if (!!query._queryConfig.entity) {\n <div class=\"et-qd-list-item\">\n <p>Entity store value</p>\n\n <div>\n <button\n [ngClass]=\"{ 'et-qd-chip-secondary': !showEntityStoreValue() }\"\n (click)=\"toggleShowEntityStoreValue()\"\n class=\"et-qd-chip et-qd-chip-bordered\"\n >\n Toggle\n </button>\n </div>\n @if (showEntityStoreValue()) {\n <pre>{{ selectedQueryEntityStoreValue$ | async | json }}</pre>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else if (viewMode() === 'authProvider') {\n <div class=\"et-qd-auth-provider__viewer\">\n @if (authProviderDetails(); as details) {\n <div class=\"et-qd-list\">\n <div class=\"et-qd-list-item\">\n <p>Type</p>\n <pre>{{ details.type }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Header value</p>\n <pre>{{ details.header() | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Config</p>\n <pre>{{ details.config | json }}</pre>\n </div>\n\n @if (details.type === 'BearerAuthProvider') {\n <div class=\"et-qd-list-item\">\n <p>Tokens</p>\n <pre>{{ details.provider.tokens$ | async | json }}</pre>\n </div>\n\n <div class=\"et-qd-list-item\">\n <p>Should refresh on unauthorized response</p>\n <pre>{{ details.provider.shouldRefreshOnUnauthorizedResponse }}</pre>\n </div>\n\n <ng-container\n *etQuery=\"\n details.provider.currentRefreshQuery$ | async as response;\n loading as loading;\n error as error;\n query as query\n \"\n >\n <div class=\"et-qd-list-item\">\n <p>Refresh query response</p>\n\n <div>\n <button (click)=\"details.provider._refreshQuery()\" class=\"et-qd-chip et-qd-chip-bordered\">\n Refresh\n </button>\n </div>\n <pre>{{ response | json }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query loading</p>\n <pre>{{ loading }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>Refresh query error</p>\n <pre>{{ error ?? 'null' }}</pre>\n </div>\n <div class=\"et-qd-list-item\">\n <p>State</p>\n <pre>{{ query?.state$ | async | json }}</pre>\n </div>\n </ng-container>\n }\n </div>\n } @else {\n <p>No auth provider set</p>\n }\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{position:fixed;top:0;z-index:1000000;font-size:14px;color:#fff}.et-query-devtools-container{position:fixed;inset:0;background-color:#25292e;z-index:10000;overflow:auto;font-family:monospace;display:grid;grid-template-rows:auto auto auto minmax(0,1fr)}.et-query-devtools-container.et-query-devtools-container--transparent{opacity:.25;pointer-events:none}.et-query-devtools-container.et-query-devtools-container--transparent .et-query-devtools-translucent-btn{pointer-events:all}.et-query-devtools-container.et-query-devtools-container--snap-left{inset-inline-start:0;inset-block-start:0;inset-block-end:0;width:50%;border-right:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-right{inset-inline-start:unset;inset-inline-end:0;inset-block-start:0;inset-block-end:0;width:50%;border-left:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-top{inset-inline-start:0;inset-block-start:0;inset-inline-end:0;height:50%;border-bottom:1px solid rgb(37,41,46)}.et-query-devtools-container.et-query-devtools-container--snap-bottom{inset-inline-start:0;inset-block-start:unset;inset-block-end:0;inset-inline-end:0;height:50%;border-top:1px solid rgb(37,41,46)}button.et-query-devtools-open-btn{position:fixed;inset-inline-end:20px;inset-block-end:0;z-index:9999;font-family:monospace;border-radius:3px 3px 0 0;line-height:14px;font-size:12px}.et-qd-header{background-color:#00ffa1;padding:12px;display:grid;grid-template-columns:1fr auto auto;gap:12px;align-items:center}.et-qd-header__title{color:#25292e;margin:0;font-size:22px}.et-qd-header__select{display:grid;background-color:#25292e;border-radius:10px;overflow:hidden}.et-qd-header__select select{width:250px;color:#fff;padding:3px 10px 2px;border:none;background-color:#25292e;font-family:monospace}.et-qd-header__select label{padding:3px 10px;color:#25292e;font-size:12px;font-weight:700;color:#fff;border-bottom:1px solid gray}.et-qd-sub-header{background-color:#00b371;padding:12px;display:flex;gap:12px;flex-wrap:wrap}.et-qd-sub-header__divider{width:1px;background-color:#25292e}.et-qd-btn{background-color:#00ffa1;color:#25292e;border:none;padding:12px;cursor:pointer;font-size:14px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;width:100%;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-btn:hover{background-color:#00cc81}.et-qd-btn.et-qd-btn-secondary{background-color:#25292e;color:#00ffa1}.et-qd-btn.et-qd-btn-secondary:hover{background-color:#3c424a}.et-qd-chip{background-color:#00ffa1;color:#25292e;border:none;padding:4px 9px;cursor:pointer;font-size:12px;font-weight:700;text-align:center;text-decoration:none;display:inline-block;transition:all .3s ease-in-out;font-family:monospace;border-radius:10px}.et-qd-chip:hover{background-color:#00cc81}.et-qd-chip.et-qd-chip-secondary{background-color:#25292e;color:#00ffa1}.et-qd-chip.et-qd-chip-secondary:hover{background-color:#3c424a}.et-qd-chip.et-qd-chip-bordered{border:1px solid rgb(0,255,161)}.et-qd-translucent-clickable{pointer-events:all}.et-qd-client{border-bottom:1px solid #3c424a;padding:12px}.et-qd-client__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-client__actions{display:flex;gap:12px;margin-top:12px}.et-qd-queries{padding:12px;display:grid;grid-template-rows:auto auto minmax(0,1fr)}.et-qd-queries__actions{display:flex;gap:12px;margin-top:12px;margin-bottom:16px}.et-qd-queries__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-queries__divider{width:1px;background-color:#3c424a}.et-qd-queries__browser{display:grid;grid-template-columns:1fr minmax(0,3fr);margin-left:-12px;margin-right:-12px;border-top:1px solid #3c424a;margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid #3c424a;list-style:none;padding:0;margin:0;display:grid;grid-auto-flow:row;grid-auto-rows:55px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-list li{margin:0}.et-qd-queries__browser-list li button{all:unset;font-family:monospace;box-sizing:border-box;width:100%;border:none;border-bottom:1px solid #3c424a;background-color:#25292e;color:#fff;text-align:left;padding:12px;height:100%;transition:all .3s ease-in-out;cursor:pointer;display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px;display:block}.et-qd-queries__browser-list li button span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.et-qd-queries__browser-list li button span:first-of-type{font-weight:700}.et-qd-queries__browser-list li button:hover,.et-qd-queries__browser-list li button.et-qd-query--active{background-color:#30363c}.et-qd-queries__browser-detail{padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-queries__browser-detail__title{margin:0;font-size:14px;color:#fff;font-weight:700}.et-qd-auth-provider__viewer{border-top:1px solid #3c424a;margin-left:-12px;margin-right:-12px;margin-bottom:-12px;padding:12px;overflow-y:auto;overflow-x:hidden}.et-qd-list{display:grid;gap:12px}.et-qd-list-item{display:grid}.et-qd-list-item p{font-weight:700;margin:0;padding-bottom:8px}.et-qd-list-item p+p{margin-top:-8px}.et-qd-list-item div+pre{margin-top:8px}.et-qd-list-item pre{margin:0;padding:4px;background-color:#0e1012;border-radius:4px;max-height:450px;overflow:auto}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: QueryShortNamePipe, name: "queryShortName" }, { kind: "directive", type: QueryDirective, selector: "[etQuery]", inputs: ["etQuery", "etQueryCache"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
2653
2653
  }
2654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2655
2655
  type: Component,
2656
2656
  args: [{ selector: 'et-query-devtools', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
2657
2657
  class: 'et-query-devtools',
@@ -2865,6 +2865,12 @@ const unableToDecryptBearerToken = (token) => {
2865
2865
  const bearerExpiresInPropertyNotNumber = (expiresIn) => {
2866
2866
  return new RuntimeError(211 /* RuntimeErrorCode.BEARER_EXPIRES_IN_PROPERTY_NOT_NUMBER */, `The expires in property is not a number: ${expiresIn}`);
2867
2867
  };
2868
+ const uncacheableRequestHasCacheKeyParam = (key) => {
2869
+ return new RuntimeError(300 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_CACHE_KEY_PARAM */, `This request is uncacheable, but a cache key was provided: ${key}. Please remove it.`);
2870
+ };
2871
+ const uncacheableRequestHasSkipCacheParam = () => {
2872
+ return new RuntimeError(301 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_SKIP_CACHE_PARAM */, `This request is uncacheable, but skipCache is set to true. Please remove it.`);
2873
+ };
2868
2874
 
2869
2875
  /* eslint-disable @typescript-eslint/no-empty-function */
2870
2876
  const defaultResponseTransformer = (response) => {
@@ -2910,7 +2916,7 @@ const createAuthProviderQuery = (config, authProviderConfig) => {
2910
2916
  return remainingTime;
2911
2917
  });
2912
2918
  const execute = (newArgs, options) => {
2913
- query.execute(newArgs);
2919
+ query.execute({ args: newArgs });
2914
2920
  triggeredInternally.set(options?.triggeredInternally ?? false);
2915
2921
  };
2916
2922
  return {
@@ -3112,7 +3118,7 @@ const createBearerAuthProviderConfig = (options) => {
3112
3118
  queryClientRef: options.queryClientRef,
3113
3119
  token,
3114
3120
  cookie: options.cookie,
3115
- expiresInPropertyName: options.expiresInPropertyName ?? 'exp',
3121
+ expiresInPropertyName: options.expiresInPropertyName || 'exp',
3116
3122
  refreshBuffer: options.refreshBuffer ?? 300000,
3117
3123
  refreshOnUnauthorizedResponse: options.refreshOnUnauthorizedResponse ?? true,
3118
3124
  login: options.login,
@@ -3134,7 +3140,19 @@ const QUERY_EFFECT_ERROR_MESSAGE = 'Effect triggered too often. This is probably
3134
3140
  const queryEffect = (fn, errorMessage, options) => {
3135
3141
  let lastTriggerTs = 0;
3136
3142
  let illegalWrites = 0;
3137
- effect(() => {
3143
+ // The first run should be synchronous anf not depend on the angular scheduler
3144
+ if (options?.injector) {
3145
+ runInInjectionContext(options.injector, () => fn());
3146
+ }
3147
+ else {
3148
+ fn();
3149
+ }
3150
+ let isFirstRun = true;
3151
+ return untracked(() => effect(() => {
3152
+ if (isFirstRun) {
3153
+ isFirstRun = false;
3154
+ return;
3155
+ }
3138
3156
  if (isDevMode()) {
3139
3157
  const now = performance.now();
3140
3158
  if (now - lastTriggerTs < 100) {
@@ -3146,7 +3164,7 @@ const queryEffect = (fn, errorMessage, options) => {
3146
3164
  lastTriggerTs = now;
3147
3165
  }
3148
3166
  fn();
3149
- }, options);
3167
+ }, options));
3150
3168
  };
3151
3169
  const shouldAutoExecuteQuery = (method) => {
3152
3170
  return method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
@@ -3266,11 +3284,28 @@ const maybeExecute = (options) => {
3266
3284
  options.execute();
3267
3285
  }
3268
3286
  };
3287
+ const createQueryObject = (options) => {
3288
+ const { state, execute, createSnapshot, destroy } = options;
3289
+ const query = {
3290
+ execute,
3291
+ args: state.args.asReadonly(),
3292
+ response: state.response.asReadonly(),
3293
+ latestHttpEvent: state.latestHttpEvent.asReadonly(),
3294
+ loading: state.loading.asReadonly(),
3295
+ error: state.error.asReadonly(),
3296
+ lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3297
+ id: execute.currentRepositoryKey,
3298
+ createSnapshot,
3299
+ destroy,
3300
+ };
3301
+ return query;
3302
+ };
3269
3303
 
3270
3304
  /* eslint-disable @typescript-eslint/no-empty-function */
3271
3305
  const SPEED_BUFFER_TIME_IN_MS = 2000;
3272
3306
  const createHttpRequest = (options) => {
3273
3307
  let currentStreamSubscription = Subscription.EMPTY;
3308
+ const { args, clientOptions, dependencies } = options;
3274
3309
  const currentEvent = signal(null);
3275
3310
  const loading = signal(null);
3276
3311
  const error = signal(null);
@@ -3283,16 +3318,16 @@ const createHttpRequest = (options) => {
3283
3318
  const expiresInTs = expiresIn();
3284
3319
  return expiresInTs === null || expiresInTs < Date.now();
3285
3320
  });
3286
- const stream = options.httpClient
3321
+ const stream = dependencies.httpClient
3287
3322
  .request(options.method, options.fullPath, {
3288
3323
  observe: 'events',
3289
- body: options.body,
3290
- reportProgress: options.reportProgress,
3291
- withCredentials: options.withCredentials,
3292
- transferCache: options.transferCache,
3293
- responseType: options.responseType || 'json',
3294
- context: options.context,
3295
- headers: options.headers,
3324
+ body: args?.body,
3325
+ reportProgress: clientOptions?.reportProgress,
3326
+ withCredentials: clientOptions?.withCredentials,
3327
+ transferCache: clientOptions?.transferCache,
3328
+ responseType: clientOptions?.responseType || 'json',
3329
+ context: clientOptions?.context,
3330
+ headers: args?.headers,
3296
3331
  })
3297
3332
  .pipe(tap((event) => updateState(event)), retry({
3298
3333
  delay: (error, retryCount) => {
@@ -3415,26 +3450,24 @@ const createHttpRequest = (options) => {
3415
3450
  return httpRequest;
3416
3451
  };
3417
3452
 
3418
- /* eslint-disable @typescript-eslint/no-empty-function */
3419
3453
  const setupQueryDependencies = (options) => {
3420
- const destroyRef = inject(DestroyRef);
3454
+ const environmentInjector = inject(EnvironmentInjector);
3455
+ const queryEnvironmentInjector = createEnvironmentInjector([], environmentInjector);
3456
+ const destroyRef = queryEnvironmentInjector.get(DestroyRef);
3421
3457
  const client = inject(options.clientConfig.token);
3422
- const injector = inject(Injector);
3423
3458
  const dependencies = {
3424
3459
  destroyRef,
3425
3460
  client,
3426
- injector,
3461
+ injector: queryEnvironmentInjector,
3427
3462
  };
3428
3463
  return dependencies;
3429
3464
  };
3430
3465
 
3431
3466
  const resetExecuteState = (options) => {
3432
3467
  const { executeState, executeOptions: opts } = options;
3433
- const { deps, state } = opts;
3434
- const { effectRefs, previousKey } = executeState;
3435
- deps.client.repository.unbind(previousKey, deps.destroyRef);
3436
- effectRefs.forEach((ref) => ref.destroy());
3437
- effectRefs.length = 0;
3468
+ const { state } = opts;
3469
+ cleanupPreviousExecute({ executeOptions: opts, executeState });
3470
+ opts.deps.client.repository.unbind(executeState.previousKey(), opts.deps.destroyRef);
3438
3471
  state.args.set(null);
3439
3472
  state.error.set(null);
3440
3473
  state.latestHttpEvent.set(null);
@@ -3445,27 +3478,28 @@ const resetExecuteState = (options) => {
3445
3478
  const setupQueryExecuteState = () => {
3446
3479
  return {
3447
3480
  effectRefs: [],
3448
- previousKey: false,
3481
+ previousKey: signal(false),
3449
3482
  };
3450
3483
  };
3451
3484
  const queryExecute = (options) => {
3452
- const { executeOptions, args, executeState } = options;
3485
+ const { executeOptions, args, executeState, options: runQueryOptions } = options;
3453
3486
  const { deps, state, creator, creatorInternals, queryConfig } = executeOptions;
3454
3487
  const { key, request } = deps.client.repository.request({
3455
- method: creatorInternals.method,
3456
3488
  route: creator.route,
3457
- reportProgress: creator.reportProgress,
3458
- withCredentials: creator.withCredentials,
3459
- transferCache: creator.transferCache,
3460
- responseType: creator.responseType || 'json',
3461
- pathParams: args?.pathParams,
3462
- queryParams: args?.queryParams,
3463
- body: args?.body,
3489
+ method: creatorInternals.method,
3490
+ args,
3491
+ clientOptions: {
3492
+ reportProgress: creator.reportProgress,
3493
+ withCredentials: creator.withCredentials,
3494
+ transferCache: creator.transferCache,
3495
+ responseType: creator.responseType,
3496
+ },
3464
3497
  destroyRef: deps.destroyRef,
3465
3498
  key: queryConfig.key,
3466
- headers: args?.headers,
3499
+ previousKey: executeState.previousKey(),
3500
+ runQueryOptions,
3467
3501
  });
3468
- executeState.previousKey = key;
3502
+ executeState.previousKey.set(key);
3469
3503
  runInInjectionContext(deps.injector, () => {
3470
3504
  const responseRef = syncSignal(request.response, state.response);
3471
3505
  const loadingRef = syncSignal(request.loading, state.loading);
@@ -3476,21 +3510,21 @@ const queryExecute = (options) => {
3476
3510
  state.lastTimeExecutedAt.set(Date.now());
3477
3511
  };
3478
3512
  const cleanupPreviousExecute = (options) => {
3479
- const { executeOptions, executeState } = options;
3480
- const { deps } = executeOptions;
3481
- deps.client.repository.unbind(executeState.previousKey, deps.destroyRef);
3513
+ const { executeState } = options;
3482
3514
  executeState.effectRefs.forEach((ref) => ref.destroy());
3483
3515
  executeState.effectRefs.length = 0;
3484
3516
  };
3485
3517
 
3486
- const createExecuteFn = (options) => {
3518
+ const createExecuteFn = (executeOptions) => {
3487
3519
  const executeState = setupQueryExecuteState();
3488
- const reset = () => resetExecuteState({ executeState, executeOptions: options });
3489
- const exec = (args = options.state.args()) => {
3490
- cleanupPreviousExecute({ executeOptions: options, executeState, args });
3491
- queryExecute({ executeOptions: options, executeState, args });
3520
+ const reset = () => resetExecuteState({ executeState, executeOptions });
3521
+ const exec = (executeArgs) => {
3522
+ const { args = executeOptions.state.args() } = executeArgs ?? {};
3523
+ cleanupPreviousExecute({ executeOptions, executeState });
3524
+ queryExecute({ executeOptions, executeState, args });
3492
3525
  };
3493
3526
  exec['reset'] = reset;
3527
+ exec['currentRepositoryKey'] = executeState.previousKey.asReadonly();
3494
3528
  return exec;
3495
3529
  };
3496
3530
 
@@ -3549,6 +3583,7 @@ const createQuerySnapshotFn = (options) => {
3549
3583
  error: snapshotState.error.asReadonly(),
3550
3584
  lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3551
3585
  isAlive: isAlive.asReadonly(),
3586
+ id: options.execute.currentRepositoryKey,
3552
3587
  };
3553
3588
  return snapshot;
3554
3589
  };
@@ -3563,7 +3598,8 @@ const createQuery = (options) => {
3563
3598
  const { creator, creatorInternals, queryConfig } = options;
3564
3599
  const flags = getQueryFeatureUsage(options);
3565
3600
  const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig: options.queryConfig });
3566
- const createSnapshot = createQuerySnapshotFn({ state, deps });
3601
+ const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3602
+ const destroy = () => deps.injector.destroy();
3567
3603
  const featureFnContext = {
3568
3604
  state,
3569
3605
  queryConfig,
@@ -3571,67 +3607,64 @@ const createQuery = (options) => {
3571
3607
  creatorInternals,
3572
3608
  execute,
3573
3609
  flags,
3610
+ deps,
3574
3611
  };
3575
3612
  applyQueryFeatures(options, featureFnContext);
3576
3613
  maybeExecute({ execute, flags });
3577
- const query = {
3578
- execute,
3579
- args: state.args.asReadonly(),
3580
- response: state.response.asReadonly(),
3581
- latestHttpEvent: state.latestHttpEvent.asReadonly(),
3582
- loading: state.loading.asReadonly(),
3583
- error: state.error.asReadonly(),
3584
- lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3585
- createSnapshot,
3586
- };
3587
- return query;
3614
+ return createQueryObject({ state, execute, createSnapshot, destroy });
3588
3615
  };
3589
3616
 
3590
- /* eslint-disable @typescript-eslint/no-explicit-any */
3591
- /* eslint-disable @typescript-eslint/no-empty-function */
3592
3617
  const createQueryRepository = (config) => {
3593
3618
  const httpClient = inject(HttpClient);
3594
3619
  const cache = new Map();
3595
3620
  const request = (options) => {
3621
+ const { args, clientOptions, runQueryOptions } = options;
3596
3622
  const shouldCache = shouldCacheQuery(options.method);
3623
+ if (!shouldCache && options.key)
3624
+ throw uncacheableRequestHasCacheKeyParam(options.key);
3625
+ if (!shouldCache && runQueryOptions?.skipCache)
3626
+ throw uncacheableRequestHasSkipCacheParam();
3597
3627
  const route = buildRoute({
3598
3628
  base: config.baseUrl,
3599
3629
  route: options.route,
3600
- pathParams: options.pathParams,
3601
- queryParams: options.queryParams,
3630
+ pathParams: args?.pathParams,
3631
+ queryParams: args?.queryParams,
3602
3632
  queryParamConfig: config.queryString,
3603
3633
  });
3604
3634
  const key = shouldCache &&
3605
3635
  buildQueryCacheKey(`${options.key ? options.key + '_' : ''}${route}`, {
3606
- body: options.body,
3607
- queryParams: options.queryParams,
3608
- pathParams: options.pathParams,
3636
+ body: args?.body,
3637
+ queryParams: args?.queryParams,
3638
+ pathParams: args?.pathParams,
3609
3639
  // TODO: remaining props
3640
+ // headers: args?.headers,
3610
3641
  });
3642
+ const previousKey = options.previousKey;
3643
+ if (key !== previousKey && previousKey) {
3644
+ unbind(previousKey, options.destroyRef);
3645
+ }
3611
3646
  if (shouldCache && key) {
3612
3647
  const cacheEntry = cache.get(key);
3613
3648
  if (cacheEntry) {
3614
3649
  bind(key, options.destroyRef, cacheEntry.request);
3615
- if (!options.skipExecution)
3650
+ if (runQueryOptions?.skipCache || cacheEntry.request.isStale()) {
3616
3651
  cacheEntry.request.execute();
3652
+ }
3617
3653
  return { key, request: cacheEntry.request };
3618
3654
  }
3619
3655
  }
3620
3656
  const request = createHttpRequest({
3621
3657
  fullPath: route,
3622
- body: options.body,
3623
- reportProgress: options.reportProgress,
3624
- withCredentials: options.withCredentials,
3625
- transferCache: options.transferCache,
3626
- responseType: options.responseType || 'json',
3658
+ args,
3627
3659
  method: options.method,
3628
- headers: options.headers,
3629
- httpClient,
3660
+ dependencies: {
3661
+ httpClient,
3662
+ },
3663
+ clientOptions,
3630
3664
  cacheAdapter: config.cacheAdapter,
3631
3665
  retryFn: config.retryFn,
3632
3666
  });
3633
- if (!options.skipExecution)
3634
- request.execute();
3667
+ request.execute();
3635
3668
  if (shouldCache && key) {
3636
3669
  bind(key, options.destroyRef, request);
3637
3670
  }
@@ -3639,19 +3672,18 @@ const createQueryRepository = (config) => {
3639
3672
  };
3640
3673
  const unbind = (key, destroyRef) => {
3641
3674
  if (!key)
3642
- return;
3675
+ return false;
3643
3676
  const cacheEntry = cache.get(key);
3644
3677
  if (!cacheEntry)
3645
- return;
3678
+ return false;
3646
3679
  cacheEntry.consumers.delete(destroyRef);
3647
3680
  if (cacheEntry.consumers.size === 0) {
3648
3681
  cacheEntry.request.destroy();
3649
3682
  cache.delete(key);
3650
3683
  }
3684
+ return true;
3651
3685
  };
3652
3686
  const bind = (key, destroyRef, request) => {
3653
- if (!key)
3654
- return;
3655
3687
  const destroyListener = destroyRef.onDestroy(() => unbind(key, destroyRef));
3656
3688
  const cacheEntry = cache.get(key);
3657
3689
  if (cacheEntry) {
@@ -3745,7 +3777,8 @@ const createSecureExecuteFn = (options) => {
3745
3777
  state.latestHttpEvent.set(null);
3746
3778
  state.args.set(null);
3747
3779
  };
3748
- const authAndExec = (args) => {
3780
+ const authAndExec = (executeArgs) => {
3781
+ const { args, options: runOptions } = executeArgs ?? {};
3749
3782
  const tokens = authProvider.tokens();
3750
3783
  let headers = args?.headers || new HttpHeaders();
3751
3784
  if (!tokens) {
@@ -3759,12 +3792,13 @@ const createSecureExecuteFn = (options) => {
3759
3792
  executeOptions: options,
3760
3793
  executeState,
3761
3794
  args: updatedArgs,
3795
+ options: runOptions,
3762
3796
  });
3763
3797
  };
3764
- const exec = (args = options.state.args()) => {
3798
+ const exec = (executeArgs) => {
3765
3799
  authQuerySubscription.unsubscribe();
3766
3800
  authQuerySubscription = Subscription.EMPTY;
3767
- cleanupPreviousExecute({ executeOptions: options, executeState, args });
3801
+ cleanupPreviousExecute({ executeOptions: options, executeState });
3768
3802
  const authQuery = authProvider.latestExecutedQuery();
3769
3803
  if (!authQuery || authQuery.loading()) {
3770
3804
  options.state.loading.set({ executeTime: Date.now(), progress: null });
@@ -3779,14 +3813,14 @@ const createSecureExecuteFn = (options) => {
3779
3813
  error(query);
3780
3814
  }
3781
3815
  else if (query.response()) {
3782
- authAndExec(args);
3816
+ authAndExec(executeArgs);
3783
3817
  }
3784
3818
  }));
3785
3819
  }))
3786
3820
  .subscribe();
3787
3821
  }
3788
3822
  else if (authQuery.response()) {
3789
- authAndExec(args);
3823
+ authAndExec(executeArgs);
3790
3824
  }
3791
3825
  else if (authQuery.error()) {
3792
3826
  error(authQuery);
@@ -3796,6 +3830,7 @@ const createSecureExecuteFn = (options) => {
3796
3830
  }
3797
3831
  };
3798
3832
  exec['reset'] = reset;
3833
+ exec['currentRepositoryKey'] = executeState.previousKey.asReadonly();
3799
3834
  return exec;
3800
3835
  };
3801
3836
 
@@ -3811,7 +3846,8 @@ const createSecureQuery = (options) => {
3811
3846
  creatorInternals,
3812
3847
  queryConfig: options.queryConfig,
3813
3848
  });
3814
- const createSnapshot = createQuerySnapshotFn({ state, deps });
3849
+ const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3850
+ const destroy = () => deps.injector.destroy();
3815
3851
  const featureFnContext = {
3816
3852
  state,
3817
3853
  queryConfig,
@@ -3819,20 +3855,11 @@ const createSecureQuery = (options) => {
3819
3855
  creatorInternals,
3820
3856
  execute,
3821
3857
  flags,
3858
+ deps,
3822
3859
  };
3823
3860
  applyQueryFeatures(options, featureFnContext);
3824
3861
  maybeExecute({ execute, flags });
3825
- const query = {
3826
- execute,
3827
- args: state.args.asReadonly(),
3828
- response: state.response.asReadonly(),
3829
- latestHttpEvent: state.latestHttpEvent.asReadonly(),
3830
- loading: state.loading.asReadonly(),
3831
- error: state.error.asReadonly(),
3832
- lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3833
- createSnapshot,
3834
- };
3835
- return query;
3862
+ return createQueryObject({ state, execute, createSnapshot, destroy });
3836
3863
  };
3837
3864
 
3838
3865
  const createSecureQueryCreator = (options, internals) => {
@@ -3899,9 +3926,9 @@ const withArgs = (args) => {
3899
3926
  }
3900
3927
  context.state.args.set(currArgsNow);
3901
3928
  if (context.flags.shouldAutoExecute)
3902
- context.execute(currArgsNow);
3929
+ context.execute({ args: currArgsNow });
3903
3930
  });
3904
- }, QUERY_EFFECT_ERROR_MESSAGE);
3931
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3905
3932
  },
3906
3933
  });
3907
3934
  };
@@ -3921,14 +3948,14 @@ const withPolling = (options) => {
3921
3948
  if (args === null)
3922
3949
  return;
3923
3950
  if (options.executeInitially) {
3924
- context.execute(args);
3951
+ context.execute({ args });
3925
3952
  }
3926
3953
  intervalId = window.setInterval(() => {
3927
- context.execute(args);
3954
+ context.execute({ args });
3928
3955
  }, options.interval);
3929
3956
  });
3930
- }, QUERY_EFFECT_ERROR_MESSAGE);
3931
- inject(DestroyRef).onDestroy(() => intervalId !== null && clearInterval(intervalId));
3957
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3958
+ context.deps.destroyRef.onDestroy(() => intervalId !== null && clearInterval(intervalId));
3932
3959
  },
3933
3960
  });
3934
3961
  };
@@ -3943,7 +3970,7 @@ const withLogging = (options) => {
3943
3970
  untracked(() => {
3944
3971
  options.logFn(event);
3945
3972
  });
3946
- });
3973
+ }, { injector: context.deps.injector });
3947
3974
  },
3948
3975
  });
3949
3976
  };
@@ -3958,7 +3985,7 @@ const withErrorHandling = (options) => {
3958
3985
  untracked(() => {
3959
3986
  options.handler(error);
3960
3987
  });
3961
- });
3988
+ }, { injector: context.deps.injector });
3962
3989
  },
3963
3990
  });
3964
3991
  };
@@ -3973,7 +4000,7 @@ const withSuccessHandling = (options) => {
3973
4000
  untracked(() => {
3974
4001
  options.handler(response);
3975
4002
  });
3976
- });
4003
+ }, { injector: context.deps.injector });
3977
4004
  },
3978
4005
  });
3979
4006
  };
@@ -3995,13 +4022,77 @@ const withAutoRefresh = (options) => {
3995
4022
  const args = context.state.args();
3996
4023
  if (args === null)
3997
4024
  return;
3998
- context.execute(args);
4025
+ context.execute({ args });
3999
4026
  });
4000
- }, QUERY_EFFECT_ERROR_MESSAGE);
4027
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
4001
4028
  },
4002
4029
  });
4003
4030
  };
4004
4031
 
4032
+ const transformArrayResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r);
4033
+ const transformPaginatedResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r.items);
4034
+ const createQueryStack = (computation, options) => {
4035
+ const { append = false, appendFn = (oldQueries, newQueries) => {
4036
+ const queries = [...oldQueries, ...newQueries];
4037
+ const lastQuery = newQueries[newQueries.length - 1] ?? oldQueries[oldQueries.length - 1] ?? null;
4038
+ return { queries, lastQuery };
4039
+ }, transform, } = options ?? {};
4040
+ const injector = inject(Injector);
4041
+ const queries = signal([]);
4042
+ const lastQuery = signal(null);
4043
+ effect(() => {
4044
+ const newQueryOrQueries = runInInjectionContext(injector, () => computation());
4045
+ const newQueries = Array.isArray(newQueryOrQueries) ? newQueryOrQueries : [newQueryOrQueries];
4046
+ untracked(() => {
4047
+ const oldQueries = queries();
4048
+ if (append) {
4049
+ const { queries: appendedQueries, lastQuery: lastAppendedQuery } = appendFn(oldQueries, newQueries);
4050
+ queries.set(appendedQueries);
4051
+ lastQuery.set(lastAppendedQuery);
4052
+ }
4053
+ else {
4054
+ for (const oldQuery of oldQueries) {
4055
+ if (!newQueries.some((q) => q.id() === oldQuery.id())) {
4056
+ oldQuery.destroy();
4057
+ }
4058
+ }
4059
+ queries.set(newQueries);
4060
+ lastQuery.set(newQueries[newQueries.length - 1] ?? null);
4061
+ }
4062
+ });
4063
+ });
4064
+ const loading = computed(() => queries().some((q) => q.loading()));
4065
+ const error = computed(() => queries()
4066
+ .map((q) => q.error())
4067
+ .find((e) => e !== null) ?? null);
4068
+ const response = computed(() => {
4069
+ const responses = queries().map((q) => q.response());
4070
+ return transform?.(responses) ?? responses;
4071
+ });
4072
+ const execute = () => {
4073
+ for (const query of queries()) {
4074
+ query.execute();
4075
+ }
4076
+ };
4077
+ const clear = () => {
4078
+ for (const query of queries()) {
4079
+ query.destroy();
4080
+ }
4081
+ queries.set([]);
4082
+ lastQuery.set(null);
4083
+ };
4084
+ const stack = {
4085
+ queries: queries.asReadonly(),
4086
+ lastQuery: lastQuery.asReadonly(),
4087
+ loading,
4088
+ error,
4089
+ response,
4090
+ execute,
4091
+ clear,
4092
+ };
4093
+ return stack;
4094
+ };
4095
+
4005
4096
  var index = /*#__PURE__*/Object.freeze({
4006
4097
  __proto__: null,
4007
4098
  QUERY_ARGS_RESET: QUERY_ARGS_RESET,
@@ -4024,8 +4115,10 @@ var index = /*#__PURE__*/Object.freeze({
4024
4115
  createQueryClient: createQueryClient,
4025
4116
  createQueryClientConfig: createQueryClientConfig,
4026
4117
  createQueryCreator: createQueryCreator,
4118
+ createQueryObject: createQueryObject,
4027
4119
  createQueryRepository: createQueryRepository,
4028
4120
  createQuerySnapshotFn: createQuerySnapshotFn,
4121
+ createQueryStack: createQueryStack,
4029
4122
  createSecureDeleteQuery: createSecureDeleteQuery,
4030
4123
  createSecureExecuteFn: createSecureExecuteFn,
4031
4124
  createSecureGetQuery: createSecureGetQuery,
@@ -4058,7 +4151,11 @@ var index = /*#__PURE__*/Object.freeze({
4058
4151
  shouldAutoExecuteQuery: shouldAutoExecuteQuery,
4059
4152
  shouldRetryRequest: shouldRetryRequest,
4060
4153
  splitQueryConfig: splitQueryConfig,
4154
+ transformArrayResponse: transformArrayResponse,
4155
+ transformPaginatedResponse: transformPaginatedResponse,
4061
4156
  unableToDecryptBearerToken: unableToDecryptBearerToken,
4157
+ uncacheableRequestHasCacheKeyParam: uncacheableRequestHasCacheKeyParam,
4158
+ uncacheableRequestHasSkipCacheParam: uncacheableRequestHasSkipCacheParam,
4062
4159
  withArgs: withArgs,
4063
4160
  withArgsQueryFeatureMissingButRouteIsFunction: withArgsQueryFeatureMissingButRouteIsFunction,
4064
4161
  withAutoRefresh: withAutoRefresh,
@@ -4401,11 +4498,20 @@ class QueryForm {
4401
4498
  if (field.data.queryParamToValueTransformFn) {
4402
4499
  deserializedValue = field.data.queryParamToValueTransformFn(value);
4403
4500
  }
4404
- else if (typeof this._getDefaultValue(key) === 'number' || !isNaN(Number(value))) {
4405
- deserializedValue = transformToNumber(value);
4406
- }
4407
- else if (typeof this._getDefaultValue(key) === 'boolean' || value === 'true' || value === 'false') {
4408
- deserializedValue = transformToBoolean(value);
4501
+ else if (!field.data.skipAutoTransform) {
4502
+ const defaultIsNum = this._getDefaultValue(key) === 'number';
4503
+ const valueIsNum = !isNaN(Number(value));
4504
+ const valueContainsWhitespace = typeof value === 'string' && value.trim() !== value;
4505
+ const valueHasLeadingZero = typeof value === 'string' && value.startsWith('0');
4506
+ const valueEndsWithDot = typeof value === 'string' && value.endsWith('.');
4507
+ const defaultIsBool = this._getDefaultValue(key) === 'boolean';
4508
+ const valueIsBool = value === 'true' || value === 'false';
4509
+ if (defaultIsNum || (valueIsNum && !valueContainsWhitespace && !valueHasLeadingZero && !valueEndsWithDot)) {
4510
+ deserializedValue = transformToNumber(value);
4511
+ }
4512
+ else if (defaultIsBool || valueIsBool) {
4513
+ deserializedValue = transformToBoolean(value);
4514
+ }
4409
4515
  }
4410
4516
  const valueIsEqualToCurrent = equal(deserializedValue, field.control.value);
4411
4517
  if (valueIsEqualToCurrent)