@ethlete/query 6.0.0-next.5 → 6.0.0-next.51

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 (31) hide show
  1. package/CHANGELOG.md +772 -0
  2. package/fesm2022/ethlete-query-testing.mjs +441 -38
  3. package/fesm2022/ethlete-query-testing.mjs.map +1 -1
  4. package/fesm2022/ethlete-query.mjs +15961 -5330
  5. package/fesm2022/ethlete-query.mjs.map +1 -1
  6. package/generators/deprecate-legacy-queries/migration.js +77 -0
  7. package/generators/deprecate-legacy-queries/schema.json +26 -0
  8. package/generators/generators.json +15 -0
  9. package/generators/migrate-query-client-features/migration.js +142 -0
  10. package/generators/migrate-query-client-features/report.js +136 -0
  11. package/generators/migrate-query-client-features/schema.json +26 -0
  12. package/generators/migrate-query-opt-in-features/migration.js +194 -0
  13. package/generators/migrate-query-opt-in-features/report.js +143 -0
  14. package/generators/migrate-query-opt-in-features/schema.json +31 -0
  15. package/generators/migrate-to-query-v3/auth-provider-scaffold.js +133 -0
  16. package/generators/migrate-to-query-v3/cleanup-migration.js +111 -99
  17. package/generators/migrate-to-query-v3/http-client-check.js +93 -0
  18. package/generators/migrate-to-query-v3/legacy-prepare-migration.js +129 -40
  19. package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +237 -152
  20. package/generators/migrate-to-query-v3/migration-scope.js +38 -0
  21. package/generators/migrate-to-query-v3/migration.js +17 -9
  22. package/generators/migrate-to-query-v3/module-graph.js +153 -0
  23. package/generators/migrate-to-query-v3/query-client-migration.js +152 -53
  24. package/generators/migrate-to-query-v3/rename-symbols.js +206 -0
  25. package/generators/migrate-to-query-v3/schema.json +12 -0
  26. package/generators/migrate-to-query-v3/shared.js +51 -2
  27. package/generators/prep-for-query-v3/migration.js +71 -14
  28. package/migrations.json +44 -0
  29. package/package.json +29 -13
  30. package/types/ethlete-query-testing.d.ts +179 -12
  31. package/types/ethlete-query.d.ts +8935 -3203
package/CHANGELOG.md CHANGED
@@ -1,5 +1,777 @@
1
1
  # @ethlete/query
2
2
 
