@ethlete/query 4.6.0 → 4.7.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 (43) hide show
  1. package/esm2022/index.mjs +2 -1
  2. package/esm2022/lib/devtools/components/public-api.mjs +2 -0
  3. package/esm2022/lib/devtools/components/query-devtools/public-api.mjs +2 -0
  4. package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +72 -0
  5. package/esm2022/lib/devtools/index.mjs +2 -0
  6. package/esm2022/lib/devtools/public-api.mjs +3 -0
  7. package/esm2022/lib/devtools/utils/index.mjs +2 -0
  8. package/esm2022/lib/devtools/utils/public-api.mjs +2 -0
  9. package/esm2022/lib/devtools/utils/query-client.utils.mjs +13 -0
  10. package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +3 -3
  11. package/esm2022/lib/directives/infinity-query.directive.mjs +3 -3
  12. package/esm2022/lib/directives/query.directive.mjs +3 -3
  13. package/esm2022/lib/entity/entity-store.mjs +28 -12
  14. package/esm2022/lib/entity/entity.types.mjs +1 -1
  15. package/esm2022/lib/entity/entity.utils.mjs +26 -2
  16. package/esm2022/lib/query/query.mjs +17 -4
  17. package/esm2022/lib/query-client/query-client.mjs +1 -1
  18. package/esm2022/lib/query-client/query-client.types.mjs +1 -1
  19. package/esm2022/lib/query-form/query-form.mjs +10 -5
  20. package/esm2022/lib/query-store/query-store.mjs +9 -2
  21. package/esm2022/lib/request/request.util.mjs +2 -1
  22. package/fesm2022/ethlete-query.mjs +174 -29
  23. package/fesm2022/ethlete-query.mjs.map +1 -1
  24. package/index.d.ts +1 -0
  25. package/lib/auth/auth-provider.types.d.ts +0 -5
  26. package/lib/auth/bearer-auth-provider.d.ts +0 -4
  27. package/lib/devtools/components/public-api.d.ts +1 -0
  28. package/lib/devtools/components/query-devtools/public-api.d.ts +1 -0
  29. package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +28 -0
  30. package/lib/devtools/index.d.ts +1 -0
  31. package/lib/devtools/public-api.d.ts +2 -0
  32. package/lib/devtools/utils/index.d.ts +1 -0
  33. package/lib/devtools/utils/public-api.d.ts +1 -0
  34. package/lib/devtools/utils/query-client.utils.d.ts +12 -0
  35. package/lib/entity/entity-store.d.ts +4 -0
  36. package/lib/entity/entity.types.d.ts +20 -0
  37. package/lib/entity/entity.utils.d.ts +10 -0
  38. package/lib/query/query.d.ts +4 -16
  39. package/lib/query/query.types.d.ts +0 -14
  40. package/lib/query-client/query-client.d.ts +0 -1
  41. package/lib/query-client/query-client.types.d.ts +5 -0
  42. package/lib/query-store/query-store.d.ts +2 -1
  43. package/package.json +1 -1
@@ -1,8 +1,10 @@
1
1
  import * as i1 from '@ethlete/core';
2
2
  import { BehaviorSubjectWithSubscriberCount, getCookie, setCookie, deleteCookie, createDestroy, DelayableDirective, RouterStateService, clone, equal, ET_PROPERTY_REMOVED } from '@ethlete/core';
3
- import { Observable, filter, takeWhile, switchMap, of, tap, BehaviorSubject, shareReplay, Subject, takeUntil, interval, skip, map, timer, combineLatest, withLatestFrom, fromEvent, startWith, debounceTime, take, concat } from 'rxjs';
3
+ import { Observable, filter, takeWhile, switchMap, of, tap, BehaviorSubject, shareReplay, Subject, takeUntil, interval, skip, map, timer, startWith, combineLatest, withLatestFrom, fromEvent, debounceTime, take, concat } from 'rxjs';
4
4
  import * as i0 from '@angular/core';
