@ethlete/query 6.0.0-next.37 → 6.0.0-next.38

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @ethlete/query
2
2
 
3
+ ## 6.0.0-next.38
4
+
5
+ ### Minor Changes
6
+
7
+ - [`9c64031`](https://github.com/ethlete-io/ethdk/commit/9c64031cb39f6ac9f5932cb32b31ab98742a9391) Thanks [@TomTomB](https://github.com/TomTomB)! - A query batch registers itself with the devtools, and each item's query is attributed to the run that
8
+ created it. Batch tombstones are capped per batch, so a bulk run cannot evict the others.
9
+
10
+ - [`9c64031`](https://github.com/ethlete-io/ethdk/commit/9c64031cb39f6ac9f5932cb32b31ab98742a9391) Thanks [@TomTomB](https://github.com/TomTomB)! - A query batch reports `itemsPerSecond()` and `remainingTime()`, so a long bulk edit can show an ETA
11
+ next to its progress. Both are `null` until the run has settled enough items to measure.
12
+
13
+ - [`9c64031`](https://github.com/ethlete-io/ethdk/commit/9c64031cb39f6ac9f5932cb32b31ab98742a9391) Thanks [@TomTomB](https://github.com/TomTomB)! - `createQueryBatch` runs one mutation over a list of items with bounded concurrency, a per-item
14
+ outcome and a `retryFailed()` that resends only what did not succeed.
15
+
16
+ - [`3bc10d1`](https://github.com/ethlete-io/ethdk/commit/3bc10d12430def3315a17a3051b14624edc591cc) Thanks [@TomTomB](https://github.com/TomTomB)! - `createQuerySubmission` submits a signal form through a mutation, mapping a failed request's
17
+ violations back onto the fields that caused them.
18
+
19
+ - [`5cb3e5e`](https://github.com/ethlete-io/ethdk/commit/5cb3e5e6ff61aea87dbca0481fbf48b8634183f6) Thanks [@TomTomB](https://github.com/TomTomB)! - `querySequence` now reports `completed()` and `progress()` (`0`-`100`), so a waterfall can drive a
20
+ progress bar or a determinate button spinner without deriving it from `currentStep()`.
21
+
3
22
  ## 6.0.0-next.37
4
23
 
5
24
  ### Minor Changes
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { inject, computed, DestroyRef, InjectionToken, Injector, EnvironmentInjector, ElementRef, ErrorHandler, createEnvironmentInjector, effect, untracked, signal, linkedSignal, runInInjectionContext, isDevMode, PLATFORM_ID, resource, DOCUMENT, VERSION, makeEnvironmentProviders, assertInInjectionContext, provideEnvironmentInitializer, ChangeDetectorRef, ViewContainerRef, TemplateRef, Input, Directive, input, Pipe, ViewEncapsulation, Component, NgZone } from '@angular/core';
3
3
  import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
4
4
  import { UrlTree, Router, RedirectCommand, ActivatedRoute } from '@angular/router';
5
- import { filter, take, map, defer, from, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, merge, EMPTY, takeWhile, firstValueFrom, concatMap, fromEvent, throttleTime, interval, combineLatest, Observable, takeUntil, startWith, pairwise, BehaviorSubject, ReplaySubject, shareReplay, skip, withLatestFrom, debounceTime } from 'rxjs';
5
+ import { filter, take, map, defer, from, Subject, Subscription, throwError, of, timer, switchMap, tap, retry, catchError, EMPTY, takeUntil, finalize, mergeMap, toArray, merge, takeWhile, firstValueFrom, concatMap, fromEvent, throttleTime, interval, combineLatest, Observable, startWith, pairwise, BehaviorSubject, ReplaySubject, shareReplay, skip, withLatestFrom, debounceTime } from 'rxjs';
6
6
  import { defineStaticProvider, RuntimeError, clamp, randomId, defineRootProvider, isObject, injectUnsavedChangesCoordinator, injectRoute, getCookie, getDomain, deleteCookie, setCookie, CORE_VERSION, createDestroy, computedTillTruthy, defineProvider, toProvideFn, toInjectFn, nextFrame, injectQueryParams, injectQueryParamChanges, clone, equal, ET_PROPERTY_REMOVED, previousSignalValue } from '@ethlete/core';
7
7
  import { HttpClient, HttpEventType, HttpErrorResponse, HttpResponse, HttpHeaders, HttpStatusCode } from '@angular/common/http';
8
8
  import { getActiveConsumer, setActiveConsumer } from '@angular/core/primitives/signals';
@@ -283,6 +283,26 @@ const setQueryDevtoolsTokenPayloadPatcher = (fn) => {
283
283
  * @internal
284
284
  */
285
285
  const patchQueryDevtoolsTokenPayload = (options) => (tokenPayloadPatcher ? tokenPayloadPatcher(options) : options.payload);
286
+ /** The batch item being created right now, or `null` outside one. */
287
+ let batchOwner = null;
288
+ /**
289
+ * Runs `create` with every query it creates attributed to `owner`'s batch and item. The attribution has
290
+ * to be ambient: a batch's item query is built by the query creator the caller handed it, which takes no
291
+ * devtools argument - so there is nothing to thread the owner through. Nested runs restore the outer one.
292
+ * @internal
293
+ */
294
+ const runInQueryDevtoolsBatch = (owner, create) => {
295
+ const outer = batchOwner;
296
+ batchOwner = owner;
297
+ try {
298
+ return create();
299
+ }
300
+ finally {
301
+ batchOwner = outer;
302
+ }
303
+ };
304
+ /** The batch item a query being created belongs to, or `null` for one created outside a batch. @internal */
305
+ const currentQueryDevtoolsBatch = () => batchOwner;
286
306
  let suppressStackRegistration = false;
287
307
  /**
288
308
  * Suppresses devtools registration for the next {@link createQueryStack} call. Used by
@@ -409,6 +429,9 @@ const QueryRuntimeErrorCode = {
409
429
  CIRCULAR_QUERY_DEPENDENCY: 800,
410
430
  // Query Sequence
411
431
  QUERY_SEQUENCE_ALREADY_RUNNING: 900,
432
+ // Query Batch
433
+ QUERY_BATCH_ALREADY_RUNNING: 910,
434
+ QUERY_BATCH_WITH_ARGS_USED: 911,
412
435
  // Legacy interop
413
436
  LEGACY_PREPARE_WITHOUT_INJECTION_CONTEXT: 950,
414
437
  LEGACY_QUERY_STATE_ALREADY_HAS_KEY: 951,
@@ -507,6 +530,12 @@ const legacyPrepareWithoutInjectionContext = (creatorName, method = 'prepare') =
507
530
  const querySequenceAlreadyRunning = () => {
508
531
  return new RuntimeError(QueryRuntimeErrorCode.QUERY_SEQUENCE_ALREADY_RUNNING, `run() was called on a query sequence that is already running. Wait for the current run to settle before starting another.`);
509
532
  };
533
+ const queryBatchAlreadyRunning = () => {
534
+ return new RuntimeError(QueryRuntimeErrorCode.QUERY_BATCH_ALREADY_RUNNING, `run() or retryFailed() was called on a query batch that is already running. Await the current run, or call cancel() first.`);
535
+ };
536
+ const queryBatchWithArgsUsed = () => {
537
+ return new RuntimeError(QueryRuntimeErrorCode.QUERY_BATCH_WITH_ARGS_USED, `The "withArgs()" feature cannot be used inside a query batch. Each item's args come from the batch's "args" option.`);
538
+ };
510
539
 
511
540
  const isClassValidatorError = (error) => {
512
541
  return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error && 'error' in error;
@@ -1204,6 +1233,7 @@ const createBaseQuery = (options) => {
1204
1233
  queryConfig: options.queryConfig,
1205
1234
  });
1206
1235
  return runInInjectionContext(deps.injector, () => {
1236
+ const batchOwner = currentQueryDevtoolsBatch();
1207
1237
  const devtoolsStats = createQueryDevtoolsStatsRecorder();
1208
1238
  const devtoolsFormLinks = createQueryDevtoolsFormLinksRecorder();
1209
1239
  const devtoolsOverrides = createQueryDevtoolsOverridesRecorder();
@@ -1271,6 +1301,8 @@ const createBaseQuery = (options) => {
1271
1301
  client: deps.client,
1272
1302
  element: deps.hostElement,
1273
1303
  gqlQuery: options.creatorInternals.query,
1304
+ batch: batchOwner?.batch,
1305
+ batchItemIndex: batchOwner?.index,
1274
1306
  },
1275
1307
  });
1276
1308
  deps.destroyRef.onDestroy(unregister);
@@ -2924,6 +2956,259 @@ const createIndexedDbQueryPersistenceAdapter = (options) => {
2924
2956
  return { loadIndex, read, write, remove, clear, isSupported: true };
2925
2957
  };
2926
2958
 
2959
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2960
+ /**
2961
+ * Runs the same mutation over a list of items - the bulk edit / bulk delete shape - with a bounded
2962
+ * number of requests in flight and a per-item outcome.
2963
+ *
2964
+ * Where a query stack fans a reactive read out over many arg sets and keeps every query alive, a
2965
+ * batch is imperative and disposable: it is triggered by a button, it tolerates a partial failure,
2966
+ * and it destroys each query as soon as that item settles.
2967
+ *
2968
+ * Call it from an injection context; the host's destruction stops an in-flight run.
2969
+ *
2970
+ * @example
2971
+ * ```ts
2972
+ * protected archivePosts = createQueryBatch({
2973
+ * queryCreator: patchPost,
2974
+ * args: (post: Post) => ({ pathParams: { id: post.id }, body: { archived: true } }),
2975
+ * concurrency: 6,
2976
+ * });
2977
+ *
2978
+ * archiveSelected() {
2979
+ * this.archivePosts
2980
+ * .run(this.selection())
2981
+ * .pipe(tap((result) => result.ok || this.toast.error(`${result.failed.length} failed`)))
2982
+ * .subscribe();
2983
+ * }
2984
+ * ```
2985
+ *
2986
+ * ```html
2987
+ * <button et-button [loading]="archivePosts.running()" [progress]="archivePosts.progress()">Archive</button>
2988
+ * @if (archivePosts.failed()) {
2989
+ * <button (click)="retry()">Retry {{ archivePosts.failed() }} failed</button>
2990
+ * }
2991
+ * ```
2992
+ */
2993
+ const createQueryBatch = (options) => {
2994
+ const { queryCreator, args: mapArgs, stopOnError, allowCache, onItemSettled, features = [] } = options;
2995
+ const concurrency = Math.max(1, Math.floor(options.concurrency ?? 4));
2996
+ if (features.some((f) => f.type === QueryFeatureType.WITH_ARGS)) {
2997
+ throw queryBatchWithArgsUsed();
2998
+ }
2999
+ const injector = inject(Injector);
3000
+ const destroyRef = inject(DestroyRef);
3001
+ const devtoolsHandle = isQueryDevtoolsEnabled()
3002
+ ? { current: null }
3003
+ : undefined;
3004
+ const status = signal('idle', /* @ts-ignore */
3005
+ ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
3006
+ const running = signal(false, /* @ts-ignore */
3007
+ ...(ngDevMode ? [{ debugName: "running" }] : /* istanbul ignore next */ []));
3008
+ const total = signal(0, /* @ts-ignore */
3009
+ ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
3010
+ const inFlight = signal(0, /* @ts-ignore */
3011
+ ...(ngDevMode ? [{ debugName: "inFlight" }] : /* istanbul ignore next */ []));
3012
+ const results = signal([], /* @ts-ignore */
3013
+ ...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
3014
+ const runStartedAt = signal(null, /* @ts-ignore */
3015
+ ...(ngDevMode ? [{ debugName: "runStartedAt" }] : /* istanbul ignore next */ []));
3016
+ const lastSettleAt = signal(null, /* @ts-ignore */
3017
+ ...(ngDevMode ? [{ debugName: "lastSettleAt" }] : /* istanbul ignore next */ []));
3018
+ const completedBeforeRun = signal(0, /* @ts-ignore */
3019
+ ...(ngDevMode ? [{ debugName: "completedBeforeRun" }] : /* istanbul ignore next */ []));
3020
+ let settled = [];
3021
+ let cancelRequested = false;
3022
+ let hostDestroyed = false;
3023
+ const hostDestroyed$ = new Subject();
3024
+ destroyRef.onDestroy(() => {
3025
+ hostDestroyed = true;
3026
+ cancelRequested = true;
3027
+ hostDestroyed$.next();
3028
+ hostDestroyed$.complete();
3029
+ });
3030
+ const publish = () => results.set(settled.filter((r) => !!r));
3031
+ const record = (result) => {
3032
+ settled[result.index] = result;
3033
+ lastSettleAt.set(Date.now());
3034
+ publish();
3035
+ onItemSettled?.(result);
3036
+ };
3037
+ const countOf = (of) => computed(() => results().filter((r) => r.status === of).length);
3038
+ const completed = computed(() => results().length, /* @ts-ignore */
3039
+ ...(ngDevMode ? [{ debugName: "completed" }] : /* istanbul ignore next */ []));
3040
+ const failedResults = computed(() => results().filter((r) => r.status === 'error'), /* @ts-ignore */
3041
+ ...(ngDevMode ? [{ debugName: "failedResults" }] : /* istanbul ignore next */ []));
3042
+ // Measured from the run's start rather than between the last two settles: items land in waves of
3043
+ // `concurrency`, so an instantaneous rate swings between zero and a burst.
3044
+ const itemsPerSecond = computed(() => {
3045
+ const startedAt = runStartedAt();
3046
+ const measuredAt = lastSettleAt();
3047
+ if (startedAt === null || measuredAt === null)
3048
+ return null;
3049
+ const elapsedMs = measuredAt - startedAt;
3050
+ const settledInRun = completed() - completedBeforeRun();
3051
+ // One settled item says nothing about a run of `concurrency` parallel ones, and a run shorter
3052
+ // than the buffer extrapolates a whole batch out of its own warm-up.
3053
+ if (elapsedMs < SPEED_BUFFER_TIME_IN_MS || settledInRun < Math.min(concurrency, total()))
3054
+ return null;
3055
+ return (settledInRun / elapsedMs) * 1000;
3056
+ }, /* @ts-ignore */
3057
+ ...(ngDevMode ? [{ debugName: "itemsPerSecond" }] : /* istanbul ignore next */ []));
3058
+ const remainingTime = computed(() => {
3059
+ const rate = itemsPerSecond();
3060
+ const outstanding = total() - completed();
3061
+ if (rate === null || rate <= 0 || outstanding <= 0)
3062
+ return null;
3063
+ return Math.round((outstanding / rate) * 1000);
3064
+ }, /* @ts-ignore */
3065
+ ...(ngDevMode ? [{ debugName: "remainingTime" }] : /* istanbul ignore next */ []));
3066
+ const runEntry = (entry) => defer(() => {
3067
+ if (cancelRequested) {
3068
+ record({ status: 'cancelled', index: entry.index, item: entry.item });
3069
+ return EMPTY;
3070
+ }
3071
+ const args = mapArgs(entry.item, entry.index);
3072
+ if (args === null) {
3073
+ record({ status: 'skipped', index: entry.index, item: entry.item });
3074
+ return EMPTY;
3075
+ }
3076
+ // The args reach the query through `execute()`, never `withArgs()`, so a function route has to
3077
+ // be told the missing feature is intentional or creating the query throws ET100.
3078
+ const create = () => queryCreator({ silenceMissingWithArgsFeatureError: true }, ...features);
3079
+ const query = runInInjectionContext(injector, () => devtoolsHandle ? runInQueryDevtoolsBatch({ batch: devtoolsHandle, index: entry.index }, create) : create());
3080
+ inFlight.update((count) => count + 1);
3081
+ query.execute({ args, options: { allowCache } });
3082
+ const snapshot = query.createSnapshot();
3083
+ return snapshot.isAlive.asObservable().pipe(filter((isAlive) => !isAlive), take(1),
3084
+ // A destroyed host tears the query down without ever settling it, so the run would hang.
3085
+ takeUntil(hostDestroyed$), tap(() => {
3086
+ const error = snapshot.error();
3087
+ if (error) {
3088
+ record({ status: 'error', index: entry.index, item: entry.item, args, error });
3089
+ if (stopOnError)
3090
+ cancelRequested = true;
3091
+ return;
3092
+ }
3093
+ record({
3094
+ status: 'success',
3095
+ index: entry.index,
3096
+ item: entry.item,
3097
+ args,
3098
+ response: snapshot.response(),
3099
+ });
3100
+ }), finalize(() => {
3101
+ inFlight.update((count) => count - 1);
3102
+ // The host's destruction already tore the query's injector down; destroying it again throws.
3103
+ if (!hostDestroyed)
3104
+ query.subtle.destroy();
3105
+ }));
3106
+ });
3107
+ const settleRun = (entries) => {
3108
+ const stoppedEarly = cancelRequested;
3109
+ for (const entry of entries) {
3110
+ settled[entry.index] ??= { status: 'cancelled', index: entry.index, item: entry.item };
3111
+ }
3112
+ publish();
3113
+ running.set(false);
3114
+ const all = results();
3115
+ const succeeded = all.filter((r) => r.status === 'success');
3116
+ const failed = all.filter((r) => r.status === 'error');
3117
+ const skipped = all.filter((r) => r.status === 'skipped');
3118
+ const notAttempted = all.filter((r) => r.status === 'cancelled');
3119
+ if (failed.length === 0)
3120
+ status.set(notAttempted.length === 0 ? 'success' : 'cancelled');
3121
+ else
3122
+ status.set(succeeded.length === 0 ? 'error' : 'partial');
3123
+ return {
3124
+ ok: failed.length === 0 && notAttempted.length === 0,
3125
+ cancelled: stoppedEarly,
3126
+ results: all,
3127
+ succeeded,
3128
+ failed,
3129
+ skipped,
3130
+ notAttempted,
3131
+ };
3132
+ };
3133
+ const runEntries = (collect) => defer(() => {
3134
+ if (running())
3135
+ throw queryBatchAlreadyRunning();
3136
+ const entries = collect();
3137
+ cancelRequested = false;
3138
+ running.set(true);
3139
+ status.set('running');
3140
+ publish();
3141
+ // After `publish()`: a retry clears its entries first, so this reads the count the retried
3142
+ // items are measured against, not the one from before they were dropped.
3143
+ completedBeforeRun.set(completed());
3144
+ runStartedAt.set(Date.now());
3145
+ lastSettleAt.set(null);
3146
+ return from(entries).pipe(mergeMap((entry) => runEntry(entry), concurrency), toArray(), map(() => settleRun(entries)));
3147
+ });
3148
+ const run = (items) => runEntries(() => {
3149
+ settled = new Array(items.length);
3150
+ total.set(items.length);
3151
+ return items.map((item, index) => ({ item, index }));
3152
+ });
3153
+ const retryFailed = () => runEntries(() => {
3154
+ const entries = results()
3155
+ .filter((r) => r.status === 'error' || r.status === 'cancelled')
3156
+ .map((r) => ({ item: r.item, index: r.index }));
3157
+ for (const entry of entries) {
3158
+ settled[entry.index] = undefined;
3159
+ }
3160
+ return entries;
3161
+ });
3162
+ const batch = {
3163
+ status: status.asReadonly(),
3164
+ running: running.asReadonly(),
3165
+ total: total.asReadonly(),
3166
+ completed,
3167
+ inFlight: inFlight.asReadonly(),
3168
+ succeeded: countOf('success'),
3169
+ failed: countOf('error'),
3170
+ skipped: countOf('skipped'),
3171
+ progress: computed(() => {
3172
+ const count = total();
3173
+ return count === 0 ? 0 : (completed() / count) * 100;
3174
+ }),
3175
+ itemsPerSecond,
3176
+ remainingTime,
3177
+ results: results.asReadonly(),
3178
+ errors: computed(() => failedResults().map((r) => r.error)),
3179
+ failedItems: computed(() => failedResults().map((r) => r.item)),
3180
+ run,
3181
+ retryFailed,
3182
+ cancel: () => {
3183
+ cancelRequested = true;
3184
+ },
3185
+ reset: () => {
3186
+ if (running())
3187
+ return;
3188
+ settled = [];
3189
+ total.set(0);
3190
+ results.set([]);
3191
+ status.set('idle');
3192
+ runStartedAt.set(null);
3193
+ lastSettleAt.set(null);
3194
+ completedBeforeRun.set(0);
3195
+ },
3196
+ };
3197
+ if (devtoolsHandle) {
3198
+ devtoolsHandle.current = batch;
3199
+ const internals = queryCreator.subtle.creatorInternals;
3200
+ const unregister = registerQueryDevtoolsEntry({
3201
+ kind: 'query-batch',
3202
+ handle: devtoolsHandle,
3203
+ route: internals.route,
3204
+ clientRef: internals.client,
3205
+ meta: { method: internals.method, concurrency, stopOnError: !!stopOnError },
3206
+ });
3207
+ destroyRef.onDestroy(unregister);
3208
+ }
3209
+ return batch;
3210
+ };
3211
+
2927
3212
  /**
2928
3213
  * Resolves an {@link QueryInvalidationOptions.url} to the absolute form request URLs are built in, so
2929
3214
  * the comparison - and the message the other tabs receive - never depends on who resolves it.
@@ -4320,6 +4605,8 @@ const buildSequence = (steps, state, devtoolsHandle) => {
4320
4605
  state.running.set(false);
4321
4606
  return { ok: true, responses: responses, snapshots };
4322
4607
  };
4608
+ const completed = computed(() => state.snapshots().length, /* @ts-ignore */
4609
+ ...(ngDevMode ? [{ debugName: "completed" }] : /* istanbul ignore next */ []));
4323
4610
  const sequence = {
4324
4611
  then: (query, mapArgs) => buildSequence([
4325
4612
  ...steps,
@@ -4328,6 +4615,8 @@ const buildSequence = (steps, state, devtoolsHandle) => {
4328
4615
  status: state.status.asReadonly(),
4329
4616
  running: state.running.asReadonly(),
4330
4617
  currentStep: state.currentStep.asReadonly(),
4618
+ completed,
4619
+ progress: computed(() => (steps.length === 0 ? 0 : (completed() / steps.length) * 100)),
4331
4620
  total: steps.length,
4332
4621
  queries: steps.map((s) => s.query),
4333
4622
  error: state.error.asReadonly(),
@@ -4500,6 +4789,54 @@ const resolveFieldTreePath = (fieldTree, path) => {
4500
4789
  return typeof current === 'function' ? current : null;
4501
4790
  };
4502
4791
 
4792
+ /**
4793
+ * Builds a signal form's `submission.action` around a mutation: submitting executes the query with
4794
+ * args derived from the form's value, waits for it to settle, and maps a failed request's violations
4795
+ * back onto the fields that caused them. `form().submitting()` therefore covers the whole round trip.
4796
+ *
4797
+ * This is the submit-time counterpart to {@link validateWithQuery}. The query's args come from the
4798
+ * submitted value rather than a `withArgs()` feature, which also means the query no longer reads the
4799
+ * form it belongs to - so it can be declared before it, and no derivation runs per keystroke.
4800
+ *
4801
+ * ```ts
4802
+ * protected createPost = createQuerySubmission({
4803
+ * queryCreator: postPost,
4804
+ * args: (value) => ({ body: value }),
4805
+ * onSuccess: (post) => this.router.navigate(['/posts', post.id]),
4806
+ * });
4807
+ *
4808
+ * protected form = form(this.model, postSchema, {
4809
+ * submission: { action: this.createPost.action },
4810
+ * });
4811
+ * ```
4812
+ *
4813
+ * ```html
4814
+ * <form [etForm]="form">…</form>
4815
+ * <et-query-error [error]="createPost.query.error()" [query]="createPost.query" />
4816
+ * ```
4817
+ *
4818
+ * Call it from an injection context.
4819
+ */
4820
+ const createQuerySubmission = (config) => {
4821
+ // The args reach the query through `execute()`, never `withArgs()`, so a function route has to be
4822
+ // told the missing feature is intentional or creating the query throws ET100.
4823
+ const query = config.queryCreator({ silenceMissingWithArgsFeatureError: true });
4824
+ const action = async (field) => {
4825
+ const args = config.args?.(field().value(), field) ?? null;
4826
+ if (config.args && args === null)
4827
+ return undefined;
4828
+ const snapshot = await executeUntilSettled(query, args === null ? undefined : { args });
4829
+ const error = snapshot.error();
4830
+ if (error) {
4831
+ return (config.mapViolations?.(error, field) ??
4832
+ mapViolationsToFormErrors({ fieldTree: field, error, rewritePath: config.rewritePath }));
4833
+ }
4834
+ config.onSuccess?.(snapshot.response(), field);
4835
+ return undefined;
4836
+ };
4837
+ return { query, action };
4838
+ };
4839
+
4503
4840
  // Shared core for the query-backed async validators (`validateWithQuery` /
4504
4841
  // `validateWithV2Query`). Everything except how the query is executed - the `factory` that turns
4505
4842
  // the debounced params into a `Resource` - is identical between the v2 and v3 variants, so it is
@@ -7466,7 +7803,7 @@ const armQueryDevtoolsOverrideTransfer = (recorder, ops) => {
7466
7803
 
7467
7804
  // Generated from package.json by tools/scripts/generate-version.js - do not edit.
7468
7805
  /** The version of `@ethlete/query` this build was cut from. */
7469
- const QUERY_VERSION = '6.0.0-next.37';
7806
+ const QUERY_VERSION = '6.0.0-next.38';
7470
7807
 
7471
7808
  /** How deep a schema is expanded before a nested branch is given up on. */
7472
7809
  const MAX_DEPTH = 12;
@@ -8447,6 +8784,12 @@ const applyQueryDevtoolsTokenTtl = (options) => {
8447
8784
  * so the list is capped for the same reason the repository caps its unused entries.
8448
8785
  */
8449
8786
  const MAX_QUERY_DEVTOOLS_TOMBSTONES = 50;
8787
+ /**
8788
+ * How many of its settled items' queries one batch keeps. Counted per batch rather than against
8789
+ * {@link MAX_QUERY_DEVTOOLS_TOMBSTONES}, so a bulk run cannot evict the tombstones the panel is read
8790
+ * for - and low, because the batch's own entry already holds every item's args, response and error.
8791
+ */
8792
+ const MAX_QUERY_BATCH_TOMBSTONES = 20;
8450
8793
  const frozen = (value) => () => value;
8451
8794
  const noop = () => undefined;
8452
8795
  /**
@@ -8668,8 +9011,8 @@ const registerEntry = (registration) => {
8668
9011
  if (index === -1)
8669
9012
  return list;
8670
9013
  const next = list.slice();
8671
- // Only queries leave a tombstone. A stack, sequence, form or auth provider is a container whose
8672
- // interesting state is the queries it owns - each of which tombstones on its own.
9014
+ // Only queries leave a tombstone. A stack, sequence, batch, form or auth provider is a container
9015
+ // whose interesting state is the queries it owns - each of which tombstones on its own.
8673
9016
  if (fullEntry.kind !== 'query') {
8674
9017
  next.splice(index, 1);
8675
9018
  return next;
@@ -8678,16 +9021,39 @@ const registerEntry = (registration) => {
8678
9021
  return capTombstones(next);
8679
9022
  });
8680
9023
  };
8681
- /** Drops the oldest tombstones once there are more than {@link MAX_QUERY_DEVTOOLS_TOMBSTONES} of them. */
9024
+ /** The oldest `count` entries of a bucket, which is what a cap drops when the bucket is over it. */
9025
+ const oldestOver = (bucket, cap) => bucket.length <= cap
9026
+ ? []
9027
+ : bucket.sort((a, b) => (a.destroyedAt ?? 0) - (b.destroyedAt ?? 0)).slice(0, bucket.length - cap);
9028
+ /**
9029
+ * Caps the tombstones the registry holds. A batch's items are counted per batch rather than against the
9030
+ * shared budget: a batch destroys one query per item as it settles, so a single 500-item run would
9031
+ * otherwise fill the whole buffer and evict every tombstone the panel is actually read for - the `401`
9032
+ * that took its component down with it. Each batch keeps its own recent tail instead.
9033
+ */
8682
9034
  const capTombstones = (list) => {
8683
- const excess = list.filter((e) => e.destroyedAt).length - MAX_QUERY_DEVTOOLS_TOMBSTONES;
8684
- if (excess <= 0)
8685
- return list;
8686
- const doomed = new Set(list
8687
- .filter((e) => e.destroyedAt)
8688
- .sort((a, b) => (a.destroyedAt ?? 0) - (b.destroyedAt ?? 0))
8689
- .slice(0, excess));
8690
- return list.filter((e) => !doomed.has(e));
9035
+ const shared = [];
9036
+ const perBatch = new Map();
9037
+ for (const entry of list) {
9038
+ if (!entry.destroyedAt)
9039
+ continue;
9040
+ const batch = entry.meta.batch;
9041
+ if (!batch) {
9042
+ shared.push(entry);
9043
+ continue;
9044
+ }
9045
+ const bucket = perBatch.get(batch);
9046
+ if (bucket)
9047
+ bucket.push(entry);
9048
+ else
9049
+ perBatch.set(batch, [entry]);
9050
+ }
9051
+ const doomed = new Set(oldestOver(shared, MAX_QUERY_DEVTOOLS_TOMBSTONES));
9052
+ for (const bucket of perBatch.values()) {
9053
+ for (const entry of oldestOver(bucket, MAX_QUERY_BATCH_TOMBSTONES))
9054
+ doomed.add(entry);
9055
+ }
9056
+ return doomed.size ? list.filter((e) => !doomed.has(e)) : list;
8691
9057
  };
8692
9058
  /**
8693
9059
  * Forgets destroyed entries the registry is holding - the panel's "clear gone" action. Pass the ids to
@@ -14271,5 +14637,5 @@ const createWebSocketClient = (options) => {
14271
14637
  * Generated bundle index. Do not edit.
14272
14638
  */
14273
14639
 
14274
- export { BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, CustomHeaderAuthProvider, DEFAULT_KEEP_UNUSED_FOR, DEFAULT_QUERY_PERSISTENCE_MAX_AGE, DEFAULT_QUERY_PERSISTENCE_MAX_ENTRIES, DEFAULT_QUERY_PERSISTENCE_VERSION, DEFAULT_QUERY_PERSISTENCE_WRITE_DELAY, DateArrayQueryField, DateQueryField, EMPTY_QUERY_DEVTOOLS_FAULT, EntityStore, IGNORED_FILTER_COUNT_FIELDS, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, LegacyQuery, LegacyQueryCreator, MAX_QUERY_DEVTOOLS_TOMBSTONES, MAX_UNUSED_ENTRIES, NumberArrayQueryField, ParseHttpErrorCodeToMessageDePipe, ParseHttpErrorCodeToMessageEnPipe, ParseHttpErrorCodeToTitleDePipe, ParseHttpErrorCodeToTitleEnPipe, QUERY_CLIENT_DEVTOOLS_TOKEN, QUERY_DEVTOOLS_FAULT_STATUSES, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, QUERY_PERSISTENCE_STORE_VERSION, QUERY_SYNC_PROTOCOL_VERSION, QUERY_VERSION, QueryClientFeatureType, QueryDevtoolsComponent, QueryDirective, QueryFeatureType, QueryField, QueryForm, QueryRuntimeErrorCode, QueryShortNamePipe, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, applyQueryDevtoolsOverrides, applyQueryDevtoolsTokenTtl, applyQueryFeatures, armAllQueryDevtoolsMocks, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, canOverrideQueryDevtoolsTokenTtl, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTokenTtl, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryDevtoolsSchemaComponents, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDefaultRetryFn, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, dateArrayQueryField, dateQueryField, decryptBearer, deepFreeze, def, defineQueryForm, deleteQueryDevtoolsMock, describeQueryDevtoolsFeatures, detectContentTypeHeader, detectPaginationShape, dynLikePaginationAdapter, effectComputed, emptyQueryArgs, ethletePaginationAdapter, executeUntilSettled, extractExpiresInSeconds, extractFormViolations, extractHtmlErrorMessage, extractQuery, fakePaginationAdapter, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsSampleNumber, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsFaults, initQueryDevtoolsMocks, initQueryDevtoolsOverridePersistence, initQueryDevtoolsSettings, injectInfinityQueryResponseDelay, injectQueryContext, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, invalidStateInsideSecureExecuteFactory, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCreateGqlQueryOptions, isCustomHeaderAuthProvider, isDateShapedLeaf, isEmptyString, isGqlQueryConfig, isHtmlErrorPayload, isLegacyQuery, isNaN$1 as isNaN, isPageOutOfRangeError, isQuery, isQueryCollection, isQueryDevtoolsEnabled, isQueryDevtoolsFaultArmed, isQueryDevtoolsRequestInterceptionEnabled, isQueryErrorResponse, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, isUnderInvalidatedUrl, legacyPrepareFallbackInjector, legacyPrepareWithoutInjectionContext, loadQueryDevtoolsSchema, mapToPaginated, mapViolationsToFormErrors, matchesQueryDevtoolsMockPattern, matchesQueryDevtoolsMockQuery, maybeExecute, measureQueryDevtoolsPayload, mergeHeaders, nestedEffect, noteQueryFormRead, numberArrayQueryField, pagedQueryStackNextPageCalledWithoutPreviousPage, pagedQueryStackPageBiggerThanTotalPages, pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, parseHttpErrorCodeToMessageDe, parseHttpErrorCodeToMessageEn, parseHttpErrorCodeToTitleDe, parseHttpErrorCodeToTitleEn, parseQueryDevtoolsOverrideTransfer, parseQueryRoute, patchQueryDevtoolsTokenPayload, pathParamsMissingInRouteFunctionError, provideInfinityQueryResponseDelay, provideLegacyPrepareFallback, provideQueryClientForDevtools, provideQueryDevtools, queryArrayComputed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsArmedMocks, queryDevtoolsArmedMocksRestored, queryDevtoolsEntries, queryDevtoolsFaults, queryDevtoolsFaultsRestored, queryDevtoolsFnDetail, queryDevtoolsMockId, queryDevtoolsMocks, queryDevtoolsOverridePersistence, queryDevtoolsRequestPath, queryDevtoolsResponseHistory, queryDevtoolsRestoredOverridesScope, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, queryDevtoolsSettings, queryDevtoolsStorage, queryDevtoolsTokenTtls, queryErrorMessage, queryErrorMessages, queryExecute, queryFeatureUsedMultipleTimes, queryField, querySequence, querySequenceAlreadyRunning, queryStackTotalQueriesAndExpectedQueriesMismatch, queryStackWithArgsUsed, queryStackWithResponseUpdateUsed, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsAppInfo, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFault, setQueryDevtoolsFaultResolver, setQueryDevtoolsFaultsScope, setQueryDevtoolsFormLinksFactory, setQueryDevtoolsMockResolver, setQueryDevtoolsOverridePersistence, setQueryDevtoolsOverridesFactory, setQueryDevtoolsOverridesScope, setQueryDevtoolsRegistrar, setQueryDevtoolsResponseHistory, setQueryDevtoolsSchemaLoader, setQueryDevtoolsSettings, setQueryDevtoolsStatsFactory, setQueryDevtoolsTokenPayloadPatcher, setQueryDevtoolsTokenTtl, setupQueryDependencies, setupQueryExecuteState, setupQueryState, shouldAutoExecuteGqlQuery, shouldAutoExecuteQuery, shouldCacheQuery, shouldRetryRequest, silenceMissingWithArgsFeatureErrorUsedButWithArgsPresent, skipPaginationPageParamCalculator, smartDuplicateArrayItem, snapshotQueryDevtoolsHandle, sortQueryField, splitQueryConfig, stringArrayQueryField, stringifyQueryRouteParts, sumQueryDevtoolsStats, suppressNextQueryStackDevtools, switchQueryCollectionState, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, transformArrayResponse, transformExecStateToQueryState, transformGql, transformMethod, transformPaginatedResponse, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray, uncacheableRequestHasAllowCacheParam, uncacheableRequestHasCacheKeyParam, unwrapQuerySyncMessage, v2BuildQueryCacheKey, v2ExtractExpiresInSeconds, v2ShouldCacheQuery, v2ShouldRetryRequest, validateWithQuery, validateWithV2Query, withArgs, withArgsQueryFeatureMissingButRouteIsFunction, withAuthenticationQuery, withAutoRefresh, withAutoRefreshUsedInManualQuery, withAutoRefreshUsedOnUnsupportedHttpMethod, withBearerAuthMultiTabSync, withDefaultRetry, withErrorHandling, withEthleteApiErrors, withHtmlErrorParsing, withInactivityLogout, withLogging, withLongPolling, withLongPollingUsedOnUnsupportedHttpMethod, withLongPollingUsedWithPolling, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
14640
+ export { BasicAuthProvider, BearerAuthFeatureType, BooleanArrayQueryField, CustomHeaderAuthProvider, DEFAULT_KEEP_UNUSED_FOR, DEFAULT_QUERY_PERSISTENCE_MAX_AGE, DEFAULT_QUERY_PERSISTENCE_MAX_ENTRIES, DEFAULT_QUERY_PERSISTENCE_VERSION, DEFAULT_QUERY_PERSISTENCE_WRITE_DELAY, DateArrayQueryField, DateQueryField, EMPTY_QUERY_DEVTOOLS_FAULT, EntityStore, IGNORED_FILTER_COUNT_FIELDS, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, LegacyQuery, LegacyQueryCreator, MAX_QUERY_BATCH_TOMBSTONES, MAX_QUERY_DEVTOOLS_TOMBSTONES, MAX_UNUSED_ENTRIES, NumberArrayQueryField, ParseHttpErrorCodeToMessageDePipe, ParseHttpErrorCodeToMessageEnPipe, ParseHttpErrorCodeToTitleDePipe, ParseHttpErrorCodeToTitleEnPipe, QUERY_CLIENT_DEVTOOLS_TOKEN, QUERY_DEVTOOLS_FAULT_STATUSES, QUERY_DEVTOOLS_TOKEN_TTL_LIMIT, QUERY_PERSISTENCE_STORE_VERSION, QUERY_SYNC_PROTOCOL_VERSION, QUERY_VERSION, QueryClientFeatureType, QueryDevtoolsComponent, QueryDirective, QueryFeatureType, QueryField, QueryForm, QueryRuntimeErrorCode, QueryShortNamePipe, QueryStore, SERVER_ERROR_KIND, SERVER_VIOLATION_ERROR_KIND, SPEED_BUFFER_TIME_IN_MS, SearchQueryField, SortQueryField, StringArrayQueryField, V2BearerAuthProvider, V2Query, V2QueryClient, V2QueryCreator, addQueryContainerHandling, applyQueryDevtoolsOverrides, applyQueryDevtoolsTokenTtl, applyQueryFeatures, armAllQueryDevtoolsMocks, armQueryDevtoolsMock, armQueryDevtoolsOverrideTransfer, authExtractTokensResponseMissingAccessToken, authExtractTokensResponseMissingRefreshToken, authExtractTokensResponseNotObject, authProviderFeatureUsedMultipleTimes, booleanArrayQueryField, buildQueryCacheKey, buildQueryString, buildRoute, buildTimestampFromSeconds, canOverrideQueryDevtoolsTokenTtl, castQueryCreatorTypes, circularQueryDependency, circularQueryDependencyChecker, clearQueryDevtoolsArmedMocks, clearQueryDevtoolsFaults, clearQueryDevtoolsMockStore, clearQueryDevtoolsOverrideStore, clearQueryDevtoolsStore, clearQueryDevtoolsTokenTtl, clearQueryDevtoolsTombstones, clearRestoredQueryDevtoolsOverrides, collectLeafPaths, collectQueryDevtoolsSchemaComponents, collectQueryFormLinks, computeQueryAuthHeader, computeQueryBody, computeQueryHeaders, computeQueryMethod, computeQueryQueryParams, consumeSuppressQueryStackDevtools, contentfulGqlLikePaginationAdapter, countUnresolvedQueryDevtoolsOverrides, createAuthGuard, createBaseQuery, createBaseQueryCreator, createBearerAuthProvider, createDefaultRetryFn, createDeleteQuery, createExecuteFn, createGetQuery, createGqlExecuteFn, createGqlMutationViaGet, createGqlMutationViaPost, createGqlQuery, createGqlQueryCreator, createGqlQueryViaGet, createGqlQueryViaPost, createHttpRequest, createIndexedDbQueryPersistenceAdapter, createInfinityQueryConfig, createLegacyQueryCreator, createNoopQueryPersistenceAdapter, createPagedQueryStack, createPatchQuery, createPersistentAuthFeature, createPostQuery, createPutQuery, createQuery, createQueryBatch, createQueryClient, createQueryCollection, createQueryCollectionSignal, createQueryCollectionSubject, createQueryContext, createQueryCreator, createQueryDevtoolsFormLinks, createQueryDevtoolsFormLinksRecorder, createQueryDevtoolsOverrides, createQueryDevtoolsOverridesRecorder, createQueryDevtoolsStats, createQueryDevtoolsStatsRecorder, createQueryErrorResponse, createQueryFeature, createQueryInvalidationFilter, createQueryKeyLockManager, createQueryObject, createQueryPersistenceEngine, createQueryRepository, createQuerySnapshotFn, createQueryStack, createQuerySubmission, createQuerySyncEngine, createQuerySyncTransport, createSecureDeleteQuery, createSecureExecuteFactory, createSecureExecuteFn, createSecureGetQuery, createSecureGqlExecuteFn, createSecureGqlMutationViaGet, createSecureGqlMutationViaPost, createSecureGqlQuery, createSecureGqlQueryCreator, createSecureGqlQueryViaGet, createSecureGqlQueryViaPost, createSecurePatchQuery, createSecurePostQuery, createSecurePutQuery, createSecureQuery, createSecureQueryCreator, createTrackingFeature, createWebSocketClient, currentQueryDevtoolsBatch, dateArrayQueryField, dateQueryField, decryptBearer, deepFreeze, def, defineQueryForm, deleteQueryDevtoolsMock, describeQueryDevtoolsFeatures, detectContentTypeHeader, detectPaginationShape, dynLikePaginationAdapter, effectComputed, emptyQueryArgs, ethletePaginationAdapter, executeUntilSettled, extractExpiresInSeconds, extractFormViolations, extractHtmlErrorMessage, extractQuery, fakePaginationAdapter, filterFailure, filterNull, filterQueryStates, filterSuccess, forEachHeader, formatQueryDevtoolsDuration, generateQueryDevtoolsNumberPreset, generateQueryDevtoolsSampleNumber, generateQueryDevtoolsStringPreset, getBearerAuthProviderName, getDefaultHeaders, getQueryClientName, getQueryFeatureUsage, getResponseUrl, ggLikePaginationAdapter, gql, gqlDataPropertyMissingInResponse, hasHeader, hasQueryDevtoolsOverridesAtPath, htmlErrorPayload, htmlQueryErrorParser, ignoreAutoRefresh, initQueryDevtoolsFaults, initQueryDevtoolsMocks, initQueryDevtoolsOverridePersistence, initQueryDevtoolsSettings, injectInfinityQueryResponseDelay, injectQueryContext, insertFrom, invalidBaseRouteError, invalidBodyError, invalidRouteError, invalidStateInsideSecureExecuteFactory, isAutoRefresh, isBasicAuthProvider, isBearerAuthProvider, isClassValidatorError, isCreateGqlQueryOptions, isCustomHeaderAuthProvider, isDateShapedLeaf, isEmptyString, isGqlQueryConfig, isHtmlErrorPayload, isLegacyQuery, isNaN$1 as isNaN, isPageOutOfRangeError, isQuery, isQueryCollection, isQueryDevtoolsEnabled, isQueryDevtoolsFaultArmed, isQueryDevtoolsRequestInterceptionEnabled, isQueryErrorResponse, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, isSymfonyError, isSymfonyFormViolationListError, isSymfonyListError, isSymfonyPagerfantaOutOfRangeError, isUnderInvalidatedUrl, legacyPrepareFallbackInjector, legacyPrepareWithoutInjectionContext, loadQueryDevtoolsSchema, mapToPaginated, mapViolationsToFormErrors, matchesQueryDevtoolsMockPattern, matchesQueryDevtoolsMockQuery, maybeExecute, measureQueryDevtoolsPayload, mergeHeaders, nestedEffect, noteQueryFormRead, numberArrayQueryField, pagedQueryStackNextPageCalledWithoutPreviousPage, pagedQueryStackPageBiggerThanTotalPages, pagedQueryStackPreviousPageCalledButAlreadyAtFirstPage, paginatedEntityValueUpdater, parseAllXhrResponseHeaders, parseHttpErrorCodeToMessageDe, parseHttpErrorCodeToMessageEn, parseHttpErrorCodeToTitleDe, parseHttpErrorCodeToTitleEn, parseQueryDevtoolsOverrideTransfer, parseQueryRoute, patchQueryDevtoolsTokenPayload, pathParamsMissingInRouteFunctionError, provideInfinityQueryResponseDelay, provideLegacyPrepareFallback, provideQueryClientForDevtools, provideQueryDevtools, queryArrayComputed, queryBatchAlreadyRunning, queryBatchWithArgsUsed, queryClientFeatureUsedMultipleTimes, queryComputed, queryComputedTillTruthy, queryDevtoolsAbout, queryDevtoolsArmedMocks, queryDevtoolsArmedMocksRestored, queryDevtoolsEntries, queryDevtoolsFaults, queryDevtoolsFaultsRestored, queryDevtoolsFnDetail, queryDevtoolsMockId, queryDevtoolsMocks, queryDevtoolsOverridePersistence, queryDevtoolsRequestPath, queryDevtoolsResponseHistory, queryDevtoolsRestoredOverridesScope, queryDevtoolsSchemaNames, queryDevtoolsSchemaRoutes, queryDevtoolsSchemaState, queryDevtoolsSettings, queryDevtoolsStorage, queryDevtoolsTokenTtls, queryErrorMessage, queryErrorMessages, queryExecute, queryFeatureUsedMultipleTimes, queryField, querySequence, querySequenceAlreadyRunning, queryStackTotalQueriesAndExpectedQueriesMismatch, queryStackWithArgsUsed, queryStackWithResponseUpdateUsed, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, queryStateErrorSignal, queryStateLoadingSignal, queryStateResponseSignal, queryStateSignal, readQueryDevtoolsStore, registerEthleteVersion, registerQueryDevtoolsEntry, registerQueryErrorParser, removeFrom, request, resetExecuteState, resetPageOnError, resolveInvalidationUrl, resolveQueryDevtoolsFault, resolveQueryDevtoolsFaultForAttempt, resolveQueryDevtoolsMock, resolveQueryDevtoolsMockForAttempt, restoredQueryDevtoolsOverrides, runDefaultQueryRetry, runInQueryDevtoolsBatch, runQueryErrorParsers, saveQueryDevtoolsMock, searchQueryField, seedQueryDevtoolsSchemaBody, seedQueryDevtoolsSchemaRoute, serializeBody, serializeQueryDevtoolsOverrideTransfer, setDefaultQueryRetryFn, setQueryDevtoolsAppInfo, setQueryDevtoolsArmedMocksScope, setQueryDevtoolsFault, setQueryDevtoolsFaultResolver, setQueryDevtoolsFaultsScope, setQueryDevtoolsFormLinksFactory, setQueryDevtoolsMockResolver, setQueryDevtoolsOverridePersistence, setQueryDevtoolsOverridesFactory, setQueryDevtoolsOverridesScope, setQueryDevtoolsRegistrar, setQueryDevtoolsResponseHistory, setQueryDevtoolsSchemaLoader, setQueryDevtoolsSettings, setQueryDevtoolsStatsFactory, setQueryDevtoolsTokenPayloadPatcher, setQueryDevtoolsTokenTtl, setupQueryDependencies, setupQueryExecuteState, setupQueryState, shouldAutoExecuteGqlQuery, shouldAutoExecuteQuery, shouldCacheQuery, shouldRetryRequest, silenceMissingWithArgsFeatureErrorUsedButWithArgsPresent, skipPaginationPageParamCalculator, smartDuplicateArrayItem, snapshotQueryDevtoolsHandle, sortQueryField, splitQueryConfig, stringArrayQueryField, stringifyQueryRouteParts, sumQueryDevtoolsStats, suppressNextQueryStackDevtools, switchQueryCollectionState, switchQueryState, symfonyQueryErrorParser, takeUntilResponse, toQuerySignal, toQuerySubject, tokensNotAvailableInsideAuthAndExec, tombstoneOf, transformArrayResponse, transformExecStateToQueryState, transformGql, transformMethod, transformPaginatedResponse, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray, uncacheableRequestHasAllowCacheParam, uncacheableRequestHasCacheKeyParam, unwrapQuerySyncMessage, v2BuildQueryCacheKey, v2ExtractExpiresInSeconds, v2ShouldCacheQuery, v2ShouldRetryRequest, validateWithQuery, validateWithV2Query, withArgs, withArgsQueryFeatureMissingButRouteIsFunction, withAuthenticationQuery, withAutoRefresh, withAutoRefreshUsedInManualQuery, withAutoRefreshUsedOnUnsupportedHttpMethod, withBearerAuthMultiTabSync, withDefaultRetry, withErrorHandling, withEthleteApiErrors, withHtmlErrorParsing, withInactivityLogout, withLogging, withLongPolling, withLongPollingUsedOnUnsupportedHttpMethod, withLongPollingUsedWithPolling, withMultiTabSync, withPageResetOnError, withPersistentAuth, withPolling, withPollingUsedOnUnsupportedHttpMethod, withQueryDevtoolsOverridePersistence, withQueryPersistence, withRefreshQuery, withResponseUpdate, withSuccessHandling, withSymfonyErrors, withTokenExpirationWarning, withTokenRevocation, withTracking, wrapAsObservableSignal, wrapQuerySyncMessage, writeQueryDevtoolsStore };
14275
14641
  //# sourceMappingURL=ethlete-query.mjs.map