3
+ ## 6.0.0-next.51
4
+
5
+ ### Patch Changes
6
+
7
+ - The devtools pills' stylesheet now carries the application's `CSP_NONCE`, so it passes a strict `style-src`.
8
+
9
+ ## 6.0.0-next.50
10
+
11
+ ### Patch Changes
12
+
13
+ - 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.
14
+
15
+ ## 6.0.0-next.49
16
+
17
+ ### Minor Changes
18
+
19
+ - `withPersistentAuth`'s `autoLogin.buildArgs` and `withTokenExpirationWarning`'s `expiresInPropertyName` now default to the refresh query's own config.
20
+ - `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.
21
+ - `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).
22
+ - The bearer auth provider gets `session()`, its session status, end cause and execution state as one signal, so a consumer no longer combines three.
23
+ - Add the `persistence` option to `defineQueryForm().observe()`, which stores the committed value and restores it when the URL carries none of the persisted fields.
24
+ - `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.
25
+ - GraphQL queries can keep the server's `errors` next to partial data with `transformResponse: unwrapGqlResponseWithErrors`.
26
+ - `withPolling` accepts a signal `interval` and opt-in `pauseWhileHidden`, `refetchOnFocus` and `refetchOnReconnect`.
27
+ - 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.
28
+ - 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`.
29
+ - `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.
30
+ - Add `send`, `auth` and `withCredentials` to `createWebSocketClient`, and a `messages$` stream of every room message next to `latestMessage`.
31
+
32
+ ### Patch Changes
33
+
34
+ - 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.
35
+ - An unreadable URL value in a query form field now falls back to the field's `defaultValue` instead of `null`.
36
+ - Mark `setupQueryDependencies`, `createQuerySyncEngine`, `createGqlExecuteFn` and `createSecureGqlExecuteFn` internal, so they leave the published types.
37
+
38
+ ## 6.0.0-next.48
39
+
40
+ ### Patch Changes
41
+
42
+ - `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'`.
43
+ - The v3 migration rewrites a legacy `prepare()` call inside an anonymous `export default class`, instead of leaving it unmigrated behind an unused `Injector` import.
44
+ - 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.
45
+ - The v3 migration reports a shorthand creator config property it cannot carry over, such as `{ secure }`, instead of dropping it silently.
46
+
47
+ ## 6.0.0-next.47
48
+
49
+ ### Patch Changes
50
+
51
+ - `QueryRuntimeErrorCode` no longer has `QUERY_STACK_TOTAL_QUERIES_AND_EXPECTED_QUERIES_MISMATCH` (502). A paged query stack could no longer throw it.
52
+ - `migrate-query-opt-in-features` no longer adds `withEthleteApiErrors()` or `withBearerAuthMultiTabSync()` to a config that already lists it.
53
+ - `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.
54
+ - 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.
55
+ - `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.
56
+ - The v3 migration keeps a shorthand property and a local `export { … }` of a renamed creator import pointing at its legacy wrapper.
57
+ - The v3 migration adds a missing value import to the first value import of a module instead of a type-only one.
58
+
59
+ ## 6.0.0-next.46
60
+
61
+ ### Minor Changes
62
+
63
+ - The Angular peer dependency moves from 22.0.7 to 22.1.6. Angular 22.0.x is affected by
64
+ GHSA-hh8m-fm6v-7cvg, a sanitization bypass through directive host bindings, fixed in 22.1.0.
65
+ - `<et-query-devtools-lazy>` renders nothing without `provideQueryDevtools()` - no floating button, no
66
+ shortcut, no panel download - and the now-public `isQueryDevtoolsEnabled()` is what it gates on.
67
+ - 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.
68
+ - 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.
69
+ - `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.
70
+ - `defineQueryForm`: `branch()` now debounces and runs the reset graph like the source form and exposes `liveValue`; the filter overlay applies `liveValue` on submit.
71
+ - HTTP queries gain `createHeadQuery` and `createOptionsQuery` with their secure twins, and `createFakeQueryPersistenceStore()` can fail a removal with `failNextRemoves(count)`.
72
+ - 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.
73
+ - 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.
74
+
75
+ ### Patch Changes
76
+
77
+ - The panel drops a client's Cache, Faults and Events entries once that client's injector is destroyed,
78
+ instead of keeping them alive for as long as one of its queries has a tombstone.
79
+ - 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.
80
+ - Legacy `V2BearerAuthProvider`: a new token now replaces the pending refresh timer instead of adding a second, parallel refresh chain.
81
+ - Legacy query: variables that differ only by whitespace or braces inside a string, or by nesting, no longer share one cached query instance.
82
+ - Legacy `etInfinityQueryTrigger`: a trigger that stays visible after a page lands now keeps loading the next page instead of stalling.
83
+ - 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`.
84
+ - `createLegacyQueryCreator`: `prepare({ variables })` now forwards the variables to a wrapped gql creator.
85
+ - Legacy query: a secure query that refreshes after a 401 now stays loading until the retry lands, instead of reporting a failure first.
86
+ - 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.
87
+ - 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`.
88
+ - 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.
89
+ - Legacy query: polling no longer resumes on window focus when its `takeUntil` notifier fired while polling was paused.
90
+ - Legacy query: a `false`, `0` or `''` body is now sent with its content type instead of being dropped.
91
+ - Legacy query: a secure query executed while logged out returns to `Prepared` instead of staying `Loading`, so executing it after login sends the request.
92
+ - Legacy query client: calling `setAuthProvider` again with the provider already set no longer cancels its scheduled token refresh.
93
+ - 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`.
94
+ - `validateWithV2Query`: a secure validate query run while logged out now reports a form-level error instead of leaving the field pending forever.
95
+ - `validateWithV2Query`: a shared GET query cancelled by another consumer is re-run instead of leaving the field pending forever.
96
+ - `fetchNextPage()` on a paged stack returns `null` and keeps its position when its args repeat an already loaded page, like `fetchPreviousPage()` does.
97
+ - 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`.
98
+ - 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.
99
+ - 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.
100
+ - 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.
101
+ - 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.
102
+ - Destroying a query client's injector now releases its retained unused cache entries and their eviction timers.
103
+ - 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.
104
+ - 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.
105
+ - 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.
106
+ - 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.
107
+ - 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__']`.
108
+ - 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.
109
+ - 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$`.
110
+ - Query forms: URL writes no longer break under an app-level `defaultQueryParamsHandling` of `'merge'` or `'preserve'`.
111
+ - Query forms: writing to the URL no longer drops its `#fragment`.
112
+ - `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.
113
+ - Query forms: `skipResets` now applies only to the fields that write changes, so a pending debounced edit to another field still resets its dependents.
114
+ - Query forms: `unobserve()` now commits a pending debounced edit to `value` instead of dropping it.
115
+ - 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.
116
+ - 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.
117
+ - `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.
118
+ - 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.
119
+ - GraphQL: the `operationName` sent with a document no longer comes from an operation that only appears in a comment above the real one.
120
+ - Query persistence: a response body IndexedDB cannot store no longer leaves a metadata record without a body on disk.
121
+ - 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.
122
+ - 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.
123
+ - 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`.
124
+ - 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`.
125
+ - Persistence: a logout now also removes secure responses another tab persisted after this one started.
126
+ - 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.
127
+ - Persistence: `whenPersistenceReady` now resolves when a custom adapter's `loadIndex` throws synchronously instead of rejecting.
128
+ - Persistent auth: a session now survives a page reload when `localStorage` refuses writes or is unavailable, instead of silently logging the user out.
129
+ - 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.
130
+ - `withRefreshQuery`'s `retryConfig.maxAttempts` now retries a failed refresh that many times, instead of one fewer.
131
+ - 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`.
132
+ - `createQuerySubmission`: a custom `mapViolations` that returns `undefined` or `null` no longer gets the default violation mapping attached to the form.
133
+ - Testing entry point: `setupQueryTest` now installs one console filter instead of nesting a
134
+ new one per call, and exposes `restoreConsole`. `installFakeWebLocks` removes the `abort`
135
+ listeners it adds. The websocket double reports `withCredentials()`.
136
+ - Query: a `transformResponse` that throws lands in `error()` with code `0`, keeps the last good `response()`, and no longer re-runs `withSuccessHandling`.
137
+ - `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.
138
+ - `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.
139
+ - 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.
140
+ - The devtools session vault no longer uses `localStorage` outside a development build, so a deployed
141
+ app can mount the panel without leaving tokens and credentials behind.
142
+ - 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.
143
+
144
+ ## 6.0.0-next.45
145
+
146
+ ### Patch Changes
147
+
148
+ - [`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.
149
+
150
+ ## 6.0.0-next.44
151
+
152
+ ### Patch Changes
153
+
154
+ - [#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.
155
+
156
+ - [`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.
157
+
158
+ ## 6.0.0-next.43
159
+
160
+ ### Patch Changes
161
+
162
+ - [#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.
163
+
164
+ - [`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.
165
+
166
+ - [#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
167
+ declare in their own `migrations.json`, and reports what needs a decision or an agent.
168
+
169
+ - [#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`.
170
+
171
+ ## 6.0.0-next.42
172
+
173
+ ### Minor Changes
174
+
175
+ - [#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
176
+ the current values and unfolds every picker on a click. A production pick keeps them unfolded.
177
+
178
+ - [#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
179
+ the panel logs in as an account with the body keys that login needs.
180
+
181
+ ### Patch Changes
182
+
183
+ - [`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.
184
+
185
+ - [#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
186
+ columns, and the fold control reads as a button instead of a lone caret.
187
+
188
+ ## 6.0.0-next.41
189
+
190
+ ### Minor Changes
191
+
192
+ - [`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.
193
+
194
+ - [`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
195
+ account declared through `provideQueryDevtools({ authAccounts })`, and can hold one tab's session
196
+ apart from the rest.
197
+
198
+ ## 6.0.0-next.40
199
+
200
+ ### Minor Changes
201
+
202
+ - [#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
203
+ `const enum`s, so a transpile-only build can consume them.
204
+
205
+ - [#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.
206
+
207
+ ### Patch Changes
208
+
209
+ - [#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.
210
+
211
+ - [#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.
212
+
213
+ ## 6.0.0-next.39
214
+
215
+ ### Minor Changes
216
+
217
+ - [`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.
218
+
219
+ ### Patch Changes
220
+
221
+ - [`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.
222
+
223
+ - [`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.
224
+
225
+ - [`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
226
+ before `observe()` survives and only the fields the URL names are overwritten.
227
+
228
+ ## 6.0.0-next.38
229
+
230
+ ### Minor Changes
231
+
232
+ - [`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
233
+ created it. Batch tombstones are capped per batch, so a bulk run cannot evict the others.
234
+
235
+ - [`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
236
+ next to its progress. Both are `null` until the run has settled enough items to measure.
237
+
238
+ - [`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
239
+ outcome and a `retryFailed()` that resends only what did not succeed.
240
+
241
+ - [`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
242
+ violations back onto the fields that caused them.
243
+
244
+ - [`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
245
+ progress bar or a determinate button spinner without deriving it from `currentStep()`.
246
+
247
+ ## 6.0.0-next.37
248
+
249
+ ### Minor Changes
250
+
251
+ - [#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.
252
+
253
+ ## 6.0.0-next.36
254
+
255
+ ### Patch Changes
256
+
257
+ - [#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.
258
+
259
+ ## 6.0.0-next.35
260
+
261
+ ### Major Changes
262
+
263
+ - [#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".
264
+
265
+ ### Minor Changes
266
+
267
+ - [`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
268
+ `maxAttempts` instead of retrying a connection failure every 5s forever, is configurable via
269
+ `withDefaultRetry({ … })` / `createDefaultRetryFn()`, and stops once the last consumer is gone.
270
+
271
+ - [`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.
272
+
273
+ ### Patch Changes
274
+
275
+ - [#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
276
+ adopts the live session instead of auto-logging in, and a tab coming back to the foreground rechecks
277
+ a refresh its throttled timer missed.
278
+
279
+ - [#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.
280
+
281
+ ## 6.0.0-next.34
282
+
283
+ ### Minor Changes
284
+
285
+ - [`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.
286
+
287
+ - [#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
288
+ with two new Settings scopes.
289
+
290
+ - [#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
291
+ one YAML or JSON document.
292
+
293
+ ### Patch Changes
294
+
295
+ - [`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.
296
+
297
+ ## 6.0.0-next.33
298
+
299
+ ### Minor Changes
300
+
301
+ - [#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.
302
+
303
+ - [#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.
304
+
305
+ - [#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.
306
+
307
+ - [`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
308
+ `provideQueryDevtools({ schema })`.
309
+
310
+ - [#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.
311
+
312
+ - [`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
313
+ values with `Set to null`, `Empty this array`, `Paste as new item` and delete.
314
+
315
+ - [#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.
316
+
317
+ ### Patch Changes
318
+
319
+ - [#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
320
+ due while it could not run.
321
+
322
+ - [#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
323
+ tab reports `'expired'` or `'inactivity'` instead of always `'otherTab'`.
324
+
325
+ - [#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.
326
+
327
+ ## 6.0.0-next.32
328
+
329
+ ### Patch Changes
330
+
331
+ - [`fcdf018`](https://github.com/ethlete-io/ethdk/commit/fcdf01864995a23bc850a748455357685ae90b6d) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix token refresh causing an infinite loop
332
+
333
+ ## 6.0.0-next.31
334
+
335
+ ### Minor Changes
336
+
337
+ - [`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
338
+ refreshed at all.
339
+
340
+ ## 6.0.0-next.30
341
+
342
+ ### Minor Changes
343
+
344
+ - [`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.
345
+
346
+ - [#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.
347
+
348
+ - [`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.
349
+
350
+ ### Patch Changes
351
+
352
+ - [#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.
353
+
354
+ - [`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
355
+ the query at execute time, which the created query now declares.
356
+
357
+ ## 6.0.0-next.29
358
+
359
+ ### Minor Changes
360
+
361
+ - [#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`.
362
+
363
+ - [#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.
364
+
365
+ - [#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.
366
+
367
+ - [#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.
368
+
369
+ - [#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.
370
+
371
+ - [#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 })`.
372
+
373
+ - [#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.
374
+
375
+ ### Patch Changes
376
+
377
+ - [#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.
378
+
379
+ - [#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.
380
+
381
+ - [#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.
382
+
383
+ - [#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.
384
+
385
+ - [#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.
386
+
387
+ - [#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.
388
+
389
+ - [#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.
390
+
391
+ - [#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.
392
+
393
+ ## 6.0.0-next.28
394
+
395
+ ### Minor Changes
396
+
397
+ - [#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`).
398
+
399
+ ### Patch Changes
400
+
401
+ - [`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.
402
+
403
+ ## 6.0.0-next.27
404
+
405
+ ### Patch Changes
406
+
407
+ - [#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.
408
+
409
+ ## 6.0.0-next.26
410
+
411
+ ### Minor Changes
412
+
413
+ - [#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.
414
+
415
+ ### Patch Changes
416
+
417
+ - [#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.
418
+
419
+ - [#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.
420
+
421
+ ## 6.0.0-next.25
422
+
423
+ ### Major Changes
424
+
425
+ - [`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
426
+ pulls `socket.io-client` (~13 kB gz) into apps that never open a socket. New:
427
+ `createWebSocketTestDouble()` in `@ethlete/query/testing`.
428
+
429
+ ### Minor Changes
430
+
431
+ - [`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`.
432
+
433
+ ### Patch Changes
434
+
435
+ - [`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
436
+ `Infinity` on a stalled or re-executed request), and show it in the query devtools.
437
+
438
+ ## 6.0.0-next.24
439
+
440
+ ### Minor Changes
441
+
442
+ - [`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
443
+ request method again, and `provideLegacyPrepareFallback()` lets `prepare()` use the root injector instead
444
+ of throwing ET950 (browser only).
445
+
446
+ - [#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`
447
+ interop, and add `nx g @ethlete/query:deprecate-legacy-queries` to tag wrappers already in source.
448
+ Removal is v7.
449
+
450
+ - [#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
451
+ the network, and how much payload they moved - as activity tiles per query plus totals per client.
452
+
453
+ - [#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
454
+ every attempt, fail-the-next-N, fail-N%, and the response status - resolved per attempt inside the
455
+ pipeline, so the retry policy re-rolls it.
456
+
457
+ - [#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,
458
+ not just its name.
459
+
460
+ - [`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.
461
+
462
+ - [#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
463
+ requests read their bearer token out of its response instead of shipping one that goes stale.
464
+
465
+ - [#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
466
+ `/post/:param`), and export requests as an Insomnia v4 collection.
467
+
468
+ - [#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
469
+ `request.subtle.retryState()` report what a retry policy is doing, and the panel shows backoff
470
+ countdowns, attempt counts and a progress bar for `reportProgress` requests.
471
+
472
+ - [#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
473
+ **Timeline** tab that draws every request on one axis and a **History** section that diffs responses.
474
+
475
+ ### Patch Changes
476
+
477
+ - [`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`
478
+ config no longer syncs a `null` response on `prepare()`, and a falsy `body` is sent instead of dropped.
479
+
480
+ - [`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`,
481
+ `effect`, RxJS operators) and adds `destroyOnResponse` when the prepared query is discarded.
482
+
483
+ ## 6.0.0-next.23
484
+
485
+ ### Major Changes
486
+
487
+ - [#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`
488
+ option is replaced by `withBearerAuthMultiTabSync()` in `features` (~1.4 kB gz off the secure entry
489
+ without it), read back as `provider.features.multiTabSync.isLeader()`. Election runs on the Web Locks
490
+ API now rather than a `localStorage` heartbeat, so a tab that closes or crashes hands over at once.
491
+ `setupAuthTest()` lost its `multiTabSync` option. Migrate with
492
+ `npx nx g @ethlete/query:migrate-query-opt-in-features`.
493
+
494
+ - [#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
495
+ `multiTabSync` / `persistence` client options are gone and a client without the features ships neither
496
+ engine. Migrate with `nx g @ethlete/query:migrate-query-client-features`.
497
+
498
+ - `withMultiTabSync()` shares reads, polls a cache key in one tab for all of them and refreshes the
499
+ others after a mutation; per-query `multiTabSync: false` keeps a query tab-local.
500
+ - `withQueryPersistence()` keeps public reads in IndexedDB, so a reload renders the last known data
501
+ while it revalidates. Secure responses need an explicit opt-in and are removed on logout.
502
+ - `refreshQueriesInUse()` also refreshes GraphQL queries transported over POST; devtools gain Sync
503
+ and Disk columns.
504
+
505
+ - [#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
506
+ client reads the plain `string` / `{ message }` / `{ detail }` / `string[]` ladder and retries
507
+ nothing, which takes ~1.4 kB gz out of an app that needs neither. Pick from `withHtmlErrorParsing()`,
508
+ `withSymfonyErrors()`, `withDefaultRetry()`, `withEthleteApiErrors()` (all three, the previous
509
+ behavior) and `registerQueryErrorParser()` for a body shape the SDK does not know. Run
510
+ `npx nx g @ethlete/query:migrate-query-opt-in-features` to keep the old behavior.
511
+
512
+ - [#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` /
513
+ `createLabels` are replaced by `defineProvider` & co., which return a definition you read with
514
+ `toProvideFn` / `toInjectFn` / `toToken`; `createQueryClient`, `createBearerAuthProvider` and
515
+ `createWebSocketClient` return that definition instead of a tuple. Every `provideX` / `injectX` /
516
+ token export keeps its name - run `nx g @ethlete/core:migrate-provider-shape` for your own call sites.
517
+ Cuts the `@ethlete/components` import floor from 89.9 to 2.4 kB gz.
518
+
519
+ ### Minor Changes
520
+
521
+ - [#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 -
522
+ after a mutation, or a push message saying something changed server-side - and tells the user's other
523
+ tabs to do the same. Narrow it with `url` (resolved against `baseUrl`, matched on path boundaries) and
524
+ `filter`, or keep it local with `otherTabs: false`; reaching other tabs needs `withMultiTabSync()`.
525
+ See [Invalidating after a change](https://ethlete-sdk-docs.web.app/query/caching#invalidating-after-a-change).
526
+
527
+ ### Patch Changes
528
+
529
+ - [#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.
530
+
531
+ - [#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.
532
+
533
+ - [#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
534
+ an app without it drops the entry registry, the route stringifier and the client-name derivation
535
+ entirely - ~0.5 kB gz off every entry. No API change; `queryDevtoolsEntries` and the
536
+ `<et-query-devtools>` contract are unchanged.
537
+
538
+ - [#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`,
539
+ `buildQueryString`, `buildTimestampFromSeconds`, `decryptBearer`, `QueryError` and the query-string
540
+ types now live in `http/internal/request-route`, and `legacy` re-exports them. Every public name is
541
+ unchanged. Also closes the `http ↔ gql` cycle.
542
+
543
+ - [#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`,
544
+ and no non-`ws` public type surfaces it, so an app that does not use the realtime client no longer
545
+ has to install it.
546
+
547
+ - [#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
548
+ `types`, and apply the resulting auto-fixes. Runtime behavior is unchanged; three fixes are visible to
549
+ TypeScript consumers: exported `types` shapes are `type` aliases rather than `interface` declarations
550
+ (so they can no longer be extended by declaration merging), `core`'s `PropsDirective.destroyRef` and
551
+ `SeoDirective.parent` are `private`, and `ConsentHandler` is a `type`. The theme name registries stay
552
+ interfaces so consumers can keep augmenting them.
553
+
554
+ ## 6.0.0-next.22
555
+
556
+ ### Minor Changes
557
+
558
+ - [#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`.
559
+
560
+ ### Patch Changes
561
+
562
+ - [#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
563
+ form, reports how many results the draft would return on its submit button, and applies on submit or discards on
564
+ dismiss. Replaces cdk's `FilterOverlayService`, rebuilt on signal forms and the current query client.
565
+
566
+ ## 6.0.0-next.21
567
+
568
+ ### Patch Changes
569
+
570
+ - [#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
571
+ `allowCache: options.skipCache !== true` for **every** method, so any `legacyPost*` / `legacyPut*` /
572
+ `legacyPatch*` / `legacyDelete*` executed without an explicit `skipCache: true` reached the repository with
573
+ `allowCache: true` and threw "This request is uncacheable, but allowCache is set to true".
574
+
575
+ `allowCache` is never read on the uncacheable path - there is no cache entry to reuse - so the throw was purely a
576
+ guard against a mistake in hand-written code. It stays for that, and gains a
577
+ `silenceUncacheableAllowCacheError` opt-out on `QueryConfig`, which `createLegacyQueryCreator` sets alongside the
578
+ `silenceMissingWithArgsFeatureError` it already passed. The cache-key guard is unaffected.
579
+
580
+ Note that dropping `allowCache: true` in the interop instead would have silently made every legacy `GET` refetch,
581
+ since an absent `allowCache` means "do not reuse the entry" rather than "use the default".
582
+
583
+ ## 6.0.0-next.20
584
+
585
+ ### Minor Changes
586
+
587
+ - [#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 }`).
588
+
589
+ - Configurable per client (`createQueryClient({ keepUnusedFor })`) and per query creator; `0` restores the previous release-immediately behavior.
590
+ - Independent of `cache-control`, so it also applies to private/authenticated responses.
591
+ - 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.
592
+
593
+ - [#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:
594
+
595
+ - **Client-level headers.** `createQueryClient({ headers })` takes `HttpHeaders` or a function
596
+ re-read on every request, so a signal can drive it. Per-query `args.headers` merge on top and win
597
+ per name. `client.refreshQueriesInUse()` re-runs every bound `GET`/`HEAD`/`OPTIONS` (in-flight ones
598
+ included) - the replacement for v2's `setDefaultHeaders({ refreshQueriesInUse: true })`.
599
+ - **`provider.setTokens(access, refresh)`** on the public bearer auth provider, for tokens issued
600
+ outside it (SSO callbacks, native shells). Previously reachable only from inside a custom feature.
601
+ - **`logout()` now resets bound secure queries.** It already unbound their cache entries, but the
602
+ query objects kept their `response()`, so a component mounted across a logout went on rendering the
603
+ previous user until something called `reset()`.
604
+ - **Legacy `prepare()` failures are diagnosable.** Calling it without an injection context throws
605
+ `ET950` naming the creator instead of a bare `NG0203`; calling it with an already destroyed injector
606
+ returns an inert query and warns in dev mode instead of throwing `NG0205` from a view's cleanup
607
+ phase. `createLegacyQueryCreator` takes a `name` for those messages.
608
+ - **Query-collection consumers accept real legacy queries.** `AnyQueryCollection` no longer pins the
609
+ arguments type, so a `createQueryCollectionSignal` result is assignable to `*etQuery`,
610
+ `queryStateErrorSignal` and `switchQueryCollectionState` without a cast.
611
+ - **`queryErrorMessages(error)` / `queryErrorMessage(error)`** flatten a `QueryErrorResponse` into
612
+ displayable strings, and `emptyQueryArgs<TArgs>()` covers argless queries in generic code (auth
613
+ registry `execute()` now takes no argument either).
614
+ - **`BearerAuthProviderOf<typeof ref>`** derives the exact provider type; `AnyBearerAuthProvider` no
615
+ longer forces bracket access on `provider.queries` under `noPropertyAccessFromIndexSignature`.
616
+
617
+ `migrate-to-query-v3` got a precision pass:
618
+
619
+ - Renames are scoped to imports that actually resolve to the migrated symbol, so same-named type
620
+ members, config properties and exports from unrelated packages are left alone; import aliases are
621
+ preserved instead of dropped.
622
+ - `--projects` / `--include` migrate one app or library at a time.
623
+ - Unused imports (`def`, `AnyLegacyQuery*`, stale client symbols) are no longer left behind.
624
+ - Auth providers are scaffolded from the v2 `V2BearerAuthProvider` config instead of `queries: []`.
625
+ - Devtools are migrated rather than deleted: the per-client `provideQueryClientForDevtools` calls
626
+ collapse into one `provideQueryDevtools()`, `QueryDevtoolsComponent` is re-imported from
627
+ `@ethlete/components`, and `<et-query-devtools>` markup is left alone - both versions use that selector.
628
+ - New report tasks for dropped v2 client options, missing `provideHttpClient()`, `setDefaultHeaders`
629
+ call sites and the auth import-cycle layout.
630
+
631
+ - [#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`.
632
+
633
+ 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.
634
+
635
+ 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.
636
+
637
+ The existing reactive-forms `QueryForm` is unchanged and remains available.
638
+
639
+ ## 6.0.0-next.19
640
+
641
+ ### Minor Changes
642
+
643
+ - [#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
644
+ queries, query stacks, paged query stacks, `querySequence`, bearer auth providers
645
+ and web socket clients so they can be inspected by `<et-query-devtools>` (from
646
+ `@ethlete/components`). Instrumentation is a no-op unless the provider is added,
647
+ so there is no overhead when it is omitted.
648
+
649
+ Supporting devtools APIs added: `querySequence` exposes a `stepArgs` signal (the
650
+ resolved input args of each step); the query repository gains
651
+ `subtle.cacheEntries()` / `subtle.cacheVersion` / `subtle.evict()`; queries gain
652
+ `subtle.setLoading()` / `subtle.setError()` (force UI states for testing);
653
+ `HttpRequest` exposes `method`, `url` and `expiresAt`; `QueryClient` exposes its
654
+ `baseUrl`; `QuerySequence` exposes its step `queries`; and web socket clients
655
+ expose a devtools handle (connection state, rooms, recent messages).
656
+
657
+ ## 6.0.0-next.18
658
+
659
+ ### Minor Changes
660
+
661
+ - [`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.
662
+
663
+ ## 6.0.0-next.17
664
+
665
+ ### Minor Changes
666
+
667
+ - [#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
668
+ validators for Angular signal forms. They adapt an `@ethlete/query` query into
669
+ `validateAsync`, so server-side validation runs through the query client (auth,
670
+ base route, caching, error normalization) instead of a raw `httpResource`. A
671
+ `422 FormViolationListView` maps each violation onto its child field by
672
+ `propertyPath` (via `mapViolationsToFormErrors`); success reports no errors and
673
+ network/other errors surface as a form-level error.
674
+
675
+ ## 6.0.0-next.16
676
+
677
+ ### Minor Changes
678
+
679
+ - [`a41491d`](https://github.com/ethlete-io/ethdk/commit/a41491db447152e69902020d19bfc30bccf3b01d) Thanks [@TomTomB](https://github.com/TomTomB)! - Server violations → signal-forms bridge:
680
+ - `@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.
681
+ - `@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.
682
+
683
+ ## 6.0.0-next.15
684
+
685
+ ### Patch Changes
686
+
687
+ - [#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.
688
+
689
+ ## 6.0.0-next.14
690
+
691
+ ### Patch Changes
692
+
693
+ - [#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
694
+ window (from `cache-control` / `expires`) elapses, so `execute({ allowCache: true })`
695
+ refetches instead of serving the cached response forever.
696
+
697
+ ## 6.0.0-next.13
698
+
699
+ ### Patch Changes
700
+
701
+ - [`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.
702
+
703
+ ## 6.0.0-next.12
704
+
705
+ ### Minor Changes
706
+
707
+ - [`edea44b`](https://github.com/ethlete-io/ethdk/commit/edea44bf1c494420f02b545202f4b24db9a6395c) Thanks [@TomTomB](https://github.com/TomTomB)! - Update to angular 22
708
+
709
+ ## 6.0.0-next.11
710
+
711
+ ### Patch Changes
712
+
713
+ - [#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.
714
+
715
+ - [#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.
716
+
717
+ ## 6.0.0-next.10
718
+
719
+ ### Patch Changes
720
+
721
+ - [`256b1b0`](https://github.com/ethlete-io/ethdk/commit/256b1b02d7598a0a6540af55447799a8ced469c4) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump only to implement fixes from 5.44.0
722
+
723
+ ## 5.44.0
724
+
725
+ ### Minor Changes
726
+
727
+ - [`8d2efef`](https://github.com/ethlete-io/ethdk/commit/8d2efef2a367db82d44977a3fdfe56396bb46515) Thanks [@TomTomB](https://github.com/TomTomB)! - Minor bump only
728
+
729
+ ## 5.43.2
730
+
731
+ ### Patch Changes
732
+
733
+ - [`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
734
+
735
+ ## 5.44.0
736
+
737
+ ### Minor Changes
738
+
739
+ - [`8d2efef`](https://github.com/ethlete-io/ethdk/commit/8d2efef2a367db82d44977a3fdfe56396bb46515) Thanks [@TomTomB](https://github.com/TomTomB)! - Minor bump only
740
+
741
+ ## 5.43.2
742
+
743
+ ### Patch Changes
744
+
745
+ - [`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
746
+
747
+ ## 6.0.0-next.9
748
+
749
+ ### Patch Changes
750
+
751
+ - [`b73a127`](https://github.com/ethlete-io/ethdk/commit/b73a127002a06e3aa0c4e7e977b1ad1f3e04e7e6) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump yet again, final one for sure, pinky promise
752
+
753
+ ## 6.0.0-beta.8
754
+
755
+ ### Patch Changes
756
+
757
+ - [`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766) Thanks [@TomTomB](https://github.com/TomTomB)! - Bump to beta
758
+
759
+ - Updated dependencies [[`ddb5d09`](https://github.com/ethlete-io/ethdk/commit/ddb5d09e4bc56e18cc8c228aa78a200441e7a766)]:
760
+ - @ethlete/types@2.0.0-beta.4
761
+ - @ethlete/core@5.0.0-beta.11
762
+
763
+ ## 6.0.0-next.7
764
+
765
+ ### Patch Changes
766
+
767
+ - [`a690217`](https://github.com/ethlete-io/ethdk/commit/a6902172efd9bd1956a16237e79acbfbd816d946) Thanks [@TomTomB](https://github.com/TomTomB)! - Version bump only
768
+
769
+ ## 6.0.0-next.6
770
+
771
+ ### Patch Changes
772
+
773
+ - [`8d31d0b`](https://github.com/ethlete-io/ethdk/commit/8d31d0b0ea523c6f79680e3a2cbf5ceba109f5d9) Thanks [@TomTomB](https://github.com/TomTomB)! - Fix bearer token revocation not working
774
+
3
775
  ## 6.0.0-next.5
4
776
 
5
777
  ### Minor Changes