@ethlete/query 5.23.0 → 5.25.0

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 (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/fesm2022/ethlete-query.mjs +611 -202
  3. package/fesm2022/ethlete-query.mjs.map +1 -1
  4. package/lib/experimental/{bearer-auth-provider-config.d.ts → auth/bearer-auth-provider-config.d.ts} +11 -3
  5. package/lib/experimental/{bearer-auth-provider.d.ts → auth/bearer-auth-provider.d.ts} +1 -1
  6. package/lib/experimental/auth/index.d.ts +2 -0
  7. package/lib/experimental/gql/gql-query-creator-templates.d.ts +11 -0
  8. package/lib/experimental/gql/gql-query-creator.d.ts +14 -0
  9. package/lib/experimental/gql/gql-query-execute.d.ts +11 -0
  10. package/lib/experimental/gql/gql-query.d.ts +12 -0
  11. package/lib/experimental/gql/index.d.ts +4 -0
  12. package/lib/experimental/http/index.d.ts +20 -0
  13. package/lib/experimental/http/paged-query-stack.d.ts +149 -0
  14. package/lib/experimental/http/query-client-config.d.ts +45 -0
  15. package/lib/experimental/{query-creator-templates.d.ts → http/query-creator-templates.d.ts} +11 -1
  16. package/lib/experimental/http/query-creator.d.ts +73 -0
  17. package/lib/experimental/{query-dependencies.d.ts → http/query-dependencies.d.ts} +5 -0
  18. package/lib/experimental/http/query-errors.d.ts +52 -0
  19. package/lib/experimental/{query-execute-utils.d.ts → http/query-execute-utils.d.ts} +15 -2
  20. package/lib/experimental/{query-execute.d.ts → http/query-execute.d.ts} +5 -3
  21. package/lib/experimental/http/query-features.d.ts +120 -0
  22. package/lib/experimental/{query-repository.d.ts → http/query-repository.d.ts} +3 -1
  23. package/lib/experimental/{query-snapshot.d.ts → http/query-snapshot.d.ts} +2 -2
  24. package/lib/experimental/http/query-stack.d.ts +101 -0
  25. package/lib/experimental/{query-state.d.ts → http/query-state.d.ts} +5 -1
  26. package/lib/experimental/{query-utils.d.ts → http/query-utils.d.ts} +25 -15
  27. package/lib/experimental/{query.d.ts → http/query.d.ts} +26 -2
  28. package/lib/experimental/{secure-query-creator.d.ts → http/secure-query-creator.d.ts} +1 -1
  29. package/lib/experimental/{secure-query-execute.d.ts → http/secure-query-execute.d.ts} +2 -2
  30. package/lib/experimental/index.d.ts +4 -22
  31. package/lib/experimental/ws/index.d.ts +2 -0
  32. package/lib/experimental/ws/web-socket-client-config.d.ts +14 -0
  33. package/lib/experimental/ws/web-socket-client.d.ts +37 -0
  34. package/lib/experimental/ws/web-socket-errors.d.ts +7 -0
  35. package/lib/gql/gql.d.ts +3 -2
  36. package/package.json +8 -7
  37. package/lib/experimental/paged-query.d.ts +0 -77
  38. package/lib/experimental/query-client-config.d.ts +0 -18
  39. package/lib/experimental/query-creator.d.ts +0 -39
  40. package/lib/experimental/query-errors.d.ts +0 -49
  41. package/lib/experimental/query-features.d.ts +0 -48
  42. package/lib/experimental/query-stack.d.ts +0 -48
  43. /package/lib/experimental/{http-request.d.ts → http/http-request.d.ts} +0 -0
  44. /package/lib/experimental/{query-client.d.ts → http/query-client.d.ts} +0 -0
  45. /package/lib/experimental/{secure-query.d.ts → http/secure-query.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import * as i1 from '@ethlete/core';
2
- import { createDestroy, computedTillTruthy, syncSignal, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, getDomain, injectQueryParamChanges, injectQueryParams, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
2
+ import { createDestroy, computedTillTruthy, syncSignal, getCookie, setCookie, deleteCookie, DelayableDirective, nextFrame, RuntimeError, isObject, injectRoute, getDomain, previousSignalValue, 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
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';
@@ -8,6 +8,8 @@ import { AsyncPipe, JsonPipe, NgClass } from '@angular/common';
8
8
  import * as i1$1 from '@angular/forms';
9
9
  import { FormControl, ReactiveFormsModule, FormGroup } from '@angular/forms';
10
10
  import { HttpErrorResponse, HttpStatusCode, HttpEventType, HttpClient, HttpHeaders } from '@angular/common/http';
11
+ import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
12
+ import { io } from 'socket.io-client';
11
13
  import { Router, ActivatedRoute } from '@angular/router';
12
14
 
13
15
  class CustomHeaderAuthProvider {
@@ -708,15 +710,15 @@ class QueryCreator {
708
710
  queryParams: computeQueryQueryParams({ config: this._queryConfig, client: this._client, args }),
709
711
  queryParamConfig: this._client.config.request?.queryParams,
710
712
  });
711
- const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey(route, args);
712
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
713
+ const cacheKey = (args?.config?.queryStoreCacheKey ?? '') + buildQueryCacheKey$1(route, args);
714
+ if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
713
715
  const existingQuery = this._store.get(cacheKey);
714
716
  if (existingQuery) {
715
717
  return existingQuery;
716
718
  }
717
719
  }
718
720
  const query = new Query(this._client, this._queryConfig, route, args ?? {}, cacheKey);
719
- if (shouldCacheQuery(this._queryConfig.method) && !args?.config?.skipQueryStore) {
721
+ if (shouldCacheQuery$1(this._queryConfig.method) && !args?.config?.skipQueryStore) {
720
722
  this._store.add(cacheKey, query);
721
723
  }
722
724
  this._store._dispatchQueryCreated(query);
@@ -961,10 +963,10 @@ class QueryClient {
961
963
  }
962
964
  }
963
965
 
964
- const shouldCacheQuery = (method) => {
966
+ const shouldCacheQuery$1 = (method) => {
965
967
  return method === 'GET' || method === 'OPTIONS' || method === 'HEAD' || method === 'GQL_QUERY';
966
968
  };
967
- const buildQueryCacheKey = (route, args) => {
969
+ const buildQueryCacheKey$1 = (route, args) => {
968
970
  const variables = JSON.stringify(args?.variables || {})
969
971
  // replace all curly braces with empty string
970
972
  .replace(/{|}/g, '')
@@ -988,12 +990,14 @@ const transformGql = (str) => {
988
990
  return function (variables) {
989
991
  const data = { query: str };
990
992
  if (variables)
991
- data['variables'] = JSON.stringify(variables);
993
+ data['variables'] = variables;
992
994
  if (name && name.length) {
993
995
  const operationName = name[2];
994
996
  if (operationName)
995
997
  data['operationName'] = name[2];
996
998
  }
999
+ // minify the query
1000
+ data.query = data.query.replace(/\s+/g, ' ').trim();
997
1001
  return data;
998
1002
  };
999
1003
  };
@@ -1314,7 +1318,7 @@ class Query {
1314
1318
  return this._queryConfig.entity?.store ?? null;
1315
1319
  }
1316
1320
  get canBeCached() {
1317
- return shouldCacheQuery(this._queryConfig.method);
1321
+ return shouldCacheQuery$1(this._queryConfig.method);
1318
1322
  }
1319
1323
  get _isInMockMode() {
1320
1324
  return !!this._arguments?.mock;
@@ -1962,10 +1966,10 @@ class QueryDirective {
1962
1966
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
1963
1967
  }
1964
1968
  }
1965
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1966
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1969
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1970
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.4", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1967
1971
  }
1968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDirective, decorators: [{
1972
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDirective, decorators: [{
1969
1973
  type: Directive,
1970
1974
  args: [{
1971
1975
  selector: '[etQuery]',
@@ -2017,7 +2021,7 @@ class InfinityQuery {
2017
2021
  this._currentPage$ = new BehaviorSubject(null);
2018
2022
  this._currentCalculatedPage$ = new BehaviorSubject(null);
2019
2023
  this._totalPages$ = new BehaviorSubject(null);
2020
- this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
2024
+ this._itemsPerPage$ = new BehaviorSubject(10);
2021
2025
  this._data$ = this._queries$.pipe(switchMap((queries) => {
2022
2026
  if (!queries.length) {
2023
2027
  return of([]);
@@ -2063,6 +2067,7 @@ class InfinityQuery {
2063
2067
  return fullData;
2064
2068
  }), shareReplay({ bufferSize: 1, refCount: true }));
2065
2069
  this._lastQuery$ = this._queries$.pipe(map((queries) => queries[queries.length - 1] ?? null), shareReplay({ bufferSize: 1, refCount: true }));
2070
+ this._itemsPerPage$.next(this._config.limitParam?.value ?? 10);
2066
2071
  }
2067
2072
  nextPage() {
2068
2073
  const newPage = (this._currentPage$.value ?? 0) + 1;
@@ -2272,10 +2277,10 @@ class InfinityQueryDirective {
2272
2277
  this._viewContext.currentQuery = null;
2273
2278
  this._data$.next([]);
2274
2279
  }
2275
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2276
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", 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 }); }
2280
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2281
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.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 }); }
2277
2282
  }
2278
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
2279
2284
  type: Directive,
2280
2285
  args: [{
2281
2286
  selector: '[etInfinityQuery]',
@@ -2327,10 +2332,10 @@ class InfinityQueryTriggerDirective {
2327
2332
  });
2328
2333
  this._observer.observe(this._elementRef.nativeElement);
2329
2334
  }
2330
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2331
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
2335
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2336
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.4", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
2332
2337
  }
2333
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2338
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
2334
2339
  type: Directive,
2335
2340
  args: [{
2336
2341
  selector: '[etInfinityQueryTrigger], et-infinity-query-trigger',
@@ -2354,10 +2359,10 @@ class QueryShortNamePipe {
2354
2359
  }
2355
2360
  return route;
2356
2361
  }
2357
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2358
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
2362
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2363
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, isStandalone: true, name: "queryShortName" }); }
2359
2364
  }
2360
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2365
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryShortNamePipe, decorators: [{
2361
2366
  type: Pipe,
2362
2367
  args: [{ name: 'queryShortName', standalone: true }]
2363
2368
  }] });
@@ -2648,10 +2653,10 @@ class QueryDevtoolsComponent {
2648
2653
  clearQueryHistory() {
2649
2654
  this.queryHistory$.next([]);
2650
2655
  }
2651
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2652
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", 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 rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);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 }); }
2656
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2657
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.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 rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);margin-bottom:-12px}.et-qd-queries__browser-list{border-right:1px solid rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);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 rgb(59.734939759,66.1927710843,74.265060241);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
2658
  }
2654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2659
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
2655
2660
  type: Component,
2656
2661
  args: [{ selector: 'et-query-devtools', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
2657
2662
  class: 'et-query-devtools',
@@ -2813,71 +2818,77 @@ const removeFrom = (store, { where, id }) => {
2813
2818
  };
2814
2819
 
2815
2820
  const queryFeatureUsedMultipleTimes = (type) => {
2816
- return new RuntimeError(0 /* RuntimeErrorCode.QUERY_FEATURE_USED_MULTIPLE_TIMES */, `The query feature "${type}()" was used multiple times.`);
2821
+ return new RuntimeError(0 /* QueryRuntimeErrorCode.QUERY_FEATURE_USED_MULTIPLE_TIMES */, `The query feature "${type}()" was used multiple times.`);
2817
2822
  };
2818
2823
  const withArgsQueryFeatureMissingButRouteIsFunction = () => {
2819
- return new RuntimeError(100 /* RuntimeErrorCode.WITH_ARGS_QUERY_FEATURE_MISSING_BUT_ROUTE_IS_FUNCTION */, `This queries route is a function, but a "withArgs()" feature is missing.`);
2824
+ return new RuntimeError(100 /* QueryRuntimeErrorCode.WITH_ARGS_QUERY_FEATURE_MISSING_BUT_ROUTE_IS_FUNCTION */, `This queries route is a function, but a "withArgs()" feature is missing.`);
2820
2825
  };
2821
2826
  const withPollingUsedOnUnsupportedHttpMethod = (method) => {
2822
- return new RuntimeError(101 /* RuntimeErrorCode.WITH_POLLING_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withPolling()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2827
+ return new RuntimeError(101 /* QueryRuntimeErrorCode.WITH_POLLING_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withPolling()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2823
2828
  };
2824
2829
  const withAutoRefreshUsedOnUnsupportedHttpMethod = (method) => {
2825
- return new RuntimeError(102 /* RuntimeErrorCode.WITH_AUTO_REFRESH_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withAutoRefresh()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2830
+ return new RuntimeError(102 /* QueryRuntimeErrorCode.WITH_AUTO_REFRESH_USED_ON_UNSUPPORTED_HTTP_METHOD */, `This is a "${method}" request, "withAutoRefresh()" is only supported for GET, HEAD, OPTIONS requests and GQL queries.`);
2826
2831
  };
2827
2832
  const withAutoRefreshUsedInManualQuery = () => {
2828
- return new RuntimeError(103 /* RuntimeErrorCode.WITH_AUTO_REFRESH_USED_IN_MANUAL_QUERY */, `"withAutoRefresh()" has been used inside a query that has "onlyManualExecution" set to true.` +
2833
+ return new RuntimeError(103 /* QueryRuntimeErrorCode.WITH_AUTO_REFRESH_USED_IN_MANUAL_QUERY */, `"withAutoRefresh()" has been used inside a query that has "onlyManualExecution" set to true.` +
2829
2834
  ` If this is intentional, set "ignoreOnlyManualExecution" to true inside the auto refresh config.`);
2830
2835
  };
2831
2836
  const cookieLoginTriedButCookieDisabled = () => {
2832
- return new RuntimeError(200 /* RuntimeErrorCode.COOKIE_LOGIN_TRIED_BUT_COOKIE_DISABLED */, `Cookie login has been tried, but the cookie is disabled.`);
2837
+ return new RuntimeError(200 /* QueryRuntimeErrorCode.COOKIE_LOGIN_TRIED_BUT_COOKIE_DISABLED */, `Cookie login has been tried, but the cookie is disabled.`);
2833
2838
  };
2834
2839
  const enableCookieCalledWithoutCookieConfig = () => {
2835
- return new RuntimeError(201 /* RuntimeErrorCode.ENABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `enableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2840
+ return new RuntimeError(201 /* QueryRuntimeErrorCode.ENABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `enableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2836
2841
  };
2837
2842
  const disableCookieCalledWithoutCookieConfig = () => {
2838
- return new RuntimeError(202 /* RuntimeErrorCode.DISABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `disableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2843
+ return new RuntimeError(202 /* QueryRuntimeErrorCode.DISABLE_COOKIE_CALLED_WITHOUT_COOKIE_CONFIG */, `disableCookie() has been called but there is no cookie config. Please set it during the auth provider creation.`);
2839
2844
  };
2840
2845
  const loginCalledWithoutConfig = () => {
2841
- return new RuntimeError(203 /* RuntimeErrorCode.LOGIN_CALLED_WITHOUT_CONFIG */, `login() has been called without a config. Please set it during the auth provider creation.`);
2846
+ return new RuntimeError(203 /* QueryRuntimeErrorCode.LOGIN_CALLED_WITHOUT_CONFIG */, `login() has been called without a config. Please set it during the auth provider creation.`);
2842
2847
  };
2843
2848
  const loginWithTokenCalledWithoutConfig = () => {
2844
- return new RuntimeError(204 /* RuntimeErrorCode.LOGIN_WITH_TOKEN_CALLED_WITHOUT_CONFIG */, `loginWithToken() has been called without a config. Please set it during the auth provider creation.`);
2849
+ return new RuntimeError(204 /* QueryRuntimeErrorCode.LOGIN_WITH_TOKEN_CALLED_WITHOUT_CONFIG */, `loginWithToken() has been called without a config. Please set it during the auth provider creation.`);
2845
2850
  };
2846
2851
  const refreshTokenCalledWithoutConfig = () => {
2847
- return new RuntimeError(205 /* RuntimeErrorCode.REFRESH_TOKEN_CALLED_WITHOUT_CONFIG */, `refreshToken() has been called without a config. Please set it during the auth provider creation.`);
2852
+ return new RuntimeError(205 /* QueryRuntimeErrorCode.REFRESH_TOKEN_CALLED_WITHOUT_CONFIG */, `refreshToken() has been called without a config. Please set it during the auth provider creation.`);
2848
2853
  };
2849
2854
  const selectRoleCalledWithoutConfig = () => {
2850
- return new RuntimeError(206 /* RuntimeErrorCode.SELECT_ROLE_CALLED_WITHOUT_CONFIG */, `selectRole() has been called without a config. Please set it during the auth provider creation.`);
2855
+ return new RuntimeError(206 /* QueryRuntimeErrorCode.SELECT_ROLE_CALLED_WITHOUT_CONFIG */, `selectRole() has been called without a config. Please set it during the auth provider creation.`);
2851
2856
  };
2852
2857
  const defaultResponseTransformerResponseNotObject = (currentType) => {
2853
- return new RuntimeError(207 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_OBJECT */, `The default response transformer expects the response to be an object, but it is a "${currentType}".`);
2858
+ return new RuntimeError(207 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_OBJECT */, `The default response transformer expects the response to be an object, but it is a "${currentType}".`);
2854
2859
  };
2855
2860
  const defaultResponseTransformerResponseNotContainingAccessToken = () => {
2856
- return new RuntimeError(208 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_ACCESS_TOKEN */, `The default response transformer expects the response to contain an "accessToken" property.`);
2861
+ return new RuntimeError(208 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_ACCESS_TOKEN */, `The default response transformer expects the response to contain an "accessToken" property.`);
2857
2862
  };
2858
2863
  const defaultResponseTransformerResponseNotContainingRefreshToken = () => {
2859
- return new RuntimeError(209 /* RuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_REFRESH_TOKEN */, `The default response transformer expects the response to contain a "refreshToken" property.`);
2864
+ return new RuntimeError(209 /* QueryRuntimeErrorCode.DEFAULT_RESPONSE_TRANSFORMER_RESPONSE_NOT_CONTAINING_REFRESH_TOKEN */, `The default response transformer expects the response to contain a "refreshToken" property.`);
2860
2865
  };
2861
2866
  const unableToDecryptBearerToken = (token) => {
2862
- return new RuntimeError(210 /* RuntimeErrorCode.UNABLE_TO_DECRYPT_BEARER_TOKEN */, `The bearer token could not be decrypted: ${token}`);
2867
+ return new RuntimeError(210 /* QueryRuntimeErrorCode.UNABLE_TO_DECRYPT_BEARER_TOKEN */, `The bearer token could not be decrypted: ${token}`);
2863
2868
  };
2864
2869
  const bearerExpiresInPropertyNotNumber = (expiresIn) => {
2865
- return new RuntimeError(211 /* RuntimeErrorCode.BEARER_EXPIRES_IN_PROPERTY_NOT_NUMBER */, `The expires in property is not a number: ${expiresIn}`);
2870
+ return new RuntimeError(211 /* QueryRuntimeErrorCode.BEARER_EXPIRES_IN_PROPERTY_NOT_NUMBER */, `The expires in property is not a number: ${expiresIn}`);
2866
2871
  };
2867
2872
  const uncacheableRequestHasCacheKeyParam = (key) => {
2868
- 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.`);
2873
+ return new RuntimeError(300 /* QueryRuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_CACHE_KEY_PARAM */, `This request is uncacheable, but a cache key was provided: ${key}. Please remove it.`);
2869
2874
  };
2870
2875
  const uncacheableRequestHasAllowCacheParam = () => {
2871
- return new RuntimeError(301 /* RuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_ALLOW_CACHE_PARAM */, `This request is uncacheable, but allowCache is set to true. Please remove it.`);
2876
+ return new RuntimeError(301 /* QueryRuntimeErrorCode.UNCACHEABLE_REQUEST_HAS_ALLOW_CACHE_PARAM */, `This request is uncacheable, but allowCache is set to true. Please remove it.`);
2877
+ };
2878
+ const pagedQueryStackPageBiggerThanTotalPages = (page, totalPages) => {
2879
+ return new RuntimeError(400 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_PAGE_BIGGER_THAN_TOTAL_PAGES */, `The page "${page}" is bigger than the total pages "${totalPages}".`);
2880
+ };
2881
+ const pagedQueryStackNextPageCalledWithoutPreviousPage = () => {
2882
+ return new RuntimeError(401 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_NEXT_PAGE_CALLED_WITHOUT_PREVIOUS_PAGE */, `fetchNextPage() has been called but the current page is not yet loaded. Please call it after the previous page has been loaded.`);
2872
2883
  };
2873
- const pagedQueryPageBiggerThanTotalPages = (page, totalPages) => {
2874
- return new RuntimeError(400 /* RuntimeErrorCode.PAGED_QUERY_PAGE_BIGGER_THAN_TOTAL_PAGES */, `The page "${page}" is bigger than the total pages "${totalPages}".`);
2884
+ const pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage = () => {
2885
+ return new RuntimeError(402 /* QueryRuntimeErrorCode.PAGED_QUERY_STACK_PREVIOUS_PAGE_CALLED_BUT_ALREADY_AT_FIRST_PAGE */, `fetchPreviousPage() has been called but the current page is already the first page.`);
2875
2886
  };
2876
- const pagedQueryNextPageCalledWithoutPreviousPage = () => {
2877
- return new RuntimeError(401 /* RuntimeErrorCode.PAGED_QUERY_NEXT_PAGE_CALLED_WITHOUT_PREVIOUS_PAGE */, `fetchNextPage() has been called but the current page is not yet loaded. Please call it after the previous page has been loaded.`);
2887
+ const queryStackWithArgsUsed = () => {
2888
+ return new RuntimeError(500 /* QueryRuntimeErrorCode.QUERY_STACK_WITH_ARGS_USED */, `withArgs() has been used in a query stack or a paged query stack. This is not supported.`);
2878
2889
  };
2879
- const pagedQueryPreviousPageCalledButAlreadyAtFirstPage = () => {
2880
- return new RuntimeError(402 /* RuntimeErrorCode.PAGED_QUERY_PREVIOUS_PAGE_CALLED_BUT_ALREADY_AT_FIRST_PAGE */, `fetchPreviousPage() has been called but the current page is already the first page.`);
2890
+ const queryStackWithResponseUpdateUsed = () => {
2891
+ return new RuntimeError(501 /* QueryRuntimeErrorCode.QUERY_STACK_WITH_RESPONSE_UPDATE_USED */, `withResponseUpdate() has been used in a query stack or a paged query stack. This is not supported.`);
2881
2892
  };
2882
2893
 
2883
2894
  const defaultResponseTransformer = (response) => {
@@ -2935,6 +2946,7 @@ const createAuthProviderQuery = (config, authProviderConfig) => {
2935
2946
  };
2936
2947
  };
2937
2948
  const createBearerAuthProvider = (options) => {
2949
+ const route = injectRoute();
2938
2950
  const cookieEnabled = signal(options.cookie === undefined ? false : (options.cookie.enabled ?? true));
2939
2951
  const cookieOptions = {
2940
2952
  expiresInDays: 30,
@@ -2943,6 +2955,7 @@ const createBearerAuthProvider = (options) => {
2943
2955
  sameSite: 'lax',
2944
2956
  domain: getDomain() ?? 'localhost',
2945
2957
  refreshArgsTransformer: (token) => ({ body: { token } }),
2958
+ autoLoginExcludeRoutes: [],
2946
2959
  ...(options.cookie ?? {}),
2947
2960
  };
2948
2961
  const loginQuery = options.login ? createAuthProviderQuery(options.login, options) : null;
@@ -3041,10 +3054,10 @@ const createBearerAuthProvider = (options) => {
3041
3054
  };
3042
3055
  const logout = () => {
3043
3056
  deleteCookie$1();
3044
- loginQuery?.query.execute.reset();
3045
- tokenLoginQuery?.query.execute.reset();
3046
- tokenRefreshQuery?.query.execute.reset();
3047
- selectRoleQuery?.query.execute.reset();
3057
+ loginQuery?.query.reset();
3058
+ tokenLoginQuery?.query.reset();
3059
+ tokenRefreshQuery?.query.reset();
3060
+ selectRoleQuery?.query.reset();
3048
3061
  latestNonInternalQuery.set(null);
3049
3062
  };
3050
3063
  const enableCookie = () => {
@@ -3107,7 +3120,9 @@ const createBearerAuthProvider = (options) => {
3107
3120
  tokens,
3108
3121
  };
3109
3122
  if (cookieEnabled()) {
3110
- tryLoginWithCookie();
3123
+ if (!cookieOptions.autoLoginExcludeRoutes.some((r) => route().startsWith(r))) {
3124
+ tryLoginWithCookie();
3125
+ }
3111
3126
  }
3112
3127
  return bearerAuthProvider;
3113
3128
  };
@@ -3136,29 +3151,85 @@ const createBearerAuthProviderConfig = (options) => {
3136
3151
  return bearerAuthProviderConfig;
3137
3152
  };
3138
3153
 
3154
+ const setupQueryState = (options) => {
3155
+ const response = signal(null);
3156
+ const args = signal(null);
3157
+ const latestHttpEvent = signal(null);
3158
+ const error = signal(null);
3159
+ const loading = signal(null);
3160
+ const lastTimeExecutedAt = signal(null);
3161
+ const request = signal(null);
3162
+ const state = {
3163
+ response,
3164
+ args,
3165
+ latestHttpEvent,
3166
+ loading,
3167
+ error,
3168
+ lastTimeExecutedAt,
3169
+ subtle: {
3170
+ request,
3171
+ },
3172
+ };
3173
+ return state;
3174
+ };
3175
+
3176
+ const createQuerySnapshotFn = (options) => {
3177
+ const { state, deps } = options;
3178
+ const snapshotFn = () => {
3179
+ const snapshotState = setupQueryState({});
3180
+ const isAlive = signal(true);
3181
+ const killEffectRef = effect(() => {
3182
+ const currentLoading = state.loading();
3183
+ const currentError = state.error();
3184
+ const currentResponse = state.response();
3185
+ const currentArgs = state.args();
3186
+ const currentLatestHttpEvent = state.latestHttpEvent();
3187
+ const currentLastTimeExecutedAt = state.lastTimeExecutedAt();
3188
+ untracked(() => {
3189
+ snapshotState.args.set(currentArgs);
3190
+ snapshotState.error.set(currentError);
3191
+ snapshotState.lastTimeExecutedAt.set(currentLastTimeExecutedAt);
3192
+ snapshotState.latestHttpEvent.set(currentLatestHttpEvent);
3193
+ snapshotState.loading.set(currentLoading);
3194
+ snapshotState.response.set(currentResponse);
3195
+ if (currentLoading)
3196
+ return;
3197
+ if (!currentResponse && !currentError)
3198
+ return;
3199
+ // kill the effect once loading is done and we either have a response or an error
3200
+ killEffectRef.destroy();
3201
+ isAlive.set(false);
3202
+ });
3203
+ }, { injector: deps.injector });
3204
+ const snapshot = {
3205
+ args: snapshotState.args.asReadonly(),
3206
+ response: snapshotState.response.asReadonly(),
3207
+ latestHttpEvent: snapshotState.latestHttpEvent.asReadonly(),
3208
+ loading: snapshotState.loading.asReadonly(),
3209
+ error: snapshotState.error.asReadonly(),
3210
+ lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3211
+ isAlive: isAlive.asReadonly(),
3212
+ id: normalizeQueryRepositoryKey(options.execute.currentRepositoryKey),
3213
+ };
3214
+ return snapshot;
3215
+ };
3216
+ return snapshotFn;
3217
+ };
3218
+
3139
3219
  /**
3140
- * Returning this inside e.g. a withComputedArgs feature will reset the query args to null.
3220
+ * Returning this inside a withArgs feature will reset the query args to null.
3141
3221
  * This will also pause polling and auto refresh until new args are set.
3142
3222
  */
3143
- const QUERY_ARGS_RESET = Symbol('QUERY_ARGS_RESET');
3223
+ const CLEAR_QUERY_ARGS = Symbol('CLEAR_QUERY_ARGS');
3144
3224
  const QUERY_EFFECT_ERROR_MESSAGE = 'Effect triggered too often. This is probably due to a circular dependency inside the query.';
3145
3225
  /** A angular effect that will throw an error in dev mode if it is called too often. This indicates a circular dependency inside the effect. */
3146
3226
  const queryEffect = (fn, errorMessage, options) => {
3147
3227
  let lastTriggerTs = 0;
3148
3228
  let illegalWrites = 0;
3149
- // The first run should be synchronous anf not depend on the angular scheduler
3150
- if (options?.injector) {
3151
- runInInjectionContext(options.injector, () => fn());
3152
- }
3153
- else {
3154
- fn();
3155
- }
3156
3229
  let isFirstRun = true;
3157
- return untracked(() => effect(() => {
3158
- if (isFirstRun) {
3159
- isFirstRun = false;
3160
- return;
3161
- }
3230
+ const activeConsumer = getActiveConsumer();
3231
+ setActiveConsumer(null);
3232
+ const eff = effect(() => {
3162
3233
  if (isDevMode()) {
3163
3234
  const now = performance.now();
3164
3235
  if (now - lastTriggerTs < 100) {
@@ -3169,12 +3240,20 @@ const queryEffect = (fn, errorMessage, options) => {
3169
3240
  }
3170
3241
  lastTriggerTs = now;
3171
3242
  }
3172
- fn();
3173
- }, options));
3243
+ fn(isFirstRun);
3244
+ if (isFirstRun) {
3245
+ isFirstRun = false;
3246
+ }
3247
+ }, options);
3248
+ setActiveConsumer(activeConsumer);
3249
+ return eff;
3174
3250
  };
3175
3251
  const shouldAutoExecuteQuery = (method) => {
3176
3252
  return method === 'GET' || method === 'HEAD' || method === 'OPTIONS';
3177
3253
  };
3254
+ const shouldAutoExecuteGqlQuery = (method) => {
3255
+ return method === 'QUERY';
3256
+ };
3178
3257
  const extractExpiresInSeconds = (headers) => {
3179
3258
  const cacheControl = headers.get('cache-control');
3180
3259
  const age = headers.get('age');
@@ -3231,8 +3310,8 @@ const shouldRetryRequest = (options) => {
3231
3310
  return { retry: false };
3232
3311
  }
3233
3312
  const { status, error: detail, headers } = error;
3234
- // Retry on 5xx errors
3235
- if (status >= 500) {
3313
+ // Retry on 5xx errors (except 500 internal server error since those are usually not recoverable)
3314
+ if (status >= 501) {
3236
3315
  // Don't retry if a requested page is out of range
3237
3316
  if (isSymfonyPagerfantaOutOfRangeError(detail)) {
3238
3317
  return { retry: false };
@@ -3260,9 +3339,11 @@ const shouldRetryRequest = (options) => {
3260
3339
  return { retry: false };
3261
3340
  };
3262
3341
  const getQueryFeatureUsage = (options) => {
3263
- const { creator, creatorInternals, features, queryConfig } = options;
3342
+ const { creator, features, queryConfig } = options;
3264
3343
  const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3265
- const shouldAutoExecuteMethod = shouldAutoExecuteQuery(creatorInternals.method);
3344
+ const shouldAutoExecuteMethod = isCreateGqlQueryOptions(options)
3345
+ ? shouldAutoExecuteGqlQuery(options.creatorInternals.method)
3346
+ : shouldAutoExecuteQuery(options.creatorInternals.method);
3266
3347
  const shouldAutoExecute = shouldAutoExecuteMethod && !queryConfig.onlyManualExecution;
3267
3348
  const hasRouteFunction = typeof creator.route === 'function';
3268
3349
  if (hasRouteFunction && !hasWithArgsFeature) {
@@ -3273,12 +3354,16 @@ const getQueryFeatureUsage = (options) => {
3273
3354
  shouldAutoExecuteMethod,
3274
3355
  shouldAutoExecute,
3275
3356
  hasRouteFunction,
3357
+ onlyManualExecution: queryConfig.onlyManualExecution,
3358
+ method: isCreateGqlQueryOptions(options)
3359
+ ? `GQL ${options.creatorInternals.method}`
3360
+ : options.creatorInternals.method,
3276
3361
  };
3277
3362
  return featureFnContext;
3278
3363
  };
3279
- const applyQueryFeatures = (options, context) => {
3364
+ const applyQueryFeatures = (features, context) => {
3280
3365
  const featureTypes = new Set();
3281
- for (const feature of options.features) {
3366
+ for (const feature of features) {
3282
3367
  if (featureTypes.has(feature.type)) {
3283
3368
  throw queryFeatureUsedMultipleTimes(feature.type);
3284
3369
  }
@@ -3286,13 +3371,17 @@ const applyQueryFeatures = (options, context) => {
3286
3371
  feature.fn(context);
3287
3372
  }
3288
3373
  };
3374
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3289
3375
  const maybeExecute = (options) => {
3290
3376
  if (options.flags.shouldAutoExecute && !options.flags.hasRouteFunction && !options.flags.hasWithArgsFeature) {
3291
3377
  options.execute();
3292
3378
  }
3293
3379
  };
3294
3380
  const createQueryObject = (options) => {
3295
- const { state, execute, createSnapshot, destroy } = options;
3381
+ const { state, execute, deps } = options;
3382
+ const destroy = () => deps.injector.destroy();
3383
+ const setResponse = (response) => state.response.set(response);
3384
+ const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3296
3385
  const query = {
3297
3386
  execute,
3298
3387
  args: state.args.asReadonly(),
@@ -3301,12 +3390,45 @@ const createQueryObject = (options) => {
3301
3390
  loading: state.loading.asReadonly(),
3302
3391
  error: state.error.asReadonly(),
3303
3392
  lastTimeExecutedAt: state.lastTimeExecutedAt.asReadonly(),
3304
- id: execute.currentRepositoryKey,
3393
+ id: normalizeQueryRepositoryKey(execute.currentRepositoryKey),
3305
3394
  createSnapshot,
3306
- destroy,
3395
+ reset: execute.reset,
3396
+ subtle: {
3397
+ destroy,
3398
+ setResponse,
3399
+ },
3307
3400
  };
3308
3401
  return query;
3309
3402
  };
3403
+ const normalizeQueryRepositoryKey = (key) => computed(() => {
3404
+ const k = key();
3405
+ if (k === false) {
3406
+ // false means the query cannot be cached and thus it is not stored in the repository
3407
+ // We generate a random id in this case to avoid confusion
3408
+ return crypto.randomUUID();
3409
+ }
3410
+ return k;
3411
+ });
3412
+ const shouldCacheQuery = (method) => {
3413
+ return method === 'GET' || method === 'OPTIONS' || method === 'HEAD';
3414
+ };
3415
+ const buildQueryCacheKey = (route, args) => {
3416
+ // We need to hash the body in case it's a gql query and the query get's transported in the body
3417
+ const body = JSON.stringify(args?.body || {})
3418
+ // replace all curly braces with empty string
3419
+ .replace(/{|}/g, '')
3420
+ // replace new lines and whitespaces with empty string
3421
+ .replace(/\s/g, '');
3422
+ const seed = `${route}_${body}`;
3423
+ let hash = 0;
3424
+ for (const char of seed) {
3425
+ hash = (Math.imul(31, hash) + char.charCodeAt(0)) << 0;
3426
+ }
3427
+ // Force positive number hash.
3428
+ // 2147483647 = equivalent of Integer.MAX_VALUE.
3429
+ hash += 2147483647 + 1;
3430
+ return hash.toString();
3431
+ };
3310
3432
 
3311
3433
  const SPEED_BUFFER_TIME_IN_MS = 2000;
3312
3434
  const createHttpRequest = (options) => {
@@ -3459,6 +3581,15 @@ const createHttpRequest = (options) => {
3459
3581
  const createQueryFeature = (config) => {
3460
3582
  return config;
3461
3583
  };
3584
+ /**
3585
+ * A query feature that allows you to set the arguments of the query.
3586
+ * The arguments are read within a computed function, so you can use reactive values.
3587
+ *
3588
+ * To set the arguments to `null`, return the symbol `CLEAR_QUERY_ARGS`.
3589
+ * If you instead return `null`, the arguments won't change.
3590
+ *
3591
+ * Changing arguments will automatically trigger a new execution of the query if it is eligible for auto execution (e.g. a GET request).
3592
+ */
3462
3593
  const withArgs = (args) => {
3463
3594
  return createQueryFeature({
3464
3595
  type: "withArgs" /* QueryFeatureType.WithArgs */,
@@ -3469,7 +3600,7 @@ const withArgs = (args) => {
3469
3600
  if (currArgsNow === null)
3470
3601
  return;
3471
3602
  untracked(() => {
3472
- if (currArgsNow === QUERY_ARGS_RESET) {
3603
+ if (currArgsNow === CLEAR_QUERY_ARGS) {
3473
3604
  context.state.args.set(null);
3474
3605
  return;
3475
3606
  }
@@ -3481,12 +3612,19 @@ const withArgs = (args) => {
3481
3612
  },
3482
3613
  });
3483
3614
  };
3615
+ /**
3616
+ * A query feature that will automatically execute the query at a given interval.
3617
+ * The interval will be cleared when the query is destroyed.
3618
+ * The interval will be reset when the arguments of the query change.
3619
+ *
3620
+ * @throws If the query is not eligible for auto execution (e.g. a POST request)
3621
+ */
3484
3622
  const withPolling = (options) => {
3485
3623
  return createQueryFeature({
3486
3624
  type: "withPolling" /* QueryFeatureType.WithPolling */,
3487
3625
  fn: (context) => {
3488
3626
  if (!context.flags.shouldAutoExecuteMethod) {
3489
- throw withPollingUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3627
+ throw withPollingUsedOnUnsupportedHttpMethod(context.flags.method);
3490
3628
  }
3491
3629
  let intervalId = null;
3492
3630
  queryEffect(() => {
@@ -3494,7 +3632,9 @@ const withPolling = (options) => {
3494
3632
  untracked(() => {
3495
3633
  if (intervalId !== null)
3496
3634
  clearInterval(intervalId);
3497
- if (args === null)
3635
+ // Don't start polling if the query doesn't have args.
3636
+ // It should have args because a withArgs feature is present.
3637
+ if (args === null && context.flags.hasWithArgsFeature)
3498
3638
  return;
3499
3639
  if (options.executeInitially) {
3500
3640
  context.execute({ args });
@@ -3508,68 +3648,78 @@ const withPolling = (options) => {
3508
3648
  },
3509
3649
  });
3510
3650
  };
3651
+ /** A query feature that can be used to log the latest http event */
3511
3652
  const withLogging = (options) => {
3512
3653
  return createQueryFeature({
3513
3654
  type: "withLogging" /* QueryFeatureType.WithLogging */,
3514
3655
  fn: (context) => {
3515
- effect(() => {
3656
+ queryEffect(() => {
3516
3657
  const event = context.state.latestHttpEvent();
3517
3658
  if (event === null)
3518
3659
  return;
3519
3660
  untracked(() => {
3520
3661
  options.logFn(event);
3521
3662
  });
3522
- }, { injector: context.deps.injector });
3663
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3523
3664
  },
3524
3665
  });
3525
3666
  };
3667
+ /** A query feature that can be used to handle errors */
3526
3668
  const withErrorHandling = (options) => {
3527
3669
  return createQueryFeature({
3528
3670
  type: "withErrorHandling" /* QueryFeatureType.WithErrorHandling */,
3529
3671
  fn: (context) => {
3530
- effect(() => {
3672
+ queryEffect(() => {
3531
3673
  const error = context.state.error();
3532
3674
  if (error === null)
3533
3675
  return;
3534
3676
  untracked(() => {
3535
3677
  options.handler(error);
3536
3678
  });
3537
- }, { injector: context.deps.injector });
3679
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3538
3680
  },
3539
3681
  });
3540
3682
  };
3683
+ /** A query feature that can be used to handle successful responses */
3541
3684
  const withSuccessHandling = (options) => {
3542
3685
  return createQueryFeature({
3543
3686
  type: "withSuccessHandling" /* QueryFeatureType.WithSuccessHandling */,
3544
3687
  fn: (context) => {
3545
- effect(() => {
3688
+ queryEffect(() => {
3546
3689
  const response = context.state.response();
3547
3690
  if (response === null)
3548
3691
  return;
3549
3692
  untracked(() => {
3550
3693
  options.handler(response);
3551
3694
  });
3552
- }, { injector: context.deps.injector });
3695
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3553
3696
  },
3554
3697
  });
3555
3698
  };
3699
+ /**
3700
+ * A query feature that will automatically execute the query when any of the provided signals change
3701
+ * @throws If the query is not eligible for auto execution (e.g. a POST request)
3702
+ * @throws If the query has the `onlyManualExecution` query config flag set and `ignoreOnlyManualExecution` is not set
3703
+ */
3556
3704
  const withAutoRefresh = (options) => {
3557
3705
  return createQueryFeature({
3558
3706
  type: "withAutoRefresh" /* QueryFeatureType.WithAutoRefresh */,
3559
3707
  fn: (context) => {
3560
3708
  if (!context.flags.shouldAutoExecuteMethod) {
3561
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3709
+ throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.flags.method);
3562
3710
  }
3563
- if (context.queryConfig.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3564
- throw withAutoRefreshUsedOnUnsupportedHttpMethod(context.creatorInternals.method);
3711
+ if (context.flags.onlyManualExecution && !options.ignoreOnlyManualExecution) {
3712
+ throw withAutoRefreshUsedInManualQuery();
3565
3713
  }
3566
3714
  queryEffect(() => {
3567
- for (const signal of options.signalChanges) {
3715
+ for (const signal of options.onSignalChanges) {
3568
3716
  signal();
3569
3717
  }
3570
3718
  untracked(() => {
3571
3719
  const args = context.state.args();
3572
- if (args === null)
3720
+ // Don't start polling if the query doesn't have args.
3721
+ // It should have args because a withArgs feature is present.
3722
+ if (args === null && context.flags.hasWithArgsFeature)
3573
3723
  return;
3574
3724
  context.execute({ args });
3575
3725
  });
@@ -3577,11 +3727,29 @@ const withAutoRefresh = (options) => {
3577
3727
  },
3578
3728
  });
3579
3729
  };
3730
+ const withResponseUpdate = (options) => {
3731
+ return createQueryFeature({
3732
+ type: "withResponseUpdate" /* QueryFeatureType.WithResponseUpdate */,
3733
+ fn: (context) => {
3734
+ queryEffect(() => {
3735
+ const currentResponse = untracked(() => context.state.response());
3736
+ const response = options.updater({ currentResponse });
3737
+ if (response === null)
3738
+ return;
3739
+ untracked(() => {
3740
+ context.state.response.set(response);
3741
+ });
3742
+ }, QUERY_EFFECT_ERROR_MESSAGE, { injector: context.deps.injector });
3743
+ },
3744
+ });
3745
+ };
3580
3746
 
3747
+ /** Transforms an array of arrays into a single array and filters out `null` values. */
3581
3748
  const transformArrayResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r);
3749
+ /** Transforms an array of paginated responses into a single array and filters out `null` values. */
3582
3750
  const transformPaginatedResponse = (responses) => responses.filter((r) => !!r).flatMap((r) => r.items);
3583
- const createQueryStack = (computation, options) => {
3584
- const { append = false, appendFn = (oldQueries, newQueries) => {
3751
+ const createQueryStack = (options) => {
3752
+ const { args, queryCreator, dependencies, append, features = [], appendFn = (oldQueries, newQueries) => {
3585
3753
  const queries = [...oldQueries, ...newQueries];
3586
3754
  const lastQuery = newQueries[newQueries.length - 1] ?? oldQueries[oldQueries.length - 1] ?? null;
3587
3755
  return { queries, lastQuery };
@@ -3589,9 +3757,25 @@ const createQueryStack = (computation, options) => {
3589
3757
  const injector = inject(Injector);
3590
3758
  const queries = signal([]);
3591
3759
  const lastQuery = signal(null);
3760
+ const hasWithArgsFeature = features.some((f) => f.type == "withArgs" /* QueryFeatureType.WithArgs */);
3761
+ const hasWithOptimisticUpdateFeature = features.some((f) => f.type == "withResponseUpdate" /* QueryFeatureType.WithResponseUpdate */);
3762
+ if (hasWithArgsFeature) {
3763
+ throw queryStackWithArgsUsed();
3764
+ }
3765
+ if (hasWithOptimisticUpdateFeature) {
3766
+ throw queryStackWithResponseUpdateUsed();
3767
+ }
3768
+ effect(() => {
3769
+ // Clear the stack if dependencies change
3770
+ dependencies?.();
3771
+ untracked(() => clear());
3772
+ });
3592
3773
  effect(() => {
3593
- const newQueryOrQueries = runInInjectionContext(injector, () => computation());
3594
- const newQueries = Array.isArray(newQueryOrQueries) ? newQueryOrQueries : [newQueryOrQueries].filter((q) => !!q);
3774
+ const newArgs = args(dependencies?.());
3775
+ if (newArgs === null)
3776
+ return;
3777
+ const newArgsArray = Array.isArray(newArgs) ? newArgs : [newArgs];
3778
+ const newQueries = runInInjectionContext(injector, () => newArgsArray.map((newArgsEntry) => queryCreator(withArgs(() => newArgsEntry), ...features)));
3595
3779
  untracked(() => {
3596
3780
  const oldQueries = queries();
3597
3781
  if (append) {
@@ -3602,7 +3786,7 @@ const createQueryStack = (computation, options) => {
3602
3786
  else {
3603
3787
  for (const oldQuery of oldQueries) {
3604
3788
  if (!newQueries.some((q) => q.id() === oldQuery.id())) {
3605
- oldQuery.destroy();
3789
+ oldQuery.subtle.destroy();
3606
3790
  }
3607
3791
  }
3608
3792
  queries.set(newQueries);
@@ -3625,7 +3809,7 @@ const createQueryStack = (computation, options) => {
3625
3809
  };
3626
3810
  const clear = () => {
3627
3811
  for (const query of queries()) {
3628
- query.destroy();
3812
+ query.subtle.destroy();
3629
3813
  }
3630
3814
  queries.set([]);
3631
3815
  lastQuery.set(null);
@@ -3684,23 +3868,31 @@ const contentfulGqlLikePaginationAdapter = (response) => {
3684
3868
  };
3685
3869
  return pagination;
3686
3870
  };
3687
- const createPagedQuery = (options) => {
3688
- const { responseNormalizer, queryCreator } = options;
3871
+ const fakePaginationAdapter = (totalHits = 10) => {
3872
+ return (response) => {
3873
+ const pagination = {
3874
+ items: [response],
3875
+ totalPages: totalHits,
3876
+ currentPage: 1,
3877
+ itemsPerPage: 1,
3878
+ totalHits,
3879
+ };
3880
+ return pagination;
3881
+ };
3882
+ };
3883
+ const createPagedQueryStack = (options) => {
3884
+ const { responseNormalizer, queryCreator, features } = options;
3689
3885
  const currentPageArgs = signal(null);
3690
3886
  const initialPage = signal(options.initialPage ?? 1);
3691
3887
  const loadedMinPage = signal(initialPage());
3692
3888
  const loadedMaxPage = signal(initialPage());
3693
3889
  const lastResetTimestamp = signal(Date.now());
3694
3890
  const pageDirection = signal('next');
3695
- const stack = createQueryStack(() => {
3696
- const args = currentPageArgs();
3697
- if (!args)
3698
- return null;
3699
- return queryCreator(withArgs(() => {
3700
- return args;
3701
- }));
3702
- }, {
3891
+ const stack = createQueryStack({
3892
+ args: () => currentPageArgs(),
3893
+ queryCreator,
3703
3894
  append: true,
3895
+ features,
3704
3896
  appendFn: (oldQueries, newQueries) => {
3705
3897
  const newQuery = newQueries[0];
3706
3898
  const dir = pageDirection();
@@ -3737,7 +3929,7 @@ const createPagedQuery = (options) => {
3737
3929
  const page = loadedMinPage() - 1;
3738
3930
  if (page < 1) {
3739
3931
  if (isDevMode()) {
3740
- throw pagedQueryPreviousPageCalledButAlreadyAtFirstPage();
3932
+ throw pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage();
3741
3933
  }
3742
3934
  return;
3743
3935
  }
@@ -3750,13 +3942,13 @@ const createPagedQuery = (options) => {
3750
3942
  const currentPagination = pagination();
3751
3943
  if (!currentPagination) {
3752
3944
  if (isDevMode()) {
3753
- throw pagedQueryNextPageCalledWithoutPreviousPage();
3945
+ throw pagedQueryStackNextPageCalledWithoutPreviousPage();
3754
3946
  }
3755
3947
  return;
3756
3948
  }
3757
3949
  if (page > currentPagination.totalPages) {
3758
3950
  if (isDevMode()) {
3759
- throw pagedQueryPageBiggerThanTotalPages(page, currentPagination.totalPages);
3951
+ throw pagedQueryStackPageBiggerThanTotalPages(page, currentPagination.totalPages);
3760
3952
  }
3761
3953
  return;
3762
3954
  }
@@ -3839,7 +4031,7 @@ const createPagedQuery = (options) => {
3839
4031
  error: stack.error,
3840
4032
  lastQuery: stack.lastQuery,
3841
4033
  isFirstLoad,
3842
- queries: stack.queries(),
4034
+ queries: stack.queries,
3843
4035
  reset,
3844
4036
  execute,
3845
4037
  };
@@ -3850,12 +4042,32 @@ const setupQueryDependencies = (options) => {
3850
4042
  const environmentInjector = inject(EnvironmentInjector);
3851
4043
  const queryEnvironmentInjector = createEnvironmentInjector([], environmentInjector);
3852
4044
  const destroyRef = queryEnvironmentInjector.get(DestroyRef);
4045
+ const scopeDestroyRef = inject(DestroyRef);
3853
4046
  const client = inject(options.clientConfig.token);
3854
4047
  const dependencies = {
3855
4048
  destroyRef,
4049
+ scopeDestroyRef,
3856
4050
  client,
3857
4051
  injector: queryEnvironmentInjector,
3858
4052
  };
4053
+ // cleanup the environment injector when the scope (e.g. the component the query is in) is destroyed
4054
+ const scopeDestroyListener = scopeDestroyRef.onDestroy(() => {
4055
+ try {
4056
+ queryEnvironmentInjector.destroy();
4057
+ }
4058
+ catch {
4059
+ // ignore
4060
+ }
4061
+ });
4062
+ destroyRef.onDestroy(() => {
4063
+ // cleanup the scope destroy listener
4064
+ try {
4065
+ scopeDestroyListener();
4066
+ }
4067
+ catch {
4068
+ // ignore
4069
+ }
4070
+ });
3859
4071
  return dependencies;
3860
4072
  };
3861
4073
 
@@ -3878,7 +4090,7 @@ const setupQueryExecuteState = () => {
3878
4090
  };
3879
4091
  };
3880
4092
  const queryExecute = (options) => {
3881
- const { executeOptions, args, executeState, options: runQueryOptions } = options;
4093
+ const { executeOptions, args, executeState, options: runQueryOptions, internalOptions: internalRunQueryOptions, transformResponse, } = options;
3882
4094
  const { deps, state, creator, creatorInternals, queryConfig } = executeOptions;
3883
4095
  const { key, request } = deps.client.repository.request({
3884
4096
  route: creator.route,
@@ -3893,17 +4105,20 @@ const queryExecute = (options) => {
3893
4105
  destroyRef: deps.destroyRef,
3894
4106
  key: queryConfig.key,
3895
4107
  previousKey: executeState.previousKey(),
4108
+ internalRunQueryOptions,
3896
4109
  runQueryOptions,
3897
4110
  });
3898
4111
  executeState.previousKey.set(key);
4112
+ const responseSignal = transformResponse ? computed(() => transformResponse(request.response())) : request.response;
3899
4113
  runInInjectionContext(deps.injector, () => {
3900
- const responseRef = syncSignal(request.response, state.response);
4114
+ const responseRef = syncSignal(responseSignal, state.response);
3901
4115
  const loadingRef = syncSignal(request.loading, state.loading);
3902
4116
  const errorRef = syncSignal(request.error, state.error);
3903
4117
  const latestHttpEventRef = syncSignal(request.currentEvent, state.latestHttpEvent);
3904
4118
  executeState.effectRefs.push(responseRef, loadingRef, errorRef, latestHttpEventRef);
3905
4119
  });
3906
4120
  state.lastTimeExecutedAt.set(Date.now());
4121
+ state.subtle.request.set(request);
3907
4122
  };
3908
4123
  const cleanupPreviousExecute = (options) => {
3909
4124
  const { executeState } = options;
@@ -3924,88 +4139,22 @@ const createExecuteFn = (executeOptions) => {
3924
4139
  return exec;
3925
4140
  };
3926
4141
 
3927
- const setupQueryState = (options) => {
3928
- const response = signal(null);
3929
- const args = signal(null);
3930
- const latestHttpEvent = signal(null);
3931
- const error = signal(null);
3932
- const loading = signal(null);
3933
- const lastTimeExecutedAt = signal(null);
3934
- const state = {
3935
- response,
3936
- args,
3937
- latestHttpEvent,
3938
- loading,
3939
- error,
3940
- lastTimeExecutedAt,
3941
- };
3942
- return state;
3943
- };
3944
-
3945
- const createQuerySnapshotFn = (options) => {
3946
- const { state, deps } = options;
3947
- const snapshotFn = () => {
3948
- const snapshotState = setupQueryState({});
3949
- const isAlive = signal(true);
3950
- const killEffectRef = effect(() => {
3951
- const currentLoading = state.loading();
3952
- const currentError = state.error();
3953
- const currentResponse = state.response();
3954
- const currentArgs = state.args();
3955
- const currentLatestHttpEvent = state.latestHttpEvent();
3956
- const currentLastTimeExecutedAt = state.lastTimeExecutedAt();
3957
- untracked(() => {
3958
- snapshotState.args.set(currentArgs);
3959
- snapshotState.error.set(currentError);
3960
- snapshotState.lastTimeExecutedAt.set(currentLastTimeExecutedAt);
3961
- snapshotState.latestHttpEvent.set(currentLatestHttpEvent);
3962
- snapshotState.loading.set(currentLoading);
3963
- snapshotState.response.set(currentResponse);
3964
- if (currentLoading)
3965
- return;
3966
- if (!currentResponse && !currentError)
3967
- return;
3968
- // kill the effect once loading is done and we either have a response or an error
3969
- killEffectRef.destroy();
3970
- isAlive.set(false);
3971
- });
3972
- }, { injector: deps.injector });
3973
- const snapshot = {
3974
- args: snapshotState.args.asReadonly(),
3975
- response: snapshotState.response.asReadonly(),
3976
- latestHttpEvent: snapshotState.latestHttpEvent.asReadonly(),
3977
- loading: snapshotState.loading.asReadonly(),
3978
- error: snapshotState.error.asReadonly(),
3979
- lastTimeExecutedAt: snapshotState.lastTimeExecutedAt.asReadonly(),
3980
- isAlive: isAlive.asReadonly(),
3981
- id: options.execute.currentRepositoryKey,
3982
- };
3983
- return snapshot;
3984
- };
3985
- return snapshotFn;
3986
- };
3987
-
3988
4142
  /* eslint-disable @typescript-eslint/no-explicit-any */
3989
4143
  const createQuery = (options) => {
3990
4144
  const deps = setupQueryDependencies({ clientConfig: options.creatorInternals.client });
3991
4145
  const state = setupQueryState({});
3992
4146
  const { creator, creatorInternals, queryConfig } = options;
3993
4147
  const flags = getQueryFeatureUsage(options);
3994
- const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig: options.queryConfig });
3995
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
3996
- const destroy = () => deps.injector.destroy();
4148
+ const execute = createExecuteFn({ deps, state, creator, creatorInternals, queryConfig });
3997
4149
  const featureFnContext = {
3998
4150
  state,
3999
- queryConfig,
4000
- creatorConfig: creator,
4001
- creatorInternals,
4002
4151
  execute,
4003
4152
  flags,
4004
4153
  deps,
4005
4154
  };
4006
- applyQueryFeatures(options, featureFnContext);
4155
+ applyQueryFeatures(options.features, featureFnContext);
4007
4156
  maybeExecute({ execute, flags });
4008
- return createQueryObject({ state, execute, createSnapshot, destroy });
4157
+ return createQueryObject({ state, execute, deps });
4009
4158
  };
4010
4159
 
4011
4160
  const createQueryRepository = (config) => {
@@ -4013,7 +4162,9 @@ const createQueryRepository = (config) => {
4013
4162
  const cache = new Map();
4014
4163
  const request = (options) => {
4015
4164
  const { args, clientOptions, runQueryOptions } = options;
4016
- const shouldCache = shouldCacheQuery(options.method);
4165
+ const shouldCache = options.internalRunQueryOptions?.useQueryRepositoryCache === false
4166
+ ? false
4167
+ : shouldCacheQuery(options.method) || options.internalRunQueryOptions?.useQueryRepositoryCache === true;
4017
4168
  if (!shouldCache && options.key)
4018
4169
  throw uncacheableRequestHasCacheKeyParam(options.key);
4019
4170
  if (!shouldCache && runQueryOptions?.allowCache)
@@ -4030,8 +4181,7 @@ const createQueryRepository = (config) => {
4030
4181
  body: args?.body,
4031
4182
  queryParams: args?.queryParams,
4032
4183
  pathParams: args?.pathParams,
4033
- // TODO: remaining props
4034
- // headers: args?.headers,
4184
+ headers: args?.headers,
4035
4185
  });
4036
4186
  const previousKey = options.previousKey;
4037
4187
  if (key !== previousKey && previousKey) {
@@ -4113,6 +4263,10 @@ const provideQueryClient = (config) => {
4113
4263
  };
4114
4264
  };
4115
4265
 
4266
+ /**
4267
+ * This function creates a query client config.
4268
+ * The config is used to create a query client using the `provideQueryClient(myConfig)` function.
4269
+ */
4116
4270
  const createQueryClientConfig = (options) => {
4117
4271
  const token = new InjectionToken(`QueryClient_${options.name}`);
4118
4272
  const clientConfig = {
@@ -4120,6 +4274,9 @@ const createQueryClientConfig = (options) => {
4120
4274
  token,
4121
4275
  name: options.name,
4122
4276
  queryString: options.queryString,
4277
+ // createHttpRequest will use fallbacks if these are not provided
4278
+ cacheAdapter: options.cacheAdapter,
4279
+ retryFn: options.retryFn,
4123
4280
  };
4124
4281
  return clientConfig;
4125
4282
  };
@@ -4236,22 +4393,17 @@ const createSecureQuery = (options) => {
4236
4393
  state,
4237
4394
  creator,
4238
4395
  creatorInternals,
4239
- queryConfig: options.queryConfig,
4396
+ queryConfig,
4240
4397
  });
4241
- const createSnapshot = createQuerySnapshotFn({ state, deps, execute });
4242
- const destroy = () => deps.injector.destroy();
4243
4398
  const featureFnContext = {
4399
+ deps,
4244
4400
  state,
4245
- queryConfig,
4246
- creatorConfig: creator,
4247
- creatorInternals,
4248
4401
  execute,
4249
4402
  flags,
4250
- deps,
4251
4403
  };
4252
- applyQueryFeatures(options, featureFnContext);
4404
+ applyQueryFeatures(options.features, featureFnContext);
4253
4405
  maybeExecute({ execute, flags });
4254
- return createQueryObject({ state, execute, createSnapshot, destroy });
4406
+ return createQueryObject({ state, execute, deps });
4255
4407
  };
4256
4408
 
4257
4409
  const createSecureQueryCreator = (options, internals) => {
@@ -4267,44 +4419,283 @@ const createSecureQueryCreator = (options, internals) => {
4267
4419
  return queryCreator;
4268
4420
  };
4269
4421
 
4422
+ /** A query creator that creates a GET query */
4270
4423
  const createGetQuery = (client) => {
4271
4424
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'GET', client });
4272
4425
  };
4426
+ /** A query creator that creates a secure GET query (requires authentication) */
4273
4427
  const createSecureGetQuery = (client, authProvider) => {
4274
4428
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'GET', client, authProvider });
4275
4429
  };
4430
+ /** A query creator that creates a POST query */
4276
4431
  const createPostQuery = (client) => {
4277
4432
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'POST', client });
4278
4433
  };
4434
+ /** A query creator that creates a secure POST query (requires authentication) */
4279
4435
  const createSecurePostQuery = (client, authProvider) => {
4280
4436
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'POST', client, authProvider });
4281
4437
  };
4438
+ /** A query creator that creates a PUT query */
4282
4439
  const createPutQuery = (client) => {
4283
4440
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PUT', client });
4284
4441
  };
4442
+ /** A query creator that creates a secure PUT query (requires authentication) */
4285
4443
  const createSecurePutQuery = (client, authProvider) => {
4286
4444
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PUT', client, authProvider });
4287
4445
  };
4446
+ /** A query creator that creates a DELETE query */
4288
4447
  const createDeleteQuery = (client) => {
4289
4448
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'DELETE', client });
4290
4449
  };
4450
+ /** A query creator that creates a secure DELETE query (requires authentication) */
4291
4451
  const createSecureDeleteQuery = (client, authProvider) => {
4292
4452
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'DELETE', client, authProvider });
4293
4453
  };
4454
+ /** A query creator that creates a PATCH query */
4294
4455
  const createPatchQuery = (client) => {
4295
4456
  return (creatorOptions) => createQueryCreator(creatorOptions, { method: 'PATCH', client });
4296
4457
  };
4458
+ /** A query creator that creates a secure PATCH query (requires authentication) */
4297
4459
  const createSecurePatchQuery = (client, authProvider) => {
4298
4460
  return (creatorOptions) => createSecureQueryCreator(creatorOptions, { method: 'PATCH', client, authProvider });
4299
4461
  };
4300
4462
 
4463
+ const createGqlExecuteFn = (executeOptions) => {
4464
+ const executeState = setupQueryExecuteState();
4465
+ const reset = () => resetExecuteState({ executeState, executeOptions });
4466
+ const exec = (executeArgs) => {
4467
+ const { args = executeOptions.state.args(), options } = executeArgs ?? {};
4468
+ cleanupPreviousExecute({ executeOptions, executeState });
4469
+ // TODO: This should get cleaned up
4470
+ const tpl = executeOptions.creator.query;
4471
+ const query = transformGql(tpl);
4472
+ let gqlParams = query(args?.variables);
4473
+ if (args?.queryParams && executeOptions.creatorInternals.transport === 'GET') {
4474
+ gqlParams = { ...gqlParams, ...args.queryParams };
4475
+ }
4476
+ const computedArgs = args ?? {};
4477
+ if (executeOptions.creatorInternals.transport === 'GET') {
4478
+ computedArgs.queryParams = gqlParams;
4479
+ }
4480
+ else {
4481
+ computedArgs.body = gqlParams;
4482
+ }
4483
+ const normalizedOpts = {
4484
+ creator: {
4485
+ route: (executeOptions.creator.route ?? ''),
4486
+ },
4487
+ creatorInternals: {
4488
+ client: executeOptions.creatorInternals.client,
4489
+ method: executeOptions.creatorInternals.transport,
4490
+ },
4491
+ deps: executeOptions.deps,
4492
+ queryConfig: executeOptions.queryConfig,
4493
+ state: executeOptions.state,
4494
+ };
4495
+ queryExecute({
4496
+ executeOptions: normalizedOpts,
4497
+ executeState,
4498
+ args: computedArgs,
4499
+ options,
4500
+ internalOptions: {
4501
+ useQueryRepositoryCache: executeOptions.creatorInternals.method === 'QUERY',
4502
+ },
4503
+ transformResponse: (originalResponse) => {
4504
+ if (originalResponse && 'data' in originalResponse) {
4505
+ return originalResponse.data;
4506
+ }
4507
+ return originalResponse;
4508
+ },
4509
+ });
4510
+ };
4511
+ exec['reset'] = reset;
4512
+ exec['currentRepositoryKey'] = executeState.previousKey.asReadonly();
4513
+ return exec;
4514
+ };
4515
+
4516
+ const isCreateGqlQueryOptions = (options) => {
4517
+ return 'transport' in options.creatorInternals;
4518
+ };
4519
+ const createGqlQuery = (options) => {
4520
+ const deps = setupQueryDependencies({ clientConfig: options.creatorInternals.client });
4521
+ const state = setupQueryState({});
4522
+ const { creator, creatorInternals, queryConfig } = options;
4523
+ const flags = getQueryFeatureUsage(options);
4524
+ const execute = createGqlExecuteFn({
4525
+ deps,
4526
+ state,
4527
+ creator,
4528
+ creatorInternals,
4529
+ queryConfig,
4530
+ });
4531
+ const featureFnContext = {
4532
+ state,
4533
+ execute,
4534
+ flags,
4535
+ deps,
4536
+ };
4537
+ applyQueryFeatures(options.features, featureFnContext);
4538
+ maybeExecute({ execute, flags });
4539
+ return createQueryObject({ state, execute, deps });
4540
+ };
4541
+
4542
+ const createGqlQueryCreator = (options, internals) => {
4543
+ function queryCreator(...args) {
4544
+ const { features, queryConfig } = splitQueryConfig(args);
4545
+ return createGqlQuery({
4546
+ creator: options,
4547
+ creatorInternals: internals,
4548
+ features,
4549
+ queryConfig,
4550
+ });
4551
+ }
4552
+ return queryCreator;
4553
+ };
4554
+
4555
+ /** A query creator that creates a GQL query where the payload is sent via GET (query params) */
4556
+ const createGqlQueryViaGet = (client) => {
4557
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'QUERY', client, transport: 'GET' });
4558
+ };
4559
+ /** A query creator that creates a GQL query where the payload is sent via POST (body) */
4560
+ const createGqlQueryViaPost = (client) => {
4561
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'QUERY', client, transport: 'POST' });
4562
+ };
4563
+ /** A query creator that creates a GQL mutation where the payload is sent via GET (query params) */
4564
+ const createGqlMutationViaGet = (client) => {
4565
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'MUTATE', client, transport: 'GET' });
4566
+ };
4567
+ /** A query creator that creates a GQL mutation where the payload is sent via POST (body) */
4568
+ const createGqlMutationViaPost = (client) => {
4569
+ return (creatorOptions) => createGqlQueryCreator(creatorOptions, { method: 'MUTATE', client, transport: 'POST' });
4570
+ };
4571
+
4572
+ const roomNotJoined = (room) => {
4573
+ return new RuntimeError(1000 /* WebSocketRuntimeErrorCode.ROOM_NOT_JOINED */, `Tried leaving the room "${room}" but it has not been joined.`);
4574
+ };
4575
+ const messageMalformed = () => {
4576
+ return new RuntimeError(1001 /* WebSocketRuntimeErrorCode.MESSAGE_MALFORMED */, 'A message has been received but it is malformed (cannot be parsed as JSON).');
4577
+ };
4578
+
4579
+ const createWebSocketClient = (config) => {
4580
+ const socket = io(config.url, {
4581
+ withCredentials: true,
4582
+ autoConnect: false,
4583
+ });
4584
+ const rooms = new Map();
4585
+ const isConnected = signal(false);
4586
+ const joinRoom = (room) => {
4587
+ const roomFn = typeof room === 'function' ? room : () => room;
4588
+ const join = (name) => {
4589
+ socket.emit('join-room', name);
4590
+ const existingRoom = rooms.get(name);
4591
+ if (existingRoom)
4592
+ return existingRoom;
4593
+ const message = signal(null);
4594
+ const newRoom = {
4595
+ latestMessage: message,
4596
+ };
4597
+ rooms.set(name, newRoom);
4598
+ return newRoom;
4599
+ };
4600
+ const pre = previousSignalValue(computed(() => roomFn()));
4601
+ const roomData = signal(null);
4602
+ effect(() => {
4603
+ const current = roomFn();
4604
+ untracked(() => {
4605
+ const previous = pre();
4606
+ if (previous === current)
4607
+ return;
4608
+ if (previous)
4609
+ leaveRoom(previous);
4610
+ if (current) {
4611
+ const joinedRoom = join(current);
4612
+ if (joinedRoom)
4613
+ roomData.set(joinedRoom);
4614
+ }
4615
+ else {
4616
+ roomData.set(null);
4617
+ }
4618
+ });
4619
+ });
4620
+ inject(DestroyRef).onDestroy(() => {
4621
+ const current = roomFn();
4622
+ if (current) {
4623
+ leaveRoom(current);
4624
+ roomData.set(null);
4625
+ }
4626
+ });
4627
+ return roomData.asReadonly();
4628
+ };
4629
+ const leaveRoom = (room) => {
4630
+ if (!rooms.has(room)) {
4631
+ if (isDevMode())
4632
+ throw roomNotJoined(room);
4633
+ }
4634
+ socket.emit('leave-room', room);
4635
+ rooms.delete(room);
4636
+ };
4637
+ const setupWebSocketConnectionListener = () => {
4638
+ socket.on('connect', () => {
4639
+ isConnected.set(true);
4640
+ for (const room of rooms.keys()) {
4641
+ joinRoom(room);
4642
+ }
4643
+ });
4644
+ socket.on('disconnect', () => isConnected.set(false));
4645
+ };
4646
+ const setupWebSocketListener = () => {
4647
+ socket.onAny((data) => {
4648
+ try {
4649
+ const json = JSON.parse(data);
4650
+ const room = rooms.get(json.room);
4651
+ if (room)
4652
+ room.latestMessage.set(json);
4653
+ }
4654
+ catch (error) {
4655
+ console.error(error);
4656
+ if (isDevMode())
4657
+ throw messageMalformed();
4658
+ }
4659
+ });
4660
+ };
4661
+ inject(DestroyRef).onDestroy(() => socket.disconnect());
4662
+ setupWebSocketConnectionListener();
4663
+ setupWebSocketListener();
4664
+ socket.connect();
4665
+ const client = {
4666
+ joinRoom,
4667
+ isConnected: isConnected.asReadonly(),
4668
+ subtle: {
4669
+ leaveRoom,
4670
+ },
4671
+ };
4672
+ return client;
4673
+ };
4674
+ const provideWebSocketClient = (config) => {
4675
+ return {
4676
+ provide: config.token,
4677
+ useFactory: () => createWebSocketClient(config),
4678
+ };
4679
+ };
4680
+
4681
+ const createWebSocketClientConfig = (options) => {
4682
+ const token = new InjectionToken(`WebSocketClient_${options.name}`);
4683
+ const clientConfig = {
4684
+ token,
4685
+ name: options.name,
4686
+ url: options.url,
4687
+ };
4688
+ return clientConfig;
4689
+ };
4690
+
4301
4691
  var index = /*#__PURE__*/Object.freeze({
4302
4692
  __proto__: null,
4303
- QUERY_ARGS_RESET: QUERY_ARGS_RESET,
4693
+ CLEAR_QUERY_ARGS: CLEAR_QUERY_ARGS,
4304
4694
  QUERY_EFFECT_ERROR_MESSAGE: QUERY_EFFECT_ERROR_MESSAGE,
4305
4695
  SPEED_BUFFER_TIME_IN_MS: SPEED_BUFFER_TIME_IN_MS,
4306
4696
  applyQueryFeatures: applyQueryFeatures,
4307
4697
  bearerExpiresInPropertyNotNumber: bearerExpiresInPropertyNotNumber,
4698
+ buildQueryCacheKey: buildQueryCacheKey,
4308
4699
  cleanupPreviousExecute: cleanupPreviousExecute,
4309
4700
  contentfulGqlLikePaginationAdapter: contentfulGqlLikePaginationAdapter,
4310
4701
  cookieLoginTriedButCookieDisabled: cookieLoginTriedButCookieDisabled,
@@ -4313,8 +4704,15 @@ var index = /*#__PURE__*/Object.freeze({
4313
4704
  createDeleteQuery: createDeleteQuery,
4314
4705
  createExecuteFn: createExecuteFn,
4315
4706
  createGetQuery: createGetQuery,
4707
+ createGqlExecuteFn: createGqlExecuteFn,
4708
+ createGqlMutationViaGet: createGqlMutationViaGet,
4709
+ createGqlMutationViaPost: createGqlMutationViaPost,
4710
+ createGqlQuery: createGqlQuery,
4711
+ createGqlQueryCreator: createGqlQueryCreator,
4712
+ createGqlQueryViaGet: createGqlQueryViaGet,
4713
+ createGqlQueryViaPost: createGqlQueryViaPost,
4316
4714
  createHttpRequest: createHttpRequest,
4317
- createPagedQuery: createPagedQuery,
4715
+ createPagedQueryStack: createPagedQueryStack,
4318
4716
  createPatchQuery: createPatchQuery,
4319
4717
  createPostQuery: createPostQuery,
4320
4718
  createPutQuery: createPutQuery,
@@ -4334,6 +4732,8 @@ var index = /*#__PURE__*/Object.freeze({
4334
4732
  createSecurePutQuery: createSecurePutQuery,
4335
4733
  createSecureQuery: createSecureQuery,
4336
4734
  createSecureQueryCreator: createSecureQueryCreator,
4735
+ createWebSocketClient: createWebSocketClient,
4736
+ createWebSocketClientConfig: createWebSocketClientConfig,
4337
4737
  defaultResponseTransformerResponseNotContainingAccessToken: defaultResponseTransformerResponseNotContainingAccessToken,
4338
4738
  defaultResponseTransformerResponseNotContainingRefreshToken: defaultResponseTransformerResponseNotContainingRefreshToken,
4339
4739
  defaultResponseTransformerResponseNotObject: defaultResponseTransformerResponseNotObject,
@@ -4342,26 +4742,34 @@ var index = /*#__PURE__*/Object.freeze({
4342
4742
  enableCookieCalledWithoutCookieConfig: enableCookieCalledWithoutCookieConfig,
4343
4743
  ethletePaginationAdapter: ethletePaginationAdapter,
4344
4744
  extractExpiresInSeconds: extractExpiresInSeconds,
4745
+ fakePaginationAdapter: fakePaginationAdapter,
4345
4746
  getQueryFeatureUsage: getQueryFeatureUsage,
4346
4747
  ggLikePaginationAdapter: ggLikePaginationAdapter,
4748
+ isCreateGqlQueryOptions: isCreateGqlQueryOptions,
4347
4749
  loginCalledWithoutConfig: loginCalledWithoutConfig,
4348
4750
  loginWithTokenCalledWithoutConfig: loginWithTokenCalledWithoutConfig,
4349
4751
  maybeExecute: maybeExecute,
4350
- pagedQueryNextPageCalledWithoutPreviousPage: pagedQueryNextPageCalledWithoutPreviousPage,
4351
- pagedQueryPageBiggerThanTotalPages: pagedQueryPageBiggerThanTotalPages,
4352
- pagedQueryPreviousPageCalledButAlreadyAtFirstPage: pagedQueryPreviousPageCalledButAlreadyAtFirstPage,
4752
+ normalizeQueryRepositoryKey: normalizeQueryRepositoryKey,
4753
+ pagedQueryStackNextPageCalledWithoutPreviousPage: pagedQueryStackNextPageCalledWithoutPreviousPage,
4754
+ pagedQueryStackPageBiggerThanTotalPages: pagedQueryStackPageBiggerThanTotalPages,
4755
+ pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage: pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage,
4353
4756
  provideBearerAuthProvider: provideBearerAuthProvider,
4354
4757
  provideQueryClient: provideQueryClient,
4758
+ provideWebSocketClient: provideWebSocketClient,
4355
4759
  queryEffect: queryEffect,
4356
4760
  queryExecute: queryExecute,
4357
4761
  queryFeatureUsedMultipleTimes: queryFeatureUsedMultipleTimes,
4762
+ queryStackWithArgsUsed: queryStackWithArgsUsed,
4763
+ queryStackWithResponseUpdateUsed: queryStackWithResponseUpdateUsed,
4358
4764
  refreshTokenCalledWithoutConfig: refreshTokenCalledWithoutConfig,
4359
4765
  resetExecuteState: resetExecuteState,
4360
4766
  selectRoleCalledWithoutConfig: selectRoleCalledWithoutConfig,
4361
4767
  setupQueryDependencies: setupQueryDependencies,
4362
4768
  setupQueryExecuteState: setupQueryExecuteState,
4363
4769
  setupQueryState: setupQueryState,
4770
+ shouldAutoExecuteGqlQuery: shouldAutoExecuteGqlQuery,
4364
4771
  shouldAutoExecuteQuery: shouldAutoExecuteQuery,
4772
+ shouldCacheQuery: shouldCacheQuery,
4365
4773
  shouldRetryRequest: shouldRetryRequest,
4366
4774
  splitQueryConfig: splitQueryConfig,
4367
4775
  transformArrayResponse: transformArrayResponse,
@@ -4378,6 +4786,7 @@ var index = /*#__PURE__*/Object.freeze({
4378
4786
  withLogging: withLogging,
4379
4787
  withPolling: withPolling,
4380
4788
  withPollingUsedOnUnsupportedHttpMethod: withPollingUsedOnUnsupportedHttpMethod,
4789
+ withResponseUpdate: withResponseUpdate,
4381
4790
  withSuccessHandling: withSuccessHandling
4382
4791
  });
4383
4792
 
@@ -4889,5 +5298,5 @@ class QueryForm {
4889
5298
  * Generated bundle index. Do not edit.
4890
5299
  */
4891
5300
 
4892
- export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, index as ExperimentalQuery, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryShortNamePipe, QueryStore, addQueryContainerHandling, buildErrorMessage, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds$1 as extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryArrayComputed, queryComputed, queryComputedTillTruthy, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest$1 as shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, toQuerySignal, toQuerySubject, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
5301
+ export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, index as ExperimentalQuery, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryShortNamePipe, QueryStore, addQueryContainerHandling, buildErrorMessage, buildQueryCacheKey$1 as buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds$1 as extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryArrayComputed, queryComputed, queryComputedTillTruthy, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery$1 as shouldCacheQuery, shouldRetryRequest$1 as shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, toQuerySignal, toQuerySubject, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
4893
5302
  //# sourceMappingURL=ethlete-query.mjs.map