@ethlete/query 3.0.4 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import * as i1 from '@ethlete/core';
2
2
  import { BehaviorSubjectWithSubscriberCount, getCookie, setCookie, deleteCookie, DestroyService, DelayableDirective, equal, clone } from '@ethlete/core';
3
- import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, shareReplay, Subject, takeUntil, tap, interval, skip, map, timer, combineLatest, withLatestFrom, fromEvent, startWith, take, concat, debounceTime, distinctUntilChanged } from 'rxjs';
3
+ import { Observable, filter, takeWhile, switchMap, of, tap, BehaviorSubject, shareReplay, Subject, takeUntil, interval, skip, map, timer, combineLatest, withLatestFrom, fromEvent, startWith, take, concat, debounceTime, distinctUntilChanged, pairwise } from 'rxjs';
4
4
  import * as i0 from '@angular/core';
5
- import { Directive, Input, InjectionToken, inject, ChangeDetectorRef, ViewContainerRef, TemplateRef, ErrorHandler, ElementRef } from '@angular/core';
5
+ import { isDevMode, Directive, Input, InjectionToken, inject, ChangeDetectorRef, ViewContainerRef, TemplateRef, ErrorHandler, ElementRef } from '@angular/core';
6
6
  import { FormGroup } from '@angular/forms';
7
7
  import { Router, ActivatedRoute } from '@angular/router';
8
8
 