5
- import { isDevMode, inject, TemplateRef, ViewContainerRef, ErrorHandler, ChangeDetectorRef, Directive, Input, InjectionToken, ElementRef, NgZone, assertInInjectionContext } from '@angular/core';
5
+ import { isDevMode, InjectionToken, inject, signal, computed, effect, Component, ChangeDetectionStrategy, ViewEncapsulation, TemplateRef, ViewContainerRef, ErrorHandler, ChangeDetectorRef, Directive, Input, ElementRef, NgZone, assertInInjectionContext } from '@angular/core';
6
+ import { NgIf, NgFor, AsyncPipe, JsonPipe } from '@angular/common';
7
+ import { toSignal } from '@angular/core/rxjs-interop';
6
8
  import { FormGroup } from '@angular/forms';
7
9
  import { Router, ActivatedRoute } from '@angular/router';
8
10
 
@@ -201,6 +203,7 @@ const serializeBody = (body) => {
201
203
  if (typeof body === 'object' || typeof body === 'boolean' || Array.isArray(body)) {
202
204
  return JSON.stringify(body);
203
205
  }
206
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
207
  return body.toString();
205
208
  };
206
209
  const transformMethod = (config) => {
@@ -744,7 +747,13 @@ class Query {
744
747
  return ++this._currentId;
745
748
  }
746
749
  get state$() {
747
- return this._state$.pipe(switchMap((s) => this._transformState(s)), shareReplay({ bufferSize: 1, refCount: true }));
750
+ return this._state$.pipe(tap((s) => {
751
+ if (!this._client.config.logging?.preparedQuerySubscriptions)
752
+ return;
753
+ if (isQueryStatePrepared(s)) {
754
+ console.warn(`Query ${this._routeWithParams} was subscribed to in the prepared state. Did you forget to call .execute()?`);
755
+ }
756
+ }), switchMap((s) => this._transformState(s)), shareReplay({ bufferSize: 1, refCount: true }));
748
757
  }
749
758
  /**
750
759
  * The current state of the query.
@@ -768,6 +777,9 @@ class Query {
768
777
  get isInUse() {
769
778
  return this._state$.subscriberCount > 0;
770
779
  }
780
+ get _subscriberCount() {
781
+ return this._state$.subscriberCount;
782
+ }
771
783
  get isPolling() {
772
784
  return !!this._pollingSubscription;
773
785
  }
@@ -794,7 +806,11 @@ class Query {
794
806
  get store() {
795
807
  return this._queryConfig.entity?.store ?? null;
796
808
  }
797
- constructor(_client, _queryConfig, _routeWithParams, _args) {
809
+ constructor(_client, _queryConfig,
810
+ /**
811
+ * @internal
812
+ */
813
+ _routeWithParams, _args) {
798
814
  this._client = _client;
799
815
  this._queryConfig = _queryConfig;
800
816
  this._routeWithParams = _routeWithParams;
@@ -1158,6 +1174,83 @@ const isClassValidatorError = (error) => {
1158
1174
  return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error && 'error' in error;
1159
1175
  };
1160
1176
 
1177
+ const QUERY_CLIENT_DEVTOOLS_TOKEN = new InjectionToken('QUERY_CLIENT_DEVTOOLS_TOKEN');
1178
+ const provideQueryClientForDevtools = (queryClient) => {
1179
+ if (!isDevMode()) {
1180
+ console.warn('You are using the Query Devtools in production mode. This increases the size of your bundle and should only be used for development purposes.');
1181
+ }
1182
+ return {
1183
+ provide: QUERY_CLIENT_DEVTOOLS_TOKEN,
1184
+ useValue: queryClient,
1185
+ multi: true,
1186
+ };
1187
+ };
1188
+
1189
+ class QueryDevtoolsComponent {
1190
+ constructor() {
1191
+ this._destroy$ = createDestroy();
1192
+ this.queryClientConfigs = inject(QUERY_CLIENT_DEVTOOLS_TOKEN);
1193
+ this.isOpen = signal(false);
1194
+ this.showResponse = signal(false);
1195
+ this.showRawResponse = signal(false);
1196
+ this.selectedClientId = signal(0);
1197
+ this.selectedQueryPath = signal(null);
1198
+ this.selectedClientConfig = computed(() => {
1199
+ if (this.queryClientConfigs.length === 1) {
1200
+ return this.queryClientConfigs[0];
1201
+ }
1202
+ const index = this.selectedClientId();
1203
+ return this.queryClientConfigs[index];
1204
+ });
1205
+ this.queryStore = computed(() => {
1206
+ const config = this.selectedClientConfig();
1207
+ return config.client._store;
1208
+ });
1209
+ this._queries$ = new BehaviorSubject([]);
1210
+ this.queries = toSignal(this._queries$);
1211
+ this.selectedQuery = computed(() => {
1212
+ const path = this.selectedQueryPath();
1213
+ if (!path) {
1214
+ return null;
1215
+ }
1216
+ return this.queries()?.find((q) => q._routeWithParams === path) ?? null;
1217
+ });
1218
+ this.trackByClient = (_, { client }) => client.config.baseRoute;
1219
+ this.trackByQuery = (_, { _routeWithParams }) => _routeWithParams;
1220
+ const change$ = new Subject();
1221
+ effect(() => {
1222
+ change$.next(true);
1223
+ const store = this.queryStore();
1224
+ store.storeChange$
1225
+ .pipe(startWith(''), map(() => store._store), tap((s) => this._queries$.next(Array.from(s.values()))), takeUntil(change$), takeUntil(this._destroy$))
1226
+ .subscribe();
1227
+ }, { allowSignalWrites: true });
1228
+ }
1229
+ toggleOpen() {
1230
+ this.isOpen.set(!this.isOpen());
1231
+ }
1232
+ toggleShowResponse() {
1233
+ this.showResponse.set(!this.showResponse());
1234
+ }
1235
+ toggleShowRawResponse() {
1236
+ this.showRawResponse.set(!this.showRawResponse());
1237
+ }
1238
+ selectClient(clientId) {
1239
+ this.selectedClientId.set(clientId);
1240
+ }
1241
+ selectQuery(query) {
1242
+ this.selectedQueryPath.set(query._routeWithParams);
1243
+ }
1244
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: QueryDevtoolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1245
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.5", type: QueryDevtoolsComponent, isStandalone: true, selector: "et-query-devtools", host: { classAttribute: "et-query-devtools" }, ngImport: i0, template: "<button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn\">Open Devtools</button>\n\n<div *ngIf=\"isOpen()\" class=\"et-query-devtools-container\">\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-close-btn\">Close Devtools</button>\n\n <ng-container *ngIf=\"queryClientConfigs.length > 1\">\n <p>Client instance:</p>\n <ul>\n <li *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\">\n <button (click)=\"selectClient(i)\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedClientConfig() as cfg\">\n <p>{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\">Force Refresh of in use queries</button> <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\">HARD Force Refresh</button>\n <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\">\n PURGE & HARD Force Refresh\n </button>\n\n <ul>\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p>{{ query._routeWithParams }}</p>\n\n <button (click)=\"query.execute()\">Execute</button> <br />\n <button (click)=\"query.execute({ skipCache: true })\">FORCE Execute</button> <br />\n <button (click)=\"query.abort()\">Abort</button> <br />\n <button (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\">Poll</button> <br />\n <button (click)=\"query.stopPolling()\">Stop polling</button> <br />\n <button (click)=\"query.pausePolling()\">Pause polling</button> <br />\n <button (click)=\"query.resumePolling()\">Resume polling</button> <br />\n\n <div>\n <p>state type</p>\n <pre>{{ (query.state$ | async)?.type }}</pre>\n </div>\n\n <div>\n <p>_enableSmartPolling:</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div>\n <p>isExpired:</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div>\n <p>isInUse:</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div>\n <p>_subscriberCount:</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div>\n <p>isPolling:</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div>\n <p>_arguments:</p>\n <pre>{{ query._arguments | json }}</pre>\n </div>\n\n <div>\n <p>state$:</p>\n <button (click)=\"toggleShowResponse()\">Show/Hide</button>\n <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\n </div>\n\n <div>\n <p>rawState:</p>\n <button (click)=\"toggleShowRawResponse()\">Show/Hide</button>\n <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </ng-container>\n</div>\n", styles: [".et-query-devtools-container{position:fixed;inset:0;background-color:#000;z-index:10000}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom }); }
1246
+ }
1247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: QueryDevtoolsComponent, decorators: [{
1248
+ type: Component,
1249
+ args: [{ selector: 'et-query-devtools', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, host: {
1250
+ class: 'et-query-devtools',
1251
+ }, imports: [NgIf, NgFor, AsyncPipe, JsonPipe], hostDirectives: [], template: "<button (click)=\"toggleOpen()\" class=\"et-query-devtools-open-btn\">Open Devtools</button>\n\n<div *ngIf=\"isOpen()\" class=\"et-query-devtools-container\">\n <button (click)=\"toggleOpen()\" class=\"et-query-devtools-close-btn\">Close Devtools</button>\n\n <ng-container *ngIf=\"queryClientConfigs.length > 1\">\n <p>Client instance:</p>\n <ul>\n <li *ngFor=\"let clientConfig of queryClientConfigs; index as i; trackBy: trackByClient\">\n <button (click)=\"selectClient(i)\">\n {{ clientConfig.displayName ?? clientConfig.client.config.baseRoute }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedClientConfig() as cfg\">\n <p>{{ cfg.displayName ?? cfg.client.config.baseRoute }}</p>\n\n <button (click)=\"cfg.client._store.refreshQueriesInUse()\">Force Refresh of in use queries</button> <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true })\">HARD Force Refresh</button>\n <br />\n <button (click)=\"cfg.client._store.refreshQueriesInUse({ ignoreCacheValidity: true, purgeUnused: true })\">\n PURGE & HARD Force Refresh\n </button>\n\n <ul>\n <li *ngFor=\"let query of queries(); trackBy: trackByQuery\">\n <button (click)=\"selectQuery(query)\">\n {{ query._routeWithParams }}\n </button>\n </li>\n </ul>\n </ng-container>\n\n <ng-container *ngIf=\"selectedQuery() as query\">\n <p>{{ query._routeWithParams }}</p>\n\n <button (click)=\"query.execute()\">Execute</button> <br />\n <button (click)=\"query.execute({ skipCache: true })\">FORCE Execute</button> <br />\n <button (click)=\"query.abort()\">Abort</button> <br />\n <button (click)=\"query.poll({ interval: 5000, takeUntil: _destroy$ })\">Poll</button> <br />\n <button (click)=\"query.stopPolling()\">Stop polling</button> <br />\n <button (click)=\"query.pausePolling()\">Pause polling</button> <br />\n <button (click)=\"query.resumePolling()\">Resume polling</button> <br />\n\n <div>\n <p>state type</p>\n <pre>{{ (query.state$ | async)?.type }}</pre>\n </div>\n\n <div>\n <p>_enableSmartPolling:</p>\n <pre>{{ query._enableSmartPolling }}</pre>\n </div>\n\n <div>\n <p>isExpired:</p>\n <pre>{{ query.isExpired }}</pre>\n </div>\n\n <div>\n <p>isInUse:</p>\n <pre>{{ query.isInUse }}</pre>\n </div>\n\n <div>\n <p>_subscriberCount:</p>\n <pre>{{ query._subscriberCount }}</pre>\n </div>\n\n <div>\n <p>isPolling:</p>\n <pre>{{ query.isPolling }}</pre>\n </div>\n\n <div>\n <p>_arguments:</p>\n <pre>{{ query._arguments | json }}</pre>\n </div>\n\n <div>\n <p>state$:</p>\n <button (click)=\"toggleShowResponse()\">Show/Hide</button>\n <pre *ngIf=\"showResponse()\">{{ query.state$ | async | json }}</pre>\n </div>\n\n <div>\n <p>rawState:</p>\n <button (click)=\"toggleShowRawResponse()\">Show/Hide</button>\n <pre *ngIf=\"showRawResponse()\">{{ query.rawState | json }}</pre>\n </div>\n </ng-container>\n</div>\n", styles: [".et-query-devtools-container{position:fixed;inset:0;background-color:#000;z-index:10000}.et-query-devtools-open-btn{position:fixed;inset-inline-start:0;inset-block-start:0;z-index:9999}\n"] }]
1252
+ }], ctorParameters: function () { return []; } });
1253
+
1161
1254
  class QueryDirective {
1162
1255
  constructor() {
1163
1256
  this._mainTemplateRef = inject(TemplateRef);
@@ -1253,10 +1346,10 @@ class QueryDirective {
1253
1346
  this._viewContainerRef.createEmbeddedView(this._mainTemplateRef, this._viewContext);
1254
1347
  }
1255
1348
  }
1256
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1257
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.3", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1349
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: QueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1350
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: QueryDirective, isStandalone: true, selector: "[etQuery]", inputs: { query: ["etQuery", "query"], cache: ["etQueryCache", "cache"] }, ngImport: i0 }); }
1258
1351
  }
