@ethlete/query 6.0.0-next.6 → 6.0.0-next.61

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 (54) hide show
  1. package/CHANGELOG.md +945 -0
  2. package/fesm2022/ethlete-query-devtools-contract.mjs +1 -0
  3. package/fesm2022/ethlete-query-ngrx-toolkit.mjs +411 -0
  4. package/fesm2022/ethlete-query-ngrx-toolkit.mjs.map +1 -0
  5. package/fesm2022/ethlete-query-testing.mjs +548 -169
  6. package/fesm2022/ethlete-query-testing.mjs.map +1 -1
  7. package/fesm2022/ethlete-query.mjs +14680 -7172
  8. package/fesm2022/ethlete-query.mjs.map +1 -1
  9. package/generators/deprecate-legacy-queries/migration.js +85 -0
  10. package/generators/deprecate-legacy-queries/schema.json +26 -0
  11. package/generators/generators.json +30 -0
  12. package/generators/migrate-from-ngrx-toolkit/args-assignability.js +140 -0
  13. package/generators/migrate-from-ngrx-toolkit/consumers.js +521 -0
  14. package/generators/migrate-from-ngrx-toolkit/creators.js +301 -0
  15. package/generators/migrate-from-ngrx-toolkit/facade.js +295 -0
  16. package/generators/migrate-from-ngrx-toolkit/feature.js +513 -0
  17. package/generators/migrate-from-ngrx-toolkit/migration.js +140 -0
  18. package/generators/migrate-from-ngrx-toolkit/report.js +154 -0
  19. package/generators/migrate-from-ngrx-toolkit/schema.json +42 -0
  20. package/generators/migrate-from-ngrx-toolkit/store-removal.js +633 -0
  21. package/generators/migrate-from-ngrx-toolkit/ts-edits.js +128 -0
  22. package/generators/migrate-query-client-features/migration.js +144 -0
  23. package/generators/migrate-query-client-features/report.js +136 -0
  24. package/generators/migrate-query-client-features/schema.json +26 -0
  25. package/generators/migrate-query-opt-in-features/migration.js +195 -0
  26. package/generators/migrate-query-opt-in-features/report.js +143 -0
  27. package/generators/migrate-query-opt-in-features/schema.json +31 -0
  28. package/generators/migrate-to-query-v3/auth-provider-scaffold.js +160 -0
  29. package/generators/migrate-to-query-v3/cleanup-migration.js +247 -125
  30. package/generators/migrate-to-query-v3/http-client-check.js +93 -0
  31. package/generators/migrate-to-query-v3/legacy-prepare-migration.js +129 -40
  32. package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +274 -152
  33. package/generators/migrate-to-query-v3/migration-scope.js +40 -0
  34. package/generators/migrate-to-query-v3/migration.js +19 -10
  35. package/generators/migrate-to-query-v3/module-graph.js +165 -0
  36. package/generators/migrate-to-query-v3/query-client-migration.js +342 -160
  37. package/generators/migrate-to-query-v3/rename-symbols.js +233 -0
  38. package/generators/migrate-to-query-v3/report.js +40 -7
  39. package/generators/migrate-to-query-v3/schema.json +12 -0
  40. package/generators/migrate-to-query-v3/shared.js +97 -3
  41. package/generators/move-devtools-contract-imports/migration.js +155 -0
  42. package/generators/move-devtools-contract-imports/moved-names.js +153 -0
  43. package/generators/move-devtools-contract-imports/schema.json +26 -0
  44. package/generators/prep-for-query-v3/migration.js +465 -65
  45. package/generators/report-legacy-query-apis/migration.js +256 -0
  46. package/generators/report-legacy-query-apis/schema.json +25 -0
  47. package/migrations/query-field-default-types.md +43 -0
  48. package/migrations/search-query-field-string.md +43 -0
  49. package/migrations.json +87 -0
  50. package/package.json +34 -14
  51. package/types/ethlete-query-devtools-contract.d.ts +2 -0
  52. package/types/ethlete-query-ngrx-toolkit.d.ts +131 -0
  53. package/types/ethlete-query-testing.d.ts +295 -160
  54. package/types/ethlete-query.d.ts +9755 -3682
package/CHANGELOG.md CHANGED
@@ -1,5 +1,950 @@
1
1
  # @ethlete/query
2
2
 