@@ -49,6 +49,25 @@ const queryStateDoesNotContainKeyError = (data) => new QueryError('005', 'The qu
49
49
  const queryStateCannotTransformError = (data) => new QueryError('006', 'The query state cannot be transformed because it is not loading', data);
50
50
  const invalidBodyError = (data) => new QueryError('007', 'The body is not valid or upsupported', data);
51
51
 
52
+ const isSymfonyError = (error) => {
53
+ if (!error || typeof error !== 'object') {
54
+ return false;
55
+ }
56
+ const symfonyError = error;
57
+ return (symfonyError.class !== undefined &&
58
+ symfonyError.detail !== undefined &&
59
+ symfonyError.status !== undefined &&
60
+ symfonyError.title !== undefined &&
61
+ symfonyError.trace !== undefined &&
62
+ symfonyError.type !== undefined);
63
+ };
64
+ const isSymfonyPagerfantaOutOfRangeError = (error) => {
65
+ if (!isSymfonyError(error)) {
66
+ return false;
67
+ }
68
+ return error.class.startsWith('Pagerfanta') && error.class.endsWith('OutOfRangeCurrentPageException');
69
+ };
70
+
52
71
  const isRequestError = (error) => error instanceof Object && 'status' in error && 'statusText' in error && 'url' in error;
53
72
  const buildRoute = (options) => {
54
73
  if (options.base.endsWith('/')) {
@@ -279,9 +298,13 @@ const shouldRetryRequest = (config) => {
279
298
  if (!isRequestError(config.error)) {
280
299
  return { retry: false };
281
300
  }
282
- const { status } = config.error;
301
+ const { status, detail } = config.error;
283
302
  // Retry on 5xx errors
284
303
  if (status >= 500) {
304
+ // Don't retry if a requested page is out of range
305
+ if (isSymfonyPagerfantaOutOfRangeError(detail)) {
306
+ return { retry: false };
307
+ }
285
308
  return { retry: true, delay: defaultRetryDelay };
286
309
  }
287
310
  // Retry on 408 or 425 errors
@@ -506,6 +529,7 @@ const gql = (strings, ...values) => {
506
529
  return str;
507
530
  };
508
531
 
532
+ /* eslint-disable @typescript-eslint/no-explicit-any */
509
533
  function filterSuccess() {
510
534
  return function (source) {
511
535
  return source.pipe(filter((value) => isQueryStateSuccess(value)));
@@ -551,6 +575,34 @@ function switchQueryCollectionState() {
551
575
  return source.pipe(switchMap((value) => value?.query.state$ ?? of(null)));
552
576
  };
553
577
  }
578
+ const resetPageOnError = (config) => (source) => {
579
+ const { queryForm, pageControlKey = 'page' } = config;
580
+ if (isDevMode() && !queryForm.form.controls[pageControlKey]) {
581
+ console.warn(`resetPageOnError: queryForm.form.controls["${pageControlKey}"] is undefined`);
582
+ }
583
+ return source.pipe(switchMap((q) => {
584
+ if (!q) {
585
+ return of(q);
586
+ }
587
+ return q.state$.pipe(tap((state) => {
588
+ if (!isQueryStateFailure(state)) {
589
+ return;
590
+ }
591
+ switch (state.error.status) {
592
+ // The page is invalid (in prod mode, code is 416)
593
+ case 416 /* HttpStatusCode.RangeNotSatisfiable */:
594
+ queryForm.form.controls[pageControlKey]?.patchValue(1);
595
+ break;
596
+ // The page might be invalid (in dev mode, code is 500)
597
+ case 500 /* HttpStatusCode.InternalServerError */:
598
+ if (isSymfonyPagerfantaOutOfRangeError(state.error.detail)) {
599
+ queryForm.form.controls[pageControlKey].patchValue(1);
600
+ }
601
+ break;
602
+ }
603
+ }), takeUntilResponse());
604
+ }));
605
+ };
554
606
  const isQueryStateLoading = (state) => state?.type === "LOADING" /* QueryStateType.Loading */;
555
607
  const isQueryStateSuccess = (state) => state?.type === "SUCCESS" /* QueryStateType.Success */;
556
608
  const isQueryStateFailure = (state) => state?.type === "FAILURE" /* QueryStateType.Failure */;
@@ -1971,7 +2023,39 @@ class QueryForm {
1971
2023
  if (options?.syncViaUrlQueryParams !== false) {
1972
2024
  this._syncViaUrlQueryParams(values);
1973
2025
  }
1974
- }));
2026
+ }), pairwise(), startWith([null, this.form.getRawValue()]), map(([previousValue, currentValue]) => ({ previousValue, currentValue })), map(({ previousValue, currentValue }) => {
2027
+ let didResetValues = false;
2028
+ for (const formFieldKey in this._fields) {
2029
+ const resets = this._fields[formFieldKey].data.isResetBy;
2030
+ if (!resets)
2031
+ continue;
2032
+ const resetConditionKeys = Array.isArray(resets) ? resets : [resets];
2033
+ for (const resetConditionKey of resetConditionKeys) {
2034
+ if (!(resetConditionKey in this._fields)) {
2035
+ if (isDevMode()) {
2036
+ console.warn(`The field "${resetConditionKey}" is not defined in the QueryForm. Is it a typo?`, this);
2037
+ }
2038
+ continue;
2039
+ }
2040
+ if (previousValue &&
2041
+ currentValue &&
2042
+ !equal(previousValue[resetConditionKey], currentValue[resetConditionKey])) {
2043
+ const defaultValueForKeyToReset = this._defaultValues[formFieldKey];
2044
+ const currentValueForKeyToReset = currentValue[formFieldKey];
2045
+ if (equal(defaultValueForKeyToReset, currentValueForKeyToReset)) {
2046
+ continue;
2047
+ }
2048
+ this.form.controls[formFieldKey].setValue(defaultValueForKeyToReset);
2049
+ didResetValues = true;
2050
+ break;
2051
+ }
2052
+ }
2053
+ }
2054
+ return (didResetValues || {
2055
+ previousValue,
2056
+ currentValue,
2057
+ });
2058
+ }), filter((value) => value !== true));
1975
2059
  }
1976
2060
  setFormValueFromUrlQueryParams(options) {
1977
2061
  if (!this._activatedRoute) {
@@ -2168,5 +2252,5 @@ const def = () => null;
2168
2252
  * Generated bundle index. Do not edit.
2169
2253
  */
2170
2254
 
2171
- export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryCreator, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, mapToPaginated, mergeHeaders, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, request, serializeBody, shouldCacheQuery, shouldRetryRequest, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
2255
+ export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, EntityStore, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryCreator, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryObjectString, buildQueryString, buildRoute, buildTimestampFromSeconds, castQueryCreatorTypes, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, ignoreAutoRefresh, invalidBaseRouteError, invalidBodyError, invalidRouteError, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, 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 };
2172
2256
  //# sourceMappingURL=ethlete-query.mjs.map