1259
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: QueryDirective, decorators: [{
1352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: QueryDirective, decorators: [{
1260
1353
  type: Directive,
1261
1354
  args: [{
1262
1355
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -1584,10 +1677,10 @@ class InfinityQueryDirective {
1584
1677
  this._viewContext.currentQuery = null;
1585
1678
  this._data$.next([]);
1586
1679
  }
1587
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1588
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.3", 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 }); }
1680
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1681
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.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 }); }
1589
1682
  }
1590
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: InfinityQueryDirective, decorators: [{
1683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: InfinityQueryDirective, decorators: [{
1591
1684
  type: Directive,
1592
1685
  args: [{
1593
1686
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -1638,10 +1731,10 @@ class InfinityQueryTriggerDirective {
1638
1731
  });
1639
1732
  this._observer.observe(this._elementRef.nativeElement);
1640
1733
  }
1641
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1642
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.3", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
1734
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1735
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[etInfinityQueryTrigger], et-infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 }); }
1643
1736
  }
1644
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
1737
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
1645
1738
  type: Directive,
1646
1739
  args: [{
1647
1740
  // eslint-disable-next-line @angular-eslint/directive-selector
@@ -1659,6 +1752,9 @@ class EntityStoreError extends Error {
1659
1752
  this.name = 'EntityStoreError';
1660
1753
  }
1661
1754
  }
1755
+ function flatten(arr) {
1756
+ return arr.reduce((acc, val) => acc.concat(val), []);
1757
+ }
1662
1758
  class EntityStore {
1663
1759
  constructor(_config) {
1664
1760
  this._config = _config;
@@ -1667,7 +1763,8 @@ class EntityStore {
1667
1763
  }
1668
1764
  select(keyOrKeys) {
1669
1765
  if (Array.isArray(keyOrKeys)) {
1670
- return this._selectMany(keyOrKeys);
1766
+ const _keys = this._normalizeKeys(keyOrKeys);
1767
+ return this._selectMany(_keys);
1671
1768
  }
1672
1769
  return this._select(keyOrKeys);
1673
1770
  }
@@ -1678,32 +1775,35 @@ class EntityStore {
1678
1775
  return this._change$.pipe(startWith(null), debounceTime(0), map(() => Array.from(this._dictionary.values()).filter(predicate)), shareReplay({ bufferSize: 1, refCount: true }));
1679
1776
  }
1680
1777
  set(keyOrKeys, valueOrValues) {
1681
- if (Array.isArray(keyOrKeys)) {
1778
+ const _keys = this._normalizeKeys(keyOrKeys);
1779
+ if (Array.isArray(_keys)) {
1682
1780
  if (!Array.isArray(valueOrValues)) {
1683
1781
  throw new EntityStoreError('When setting multiple keys, values must be an array', {
1684
- keyOrValues: keyOrKeys,
1782
+ keyOrValues: _keys,
1685
1783
  valueOrValues,
1686
1784
  });
1687
1785
  }
1688
- for (let i = 0; i < keyOrKeys.length; i++) {
1689
- this._set(keyOrKeys[i], valueOrValues[i]);
1786
+ const _values = (Array.isArray(valueOrValues[0]) ? flatten(valueOrValues) : valueOrValues);
1787
+ for (let i = 0; i < _keys.length; i++) {
1788
+ this._set(_keys[i], _values[i]);
1690
1789
  }
1691
1790
  }
1692
1791
  else {
1693
- this._set(keyOrKeys, valueOrValues);
1792
+ this._set(_keys, valueOrValues);
1694
1793
  }
1695
- this._change$.next(keyOrKeys);
1794
+ this._change$.next(_keys);
1696
1795
  }
1697
1796
  remove(keyOrKeys) {
1698
- if (Array.isArray(keyOrKeys)) {
1699
- for (const key of keyOrKeys) {
1797
+ const _keys = this._normalizeKeys(keyOrKeys);
1798
+ if (Array.isArray(_keys)) {
1799
+ for (const key of _keys) {
1700
1800
  this._remove(key);
1701
1801
  }
1702
1802
  }
1703
1803
  else {
1704
- this._remove(keyOrKeys);
1804
+ this._remove(_keys);
1705
1805
  }
1706
- this._change$.next(keyOrKeys);
1806
+ this._change$.next(_keys);
1707
1807
  }
1708
1808
  logState() {
1709
1809
  console.log('EntityStore:', this._config.name, {
@@ -1750,11 +1850,44 @@ class EntityStore {
1750
1850
  }
1751
1851
  this._dictionary.delete(key);
1752
1852
  }
1853
+ _normalizeKeys(keys) {
1854
+ if (Array.isArray(keys)) {
1855
+ if (Array.isArray(keys[0])) {
1856
+ return flatten(keys);
1857
+ }
1858
+ return keys;
1859
+ }
1860
+ return keys;
1861
+ }
1753
1862
  }
1754
1863
 
1755
1864
  function mapToPaginated(response) {
1756
1865
  return map((items) => ({ ...response, items }));
1757
1866
  }
1867
+ // FIXME: This breaks if SubStoreType is an array
1868
+ /**
1869
+ * Use an other store to represent a property of the current entity.
1870
+ */
1871
+ const insertFrom = (store, { for: key, id }) => switchMap((value) => {
1872
+ if (!value)
1873
+ return of(null);
1874
+ const ids = id(value);
1875
+ if (Array.isArray(ids)) {
1876
+ return store.select(ids).pipe(map((data) => ({ ...value, [key]: data })));
1877
+ }
1878
+ else {
1879
+ return store.select(ids).pipe(map((data) => ({ ...value, [key]: data })));
1880
+ }
1881
+ });
1882
+ /**
1883
+ * Remove entities from a store based on a where function.
1884
+ */
1885
+ const removeFrom = (store, { where, id }) => {
1886
+ store
1887
+ .selectWhere(where)
1888
+ .pipe(tap((entities) => store.remove(entities.map(id))), take(1))
1889
+ .subscribe();
1890
+ };
1758
1891
 
1759
1892
  class QueryCreator {
1760
1893
  constructor(_queryConfig, _client, _store) {
@@ -1791,16 +1924,22 @@ class QueryCreator {
1791
1924
  class QueryStore {
1792
1925
  constructor(_config) {
1793
1926
  this._config = _config;
1927
+ /**
1928
+ * @internal
1929
+ */
1794
1930
  this._store = new Map();
1795
1931
  this._garbageCollector = null;
1796
1932
  this._isInLowResourceMode = false;
1797
1933
  this._lastBlurTimestamp = Date.now();
1934
+ this._storeChange$ = new Subject();
1935
+ this.storeChange$ = this._storeChange$.asObservable();
1798
1936
  this._initSmartQueryHandling();
1799
1937
  }
1800
1938
  add(id, query) {
1801
1939
  this._store.set(id, query);
1802
1940
  this._initGarbageCollector();
1803
1941
  this._logState(id, query, 'SET');
1942
+ this._storeChange$.next(id);
1804
1943
  }
1805
1944
  get(id) {
1806
1945
  return this._store.get(id) ?? null;
@@ -1809,6 +1948,7 @@ class QueryStore {
1809
1948
  this.get(id)?._destroy();
1810
1949
  this._store.delete(id);
1811
1950
  this._logState(id, null, 'REMOVE');
1951
+ this._storeChange$.next(id);
1812
1952
  }
1813
1953
  forEach(callback) {
1814
1954
  for (const [key, query] of this._store) {
@@ -2005,6 +2145,7 @@ const buildGqlCacheKey = (config, args) => {
2005
2145
  return `${queryFirst50Chars}...${queryMiddle25Chars}...${queryLast50Chars}...${vars}`;
2006
2146
  };
2007
2147
 
2148
+ const ET_ARR_PREFIX = 'ET_ARR__';
2008
2149
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2009
2150
  class QueryFormGroup extends FormGroup {
2010
2151
  patchValue(
@@ -2148,7 +2289,7 @@ class QueryForm {
2148
2289
  if (previousValue &&
2149
2290
  currentValue &&
2150
2291
  !equal(previousValue[resetConditionKey], currentValue[resetConditionKey])) {
2151
- const defaultValueForKeyToReset = this._defaultValues[formFieldKey];
2292
+ const defaultValueForKeyToReset = this._getDefaultValue(formFieldKey);
2152
2293
  const currentValueForKeyToReset = currentValue[formFieldKey];
2153
2294
  if (equal(defaultValueForKeyToReset, currentValueForKeyToReset)) {
2154
2295
  continue;
@@ -2183,10 +2324,14 @@ class QueryForm {
2183
2324
  }
2184
2325
  }
2185
2326
  _getDefaultValue(key) {
2186
- return this._defaultValues[key] ?? null;
2327
+ const val = this._defaultValues[key];
2328
+ if (typeof val === 'string' && val.startsWith(ET_ARR_PREFIX)) {
2329
+ return JSON.parse(val.slice(ET_ARR_PREFIX.length));
2330
+ }
2331
+ return val ?? null;
2187
2332
  }
2188
2333
  _isDefaultValue(key, value) {
2189
- const normalizedValue = Array.isArray(value) ? JSON.stringify(value) : value;
2334
+ const normalizedValue = Array.isArray(value) ? `${ET_ARR_PREFIX}${JSON.stringify(value)}` : value;
2190
2335
  return this._getDefaultValue(key) === normalizedValue;
2191
2336
  }
2192
2337
  _setupFormGroup() {
@@ -2204,7 +2349,7 @@ class QueryForm {
2204
2349
  continue;
2205
2350
  }
2206
2351
  if (Array.isArray(value)) {
2207
- defaultValues[key] = JSON.stringify(value);
2352
+ defaultValues[key] = `${ET_ARR_PREFIX}${JSON.stringify(value)}`;
2208
2353
  }
2209
2354
  else {
2210
2355
  defaultValues[key] = value;
@@ -2360,5 +2505,5 @@ const def = () => null;
2360
2505
  * Generated bundle index. Do not edit.
2361
2506
  */
2362
2507
 
2363
- export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryCreator, QueryDirective, QueryError, QueryField, QueryForm, QueryFormGroup, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCustomHeaderAuthProvider, isEmptyString, isGqlQueryConfig, isNaN$1 as isNaN, isQuery, isQueryCollection, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
2508
+ export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, QUERY_CLIENT_DEVTOOLS_TOKEN, Query, QueryClient, QueryCreator, QueryDevtoolsComponent, QueryDirective, QueryError, QueryField, QueryForm, QueryFormGroup, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, 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, isSymfonyPagerfantaOutOfRangeError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, provideQueryClientForDevtools, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, removeFrom, request, resetPageOnError, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
2364
2509
  //# sourceMappingURL=ethlete-query.mjs.map