3
+ ## 6.0.0-next.61
4
+
5
+ ### Patch Changes
6
+
7
+ - The `@nx/devkit` peer range is now `>=23.0.0`, matching the Nx floor of the migration guide.
8
+
9
+ ## 6.0.0-next.60
10
+
11
+ ### Patch Changes
12
+
13
+ - Update all dependencies to their latest versions (Nx 24, Vitest 5, jsdom 30, ts-morph 28, @types/node 26 and others). The optional `@nx/devkit` peer dependency now requires `^24.0.0`, and the optional `ts-morph` peer of `@ethlete/core` requires `^28.0.0`.
14
+
15
+ ## 6.0.0-next.59
16
+
17
+ ### Patch Changes
18
+
19
+ - Migrations: show zero-file scans as done, include failed detection output, and detect remaining legacy query wrappers before recommending deprecation.
20
+
21
+ ## 6.0.0-next.58
22
+
23
+ ### Patch Changes
24
+
25
+ - Skip the router navigation of a query form URL write when the URL already holds the form values. The skipped same-URL navigation made the router scroll to the top after a back navigation restored the scroll position.
26
+
27
+ ## 6.0.0-next.57
28
+
29
+ ### Minor Changes
30
+
31
+ - `defineQueryForm().observe()` takes `navigationExtras` (`scroll`, `state`) for each navigation that writes the form's params. With `scroll: 'manual'`, a debounced search no longer scrolls the page to the top under `withInMemoryScrolling`.
32
+
33
+ ## 6.0.0-next.56
34
+
35
+ ### Minor Changes
36
+
37
+ - A web socket client with an `authProvider` now reconnects on user switches and logouts, rejoins rooms after login and drops stale emits; the bearer auth provider gains `sessionId()`.
38
+
39
+ ### Patch Changes
40
+
41
+ - Add the internal `ɵresetQueryDevtoolsForTesting()`, which undoes `provideQueryDevtools()` so a spec that shares a worker with another sees the devtools disabled again.
42
+ - Fix a query form's `activeFilterCount` staying stale when a function `defaultValue` re-resolves to the value already committed.
43
+ - Fix `keepUnusedFor: Infinity` evicting at once, hanging `executeUntilSettled`, leftover optimistic updates, `gql` printing `false`, GET variable order splitting the cache, and legacy `request()` bugs.
44
+
45
+ ## 6.0.0-next.55
46
+
47
+ ### Major Changes
48
+
49
+ - The devtools contract moved from `@ethlete/query` to the new `@ethlete/query/devtools-contract` entry point, and `et update` rewrites the imports; `provideQueryDevtools` and its option types stay put.
50
+ - `setupQueryTest` rethrows non-request errors, `setupAuthTest` retries 401s by default, `mintTestToken` is exported, `isExpiringSoon` ignores routine refreshes, and dates reach the URL as ISO strings.
51
+ - Route errors are renumbered to `ET010`-`ET012` and invalidation URLs must start with `/`; `withResponseUpdate` now works on GraphQL and transformed queries, and misconfigured clients and creators fail early.
52
+
53
+ ### Minor Changes
54
+
55
+ - Add `createQueryGroup`, a fixed set of queries of which the one executed last drives `loading()`, `error()`, `latest()`, the retry target `execute()` and `succeeded$`.
56
+ - Add `invalidates` to mutation creators and `tags` to read creators, plus `invalidateQueries({ tag })`, so a mutation declares what it makes stale.
57
+ - Add `withOptimisticUpdate`, which writes a mutation's expected result into the cached reads its `target` matches before the request and rolls it back on failure.
58
+ - Add the optional, report-only `report-legacy-query-apis` generator (`nx g @ethlete/query:report-legacy-query-apis`; `et update` does not run it), which lists every query collection, infinity query and entity store in `query-v3-migration-tasks.md`, and point the entity follow-up of `migrate-to-query-v3` at `invalidates`, `tags` and `withOptimisticUpdate`.
59
+ - Queries expose the resolved request URL as `url()` (interop queries as `query.url`), and `retryableStatusCodes` also takes a `(status, isRetryableByDefault) => boolean` predicate to add a status to the defaults.
60
+ - `createWebSocketClient` accepts an `authProvider`: the handshake carries its access token, the socket waits for the session restore, reconnects on login, and disconnects and completes its rooms on logout.
61
+
62
+ ### Patch Changes
63
+
64
+ - Peer dependencies are ranges (`^22.1.0` for Angular, `^7.8.0` for RxJS, ...) instead of the workspace's exact versions. The test-only `vite` and `@analogjs/vite-plugin-angular` peers are gone. `report-legacy-query-apis` now lists every `*etQuery` / `[etQuery]` template site.
65
+ - Queries and snapshots no longer create ten effects each up front: one shared effect starts on the first `asObservable()` call, and a late subscriber gets the current value synchronously.
66
+ - Mark every migration with a `level`, so `et update` runs only the required ones.
67
+ - Fix bearer auth event handlers that end the session or create a query throwing NG0602. The handlers now run untracked. The query devtools also skip an invalid stored account, and the provider that registers no longer fails.
68
+ - Document `latestExecutedQuery` and `latestNonInternalQuery` on the bearer auth provider.
69
+ - `createQueryBatch`: a `concurrency` of `NaN` falls back to the default of 4 instead of leaving the run stuck forever.
70
+ - Creators that differ in `responseType`, `withCredentials`, `reportErrors`, `reportProgress` or `retryFn` no longer share one cache entry on the same URL.
71
+ - Keep queries that differ only in `responseType` or `withCredentials` in separate cache entries.
72
+ - The `migrate-query-client-features` migration no longer records a "createQueryClient already has a features array" task for a client that has a `features` array and neither `multiTabSync` nor `persistence`, so running it again over its own output reports nothing.
73
+ - `queryErrorMessages` and `queryErrorMessage` drop blank messages and fall back to the raw response message, and the devtools token TTL override honors a custom `expiresInPropertyName`.
74
+ - Serve a devtools mock whose declared query parameter is one of several values the request repeats.
75
+ - Skip a pasted or stored devtools override that lacks a field its type replays with, instead of arming it and corrupting the response.
76
+ - Fall back to five retained bodies when `provideQueryDevtools({ responseHistory })` is `NaN`, instead of dropping every body.
77
+ - Keep a placeholder or realistic devtools seed inside a schema's `maximum`, and a placeholder string inside its `minLength`/`maxLength`.
78
+ - Keep the args, response and execution state of `execute({ args })` on a query whose `withArgs` returns `null`.
79
+ - A query form now commits `undefined`, `NaN` or an invalid `Date` as the field default, and reads a repeated or non-finite URL param for a single-value field as the default.
80
+ - Stop a GraphQL field named `query` or `mutation` inside an anonymous operation from being sent as its `operationName`.
81
+ - Mark an unused entry waiting out `keepUnusedFor` stale on an invalidation, so an `allowCache` execution refetches it instead of serving pre-mutation data.
82
+ - Legacy `*etQuery`: `scope` now holds the collection key when the directive is given a query collection, instead of always `null`.
83
+ - Freshness: a `cache-control` carrying both `s-maxage` and `max-age` now takes its window from `max-age`.
84
+ - Freshness: a `cacheAdapter` answering `NaN` no longer keeps the response fresh forever; it counts as no freshness window, like `null`.
85
+ - `createPagedQueryStack`: `direction()` reads `'next'` again after an args change reloads the stack, as it already did after `reset()`.
86
+ - A bare `execute()` on a query whose `withArgs` source returns `null` now does nothing and warns in dev mode, instead of a request with `null` args.
87
+ - `et migrations` offers `report-legacy-query-apis` as an optional migration, with the number of files that still use a legacy query collection, infinity query or entity store.
88
+ - Routes with an existing query string now append params with `&`, sort fields keep colons, and GraphQL operations with directives send their `operationName`.
89
+ - Restart a read once when a mutation's refresh and its `invalidates` targets all match it, in the mutating tab and in the other tabs.
90
+ - The JSDoc example of the `createWebSocketClient` `auth` option no longer reads the token from the auth provider: the function runs outside an injection context, so it reads the token from the app's own store.
91
+ - Stop a reactive `joinRoom` from joining its room a second time when a signal it reads changes without changing the room name, which left the room joined after the consumer was destroyed.
92
+ - `RawResponseType` resolves to the `response` type when the args declare no `rawResponse`, instead of `unknown`.
93
+
94
+ ## 6.0.0-next.54
95
+
96
+ ### Patch Changes
97
+
98
+ - Stop a legacy `InfinityQuery` from aborting a non-cacheable page (such as a POST) that is still loading when it is reset or destroyed; the page now finishes and is destroyed once it settles.
99
+ - A legacy query container or collection destroyed while its mutation is in flight now lets the request finish instead of cancelling it.
100
+ - An interop mutation whose prepare injector is destroyed while its request is in flight now finishes before it is destroyed, as it did in v2.
101
+ - Destroying the owner of a legacy mutation that waits to settle after its container let go no longer throws NG0205.
102
+ - A mutation whose `withArgs` source returns `null` while its request is in flight is no longer aborted; it finishes and the query parks once it has settled.
103
+
104
+ ## 6.0.0-next.53
105
+
106
+ ### Major Changes
107
+
108
+ - Calling a query creator whose route uses `pathParams` without `withArgs` is now a type error; opt out with the literal `silenceMissingWithArgsFeatureError: true`, and let a stored `withArgs` feature's type be inferred rather than annotated `QueryFeature`.
109
+
110
+ ### Minor Changes
111
+
112
+ - Add the `reportErrors` creator option: set it to `false` to keep a query's failed requests away from Angular's `ErrorHandler`.
113
+ - `tableSortQueryField()` holds the `et-table` sort and keeps it in the URL, so `[(sort)]="qf.fields.sort().value"` binds it with no mapping.
114
+
115
+ ### Patch Changes
116
+
117
+ - Legacy v2 queries that differ only in headers are now cached separately, `InfinityQuery` retries a failed page instead of skipping it, and `poll()` works again after `stopPolling()` ran while polling was blur-paused.
118
+ - An aborted execution no longer counts as a success: `createQuerySubmission` skips `onSuccess`, `querySequence` stops with `error: null`, and `executeUntilSettled` on a destroyed query resolves a cancelled snapshot instead of throwing NG0205.
119
+ - Auth: `createPersistentAuthFeature` and `createTrackingFeature` run in the feature context's injector, so calling them outside an injection context no longer throws NG0203.
120
+ - Auth: `AuthQueryConfig.retryFn` is now part of the published type declarations.
121
+ - Auth fixes: `redirectOnSessionEnd` fires with `withTokenRevocation`, only the tab a logout started in revokes tokens, a logout during an in-flight revocation still revokes, and multi-tab sync is inert on the server.
122
+ - Auth: the `withPersistentAuth` guide now says the remember-me cookie token is obfuscated with a per-origin key, not encrypted.
123
+ - Query batch: `retryFailed()` no longer resends a mutation that an unsubscribe aborted in flight, since the server may already have applied it.
124
+ - Query: `queryParams` written in a different key order now share one cache entry, in the current and the legacy client, while the URL keeps the written order.
125
+ - `prep-for-query-v3` rewrites `CLEAR_QUERY_ARGS` to `null` and drops its import, and warns about each `withArgs` callback that returns `null`, which now parks the query instead of keeping the previous args.
126
+ - A `Date` in `queryParams` is now sent as its ISO string and keys the cache, retries resolve headers again per attempt, and a root-path devtools override no longer invents a response while nothing has settled.
127
+ - The devtools serialize a response body once for the stats and the event log, and an event row finds its query only when it renders.
128
+ - Devtools mocks now match clients whose `baseUrl` has a path, batch item tombstones stay bounded, bad stored overrides and vault values are ignored, and `setupAuthTest().refresh` honours `buildRefreshArgs`.
129
+ - A query error's `retryState.retry` now says whether a manual retry is worth offering, even after automatic retries are exhausted or without `withDefaultRetry()`; a configured retry policy alone decides it, so `<et-query-error>` shows Retry without `alwaysAllowRetry`.
130
+ - Two signal query forms on one route that commit in the same tick no longer re-parse their own URL write, so no spurious commit, refetch or dropped debounce follows and a committed `Date` keeps its milliseconds.
131
+ - `migrate-to-query-v3` now renames only identifiers bound to the migrated client, keeps default and `type` imports, resolves `.js` and `baseUrl` imports, rewrites `.prepare()` only on legacy creators, and merges a scoped run into the existing report.
132
+ - `execute({ args })` without `withArgs` now records the args so a bare `execute()` re-sends them and polling does not execute twice; refreshes update `lastTimeExecutedAt()` and `triggeredBy()`, and `subtle.setResponse` no longer re-runs `transformResponse`.
133
+ - Legacy `[etInfinityQuery]`: `canLoadMore` stays `true` while the current page has failed or is retrying, so a trigger shown only when it is `true` can retry the first or last page.
134
+ - A secure interop query that waits for a token no longer reports its own request as an `auto` refresh once the token arrives; the load keeps the trigger it was started with.
135
+ - Auth: a negative numeric `refreshStrategy` now counts as `0`, so the proactive refresh fires at token expiry instead of after it.
136
+ - The ngrx-toolkit interop no longer shares a handle between `FormData`, `Blob`, `Map` or `Set` args it cannot tell apart, keys `Date` args by time value, and every `toolkitCall` sends its own headers and args.
137
+ - `migrate-from-ngrx-toolkit` now reports `on()` / `once()` calls on a migrated facade as `NTK-FACADE-ON`, and `NTK-UNCONVERTED-ACTION-GROUP` says the file does not typecheck against migrated facades.
138
+ - A response that cannot be structured-cloned is now skipped with a dev warning instead of disabling persistence writes; in `@ethlete/query/testing`, the fake `BroadcastChannel` delivers as a task (await `flushMultiTabSync()`) and fake store reads are consistent.
139
+ - Auth: `withPersistentAuth` no longer sends a garbled token, or deletes the shared cookie, when a sibling subdomain finds a remember-me cookie another origin wrote under `cookie.domain`.
140
+ - `prep-for-query-v3` now handles re-exported `CLEAR_QUERY_ARGS`, leaves shadowing local names alone, and checks `withArgs` callbacks passed by reference, listing the ones it cannot follow.
141
+ - Query repository: the `unbind` JSDoc now says an entry with a response is kept for `keepUnusedFor` instead of destroyed.
142
+ - `withTokenRevocation` no longer sends a logout revocation queued behind another one when its tokens are live again by the time its turn comes.
143
+ - Paged query stacks now report `isLastPageLoaded` for empty and shrunk results and allow `fetchNextPage()` during a load with `blockExecutionDuringLoading: false`; a query batch unsubscribed mid-flight settles as `cancelled` and `retryFailed()` resends it.
144
+ - `refresh()` and `startPolling()` on a toolkit handle a newer unhashable-args call released now do nothing and warn once, naming the release, instead of warning on every call or polling tick.
145
+ - The web socket client now reconnects with backoff and the current `auth` after a server disconnect or rejected handshake, resets its backoff after 10 s of uptime, and opens no connection during a server render.
146
+
147
+ ## 6.0.0-next.52
148
+
149
+ ### Major Changes
150
+
151
+ - **Breaking:** `queryField<T>()` with a default is typed `T`, not `T | null`, and reads the URL into the default's type instead of guessing; without a default, a non-string `T` needs a `queryParamToValue`.
152
+ - **Breaking:** `searchQueryField()` is typed `string` and starts at `''` instead of `null`, so `[formField]` binds it to `<et-input>` under `strictTemplates`; write `''` where you wrote `search: null`.
153
+
154
+ ### Minor Changes
155
+
156
+ - Add `query.abort()`, which stops the execution in flight and puts `response()`, `error()` and `executionState()` back to where they were before it.
157
+ - `dateQueryField({ as: 'string' })` types the field `string | null`, so `[formField]` binds it to `<et-date-input>`, `<et-date-time-input>` and `<et-time-input>` under `strictTemplates`; the URL carries the control's `valueFormat` string verbatim. `dateQueryField()` without the option still holds a `Date`.
158
+ - Query: add `executeUntilSettled$`, a cold Observable that executes on subscribe, emits the settled snapshot and aborts the request when unsubscribed early; the dropzone delete executor now uses it.
159
+ - Every query request now carries the exported `IS_QUERY_REQUEST` `HttpContextToken`, so an app `HttpInterceptor` can skip requests sent by `@ethlete/query`.
160
+ - Queries keep the previous response while new `withArgs` args load (as `executionState().cachedResponse`) and clear it when parked; opt out per query with `keepPreviousResponse: false`.
161
+ - Add the `@ethlete/query:migrate-from-ngrx-toolkit` generator, which moves `@tomtomb/ngrx-toolkit` features onto v3 query creators and `toolkitCall` facades, points their consumers at `@ethlete/query/ngrx-toolkit`, and lists what is left in `query-toolkit-migration-tasks.md`.
162
+ - New `@ethlete/query/ngrx-toolkit` entry point runs `@tomtomb/ngrx-toolkit` facades and templates on query v3: `toolkitCall`, `toolkitSelect`, the `suspense` pipes, `joinLoading` and `joinErrors`.
163
+ - Query: `withPolling`, `withLongPolling` and `withAutoRefresh` take an `enabled` signal and run only while it is `true`, which replaces stopping a poll with `takeUntil`.
164
+ - `activeFilterCount` no longer counts a `searchQueryField()` or `sortQueryField()`, whatever its key.
165
+
166
+ ### Patch Changes
167
+
168
+ - `*etQuery` over an interop legacy query no longer reports each failed request to the `ErrorHandler` a second time.
169
+ - `*etInfinityQuery` over an interop legacy query no longer reports each failed page to the `ErrorHandler` a second time.
170
+ - Interop queries now report a load they did not start (`refreshQueriesInUse()`, an invalidation) as an `auto` refresh, so `*etQuery` shows `refreshing` instead of `loading` and `ignoreAutoRefresh()` filters it.
171
+ - Legacy `queryComputed` no longer runs its computation twice on creation, which sent a mutation twice and replaced the query it returned synchronously.
172
+ - The legacy `QueryForm` no longer re-emits its unchanged value one debounce after `observe()`, which sent a second identical request from a `queryComputed` reading `currentValue()`.
173
+ - Legacy `QueryForm`: a debounced field that resets an `isResetBy` field (a search resetting the page) keeps its debounce instead of committing its first keystroke at once.
174
+ - Calling `execute()` or `reset()` on a query inside an `effect` no longer re-runs the effect in an endless request loop.
175
+ - `withPolling` executions now report `triggeredBy()` as `'polling'` and `withAutoRefresh` executions as `'auto-refresh'`, so a UI can tell a background refresh from a user-started load.
176
+ - `prep-for-query-v3` now warns about installed dependencies whose declarations import names `@ethlete/query` v3 renames, so they can be rebuilt before the upgrade.
177
+ - Stack, paged-stack and auth `execute()` calls, `createSnapshot()` and `asObservable({ injector })` now work inside an effect or computed, `queryComputedTillTruthy` stops after its first query, and creating a query there throws `ET001`.
178
+ - A migration task covers the `searchQueryField()` change from `null` to `''`.
179
+ - `migrate-to-query-v3` now adds `withEthleteApiErrors()` to migrated clients, carries `entity` and more auth options, and reports the v2 defaults, gql creators and `ExperimentalQuery` helpers it cannot migrate.
180
+ - The `ET100` error now says mutations need `withArgs` too and calls `silenceMissingWithArgsFeatureError` an escape hatch; the query skill recommends `withArgs` for mutations.
181
+
182
+ ## 6.0.0-next.51
183
+
184
+ ### Patch Changes
185
+
186
+ - The devtools pills' stylesheet now carries the application's `CSP_NONCE`, so it passes a strict `style-src`.
187
+
188
+ ## 6.0.0-next.50
189
+
190
+ ### Patch Changes
191
+
192
+ - Legacy interop: `execute()` and `abort()` read the query state untracked again, so `queryComputed(() => legacyQuery.prepare(...).execute())` no longer re-runs on every state change and floods the API until the tab runs out of memory.
193
+
194
+ ## 6.0.0-next.49
195
+
196
+ ### Minor Changes
197
+
198
+ - `withPersistentAuth`'s `autoLogin.buildArgs` and `withTokenExpirationWarning`'s `expiresInPropertyName` now default to the refresh query's own config.
199
+ - `createAuthGuard` gets `redirectOnSessionEnd`, to send a visitor on a protected route to the login, and `redirectOnSessionStart`, to send a visitor on the login route to the return URL once a session starts.
200
+ - `createAuthGuard` stops waiting for a session restore after `restoreTimeoutMs` (default 10s) and gets `canMatchWith`/`canActivateWith` permission guards; the refresh query now retries at most 8 times by default instead of forever (`retryConfig.maxAttempts: 0` restores that).
201
+ - The bearer auth provider gets `session()`, its session status, end cause and execution state as one signal, so a consumer no longer combines three.
202
+ - Add the `persistence` option to `defineQueryForm().observe()`, which stores the committed value and restores it when the URL carries none of the persisted fields.
203
+ - `defineQueryForm` writes from code (`setValue`, `patchValue`, resets) now commit at once, skipping the field debounce, so `value()` is current on the next line; pass `{ debounce: true }` to keep the debounce.
204
+ - GraphQL queries can keep the server's `errors` next to partial data with `transformResponse: unwrapGqlResponseWithErrors`.
205
+ - `withPolling` accepts a signal `interval` and opt-in `pauseWhileHidden`, `refetchOnFocus` and `refetchOnReconnect`.
206
+ - Client `headers` and per-request `args.headers` accept a plain record as well as `HttpHeaders`, for secure queries too, so a client needs no `@angular/*` import to set a header.
207
+ - Behavior change: the default retry policy no longer retries a `POST`, a `PATCH` or a GraphQL mutation; opt back in with `createDefaultRetryFn({ retryNonIdempotent: true })`, and a `retryFn` now receives the request's `method` and `idempotent`.
208
+ - `withTokenRevocation` gets `revokeOn`, to revoke automatically only for some session end causes, and `bearer`, to send the revoked access token as an `Authorization` header. `buildArgs` is now optional.
209
+ - Add `send`, `auth` and `withCredentials` to `createWebSocketClient`, and a `messages$` stream of every room message next to `latestMessage`.
210
+
211
+ ### Patch Changes
212
+
213
+ - Outside a development build the devtools session vault now defaults to `none`, so a plain login no longer leaves tokens in `sessionStorage`, and a vault left in either store is removed on load.
214
+ - An unreadable URL value in a query form field now falls back to the field's `defaultValue` instead of `null`.
215
+ - Mark `setupQueryDependencies`, `createQuerySyncEngine`, `createGqlExecuteFn` and `createSecureGqlExecuteFn` internal, so they leave the published types.
216
+
217
+ ## 6.0.0-next.48
218
+
219
+ ### Patch Changes
220
+
221
+ - `prep-for-query-v3` renames symbols and flattens `ExperimentalQuery` when they are reached through a namespace import such as `import * as q from '@ethlete/query'`.
222
+ - The v3 migration rewrites a legacy `prepare()` call inside an anonymous `export default class`, instead of leaving it unmigrated behind an unused `Injector` import.
223
+ - The v3 migration now warns about a creator whose `secure` value is not a literal `true` or `false`, instead of silently generating a non-secure creator.
224
+ - The v3 migration reports a shorthand creator config property it cannot carry over, such as `{ secure }`, instead of dropping it silently.
225
+
226
+ ## 6.0.0-next.47
227
+
228
+ ### Patch Changes
229
+
230
+ - `QueryRuntimeErrorCode` no longer has `QUERY_STACK_TOTAL_QUERIES_AND_EXPECTED_QUERIES_MISMATCH` (502). A paged query stack could no longer throw it.
231
+ - `migrate-query-opt-in-features` no longer adds `withEthleteApiErrors()` or `withBearerAuthMultiTabSync()` to a config that already lists it.
232
+ - `migrate-to-query-v3`: query clients with aliased imports, shorthand or spread options, a non-literal config, or no variable now migrate correctly or get a report task instead of producing broken code.
233
+ - The v3 migration handles a shorthand `route`, a spread config, several creators in one statement, a creator inside a function and barrel re-exports regardless of file order.
234
+ - `migrate-to-query-v3`: a query polled through `this.x.poll()` no longer gets `destroyOnResponse: true`, and the inserted injector lines keep the surrounding indentation.
235
+ - The v3 migration keeps a shorthand property and a local `export { … }` of a renamed creator import pointing at its legacy wrapper.
236
+ - The v3 migration adds a missing value import to the first value import of a module instead of a type-only one.
237
+
238
+ ## 6.0.0-next.46
239
+
240
+ ### Minor Changes
241
+
242
+ - The Angular peer dependency moves from 22.0.7 to 22.1.6. Angular 22.0.x is affected by
243
+ GHSA-hh8m-fm6v-7cvg, a sanitization bypass through directive host bindings, fixed in 22.1.0.
244
+ - `<et-query-devtools-lazy>` renders nothing without `provideQueryDevtools()` - no floating button, no
245
+ shortcut, no panel download - and the now-public `isQueryDevtoolsEnabled()` is what it gates on.
246
+ - A GraphQL `200` with `errors` and no `data` now fails with `ET601` carrying the server's errors, and the error-message ladder reads `{ errors: [{ message }] }` and `[{ message }]` bodies.
247
+ - GQL over POST sends `variables` as a JSON object, as the spec requires, instead of a JSON string. A server that relied on the string must accept the map. GET is unchanged.
248
+ - `withDefaultRetry()` and `withEthleteApiErrors()` now retry only the client they are on. Before, the first call installed the policy process-wide. Migration: add the feature to every client that should retry - a second client without it no longer retries.
249
+ - `defineQueryForm`: `branch()` now debounces and runs the reset graph like the source form and exposes `liveValue`; the filter overlay applies `liveValue` on submit.
250
+ - HTTP queries gain `createHeadQuery` and `createOptionsQuery` with their secure twins, and `createFakeQueryPersistenceStore()` can fail a removal with `failNextRemoves(count)`.
251
+ - WebSocket client: a room joined after the ping expired, or held across a recovered reconnect, is no longer joined twice. `WebSocketClientSocket` now requires `onAnyOutgoing` and `recovered`; add both to a hand-written fake.
252
+ - Auth: `withTokenExpirationWarning` reads the expiry claim named by its new `expiresInPropertyName` option, so a token that carries the expiry under another name no longer reports no expiry at all.
253
+
254
+ ### Patch Changes
255
+
256
+ - The panel drops a client's Cache, Faults and Events entries once that client's injector is destroyed,
257
+ instead of keeping them alive for as long as one of its queries has a tombstone.
258
+ - Query persistence now opens the IndexedDB database again after the browser closes the connection, for example when the user clears the site data. Before, every later write failed and persistence stopped for the rest of the session.
259
+ - Legacy `V2BearerAuthProvider`: a new token now replaces the pending refresh timer instead of adding a second, parallel refresh chain.
260
+ - Legacy query: variables that differ only by whitespace or braces inside a string, or by nesting, no longer share one cached query instance.
261
+ - Legacy `etInfinityQueryTrigger`: a trigger that stays visible after a page lands now keeps loading the next page instead of stalling.
262
+ - Legacy interop: `abort()` publishes `Cancelled`, a second `execute()` while loading is a no-op again, a poll reports `refreshing`, `triggerImmediately` runs at once, and `state$` replays `Prepared`.
263
+ - `createLegacyQueryCreator`: `prepare({ variables })` now forwards the variables to a wrapped gql creator.
264
+ - Legacy query: a secure query that refreshes after a 401 now stays loading until the retry lands, instead of reporting a failure first.
265
+ - Legacy query containers: teardown destroys an uncacheable query, stops the poll of the last container, tracks dependents per injector, tears down the store's listeners, and leaves a superseded mutation to settle.
266
+ - Legacy `QueryForm`: a value arriving through a navigation (back/forward, a link) now commits at once instead of waiting out the field's debounce, matching `defineQueryForm`.
267
+ - Legacy `QueryForm`: values track control writes without `observe()`, a commit no longer cancels an in-flight route change, and a committed value keeps its type through the form's own URL write.
268
+ - Legacy query: polling no longer resumes on window focus when its `takeUntil` notifier fired while polling was paused.
269
+ - Legacy query: a `false`, `0` or `''` body is now sent with its content type instead of being dropped.
270
+ - Legacy query: a secure query executed while logged out returns to `Prepared` instead of staying `Loading`, so executing it after login sends the request.
271
+ - Legacy query client: calling `setAuthProvider` again with the provider already set no longer cancels its scheduled token refresh.
272
+ - Legacy: `[etInfinityQueryTrigger]` no longer throws NG0200, `v2BuildQueryCacheKey` takes the method, `setAuthProvider` keeps the refresh cookie, the prepare fallback survives several applications, and the barrel's re-exports carry `@deprecated`.
273
+ - `validateWithV2Query`: a secure validate query run while logged out now reports a form-level error instead of leaving the field pending forever.
274
+ - `validateWithV2Query`: a shared GET query cancelled by another consumer is re-run instead of leaving the field pending forever.
275
+ - `fetchNextPage()` on a paged stack returns `null` and keeps its position when its args repeat an already loaded page, like `fetchPreviousPage()` does.
276
+ - Multi-tab auth: a follower waits for the leader's in-flight refresh and spends one token per rotation, a cached login is no longer broadcast, and `withTracking` honors `trackInternalEvents`.
277
+ - Bearer auth: a login that races the cookie restore, an empty `2xx` body and a refresh that yields no tokens now settle the session instead of stranding it, and the cookie clears in every reachable scope.
278
+ - Caching: the key covers the request method and case-folds header names, and an entry's secure, refreshable and retention flags follow the queries still bound to it rather than the one that made it.
279
+ - Cache keys no longer merge request bodies that differ only in whitespace or braces inside strings (GraphQL POST variables like `'new york'` vs `'newyork'`); persisted entries of requests with a body miss once after upgrading.
280
+ - Query: the `ET800` circular-dependency guard counts only executions with identical args and measures its window with its own clock, so a fast-typed search no longer trips it.
281
+ - Destroying a query client's injector now releases its retained unused cache entries and their eviction timers.
282
+ - Query devtools: a tombstone drops the destroyed view, override recorders and host elements are released, the floating pills settle after first paint, and the Forms tab links every reader of a form.
283
+ - Error handling: a malformed `violations` body degrades to a form-level `etServerError` instead of throwing, and the `416`, `408`, `410` and `425` status texts are corrected.
284
+ - Query: `execute()` after destroy warns instead of throwing NG0205, `executeUntilSettled` settles on cancel, `reset()` detaches the request, a batch records a throwing item, and snapshots keep their own signals.
285
+ - A follower tab whose refresh takeover was made moot by a new token pair now re-asks and takes over its next unanswered delegated refresh again.
286
+ - Query forms: an array field with a non-null default now survives a reload holding an empty list or `null`, instead of restoring its default or `['ET_NULL__']`.
287
+ - Query forms: a date-only URL value like `2026-09-01` now reads as local midnight of that day instead of shifting a day west of UTC.
288
+ - A deprecated `QueryForm` field with a function `defaultValue` treats a value equal to its result as the default again, so it is neither written to the URL nor counted in `activeFilterCount$`.
289
+ - Query forms: URL writes no longer break under an app-level `defaultQueryParamsHandling` of `'merge'` or `'preserve'`.
290
+ - Query forms: writing to the URL no longer drops its `#fragment`.
291
+ - `defineQueryForm`: an emptied array commits as its `null` default, `skipResets` and `skipFields` no longer leak into the next change, a value written before `observe()` survives, and `liveValue` reports the controls.
292
+ - Query forms: `skipResets` now applies only to the fields that write changes, so a pending debounced edit to another field still resets its dependents.
293
+ - Query forms: `unobserve()` now commits a pending debounced edit to `value` instead of dropping it.
294
+ - Query forms: restoring an empty or unparseable URL value no longer counts as a change, so `?search=&page=3` keeps page 3 instead of resetting it.
295
+ - Query forms: `searchQueryField` restores `?search=2024` as a string, and a field with an array default restores a single URL value as a one-item array.
296
+ - `defineQueryForm`: two forms writing in one tick keep each other's params, `appendToUrl: false` leaves a foreign param alone, `0` reads back as a number, and a commit no longer cancels a route change.
297
+ - GraphQL: a document is parsed once and minified without breaking on comments or string literals, `rawResponse` can declare its own envelope, and secure queries over POST cache like the rest.
298
+ - GraphQL: the `operationName` sent with a document no longer comes from an operation that only appears in a comment above the real one.
299
+ - Query persistence: a response body IndexedDB cannot store no longer leaves a metadata record without a body on disk.
300
+ - Query persistence: mutations are never stored, one opted-in consumer is enough, GraphQL over POST persists, a failed IndexedDB open is retried, and a purge always beats a hydration or index load in flight.
301
+ - Query persistence: only a `QuotaExceededError` frees the oldest half of the store before the write is retried; any other write failure retries without deleting entries.
302
+ - Persistence: a tab no longer hydrates a body that a build with another `version` wrote over the same key; custom adapters should return `version` from `read`.
303
+ - Query persistence: entries written under another `version` are ignored instead of deleted, so two tabs on either side of a deploy no longer wipe each other's store; they are removed once past `maxAge`.
304
+ - Persistence: a logout now also removes secure responses another tab persisted after this one started.
305
+ - Persistence: secure responses are held back until the session is known and purged when a tab starts without one, so a session that ended without a logout no longer hydrates the previous user's data.
306
+ - Persistence: `whenPersistenceReady` now resolves when a custom adapter's `loadIndex` throws synchronously instead of rejecting.
307
+ - Persistent auth: a session now survives a page reload when `localStorage` refuses writes or is unavailable, instead of silently logging the user out.
308
+ - Query types: `QueryContext` and `setDefaultQueryRetryFn` leave the published types, `createQueryFeature()` takes any `type` string, and `createQuerySubmission`'s `onSuccess` allows the `null` a `204` hands it.
309
+ - `withRefreshQuery`'s `retryConfig.maxAttempts` now retries a failed refresh that many times, instead of one fewer.
310
+ - Query stacks and sequences: `deduplicateArgs` applies without `append`, each response runs its features once, `fetchPreviousPage()` returns the page it made, and every link reports the built `total`.
311
+ - `createQuerySubmission`: a custom `mapViolations` that returns `undefined` or `null` no longer gets the default violation mapping attached to the form.
312
+ - Testing entry point: `setupQueryTest` now installs one console filter instead of nesting a
313
+ new one per call, and exposes `restoreConsole`. `installFakeWebLocks` removes the `abort`
314
+ listeners it adds. The websocket double reports `withCredentials()`.
315
+ - Query: a `transformResponse` that throws lands in `error()` with code `0`, keeps the last good `response()`, and no longer re-runs `withSuccessHandling`.
316
+ - `validateWithQuery`: the in-flight request stops when the field goes idle, and the internal query's cache entry and resource are released with the form that owns them.
317
+ - `validateWithQuery` / `validateWithV2Query`: a network or other non-violation error keeps its form-level error when a custom `mapViolations` is set, instead of validating the field as clean.
318
+ - WebSockets: a room joined before the socket connects sends one `join-room`, and a frame carrying no `room` string is reported as malformed without flooding production logs.
319
+ - The devtools session vault no longer uses `localStorage` outside a development build, so a deployed
320
+ app can mount the panel without leaving tokens and credentials behind.
321
+ - A room left while the web socket is down no longer sends a `leave-room` to a fresh session that never joined it; after a recovered reconnect the leave is still sent.
322
+
323
+ ## 6.0.0-next.45
324
+
325
+ ### Patch Changes
326
+
327
+ - [`cd8956e`](https://github.com/ethlete-io/ethdk/commit/cd8956ed2303074e4de564e6a2763e385acb17ee) Thanks [@TomTomB](https://github.com/TomTomB)! - Query: `withPersistentAuth` no longer leaves a second auth cookie behind on a subdomain, and logout removes the one it wrote.
328
+
329
+ ## 6.0.0-next.44
330
+
331
+ ### Patch Changes
332
+
333
+ - [#3077](https://github.com/ethlete-io/ethdk/pull/3077) [`8c2cb3a`](https://github.com/ethlete-io/ethdk/commit/8c2cb3a7b8a311363255d66b0f3c07fcfc4f6bdb) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth: `onRefreshFailure` and the `logout()` it triggers now run outside the reactive context of the effect that detects the failure. A consumer reacting to the session ending could otherwise throw `NG0602` instead of handling the logout.
334
+
335
+ - [`f7d6bb1`](https://github.com/ethlete-io/ethdk/commit/f7d6bb12a799b680ce72c90cbdcfd96ae3ea2fc0) Thanks [@TomTomB](https://github.com/TomTomB)! - A secure query now waits for the token refresh instead of sending an access token that is already expired, so a session seeded by SSO no longer costs a `401` and a retry.
336
+
337
+ ## 6.0.0-next.43
338
+
339
+ ### Patch Changes
340
+
341
+ - [#3075](https://github.com/ethlete-io/ethdk/pull/3075) [`48488fb`](https://github.com/ethlete-io/ethdk/commit/48488fbdc0d61bafe5e8117844e5efa2c31c330a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth: a rejected cookie auto-login now ends the session through `onRefreshFailure` with `sessionEndCause()` `'expired'`, and `setTokens()` supersedes an auto-login still in flight so its late `401` no longer overwrites the seeded session.
342
+
343
+ - [`a533863`](https://github.com/ethlete-io/ethdk/commit/a533863ce73cbb9e3454b6016be39487aa965c7a) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: a session that ends as expired is dropped from the auth vault, so a tab seeded with it no longer meets the same dead token on every reload.
344
+
345
+ - [#3075](https://github.com/ethlete-io/ethdk/pull/3075) [`1d38e7e`](https://github.com/ethlete-io/ethdk/commit/1d38e7e0a025769f065d8ca7d506cb75ad89139a) Thanks [@github-actions](https://github.com/apps/github-actions)! - `et update` moves the `@ethlete/*` packages to a newer version, runs the codemods those versions
346
+ declare in their own `migrations.json`, and reports what needs a decision or an agent.
347
+
348
+ - [#3075](https://github.com/ethlete-io/ethdk/pull/3075) [`f9fbd3a`](https://github.com/ethlete-io/ethdk/commit/f9fbd3a6959a99af7c6de60d7ceaf2781e8a58d2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Re-export types explicitly with `export type` so the barrels type-check under `isolatedModules`.
349
+
350
+ ## 6.0.0-next.42
351
+
352
+ ### Minor Changes
353
+
354
+ - [#3074](https://github.com/ethlete-io/ethdk/pull/3074) [`ee8e7d1`](https://github.com/ethlete-io/ethdk/commit/ee8e7d12b6ef06245f18df017c217d2bbe66e616) Thanks [@github-actions](https://github.com/apps/github-actions)! - The devtools' floating API env and session pickers are now folded into one small chip, which reads
355
+ the current values and unfolds every picker on a click. A production pick keeps them unfolded.
356
+
357
+ - [#3074](https://github.com/ethlete-io/ethdk/pull/3074) [`ee8e7d1`](https://github.com/ethlete-io/ethdk/commit/ee8e7d12b6ef06245f18df017c217d2bbe66e616) Thanks [@github-actions](https://github.com/apps/github-actions)! - The devtools session vault keeps one session per user on a backend that issues no `sub` claim, and
358
+ the panel logs in as an account with the body keys that login needs.
359
+
360
+ ### Patch Changes
361
+
362
+ - [`67b6128`](https://github.com/ethlete-io/ethdk/commit/67b6128035bcafa21539a7d69b8f0dd4df2737be) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix the devtools **Log in as** landing one login behind: the previous user's cached data is now dropped once the login's tokens are in force, not while the old token is still the one every secure query re-runs on.
363
+
364
+ - [#3074](https://github.com/ethlete-io/ethdk/pull/3074) [`6b00cbe`](https://github.com/ethlete-io/ethdk/commit/6b00cbe0d09d44dbc292a9c1d8173021cf88a5d7) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: the floating pills now share one height, one set of edges and one set of picker
365
+ columns, and the fold control reads as a button instead of a lone caret.
366
+
367
+ ## 6.0.0-next.41
368
+
369
+ ### Minor Changes
370
+
371
+ - [`acc396a`](https://github.com/ethlete-io/ethdk/commit/acc396aa73313204fc09d54b083562cea5afb5b1) Thanks [@TomTomB](https://github.com/TomTomB)! - `provideQueryDevtools({ apiEnvs })` puts an API environment picker beside the floating toggle and on the Settings tab; a pick writes the app's own `localStorage` key and reloads. An env marked `production` makes the picker shout.
372
+
373
+ - [`d8fea59`](https://github.com/ethlete-io/ethdk/commit/d8fea594beb1094b0715ce24e308862d2ddd4f21) Thanks [@TomTomB](https://github.com/TomTomB)! - The devtools Auth tab now keeps every session you log in as and switches between them, logs in as an
374
+ account declared through `provideQueryDevtools({ authAccounts })`, and can hold one tab's session
375
+ apart from the rest.
376
+
377
+ ## 6.0.0-next.40
378
+
379
+ ### Minor Changes
380
+
381
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`a9113cb`](https://github.com/ethlete-io/ethdk/commit/a9113cb6ce63942ffce0e26ca7df7f0556a14838) Thanks [@github-actions](https://github.com/apps/github-actions)! - The legacy `QueryStateType` and `AuthBearerRefreshStrategy` are const objects instead of
382
+ `const enum`s, so a transpile-only build can consume them.
383
+
384
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`56e301f`](https://github.com/ethlete-io/ethdk/commit/56e301f6e3b455b1e7e2de54f101206bb890b557) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query: harden auth, caching, forms, GraphQL, WebSockets and legacy lifecycle behavior; add lifecycle-scoped form branches and secure host-only auth cookies.
385
+
386
+ ### Patch Changes
387
+
388
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`0c324b0`](https://github.com/ethlete-io/ethdk/commit/0c324b0d765fb6a07ec9a5766638bd5b52006651) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: list a query's request headers in their own section, so a secure query's `Authorization` is readable however its args reached it.
389
+
390
+ - [#3069](https://github.com/ethlete-io/ethdk/pull/3069) [`55736ec`](https://github.com/ethlete-io/ethdk/commit/55736ec21189efa86fd107043579fc4c65e4452e) Thanks [@github-actions](https://github.com/apps/github-actions)! - Correct reactive state mutability declarations across Query, Contentful and Query Devtools.
391
+
392
+ ## 6.0.0-next.39
393
+
394
+ ### Minor Changes
395
+
396
+ - [`194e668`](https://github.com/ethlete-io/ethdk/commit/194e668efec08272b5a6fc82c16f1593b03d4584) Thanks [@TomTomB](https://github.com/TomTomB)! - Queries: omit response metadata from request args and expose retained responses on loading and failed execution states.
397
+
398
+ ### Patch Changes
399
+
400
+ - [`a9bf390`](https://github.com/ethlete-io/ethdk/commit/a9bf390952d78d436bd23d33c86b57369a990fce) Thanks [@TomTomB](https://github.com/TomTomB)! - Auth multi-tab sync: a tab the browser froze now gives the leadership up instead of holding it while it refreshes nothing, and a follower whose token goes stale takes the refresh over when the leader does not answer.
401
+
402
+ - [`4c97b3e`](https://github.com/ethlete-io/ethdk/commit/4c97b3e584aed96f905ec48e409f90ab8e334af8) Thanks [@TomTomB](https://github.com/TomTomB)! - The bearer auth leadership now follows the visible tab: a hidden leader gives way, and one that stopped running has the lock taken off it, so a sleeping tab no longer strands the others on a dead token.
403
+
404
+ - [`78e46fa`](https://github.com/ethlete-io/ethdk/commit/78e46fa8643d37c11e13d3f50065dea29f5c3e46) Thanks [@TomTomB](https://github.com/TomTomB)! - `defineQueryForm().observe()` now merges the URL onto the form's live model, so a value written
405
+ before `observe()` survives and only the fields the URL names are overwritten.
406
+
407
+ ## 6.0.0-next.38
408
+
409
+ ### Minor Changes
410
+
411
+ - [`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
412
+ created it. Batch tombstones are capped per batch, so a bulk run cannot evict the others.
413
+
414
+ - [`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
415
+ next to its progress. Both are `null` until the run has settled enough items to measure.
416
+
417
+ - [`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
418
+ outcome and a `retryFailed()` that resends only what did not succeed.
419
+
420
+ - [`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
421
+ violations back onto the fields that caused them.
422
+
423
+ - [`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
424
+ progress bar or a determinate button spinner without deriving it from `currentStep()`.
425
+
426
+ ## 6.0.0-next.37
427
+
428
+ ### Minor Changes
429
+
430
+ - [#3058](https://github.com/ethlete-io/ethdk/pull/3058) [`b6c106e`](https://github.com/ethlete-io/ethdk/commit/b6c106e17d8925fd881eb94974782e94ae03686d) Thanks [@github-actions](https://github.com/apps/github-actions)! - The Mocks tab seeds a body in a placeholder, realistic or stress value style, and `provideQueryDevtools({ schema })` takes one API description per query client.
431
+
432
+ ## 6.0.0-next.36
433
+
434
+ ### Patch Changes
435
+
436
+ - [#3056](https://github.com/ethlete-io/ethdk/pull/3056) [`3595aa0`](https://github.com/ethlete-io/ethdk/commit/3595aa0e847afcd23b294027fc5daaceb8fcf0f2) Thanks [@github-actions](https://github.com/apps/github-actions)! - A tab that adopts its session from another tab now reports it as a token seed, so its secure queries and anything else waiting on a login no longer wait forever.
437
+
438
+ ## 6.0.0-next.35
439
+
440
+ ### Major Changes
441
+
442
+ - [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`695c2e9`](https://github.com/ethlete-io/ethdk/commit/695c2e9d08f2e283816488938b446009acd4ad99) Thanks [@github-actions](https://github.com/apps/github-actions)! - `withArgs`: return `null` to park a query. `CLEAR_QUERY_ARGS` is removed, and `null` no longer means "keep the previous args".
443
+
444
+ ### Minor Changes
445
+
446
+ - [`8e175ba`](https://github.com/ethlete-io/ethdk/commit/8e175bae730ea171a4f9e5727c9a5a4b4739f230) Thanks [@TomTomB](https://github.com/TomTomB)! - Retries: the default policy now backs off exponentially with jitter and gives up after
447
+ `maxAttempts` instead of retrying a connection failure every 5s forever, is configurable via
448
+ `withDefaultRetry({ … })` / `createDefaultRetryFn()`, and stops once the last consumer is gone.
449
+
450
+ - [`bf291f9`](https://github.com/ethlete-io/ethdk/commit/bf291f95d69d1aa4c8e07952ad8b55432a921936) Thanks [@TomTomB](https://github.com/TomTomB)! - Add the `withLongPolling` query feature: each round starts once the previous one settled, with args derived from its response, and a failed round is repeated with a growing delay.
451
+
452
+ ### Patch Changes
453
+
454
+ - [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`6776ec2`](https://github.com/ethlete-io/ethdk/commit/6776ec282ae9513d36fdfb199958728af083dc8f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth multi-tab fixes: a follower no longer duplicates the leader's scheduled refresh, a joining tab
455
+ adopts the live session instead of auto-logging in, and a tab coming back to the foreground rechecks
456
+ a refresh its throttled timer missed.
457
+
458
+ - [#3055](https://github.com/ethlete-io/ethdk/pull/3055) [`cd8072e`](https://github.com/ethlete-io/ethdk/commit/cd8072e58977194422cf86e4b52c40b3f5d4f35b) Thanks [@github-actions](https://github.com/apps/github-actions)! - `withInactivityLogout` now times out on the session being idle rather than one tab being idle, so a forgotten tab no longer logs the user out of the one they are working in.
459
+
460
+ ## 6.0.0-next.34
461
+
462
+ ### Minor Changes
463
+
464
+ - [`d9dada4`](https://github.com/ethlete-io/ethdk/commit/d9dada4189ece040a7b5c6423ad802228ace0e88) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: override an auth provider's access-token lifetime from the Auth tab, so the proactive refresh, the expiration warning and the logout behind them happen in seconds instead of hours.
465
+
466
+ - [#3054](https://github.com/ethlete-io/ethdk/pull/3054) [`9bd94f6`](https://github.com/ethlete-io/ethdk/commit/9bd94f62d01ff000c5e3e84c4f010bd109422e4c) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: arm every designed mock in one click, and keep armed mocks or faults across a reload
467
+ with two new Settings scopes.
468
+
469
+ - [#3054](https://github.com/ethlete-io/ethdk/pull/3054) [`3b0f1ea`](https://github.com/ethlete-io/ethdk/commit/3b0f1ea09f2539091a1f3da091f94cbd4e2cbec5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: export designed mocks as OpenAPI 3.1 - one route to the clipboard, or the whole library as
470
+ one YAML or JSON document.
471
+
472
+ ### Patch Changes
473
+
474
+ - [`1d77cb9`](https://github.com/ethlete-io/ethdk/commit/1d77cb960587005bb97fde4825a21e09f6980caf) Thanks [@TomTomB](https://github.com/TomTomB)! - Auth: a 401 from a request sent with an already-replaced access token no longer triggers another token refresh - with rotating refresh tokens this looped refreshes indefinitely; the query now just retries with the current token.
475
+
476
+ ## 6.0.0-next.33
477
+
478
+ ### Minor Changes
479
+
480
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`4f6e1df`](https://github.com/ethlete-io/ethdk/commit/4f6e1df7b43d0a2805aed555acfff65634c2cbe8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth: `withPersistentAuth`'s `autoLogin` takes a `shouldAutoLogin(url)` predicate alongside `excludeRoutes`, so route policy can be an exact match rather than a prefix.
481
+
482
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`d3f1b2b`](https://github.com/ethlete-io/ethdk/commit/d3f1b2b8d3c2a6a0e68013ba130bd833ac72d7fe) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a "Keep across reloads" toggle stores armed response overrides in `sessionStorage` and replays them on the next load, announcing in a banner what came back and what matched no query.
483
+
484
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`f426563`](https://github.com/ethlete-io/ethdk/commit/f4265630749f162d097b147da55256e8bfa056ad) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: an About tab reporting the loaded `@ethlete/*` and Angular versions plus `provideQueryDevtools({ about })`, mirrored on `window.ethlete` and in the session export.
485
+
486
+ - [`908f35a`](https://github.com/ethlete-io/ethdk/commit/908f35a7a68445467cfe6fe60393f9dc9b140503) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: design a mock's body in the value explorer, and seed it from your API description via
487
+ `provideQueryDevtools({ schema })`.
488
+
489
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`d14fcf0`](https://github.com/ethlete-io/ethdk/commit/d14fcf0cf4537bca49aee2671b178c1af0df5d39) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a Mocks tab that answers a route with a designed response instead of sending the request, and copies that route back out as a typed query definition.
490
+
491
+ - [`5feb1dc`](https://github.com/ethlete-io/ethdk/commit/5feb1dcc9b5428357faba170acfce1101fa29150) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: copy a query's whole armed override set and paste it onto another, and edit response
492
+ values with `Set to null`, `Empty this array`, `Paste as new item` and delete.
493
+
494
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`a51e919`](https://github.com/ethlete-io/ethdk/commit/a51e9192e7166ea22ff3cfcabdbd96ae4cb94e54) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a Settings panel behind the header's gear - a storage scope per kind of panel state, runtime limits, a reset, and every panel-wide switch in one place.
495
+
496
+ ### Patch Changes
497
+
498
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`b20c79c`](https://github.com/ethlete-io/ethdk/commit/b20c79cca0e3c2ebca96ca103d27fbe3628e9402) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix the proactive token refresh never firing, and re-arm a scheduled refresh that came
499
+ due while it could not run.
500
+
501
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`bb32533`](https://github.com/ethlete-io/ethdk/commit/bb3253307d958abd70a103aa14a542df7a0cab51) Thanks [@github-actions](https://github.com/apps/github-actions)! - Carry the cause a logout ended the session with across multi-tab sync, so a receiving
502
+ tab reports `'expired'` or `'inactivity'` instead of always `'otherTab'`.
503
+
504
+ - [#3053](https://github.com/ethlete-io/ethdk/pull/3053) [`2192f8d`](https://github.com/ethlete-io/ethdk/commit/2192f8d400df006525dba488248c45b5f09fc24d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Secure queries now send the current access token after a token refresh instead of the one they were first built with, which used to `401` and could loop refresh-and-retry forever.
505
+
506
+ ## 6.0.0-next.32
507
+
508
+ ### Patch Changes
509
+
510
+ - [`fcdf018`](https://github.com/ethlete-io/ethdk/commit/fcdf01864995a23bc850a748455357685ae90b6d) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix token refresh causing an infinite loop
511
+
512
+ ## 6.0.0-next.31
513
+
514
+ ### Minor Changes
515
+
516
+ - [`458f5b7`](https://github.com/ethlete-io/ethdk/commit/458f5b7ecfe9b4360fc220a8465d46833f831ffd) Thanks [@TomTomB](https://github.com/TomTomB)! - Add `buildArgs` to `withRefreshQuery`, so an API that does not name the refresh field `token` can be
517
+ refreshed at all.
518
+
519
+ ## 6.0.0-next.30
520
+
521
+ ### Minor Changes
522
+
523
+ - [`70a0602`](https://github.com/ethlete-io/ethdk/commit/70a06025c2f919bd1582b2d0adbf80b21a25696a) Thanks [@TomTomB](https://github.com/TomTomB)! - `withBearerAuthMultiTabSync` exposes `leadership` (`election` / `off` / `unsupported`), so a tab reading `isLeader: true` can tell a won election from one that never ran.
524
+
525
+ - [#3050](https://github.com/ethlete-io/ethdk/pull/3050) [`cab3d1a`](https://github.com/ethlete-io/ethdk/commit/cab3d1ae2f3ef37df63663b62edb842e8e4a8f9b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth: add `createAuthGuard(providerRef, config)` - route guards that wait out a session restore, redirect to your login URL with the attempted URL attached, and navigate back afterwards.
526
+
527
+ - [`33e705b`](https://github.com/ethlete-io/ethdk/commit/33e705bfb989ec80e245b4bd9e2091c57cd337b8) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: **Forget** shows only while the **Gone** chip is lit, drops exactly the tombstones the list is showing, and is styled as the destructive action it is instead of as a filter clear. `clearQueryDevtoolsTombstones()` takes optional ids.
528
+
529
+ ### Patch Changes
530
+
531
+ - [#3050](https://github.com/ethlete-io/ethdk/pull/3050) [`e7ffcfc`](https://github.com/ethlete-io/ethdk/commit/e7ffcfc5049e81f27732bda7d71ba4e467778fed) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query persistence: a logout purge or `clearPersistedQueries()` can no longer be undone by a write that was already on its way to disk, and `maxEntries` is applied at startup as well.
532
+
533
+ - [`4b8499d`](https://github.com/ethlete-io/ethdk/commit/4b8499dbd099b81a593ced27bd6df63b4047e173) Thanks [@TomTomB](https://github.com/TomTomB)! - `validateWithQuery` no longer throws `ET100` when the creator's route is a function - its args reach
534
+ the query at execute time, which the created query now declares.
535
+
536
+ ## 6.0.0-next.29
537
+
538
+ ### Minor Changes
539
+
540
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`4c6c06f`](https://github.com/ethlete-io/ethdk/commit/4c6c06f072830999cf9f06730181833090db4537) Thanks [@github-actions](https://github.com/apps/github-actions)! - A refresh that fails for good now ends the session instead of leaving it looking valid - override with `onRefreshFailure`. A 401 in a follower tab asks the leader to refresh, and is no longer throttled by `minRefreshInterval`.
541
+
542
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`d17e79d`](https://github.com/ethlete-io/ethdk/commit/d17e79db20c93f3e04033feb8e88f0db9efce6b6) Thanks [@github-actions](https://github.com/apps/github-actions)! - The bearer auth provider now publishes `sessionStatus()` (`unknown | restoring | authenticated | anonymous`) and `sessionEndCause()`, and `logout()` takes a cause. Only the most recent token-issuing execution applies its tokens and writes `executionState()`, across registry keys.
543
+
544
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`86659a1`](https://github.com/ethlete-io/ethdk/commit/86659a1adc3f90c8d8ce4b76ceb955c55aa61b62) Thanks [@github-actions](https://github.com/apps/github-actions)! - Auth: a tab receiving synced tokens now retries its failed queries, a cross-tab logout is a real logout, and the remember-me cookie survives startup. Query devtools: a failed run keeps its status and body.
545
+
546
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`9fc5ec5`](https://github.com/ethlete-io/ethdk/commit/9fc5ec5ace959b50402c0688bebf721d69bd4945) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools overrides: type a custom value or paste a copied subtree as a replayed rule, and presets (including the new long-word one) now generate a varied sample per arm instead of one frozen value.
547
+
548
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`1d181d7`](https://github.com/ethlete-io/ethdk/commit/1d181d7ecec575a2cae17f42f6914b70b4dd95ac) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a destroyed query stays readable as a tombstone - a muted row the **Gone** chip narrows to - and the repository emits `entry-destroyed` so the panel can say why a cache entry disappeared.
549
+
550
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`7081567`](https://github.com/ethlete-io/ethdk/commit/7081567496b2a6416b6c1a74223a278c6a2a2c1d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: pick both ends of a response diff instead of only comparing a run against its predecessor, and raise how many bodies are kept with `provideQueryDevtools({ responseHistory })`.
551
+
552
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`089d41b`](https://github.com/ethlete-io/ethdk/commit/089d41bc3180d09a0d8c0cc0da1be1ba0219cd1b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query stack: a custom `transform` is now typed with the `null` responses it actually receives (a compile-time break for callbacks that assumed otherwise), and `lastQuery` no longer points at a query `maxQueries` just evicted.
553
+
554
+ ### Patch Changes
555
+
556
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`b31de2f`](https://github.com/ethlete-io/ethdk/commit/b31de2ff3fa0ceaea22b3f314ee4ba5ef44a6cd8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bearer auth multi-tab sync: the broadcast channel and the leader lock are namespaced by the provider's `name`, so two providers on one origin no longer share a token channel and one leader.
557
+
558
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`b31de2f`](https://github.com/ethlete-io/ethdk/commit/b31de2ff3fa0ceaea22b3f314ee4ba5ef44a6cd8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bearer auth: each registry key now reuses one query across executions, so logins and token refreshes stop leaking an injector, an effect and cached credentials per attempt.
559
+
560
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`16e2f77`](https://github.com/ethlete-io/ethdk/commit/16e2f77e9ae9c89bda41f744195c4233e62bc06d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bearer auth: a response the `extractTokens` step rejects now puts `executionState` into `error` instead of reporting a `success` that never authenticated the tab.
561
+
562
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`c984b8c`](https://github.com/ethlete-io/ethdk/commit/c984b8cc7e71596b0218763f90e1411d3afaf3e4) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a `null`/`undefined` value can now be overridden instead of showing an empty menu, and **Reset** appears only where something is armed and clears the whole subtree.
563
+
564
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`089d41b`](https://github.com/ethlete-io/ethdk/commit/089d41bc3180d09a0d8c0cc0da1be1ba0219cd1b) Thanks [@github-actions](https://github.com/apps/github-actions)! - Paged query stack: `canFetchNextPage` / `canFetchPreviousPage` are now false while a page is loading, and `isFirstPageLoaded` reports whether page 1 is loaded instead of always being true.
565
+
566
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`69823ed`](https://github.com/ethlete-io/ethdk/commit/69823ed509254101c31df0ffd429171a40f7325b) Thanks [@github-actions](https://github.com/apps/github-actions)! - `defineQueryForm`: `isResetBy` resets now cascade transitively, so changing `country` clears `league` **and** the `team` that depends on it, in one committed change.
567
+
568
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`fd41d42`](https://github.com/ethlete-io/ethdk/commit/fd41d42d1f7c2858b7ea19e1936ec13ada4570bc) Thanks [@github-actions](https://github.com/apps/github-actions)! - `refreshQueriesInUse()` and `invalidateQueries()` now only re-fire reads, so a cached auth `POST` is never replayed. GraphQL queries over `POST` keep refreshing.
569
+
570
+ - [#3048](https://github.com/ethlete-io/ethdk/pull/3048) [`8847481`](https://github.com/ethlete-io/ethdk/commit/8847481e6ef505754c56b5c1ab9d3ca19ed4f784) Thanks [@github-actions](https://github.com/apps/github-actions)! - Web socket rooms: joins are counted, so one subscriber unmounting no longer leaves a room the others still hold - they used to silently stop receiving messages.
571
+
572
+ ## 6.0.0-next.28
573
+
574
+ ### Minor Changes
575
+
576
+ - [#3047](https://github.com/ethlete-io/ethdk/pull/3047) [`e266740`](https://github.com/ethlete-io/ethdk/commit/e266740c41f1eae06e2ddf16fae6cda29c6ed5a6) Thanks [@github-actions](https://github.com/apps/github-actions)! - The prerelease's `createQueryForm()` is now `defineQueryForm()` and returns a plain object rather than a class instance (`CreateQueryFormConfig` → `DefineQueryFormConfig`).
577
+
578
+ ### Patch Changes
579
+
580
+ - [`53cd2a5`](https://github.com/ethlete-io/ethdk/commit/53cd2a5d0a618c298bd9f631ea4dea32f6f9f590) Thanks [@TomTomB](https://github.com/TomTomB)! - Secure queries that outlive a logout now run again once the user logs back in, instead of staying idle for the rest of the page load.
581
+
582
+ ## 6.0.0-next.27
583
+
584
+ ### Patch Changes
585
+
586
+ - [#3046](https://github.com/ethlete-io/ethdk/pull/3046) [`291e8a9`](https://github.com/ethlete-io/ethdk/commit/291e8a9c6ecb9c51c191b4ed6e40d41465ff4cfa) Thanks [@github-actions](https://github.com/apps/github-actions)! - Secure queries executed after `setTokens()` (SSO/OIDC callbacks, native shells) no longer wait forever - they now also proceed once `executionState` reports a successful token seed.
587
+
588
+ ## 6.0.0-next.26
589
+
590
+ ### Minor Changes
591
+
592
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`b2ac74b`](https://github.com/ethlete-io/ethdk/commit/b2ac74b0fad22ba656d7b2028d19dd25f06e57d8) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: add a persistent, path-addressed response-override registry that replays edits (value presets, array/pagination duplication, resets) against a query's response on every fetch.
593
+
594
+ ### Patch Changes
595
+
596
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`5c676cf`](https://github.com/ethlete-io/ethdk/commit/5c676cf29dbe18d5ca81e8a5c45144a4ec93d712) Thanks [@github-actions](https://github.com/apps/github-actions)! - `BearerAuthProvider.setTokens()` now sets `executionState` to `{ type: 'tokenSeed', state: 'success' }`, so SSO/OIDC callback and native-shell logins work with the same `executionState`-driven redirect logic as a query-driven login.
597
+
598
+ - [#3045](https://github.com/ethlete-io/ethdk/pull/3045) [`321da6a`](https://github.com/ethlete-io/ethdk/commit/321da6a9d1b97dc34204011d1372fe1c7bfadb3d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Internal: route-building and legacy query-state errors now throw `RuntimeError` (from `@ethlete/core`) instead of the ad hoc `QueryError` class, which is removed.
599
+
600
+ ## 6.0.0-next.25
601
+
602
+ ### Major Changes
603
+
604
+ - [`e9fbdab`](https://github.com/ethlete-io/ethdk/commit/e9fbdab00dfe50a20c1b7fe284ab29fd91a25e77) Thanks [@TomTomB](https://github.com/TomTomB)! - `createWebSocketClient` now takes socket.io's `io` as a required option, so `@ethlete/query` no longer
605
+ pulls `socket.io-client` (~13 kB gz) into apps that never open a socket. New:
606
+ `createWebSocketTestDouble()` in `@ethlete/query/testing`.
607
+
608
+ ### Minor Changes
609
+
610
+ - [`fb32936`](https://github.com/ethlete-io/ethdk/commit/fb32936caa749895fc77348a6213d0d3ab6bd056) Thanks [@TomTomB](https://github.com/TomTomB)! - Web socket devtools now record outgoing traffic and can emit test messages, and a request reports how long its last execution took via `subtle.lastDurationMs`.
611
+
612
+ ### Patch Changes
613
+
614
+ - [`a50a6a0`](https://github.com/ethlete-io/ethdk/commit/a50a6a01e722746cf74fe6181d2da301912528ab) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix `HttpRequestLoadingProgressState.speed`, which reported 1000x the actual rate (and
615
+ `Infinity` on a stalled or re-executed request), and show it in the query devtools.
616
+
617
+ ## 6.0.0-next.24
618
+
619
+ ### Minor Changes
620
+
621
+ - [`41354e7`](https://github.com/ethlete-io/ethdk/commit/41354e7c64ad713caa2393e6a3df592a410b53be) Thanks [@TomTomB](https://github.com/TomTomB)! - Legacy interop: containers accept `{ injector }` like `prepare()` does and default their cleanup by
622
+ request method again, and `provideLegacyPrepareFallback()` lets `prepare()` use the root injector instead
623
+ of throwing ET950 (browser only).
624
+
625
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`cf41b4e`](https://github.com/ethlete-io/ethdk/commit/cf41b4e64268eef05bbd69b501e9d08581d09697) Thanks [@github-actions](https://github.com/apps/github-actions)! - Mark every legacy (v2) query export as `@deprecated`, including the `createLegacyQueryCreator`
626
+ interop, and add `nx g @ethlete/query:deprecate-legacy-queries` to tag wrappers already in source.
627
+ Removal is v7.
628
+
629
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`156659d`](https://github.com/ethlete-io/ethdk/commit/156659de868ff8a66f9b0b6acbb59c637979500d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: count what every query cost - how often it refreshed, how many refreshes reached
630
+ the network, and how much payload they moved - as activity tiles per query plus totals per client.
631
+
632
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`ebc94d4`](https://github.com/ethlete-io/ethdk/commit/ebc94d456176f350a02a29d8b23c1c6fbb573cd5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: a new **Faults** tab arms real request failures per query client - latency before
633
+ every attempt, fail-the-next-N, fail-N%, and the response status - resolved per attempt inside the
634
+ pipeline, so the retry policy re-rolls it.
635
+
636
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`156659d`](https://github.com/ethlete-io/ethdk/commit/156659de868ff8a66f9b0b6acbb59c637979500d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: list every query, auth and client feature with the options it was configured with,
637
+ not just its name.
638
+
639
+ - [`6c6213b`](https://github.com/ethlete-io/ethdk/commit/6c6213b48f8e5c5ccf0fcb526dd50884e768fb82) Thanks [@TomTomB](https://github.com/TomTomB)! - Query devtools: add a **Forms** tab covering `createQueryForm` - its fields, URL params and the query it drives - and log each invalidation with every query it refetched.
640
+
641
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`9f5f9ec`](https://github.com/ethlete-io/ethdk/commit/9f5f9ecc64a0290f753b9979e2667fbe3de238a0) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: the Insomnia export now includes the auth provider's token refresh, and secure
642
+ requests read their bearer token out of its response instead of shipping one that goes stale.
643
+
644
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`156659d`](https://github.com/ethlete-io/ethdk/commit/156659de868ff8a66f9b0b6acbb59c637979500d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: list queries with their path params filled in from args (`/post/12` instead of
645
+ `/post/:param`), and export requests as an Insomnia v4 collection.
646
+
647
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`8b665a3`](https://github.com/ethlete-io/ethdk/commit/8b665a39bccf09e51fac34c6d05b9b9d2793d4e5) Thanks [@github-actions](https://github.com/apps/github-actions)! - Surface retries and transfer progress in the query devtools: `request.subtle.attempts()` and
648
+ `request.subtle.retryState()` report what a retry policy is doing, and the panel shows backoff
649
+ countdowns, attempt counts and a progress bar for `reportProgress` requests.
650
+
651
+ - [#3043](https://github.com/ethlete-io/ethdk/pull/3043) [`37a74ae`](https://github.com/ethlete-io/ethdk/commit/37a74aec9c149a00f493894a75499c7e86d83cf7) Thanks [@github-actions](https://github.com/apps/github-actions)! - Record what a query did per run: its last 25 runs land on the devtools stats handle, feeding a new
652
+ **Timeline** tab that draws every request on one axis and a **History** section that diffs responses.
653
+
654
+ ### Patch Changes
655
+
656
+ - [`41354e7`](https://github.com/ethlete-io/ethdk/commit/41354e7c64ad713caa2393e6a3df592a410b53be) Thanks [@TomTomB](https://github.com/TomTomB)! - Legacy interop fixes: `destroyOnResponse` no longer strands its watcher on an aborted query, an `entity`
657
+ config no longer syncs a `null` response on `prepare()`, and a falsy `body` is sent instead of dropped.
658
+
659
+ - [`41354e7`](https://github.com/ethlete-io/ethdk/commit/41354e7c64ad713caa2393e6a3df592a410b53be) Thanks [@TomTomB](https://github.com/TomTomB)! - `migrate-to-query-v3` now threads an injector into `prepare()` calls inside callbacks (`computed`,
660
+ `effect`, RxJS operators) and adds `destroyOnResponse` when the prepared query is discarded.
661
+
662
+ ## 6.0.0-next.23
663
+
664
+ ### Major Changes
665
+
666
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`53fcc97`](https://github.com/ethlete-io/ethdk/commit/53fcc97ef5b982fa8a3c5912c0800de1416feca6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Bearer auth multi-tab sync and leader election are opt-in: `createBearerAuthProvider`'s `multiTabSync`
667
+ option is replaced by `withBearerAuthMultiTabSync()` in `features` (~1.4 kB gz off the secure entry
668
+ without it), read back as `provider.features.multiTabSync.isLeader()`. Election runs on the Web Locks
669
+ API now rather than a `localStorage` heartbeat, so a tab that closes or crashes hands over at once.
670
+ `setupAuthTest()` lost its `multiTabSync` option. Migrate with
671
+ `npx nx g @ethlete/query:migrate-query-opt-in-features`.
672
+
673
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`8b13854`](https://github.com/ethlete-io/ethdk/commit/8b13854aa079196c84fc08da0aee685f728a441d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query client: multi-tab sync and response persistence are opt-in `features` instead of defaults - the
674
+ `multiTabSync` / `persistence` client options are gone and a client without the features ships neither
675
+ engine. Migrate with `nx g @ethlete/query:migrate-query-client-features`.
676
+
677
+ - `withMultiTabSync()` shares reads, polls a cache key in one tab for all of them and refreshes the
678
+ others after a mutation; per-query `multiTabSync: false` keeps a query tab-local.
679
+ - `withQueryPersistence()` keeps public reads in IndexedDB, so a reload renders the last known data
680
+ while it revalidates. Secure responses need an explicit opt-in and are removed on logout.
681
+ - `refreshQueriesInUse()` also refreshes GraphQL queries transported over POST; devtools gain Sync
682
+ and Disk columns.
683
+
684
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`53fcc97`](https://github.com/ethlete-io/ethdk/commit/53fcc97ef5b982fa8a3c5912c0800de1416feca6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Error-response parsing and the default retry policy are opt-in query client features - without them a
685
+ client reads the plain `string` / `{ message }` / `{ detail }` / `string[]` ladder and retries
686
+ nothing, which takes ~1.4 kB gz out of an app that needs neither. Pick from `withHtmlErrorParsing()`,
687
+ `withSymfonyErrors()`, `withDefaultRetry()`, `withEthleteApiErrors()` (all three, the previous
688
+ behavior) and `registerQueryErrorParser()` for a body shape the SDK does not know. Run
689
+ `npx nx g @ethlete/query:migrate-query-opt-in-features` to keep the old behavior.
690
+
691
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`42ec970`](https://github.com/ethlete-io/ethdk/commit/42ec970d6963bb5a3aa3af4e207ef2cac801c915) Thanks [@github-actions](https://github.com/apps/github-actions)! - DI: `createProvider` / `createRootProvider` / `createStaticProvider` / `createStaticRootProvider` /
692
+ `createLabels` are replaced by `defineProvider` & co., which return a definition you read with
693
+ `toProvideFn` / `toInjectFn` / `toToken`; `createQueryClient`, `createBearerAuthProvider` and
694
+ `createWebSocketClient` return that definition instead of a tuple. Every `provideX` / `injectX` /
695
+ token export keeps its name - run `nx g @ethlete/core:migrate-provider-shape` for your own call sites.
696
+ Cuts the `@ethlete/components` import floor from 89.9 to 2.4 kB gz.
697
+
698
+ ### Minor Changes
699
+
700
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`e040432`](https://github.com/ethlete-io/ethdk/commit/e040432bdfdce6b46073589bc66fd3a8bdf66111) Thanks [@github-actions](https://github.com/apps/github-actions)! - New `client.invalidateQueries()` re-runs the queries this client has on screen whose data went stale -
701
+ after a mutation, or a push message saying something changed server-side - and tells the user's other
702
+ tabs to do the same. Narrow it with `url` (resolved against `baseUrl`, matched on path boundaries) and
703
+ `filter`, or keep it local with `otherTabs: false`; reaching other tabs needs `withMultiTabSync()`.
704
+ See [Invalidating after a change](https://ethlete-sdk-docs.web.app/query/caching#invalidating-after-a-change).
705
+
706
+ ### Patch Changes
707
+
708
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`a935328`](https://github.com/ethlete-io/ethdk/commit/a9353288d4e4ee41607005e8a1ab81921c21cf83) Thanks [@github-actions](https://github.com/apps/github-actions)! - `logout()` now abandons every unsaved-changes guard (`injectUnsavedChangesCoordinator().abandonAll('logout')`). Pressing logout with a dirty form used to leave a "discard your changes?" dialog floating over the login page the app had already redirected to, plus a tab still locked against closing - over edits that can no longer be saved. Guards created after a re-login work normally again.
709
+
710
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`353777b`](https://github.com/ethlete-io/ethdk/commit/353777bb56e42ad1c02058a2ccf694f69c94b025) Thanks [@github-actions](https://github.com/apps/github-actions)! - Mark build-tooling peer dependencies (`vite`, `typescript`, `ts-morph`, `@nx/devkit`, `@analogjs/*`) and feature-scoped runtime peers (`date-fns` in components) as optional via `peerDependenciesMeta`. They are only needed when running the Nx generators or using the date/time components - consumers no longer have to install them just to use the libraries.
711
+
712
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`53fcc97`](https://github.com/ethlete-io/ethdk/commit/53fcc97ef5b982fa8a3c5912c0800de1416feca6) Thanks [@github-actions](https://github.com/apps/github-actions)! - Devtools instrumentation is now registered through a hook that `provideQueryDevtools()` installs, so
713
+ an app without it drops the entry registry, the route stringifier and the client-name derivation
714
+ entirely - ~0.5 kB gz off every entry. No API change; `queryDevtoolsEntries` and the
715
+ `<et-query-devtools>` contract are unchanged.
716
+
717
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`42ec970`](https://github.com/ethlete-io/ethdk/commit/42ec970d6963bb5a3aa3af4e207ef2cac801c915) Thanks [@github-actions](https://github.com/apps/github-actions)! - Internal: the current generation no longer imports anything from the legacy V2 tree - `buildRoute`,
718
+ `buildQueryString`, `buildTimestampFromSeconds`, `decryptBearer`, `QueryError` and the query-string
719
+ types now live in `http/internal/request-route`, and `legacy` re-exports them. Every public name is
720
+ unchanged. Also closes the `http ↔ gql` cycle.
721
+
722
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`53fcc97`](https://github.com/ethlete-io/ethdk/commit/53fcc97ef5b982fa8a3c5912c0800de1416feca6) Thanks [@github-actions](https://github.com/apps/github-actions)! - `socket.io-client` is an optional peer dependency. It is only imported by `createWebSocketClient`,
723
+ and no non-`ws` public type surfaces it, so an app that does not use the realtime client no longer
724
+ has to install it.
725
+
726
+ - [#3041](https://github.com/ethlete-io/ethdk/pull/3041) [`353777b`](https://github.com/ethlete-io/ethdk/commit/353777bb56e42ad1c02058a2ccf694f69c94b025) Thanks [@github-actions](https://github.com/apps/github-actions)! - Adopt the `@ethlete/eslint-plugin` styleguide flat configs in `core`, `query`, `contentful` and
727
+ `types`, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible to
728
+ TypeScript consumers: exported `types` shapes are `type` aliases rather than `interface` declarations
729
+ (so they can no longer be extended by declaration merging), `core`'s `PropsDirective.destroyRef` and
730
+ `SeoDirective.parent` are `private`, and `ConsentHandler` is a `type`. The theme name registries stay
731
+ interfaces so consumers can keep augmenting them.
732
+
733
+ ## 6.0.0-next.22
734
+
735
+ ### Minor Changes
736
+
737
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`dcd8585`](https://github.com/ethlete-io/ethdk/commit/dcd8585423c4d0a66d968016a6e88b03c87b168a) Thanks [@github-actions](https://github.com/apps/github-actions)! - Error normalization: reduce an HTML error page (a proxy's `502`, a maintenance page) to its heading and message text instead of using the raw markup as the message. Exposes `isHtmlErrorPayload`, `htmlErrorPayload` and `extractHtmlErrorMessage`.
738
+
739
+ ### Patch Changes
740
+
741
+ - [#3040](https://github.com/ethlete-io/ethdk/pull/3040) [`bc8aca7`](https://github.com/ethlete-io/ethdk/commit/bc8aca76900a47a3faed4ad2be2ce2ab7b70b27d) Thanks [@github-actions](https://github.com/apps/github-actions)! - Filter overlay: new `provideFilterOverlay` / `injectFilterOverlay` - a filter panel that drafts the page's query
742
+ form, reports how many results the draft would return on its submit button, and applies on submit or discards on
743
+ dismiss. Replaces cdk's `FilterOverlayService`, rebuilt on signal forms and the current query client.
744
+
745
+ ## 6.0.0-next.21
746
+
747
+ ### Patch Changes
748
+
749
+ - [#3038](https://github.com/ethlete-io/ethdk/pull/3038) [`0be9397`](https://github.com/ethlete-io/ethdk/commit/0be939765c6074a518c5c05a7110513f1e3e8ef0) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix `ET301` on every legacy interop mutation. `LegacyQuery.execute()` translates v2's single `skipCache` into
750
+ `allowCache: options.skipCache !== true` for **every** method, so any `legacyPost*` / `legacyPut*` /
751
+ `legacyPatch*` / `legacyDelete*` executed without an explicit `skipCache: true` reached the repository with
752
+ `allowCache: true` and threw "This request is uncacheable, but allowCache is set to true".
753
+
754
+ `allowCache` is never read on the uncacheable path - there is no cache entry to reuse - so the throw was purely a
755
+ guard against a mistake in hand-written code. It stays for that, and gains a
756
+ `silenceUncacheableAllowCacheError` opt-out on `QueryConfig`, which `createLegacyQueryCreator` sets alongside the
757
+ `silenceMissingWithArgsFeatureError` it already passed. The cache-key guard is unaffected.
758
+
759
+ Note that dropping `allowCache: true` in the interop instead would have silently made every legacy `GET` refetch,
760
+ since an absent `allowCache` means "do not reuse the entry" rather than "use the default".
761
+
762
+ ## 6.0.0-next.20
763
+
764
+ ### Minor Changes
765
+
766
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`a83cfe4`](https://github.com/ethlete-io/ethdk/commit/a83cfe4b3e69c3e70ac20f81a5c287bdb6278a63) Thanks [@github-actions](https://github.com/apps/github-actions)! - Cache entries are now kept for `keepUnusedFor` (5 minutes by default) after their last consumer was destroyed, instead of being discarded immediately. A query that mounts again within that window - a list page reached via browser back navigation, for instance - binds to the existing entry and renders its previous response right away while revalidating in the background (`executionState()` reports `{ type: 'loading', hasCachedResponse: true }`).
767
+
768
+ - Configurable per client (`createQueryClient({ keepUnusedFor })`) and per query creator; `0` restores the previous release-immediately behavior.
769
+ - Independent of `cache-control`, so it also applies to private/authenticated responses.
770
+ - Only entries holding a response are kept - in-flight and errored ones are still aborted immediately. At most 50 unused entries per client are retained, and retention is disabled on the server.
771
+
772
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`7ae9eaa`](https://github.com/ethlete-io/ethdk/commit/7ae9eaa878c6c3bfa80876c67ac1f9360a1c24ec) Thanks [@github-actions](https://github.com/apps/github-actions)! - Close the gaps found while migrating a real workspace from the legacy client to v3:
773
+
774
+ - **Client-level headers.** `createQueryClient({ headers })` takes `HttpHeaders` or a function
775
+ re-read on every request, so a signal can drive it. Per-query `args.headers` merge on top and win
776
+ per name. `client.refreshQueriesInUse()` re-runs every bound `GET`/`HEAD`/`OPTIONS` (in-flight ones
777
+ included) - the replacement for v2's `setDefaultHeaders({ refreshQueriesInUse: true })`.
778
+ - **`provider.setTokens(access, refresh)`** on the public bearer auth provider, for tokens issued
779
+ outside it (SSO callbacks, native shells). Previously reachable only from inside a custom feature.
780
+ - **`logout()` now resets bound secure queries.** It already unbound their cache entries, but the
781
+ query objects kept their `response()`, so a component mounted across a logout went on rendering the
782
+ previous user until something called `reset()`.
783
+ - **Legacy `prepare()` failures are diagnosable.** Calling it without an injection context throws
784
+ `ET950` naming the creator instead of a bare `NG0203`; calling it with an already destroyed injector
785
+ returns an inert query and warns in dev mode instead of throwing `NG0205` from a view's cleanup
786
+ phase. `createLegacyQueryCreator` takes a `name` for those messages.
787
+ - **Query-collection consumers accept real legacy queries.** `AnyQueryCollection` no longer pins the
788
+ arguments type, so a `createQueryCollectionSignal` result is assignable to `*etQuery`,
789
+ `queryStateErrorSignal` and `switchQueryCollectionState` without a cast.
790
+ - **`queryErrorMessages(error)` / `queryErrorMessage(error)`** flatten a `QueryErrorResponse` into
791
+ displayable strings, and `emptyQueryArgs<TArgs>()` covers argless queries in generic code (auth
792
+ registry `execute()` now takes no argument either).
793
+ - **`BearerAuthProviderOf<typeof ref>`** derives the exact provider type; `AnyBearerAuthProvider` no
794
+ longer forces bracket access on `provider.queries` under `noPropertyAccessFromIndexSignature`.
795
+
796
+ `migrate-to-query-v3` got a precision pass:
797
+
798
+ - Renames are scoped to imports that actually resolve to the migrated symbol, so same-named type
799
+ members, config properties and exports from unrelated packages are left alone; import aliases are
800
+ preserved instead of dropped.
801
+ - `--projects` / `--include` migrate one app or library at a time.
802
+ - Unused imports (`def`, `AnyLegacyQuery*`, stale client symbols) are no longer left behind.
803
+ - Auth providers are scaffolded from the v2 `V2BearerAuthProvider` config instead of `queries: []`.
804
+ - Devtools are migrated rather than deleted: the per-client `provideQueryClientForDevtools` calls
805
+ collapse into one `provideQueryDevtools()`, `QueryDevtoolsComponent` is re-imported from
806
+ `@ethlete/components`, and `<et-query-devtools>` markup is left alone - both versions use that selector.
807
+ - New report tasks for dropped v2 client options, missing `provideHttpClient()`, `setDefaultHeaders`
808
+ call sites and the auth import-cycle layout.
809
+
810
+ - [#3037](https://github.com/ethlete-io/ethdk/pull/3037) [`0c30546`](https://github.com/ethlete-io/ethdk/commit/0c30546c220bc40f5a167c9d5cbad2757e9c7108) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add a signals-first query form: `createQueryForm({ fields, queryParamPrefix? })` alongside field creators `queryField`, `searchQueryField`, `sortQueryField`, `stringArrayQueryField`, `numberArrayQueryField`, `booleanArrayQueryField`, `dateQueryField`, `dateArrayQueryField`.
811
+
812
+ Built on Angular signal forms, so each field is bindable to the SDK's own controls with `[formField]` (e.g. `<input etInput [formField]="qf.fields.search" />`). Fields commit as a debounced signal `value`, sync to the URL query params (default elision, `ET_NULL__` sentinel, `active:direction` sort format, prefix namespacing), reset dependents via the `isResetBy` graph, expose `activeFilterCount` as a signal, and support a detached `branch()` for edit-then-apply filter flows.
813
+
814
+ Also adds a `withPageResetOnError` query feature that resets the page (a signal or a query-form field) when the current page goes out of range (HTTP `416`, or a dev-mode `500` Pagerfanta out-of-range error), plus the exported `isPageOutOfRangeError` predicate.
815
+
816
+ The existing reactive-forms `QueryForm` is unchanged and remains available.
817
+
818
+ ## 6.0.0-next.19
819
+
820
+ ### Minor Changes
821
+
822
+ - [#3036](https://github.com/ethlete-io/ethdk/pull/3036) [`aa4bdde`](https://github.com/ethlete-io/ethdk/commit/aa4bdde586615ed13735ed9c970831b91323ebad) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query devtools: add `provideQueryDevtools()` and a registry that instruments
823
+ queries, query stacks, paged query stacks, `querySequence`, bearer auth providers
824
+ and web socket clients so they can be inspected by `<et-query-devtools>` (from
825
+ `@ethlete/components`). Instrumentation is a no-op unless the provider is added,
826
+ so there is no overhead when it is omitted.
827
+
828
+ Supporting devtools APIs added: `querySequence` exposes a `stepArgs` signal (the
829
+ resolved input args of each step); the query repository gains
830
+ `subtle.cacheEntries()` / `subtle.cacheVersion` / `subtle.evict()`; queries gain
831
+ `subtle.setLoading()` / `subtle.setError()` (force UI states for testing);
832
+ `HttpRequest` exposes `method`, `url` and `expiresAt`; `QueryClient` exposes its
833
+ `baseUrl`; `QuerySequence` exposes its step `queries`; and web socket clients
834
+ expose a devtools handle (connection state, rooms, recent messages).
835
+
836
+ ## 6.0.0-next.18
837
+
838
+ ### Minor Changes
839
+
840
+ - [`5685798`](https://github.com/ethlete-io/ethdk/commit/56857988a9fb579a791950cd85d015dfd36921a3) Thanks [@TomTomB](https://github.com/TomTomB)! - Add `querySequence` for imperative waterfalls of dependent queries - chain mutations with `.then()`, thread each response into the next, and `run()` to a typed, discriminated result that aborts on the first error. Exposes `status`/`running`/`currentStep`/`error` progress signals for driving UI.
841
+
842
+ ## 6.0.0-next.17
843
+
844
+ ### Minor Changes
845
+
846
+ - [#3030](https://github.com/ethlete-io/ethdk/pull/3030) [`47e4109`](https://github.com/ethlete-io/ethdk/commit/47e41097adf96788120840bdd03cad25306628f2) Thanks [@github-actions](https://github.com/apps/github-actions)! - Add `validateWithQuery` (v3) and `validateWithV2Query` (v2) - query-backed async
847
+ validators for Angular signal forms. They adapt an `@ethlete/query` query into
848
+ `validateAsync`, so server-side validation runs through the query client (auth,
849
+ base route, caching, error normalization) instead of a raw `httpResource`. A
850
+ `422 FormViolationListView` maps each violation onto its child field by
851
+ `propertyPath` (via `mapViolationsToFormErrors`); success reports no errors and
852
+ network/other errors surface as a form-level error.
853
+
854
+ ## 6.0.0-next.16
855
+
856
+ ### Minor Changes
857
+
858
+ - [`a41491d`](https://github.com/ethlete-io/ethdk/commit/a41491db447152e69902020d19bfc30bccf3b01d) Thanks [@TomTomB](https://github.com/TomTomB)! - Server violations → signal-forms bridge:
859
+ - `@ethlete/query`: `mapViolationsToFormErrors({ fieldTree, error, rewritePath?, onUnmappedViolation? })` maps an API error's violation list onto a signal form's fields (unmapped violations become form-level errors, violation-free failures degrade to a form-level `etServerError`), plus `extractFormViolations(error)`, `executeUntilSettled(query, executeArgs?)` for awaiting one execution as a settled snapshot, and the `isQueryErrorResponse` guard.
860
+ - `@ethlete/components`: `provideFormErrorMessageResolver(resolver)` lets apps centralize/localize the text `et-form-error` renders by error `kind`; the error's own `message` stays the default.
861
+
862
+ ## 6.0.0-next.15
863
+
864
+ ### Patch Changes
865
+
866
+ - [#3022](https://github.com/ethlete-io/ethdk/pull/3022) [`9431073`](https://github.com/ethlete-io/ethdk/commit/9431073bb693aa10bbb84d5196597cb2c4b7463f) Thanks [@github-actions](https://github.com/apps/github-actions)! - Overlays and menus now open on insecure origins (plain-HTTP pages on a LAN IP, not just `localhost`/HTTPS). Id generation used `crypto.randomUUID()`, which is `undefined` outside a secure context, so opening any dialog, sheet, anchored overlay or menu threw and only the backdrop appeared. A new `randomId()` helper in `@ethlete/core` uses `crypto.randomUUID()` when available and falls back to `getRandomValues` otherwise.
867
+
868
+ ## 6.0.0-next.14
869
+
870
+ ### Patch Changes
871
+
872
+ - [#3019](https://github.com/ethlete-io/ethdk/pull/3019) [`b5655a9`](https://github.com/ethlete-io/ethdk/commit/b5655a9124b2ffc4d6982ca20be360b227a37107) Thanks [@github-actions](https://github.com/apps/github-actions)! - Query cache: a cached request now correctly becomes stale once its freshness
873
+ window (from `cache-control` / `expires`) elapses, so `execute({ allowCache: true })`
874
+ refetches instead of serving the cached response forever.
875
+
876
+ ## 6.0.0-next.13
877
+
878
+ ### Patch Changes
879
+
880
+ - [`4e9f2b4`](https://github.com/ethlete-io/ethdk/commit/4e9f2b4d12335fafef192350aef8ffc584996a91) Thanks [@TomTomB](https://github.com/TomTomB)! - Remove the now-redundant `changeDetection: ChangeDetectionStrategy.OnPush` declaration (and its `ChangeDetectionStrategy` import) from all components. OnPush is the default change detection strategy since Angular 22, so this is a no-op cleanup with no behavioral change.
881
+
882
+ ## 6.0.0-next.12
883
+
884
+ ### Minor Changes
885
+
886
+ - [`edea44b`](https://github.com/ethlete-io/ethdk/commit/edea44bf1c494420f02b545202f4b24db9a6395c) Thanks [@TomTomB](https://github.com/TomTomB)! - Update to angular 22
887
+
888
+ ## 6.0.0-next.11
889
+
890
+ ### Patch Changes
891
+
892
+ - [#2995](https://github.com/ethlete-io/ethdk/pull/2995) [`9038da9`](https://github.com/ethlete-io/ethdk/commit/9038da9dba1af6597ce24056f45354b4073673aa) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix `withSuccessHandling`, `withErrorHandling` and `withLogging` callbacks sometimes being skipped when a query re-executes in quick succession (e.g. polling, auto-refresh, or fast repeated requests). Each execution's result now reliably triggers its handler.
893
+
894
+ - [#2995](https://github.com/ethlete-io/ethdk/pull/2995) [`24b4fd7`](https://github.com/ethlete-io/ethdk/commit/24b4fd7e1aebda8a4844d4a8ec9700aa1a89a0ee) Thanks [@github-actions](https://github.com/apps/github-actions)! - Fix secure queries intermittently throwing `tokensNotAvailableInsideAuthAndExec` when the auth query completes on a different reactive timeline than the access token is set on (e.g. a cross-client / secure login query whose token is populated by a separate effect). The secure execute factory now waits for the access token to be available before running the request instead of assuming it is set the moment the auth query has a response, and recovers automatically once the token arrives.
895
+
896
+ ## 6.0.0-next.10
897
+
898
+ ### Patch Changes
899
+
900
+ - [`256b1b0`](https://github.com/ethlete-io/ethdk/commit/256b1b02d7598a0a6540af55447799a8ced469c4) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump only to implement fixes from 5.44.0
901
+
902
+ ## 5.44.0
903
+
904
+ ### Minor Changes
905
+
906
+ - [`8d2efef`](https://github.com/ethlete-io/ethdk/commit/8d2efef2a367db82d44977a3fdfe56396bb46515) Thanks [@TomTomB](https://github.com/TomTomB)! - Minor bump only
907
+
908
+ ## 5.43.2
909
+
910
+ ### Patch Changes
911
+
912
+ - [`830b987`](https://github.com/ethlete-io/ethdk/commit/830b987eba43a51252c3c55eee5590ceef8bf1cb) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix query v3 features not reacting to 204 responses due to null checks
913
+
914
+ ## 5.44.0
915
+
916
+ ### Minor Changes
917
+
918
+ - [`8d2efef`](https://github.com/ethlete-io/ethdk/commit/8d2efef2a367db82d44977a3fdfe56396bb46515) Thanks [@TomTomB](https://github.com/TomTomB)! - Minor bump only
919
+
920
+ ## 5.43.2
921
+
922
+ ### Patch Changes
923
+
924
+ - [`830b987`](https://github.com/ethlete-io/ethdk/commit/830b987eba43a51252c3c55eee5590ceef8bf1cb) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix query v3 features not reacting to 204 responses due to null checks
925
+
926
+ ## 6.0.0-next.9
927
+
928
+ ### Patch Changes
929
+
930
+ - [`b73a127`](https://github.com/ethlete-io/ethdk/commit/b73a127002a06e3aa0c4e7e977b1ad1f3e04e7e6) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump yet again, final one for sure, pinky promise
931
+
932
+ ## 6.0.0-beta.8
933
+
934
+ ### Patch Changes
935
+
936
+ - [`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump to beta
937
+
938
+ - Updated dependencies [[`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766)]:
939
+ - @ethlete/types@2.0.0-beta.4
940
+ - @ethlete/core@5.0.0-beta.11
941
+
942
+ ## 6.0.0-next.7
943
+
944
+ ### Patch Changes
945
+
946
+ - [`a690217`](https://github.com/ethlete-io/ethdk/commit/a6902172efd9bd1956a16237e79acbfbd816d946) Thanks [@TomTomB](https://github.com/TomTomB)! - Version bump only
947
+
3
948
  ## 6.0.0-next.6
4
949
 
5
950
  ### Patch Changes