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

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 (37) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/fesm2022/ethlete-query-ngrx-toolkit.mjs +393 -0
  3. package/fesm2022/ethlete-query-ngrx-toolkit.mjs.map +1 -0
  4. package/fesm2022/ethlete-query-testing.mjs +67 -25
  5. package/fesm2022/ethlete-query-testing.mjs.map +1 -1
  6. package/fesm2022/ethlete-query.mjs +7895 -7226
  7. package/fesm2022/ethlete-query.mjs.map +1 -1
  8. package/generators/generators.json +5 -0
  9. package/generators/migrate-from-ngrx-toolkit/args-assignability.js +140 -0
  10. package/generators/migrate-from-ngrx-toolkit/consumers.js +521 -0
  11. package/generators/migrate-from-ngrx-toolkit/creators.js +301 -0
  12. package/generators/migrate-from-ngrx-toolkit/facade.js +295 -0
  13. package/generators/migrate-from-ngrx-toolkit/feature.js +513 -0
  14. package/generators/migrate-from-ngrx-toolkit/migration.js +140 -0
  15. package/generators/migrate-from-ngrx-toolkit/report.js +154 -0
  16. package/generators/migrate-from-ngrx-toolkit/schema.json +42 -0
  17. package/generators/migrate-from-ngrx-toolkit/store-removal.js +633 -0
  18. package/generators/migrate-from-ngrx-toolkit/ts-edits.js +128 -0
  19. package/generators/migrate-query-opt-in-features/migration.js +10 -9
  20. package/generators/migrate-to-query-v3/auth-provider-scaffold.js +29 -2
  21. package/generators/migrate-to-query-v3/cleanup-migration.js +163 -53
  22. package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +39 -2
  23. package/generators/migrate-to-query-v3/migration-scope.js +2 -0
  24. package/generators/migrate-to-query-v3/migration.js +5 -4
  25. package/generators/migrate-to-query-v3/module-graph.js +41 -29
  26. package/generators/migrate-to-query-v3/query-client-migration.js +209 -126
  27. package/generators/migrate-to-query-v3/rename-symbols.js +38 -11
  28. package/generators/migrate-to-query-v3/report.js +40 -7
  29. package/generators/migrate-to-query-v3/shared.js +46 -1
  30. package/generators/prep-for-query-v3/migration.js +400 -57
  31. package/migrations/query-field-default-types.md +43 -0
  32. package/migrations/search-query-field-string.md +43 -0
  33. package/migrations.json +16 -0
  34. package/package.json +5 -1
  35. package/types/ethlete-query-ngrx-toolkit.d.ts +143 -0
  36. package/types/ethlete-query-testing.d.ts +28 -11
  37. package/types/ethlete-query.d.ts +789 -584
package/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # @ethlete/query
2
2
 
3
+ ## 6.0.0-next.53
4
+
5
+ ### Major Changes
6
+
7
+ - 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`.
8
+
9
+ ### Minor Changes
10
+
11
+ - Add the `reportErrors` creator option: set it to `false` to keep a query's failed requests away from Angular's `ErrorHandler`.
12
+ - `tableSortQueryField()` holds the `et-table` sort and keeps it in the URL, so `[(sort)]="qf.fields.sort().value"` binds it with no mapping.
13
+
14
+ ### Patch Changes
15
+
16
+ - 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.
17
+ - 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.
18
+ - Auth: `createPersistentAuthFeature` and `createTrackingFeature` run in the feature context's injector, so calling them outside an injection context no longer throws NG0203.
19
+ - Auth: `AuthQueryConfig.retryFn` is now part of the published type declarations.
20
+ - 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.
21
+ - Auth: the `withPersistentAuth` guide now says the remember-me cookie token is obfuscated with a per-origin key, not encrypted.
22
+ - Query batch: `retryFailed()` no longer resends a mutation that an unsubscribe aborted in flight, since the server may already have applied it.
23
+ - 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.
24
+ - `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.
25
+ - 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.
26
+ - 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.
27
+ - 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`.
28
+ - 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`.
29
+ - 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.
30
+ - `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.
31
+ - `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`.
32
+ - 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.
33
+ - 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.
34
+ - Auth: a negative numeric `refreshStrategy` now counts as `0`, so the proactive refresh fires at token expiry instead of after it.
35
+ - 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.
36
+ - `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.
37
+ - 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.
38
+ - 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`.
39
+ - `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.
40
+ - Query repository: the `unbind` JSDoc now says an entry with a response is kept for `keepUnusedFor` instead of destroyed.
41
+ - `withTokenRevocation` no longer sends a logout revocation queued behind another one when its tokens are live again by the time its turn comes.
42
+ - 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.
43
+ - `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.
44
+ - 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.
45
+
46
+ ## 6.0.0-next.52
47
+
48
+ ### Major Changes
49
+
50
+ - **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`.
51
+ - **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`.
52
+
53
+ ### Minor Changes
54
+
55
+ - Add `query.abort()`, which stops the execution in flight and puts `response()`, `error()` and `executionState()` back to where they were before it.
56
+ - `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`.
57
+ - 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.
58
+ - Every query request now carries the exported `IS_QUERY_REQUEST` `HttpContextToken`, so an app `HttpInterceptor` can skip requests sent by `@ethlete/query`.
59
+ - 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`.
60
+ - 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`.
61
+ - 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`.
62
+ - Query: `withPolling`, `withLongPolling` and `withAutoRefresh` take an `enabled` signal and run only while it is `true`, which replaces stopping a poll with `takeUntil`.
63
+ - `activeFilterCount` no longer counts a `searchQueryField()` or `sortQueryField()`, whatever its key.
64
+
65
+ ### Patch Changes
66
+
67
+ - `*etQuery` over an interop legacy query no longer reports each failed request to the `ErrorHandler` a second time.
68
+ - `*etInfinityQuery` over an interop legacy query no longer reports each failed page to the `ErrorHandler` a second time.
69
+ - 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.
70
+ - Legacy `queryComputed` no longer runs its computation twice on creation, which sent a mutation twice and replaced the query it returned synchronously.
71
+ - 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()`.
72
+ - 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.
73
+ - Calling `execute()` or `reset()` on a query inside an `effect` no longer re-runs the effect in an endless request loop.
74
+ - `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.
75
+ - `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.
76
+ - 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`.
77
+ - A migration task covers the `searchQueryField()` change from `null` to `''`.
78
+ - `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.
79
+ - The `ET100` error now says mutations need `withArgs` too and calls `silenceMissingWithArgsFeatureError` an escape hatch; the query skill recommends `withArgs` for mutations.
80
+
3
81
  ## 6.0.0-next.51
4
82
 
5
83
  ### Patch Changes
@@ -0,0 +1,393 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ChangeDetectorRef, DestroyRef, Pipe, NgModule, signal, computed, effect, untracked, isDevMode, EnvironmentInjector, assertInInjectionContext } from '@angular/core';
3
+ import { Subscription, combineLatest, startWith, map, Subject, defer, of, distinctUntilChanged, interval, takeUntil, finalize, filter } from 'rxjs';
4
+ import { resolveQueryHeaders } from '@ethlete/query';
5
+
6
+ const createToolkitPipeTransform = (options) => {
7
+ const cdr = inject(ChangeDetectorRef);
8
+ let subscription = Subscription.EMPTY;
9
+ let current = null;
10
+ let state = options.initialState;
11
+ const dispose = () => {
12
+ subscription.unsubscribe();
13
+ current = null;
14
+ state = options.disposedState;
15
+ };
16
+ const subscribe = (value) => {
17
+ current = value;
18
+ subscription = options.state$(value).subscribe((next) => {
19
+ state = next;
20
+ cdr.markForCheck();
21
+ });
22
+ };
23
+ inject(DestroyRef).onDestroy(dispose);
24
+ return (value) => {
25
+ if (!current && value)
26
+ subscribe(value);
27
+ if (current !== value) {
28
+ dispose();
29
+ if (value)
30
+ subscribe(value);
31
+ }
32
+ return state;
33
+ };
34
+ };
35
+
36
+ const noop = () => undefined;
37
+ const DEFAULT_STATE = {
38
+ args: null,
39
+ cachedResponse: null,
40
+ callState: null,
41
+ error: null,
42
+ isError: false,
43
+ isInit: false,
44
+ isLoading: false,
45
+ isSuccess: false,
46
+ response: null,
47
+ timestamp: null,
48
+ refresh: noop,
49
+ remove: noop,
50
+ startPolling: noop,
51
+ stopPolling: noop,
52
+ };
53
+ const suspenseState$ = (handle) => combineLatest({
54
+ args: handle.args$,
55
+ cachedResponse: handle.cachedResponse$.pipe(startWith(null)),
56
+ callState: handle.callState$,
57
+ error: handle.error$,
58
+ isError: handle.isError$,
59
+ isInit: handle.isInit$,
60
+ isLoading: handle.isLoading$,
61
+ isSuccess: handle.isSuccess$,
62
+ response: handle.response$,
63
+ timestamp: handle.timestamp$,
64
+ }).pipe(map((values) => ({
65
+ ...values,
66
+ refresh: handle.refresh,
67
+ remove: handle.remove,
68
+ startPolling: handle.startPolling,
69
+ stopPolling: handle.stopPolling,
70
+ })));
71
+ /** Subscribes to a toolkit handle and renders its current state, like the `suspense` pipe of `@tomtomb/ngrx-toolkit`. */
72
+ class SuspensePipe {
73
+ constructor() {
74
+ this.transform = createToolkitPipeTransform({
75
+ initialState: DEFAULT_STATE,
76
+ disposedState: null,
77
+ state$: suspenseState$,
78
+ });
79
+ }
80
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
81
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, isStandalone: true, name: "suspense", pure: false }); }
82
+ }
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, decorators: [{
84
+ type: Pipe,
85
+ args: [{ name: 'suspense', pure: false }]
86
+ }] });
87
+
88
+ const suspenseMultiState$ = (handles) => combineLatest(Object.entries(handles).flatMap(([key, handle]) => handle ? [suspenseState$(handle).pipe(map((state) => [key, state]))] : [])).pipe(map((states) => Object.fromEntries(states)));
89
+ /**
90
+ * Subscribes to a record of toolkit handles and renders each one's current state, like the `suspenseMulti` pipe of
91
+ * `@tomtomb/ngrx-toolkit`. Nothing renders until every non-null handle has emitted.
92
+ */
93
+ class SuspenseMultiPipe {
94
+ constructor() {
95
+ this.transform = createToolkitPipeTransform({
96
+ initialState: {},
97
+ disposedState: {},
98
+ state$: suspenseMultiState$,
99
+ });
100
+ }
101
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
102
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, isStandalone: true, name: "suspenseMulti", pure: false }); }
103
+ }
104
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, decorators: [{
105
+ type: Pipe,
106
+ args: [{ name: 'suspenseMulti', pure: false }]
107
+ }] });
108
+
109
+ /** Exports the `suspense` and `suspenseMulti` pipes, like the `NgRxToolkitModule` of `@tomtomb/ngrx-toolkit`. */
110
+ class NgRxToolkitModule {
111
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
112
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, imports: [SuspensePipe, SuspenseMultiPipe], exports: [SuspensePipe, SuspenseMultiPipe] }); }
113
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule }); }
114
+ }
115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, decorators: [{
116
+ type: NgModule,
117
+ args: [{
118
+ imports: [SuspensePipe, SuspenseMultiPipe],
119
+ exports: [SuspensePipe, SuspenseMultiPipe],
120
+ }]
121
+ }] });
122
+
123
+ /** The call state of a toolkit handle, as `@tomtomb/ngrx-toolkit` names it. */
124
+ const CallState = {
125
+ INIT: 'INIT',
126
+ LOADING: 'LOADING',
127
+ SUCCESS: 'SUCCESS',
128
+ ERROR: 'ERROR',
129
+ };
130
+
131
+ const EMPTY_SNAPSHOT = {
132
+ args: null,
133
+ callState: null,
134
+ response: null,
135
+ error: null,
136
+ timestamp: null,
137
+ };
138
+ const toCallState = (state) => {
139
+ switch (state?.type) {
140
+ case 'success':
141
+ return CallState.SUCCESS;
142
+ case 'failure':
143
+ return CallState.ERROR;
144
+ default:
145
+ return CallState.LOADING;
146
+ }
147
+ };
148
+ const toToolkitError = (error) => ({
149
+ status: error.raw.status,
150
+ message: error.raw.message,
151
+ data: error.raw.error ?? null,
152
+ });
153
+ const handleReleasedMessage = (method) => `${method}() was called on a toolkit handle that a newer toolkitCall() released. Args that cannot be hashed ` +
154
+ `(FormData, Blob, Map, ...) never share a handle, so the next call for the same creator releases the previous ` +
155
+ `handle once its request settles. The call was ignored - call toolkitCall() again with the args instead of ` +
156
+ `reusing the old handle. This warning is shown once per handle.`;
157
+ const toQueryArgs = (args) => {
158
+ const actionOptions = args['actionOptions'];
159
+ const queryArgs = {};
160
+ if (args['queryParams'] !== undefined)
161
+ queryArgs['pathParams'] = args['queryParams'];
162
+ if (args['params'] !== undefined)
163
+ queryArgs['queryParams'] = args['params'];
164
+ if (args['body'] !== undefined)
165
+ queryArgs['body'] = args['body'];
166
+ if (actionOptions?.headers !== undefined)
167
+ queryArgs['headers'] = actionOptions.headers;
168
+ return queryArgs;
169
+ };
170
+ const createToolkitHandle = (creator, injector) => {
171
+ const query = creator({ injector, onlyManualExecution: true, silenceMissingWithArgsFeatureError: true });
172
+ const calledArgs = signal(null, /* @ts-ignore */
173
+ ...(ngDevMode ? [{ debugName: "calledArgs" }] : /* istanbul ignore next */ []));
174
+ const toolkitError = computed(() => {
175
+ const error = query.error();
176
+ return error ? toToolkitError(error) : null;
177
+ }, /* @ts-ignore */
178
+ ...(ngDevMode ? [{ debugName: "toolkitError" }] : /* istanbul ignore next */ []));
179
+ const snapshot = computed(() => {
180
+ const currentArgs = calledArgs();
181
+ if (!currentArgs)
182
+ return EMPTY_SNAPSHOT;
183
+ const state = query.executionState();
184
+ const callState = toCallState(state);
185
+ return {
186
+ args: currentArgs,
187
+ callState,
188
+ response: state?.type === 'success' ? state.response : null,
189
+ error: callState === CallState.ERROR ? toolkitError() : null,
190
+ timestamp: Date.now(),
191
+ };
192
+ }, /* @ts-ignore */
193
+ ...(ngDevMode ? [{ debugName: "snapshot" }] : /* istanbul ignore next */ []));
194
+ const changes = new Subject();
195
+ const changesEffect = effect(() => {
196
+ const current = snapshot();
197
+ untracked(() => changes.next(current));
198
+ }, { ...(ngDevMode ? { debugName: "changesEffect" } : /* istanbul ignore next */ {}), injector });
199
+ let releasedSnapshot = null;
200
+ let warnedAboutRelease = false;
201
+ const ignoredAfterRelease = (method) => {
202
+ if (!releasedSnapshot)
203
+ return false;
204
+ if (isDevMode() && !warnedAboutRelease) {
205
+ warnedAboutRelease = true;
206
+ console.warn(handleReleasedMessage(method));
207
+ }
208
+ return true;
209
+ };
210
+ const select = (pick) => defer(() => (releasedSnapshot ? of(releasedSnapshot) : changes.pipe(startWith(untracked(snapshot))))).pipe(map(pick), distinctUntilChanged());
211
+ const call = (args) => {
212
+ calledArgs.set(args);
213
+ query.execute({ args: toQueryArgs(args) });
214
+ };
215
+ const refresh = () => {
216
+ if (ignoredAfterRelease('refresh'))
217
+ return;
218
+ const lastArgs = untracked(calledArgs);
219
+ if (lastArgs)
220
+ call(lastArgs);
221
+ };
222
+ let pollingSubscription = Subscription.EMPTY;
223
+ const stopPolling = () => pollingSubscription.unsubscribe();
224
+ const startPolling = ({ intervalDuration, killSwitch }) => {
225
+ if (ignoredAfterRelease('startPolling') || !pollingSubscription.closed)
226
+ return;
227
+ pollingSubscription = interval(intervalDuration)
228
+ .pipe(takeUntil(killSwitch), finalize(() => (pollingSubscription = Subscription.EMPTY)))
229
+ .subscribe(() => refresh());
230
+ };
231
+ const remove = () => {
232
+ stopPolling();
233
+ calledArgs.set(null);
234
+ query.reset();
235
+ };
236
+ const removeDestroyListener = injector.get(DestroyRef).onDestroy(() => {
237
+ stopPolling();
238
+ changes.complete();
239
+ });
240
+ const release = () => {
241
+ releasedSnapshot = untracked(snapshot);
242
+ stopPolling();
243
+ changesEffect.destroy();
244
+ removeDestroyListener();
245
+ changes.complete();
246
+ query.subtle.destroy();
247
+ };
248
+ const releaseWhenSettled = () => {
249
+ const releaseEffect = effect(() => {
250
+ if (snapshot().callState === CallState.LOADING)
251
+ return;
252
+ releaseEffect.destroy();
253
+ untracked(release);
254
+ }, { ...(ngDevMode ? { debugName: "releaseEffect" } : /* istanbul ignore next */ {}), injector });
255
+ };
256
+ const response$ = select((current) => current.response);
257
+ const handle = {
258
+ response$,
259
+ cachedResponse$: response$.pipe(filter((response) => !!response)),
260
+ error$: select((current) => current.error),
261
+ args$: select((current) => current.args),
262
+ isInit$: select((current) => current.callState === CallState.INIT),
263
+ isLoading$: select((current) => current.callState === CallState.LOADING),
264
+ isSuccess$: select((current) => current.callState === CallState.SUCCESS),
265
+ isError$: select((current) => current.callState === CallState.ERROR),
266
+ timestamp$: select((current) => current.timestamp),
267
+ callState$: select((current) => current.callState),
268
+ refresh,
269
+ remove,
270
+ startPolling,
271
+ stopPolling,
272
+ };
273
+ return { handle, call, releaseWhenSettled };
274
+ };
275
+
276
+ const registries = /* @__PURE__ */ new WeakMap();
277
+ class UnhashableValueError extends Error {
278
+ }
279
+ const isPlainObject = (value) => {
280
+ const prototype = Object.getPrototypeOf(value);
281
+ return prototype === Object.prototype || prototype === null;
282
+ };
283
+ const hashableValue = (value) => {
284
+ if (Array.isArray(value))
285
+ return value.map(hashableValue);
286
+ if (typeof value !== 'object' || value === null)
287
+ return value;
288
+ if (value instanceof Date)
289
+ return { '\u0000date': value.getTime() };
290
+ if (!isPlainObject(value))
291
+ throw new UnhashableValueError();
292
+ return Object.fromEntries(Object.keys(value)
293
+ .sort()
294
+ .map((key) => [key, hashableValue(value[key])]));
295
+ };
296
+ const hashableHeaders = (headers) => {
297
+ const resolved = resolveQueryHeaders(headers);
298
+ return resolved
299
+ ?.keys()
300
+ .map((name) => name.toLowerCase())
301
+ .sort()
302
+ .map((name) => [name, resolved.getAll(name)]);
303
+ };
304
+ /**
305
+ * Returns `null` for args holding a value JSON cannot represent (FormData, Blob, Map, ...). Those never share a handle,
306
+ * and each one is released once the next one for the same creator starts and its own call has settled.
307
+ */
308
+ const hashArgs = (args) => {
309
+ const { headers, ...rest } = args;
310
+ try {
311
+ return JSON.stringify([hashableValue(rest), hashableHeaders(headers) ?? null]);
312
+ }
313
+ catch (error) {
314
+ if (error instanceof UnhashableValueError)
315
+ return null;
316
+ throw error;
317
+ }
318
+ };
319
+ const resolveEnvironmentInjector = (fn, options) => {
320
+ if (options?.injector)
321
+ return options.injector.get(EnvironmentInjector);
322
+ assertInInjectionContext(fn);
323
+ return inject(EnvironmentInjector);
324
+ };
325
+ const resolveEntry = (creator, args, injector) => {
326
+ let registry = registries.get(injector);
327
+ if (!registry) {
328
+ registry = { shared: new WeakMap(), latestUnshared: new WeakMap() };
329
+ registries.set(injector, registry);
330
+ }
331
+ const key = hashArgs(toQueryArgs(args));
332
+ if (key === null) {
333
+ const entry = createToolkitHandle(creator, injector);
334
+ registry.latestUnshared.get(creator)?.releaseWhenSettled();
335
+ registry.latestUnshared.set(creator, entry);
336
+ return entry;
337
+ }
338
+ let entries = registry.shared.get(creator);
339
+ if (!entries) {
340
+ entries = new Map();
341
+ registry.shared.set(creator, entries);
342
+ }
343
+ let entry = entries.get(key);
344
+ if (!entry) {
345
+ entry = createToolkitHandle(creator, injector);
346
+ entries.set(key, entry);
347
+ }
348
+ return entry;
349
+ };
350
+ /**
351
+ * Returns the handle for a creator and args without executing it - the `FacadeBase.select(group, actionId)` of
352
+ * `@tomtomb/ngrx-toolkit`. Args that build the same request (in any key order, other keys ignored) give the same
353
+ * handle `toolkitCall` returns, so `toolkitSelect(getTeam, args, { injector }).refresh()` re-runs a request another
354
+ * component started.
355
+ */
356
+ const toolkitSelect = (creator, args, options) => resolveEntry(creator, args, resolveEnvironmentInjector(toolkitSelect, options)).handle;
357
+ /**
358
+ * Executes a query creator with toolkit-shaped args and returns its handle - the `FacadeBase.call(group, args)` of
359
+ * `@tomtomb/ngrx-toolkit`. Every call sends the request again; equal args return the same handle, which lives as
360
+ * long as the injector.
361
+ *
362
+ * @example
363
+ * ```ts
364
+ * @Injectable({ providedIn: 'root' })
365
+ * export class TeamFacade {
366
+ * private injector = inject(Injector);
367
+ *
368
+ * getTeam(args: ActionCallArgs<typeof getTeam>) {
369
+ * return toolkitCall(getTeam, args, { injector: this.injector });
370
+ * }
371
+ * }
372
+ * ```
373
+ */
374
+ const toolkitCall = (creator, args, options) => {
375
+ const entry = resolveEntry(creator, args, resolveEnvironmentInjector(toolkitCall, options));
376
+ entry.call(args);
377
+ return entry.handle;
378
+ };
379
+
380
+ /** Emits `true` while any of the given loading streams is `true`. Nullish entries are skipped. */
381
+ const joinLoading = (observables) => combineLatest(observables.filter((o) => !!o)).pipe(map((values) => values.some((value) => !!value)));
382
+ /** Emits every non-null error of the given error streams, or `null` when there is none. Nullish entries are skipped. */
383
+ const joinErrors = (observables) => combineLatest(observables.filter((o) => !!o)).pipe(map((values) => {
384
+ const errors = values.filter((value) => !!value);
385
+ return errors.length ? errors : null;
386
+ }));
387
+
388
+ /**
389
+ * Generated bundle index. Do not edit.
390
+ */
391
+
392
+ export { CallState, NgRxToolkitModule, SuspenseMultiPipe, SuspensePipe, joinErrors, joinLoading, toolkitCall, toolkitSelect };
393
+ //# sourceMappingURL=ethlete-query-ngrx-toolkit.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ethlete-query-ngrx-toolkit.mjs","sources":["../../../../libs/query/ngrx-toolkit/toolkit-pipe-transform.ts","../../../../libs/query/ngrx-toolkit/suspense.pipe.ts","../../../../libs/query/ngrx-toolkit/suspense-multi.pipe.ts","../../../../libs/query/ngrx-toolkit/ngrx-toolkit.module.ts","../../../../libs/query/ngrx-toolkit/toolkit-types.ts","../../../../libs/query/ngrx-toolkit/toolkit-handle.ts","../../../../libs/query/ngrx-toolkit/toolkit-call.ts","../../../../libs/query/ngrx-toolkit/toolkit-join.ts","../../../../libs/query/ngrx-toolkit/ethlete-query-ngrx-toolkit.ts"],"sourcesContent":["import { ChangeDetectorRef, DestroyRef, inject } from '@angular/core';\nimport { Observable, Subscription } from 'rxjs';\n\nexport type CreateToolkitPipeTransformOptions<TValue, TState> = {\n initialState: TState;\n disposedState: TState;\n state$: (value: TValue) => Observable<TState>;\n};\n\nexport const createToolkitPipeTransform = <TValue extends object, TState>(\n options: CreateToolkitPipeTransformOptions<TValue, TState>,\n) => {\n const cdr = inject(ChangeDetectorRef);\n let subscription = Subscription.EMPTY;\n let current: TValue | null = null;\n let state = options.initialState;\n\n const dispose = () => {\n subscription.unsubscribe();\n current = null;\n state = options.disposedState;\n };\n\n const subscribe = (value: TValue) => {\n current = value;\n subscription = options.state$(value).subscribe((next) => {\n state = next;\n cdr.markForCheck();\n });\n };\n\n inject(DestroyRef).onDestroy(dispose);\n\n return (value: TValue | null | undefined) => {\n if (!current && value) subscribe(value);\n\n if (current !== value) {\n dispose();\n if (value) subscribe(value);\n }\n\n return state;\n };\n};\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { combineLatest, map, Observable, startWith } from 'rxjs';\nimport { createToolkitPipeTransform } from './toolkit-pipe-transform';\nimport { AnyMappedEntityState, ToolkitPollingOptions } from './toolkit-types';\n\ntype ExtractFrom<T> = T extends Observable<infer U> ? U : never;\n\n/** What `suspense` and `suspenseMulti` render for a handle: every stream's current value, plus the handle's methods. */\nexport type ToolkitSuspenseState<T extends AnyMappedEntityState | null | undefined> = T extends AnyMappedEntityState\n ? {\n args: ExtractFrom<T['args$']>;\n cachedResponse: ExtractFrom<T['cachedResponse$']> | null;\n callState: ExtractFrom<T['callState$']>;\n error: ExtractFrom<T['error$']>;\n isError: ExtractFrom<T['isError$']>;\n isInit: ExtractFrom<T['isInit$']>;\n isLoading: ExtractFrom<T['isLoading$']>;\n isSuccess: ExtractFrom<T['isSuccess$']>;\n response: ExtractFrom<T['response$']>;\n timestamp: ExtractFrom<T['timestamp$']>;\n refresh: () => void;\n remove: () => void;\n startPolling: (options: ToolkitPollingOptions) => void;\n stopPolling: () => void;\n }\n : T;\n\ntype AnySuspenseState = ToolkitSuspenseState<AnyMappedEntityState>;\n\nconst noop = () => undefined;\n\nconst DEFAULT_STATE: AnySuspenseState = {\n args: null,\n cachedResponse: null,\n callState: null,\n error: null,\n isError: false,\n isInit: false,\n isLoading: false,\n isSuccess: false,\n response: null,\n timestamp: null,\n refresh: noop,\n remove: noop,\n startPolling: noop,\n stopPolling: noop,\n};\n\nexport const suspenseState$ = (handle: AnyMappedEntityState): Observable<AnySuspenseState> =>\n combineLatest({\n args: handle.args$,\n cachedResponse: handle.cachedResponse$.pipe(startWith(null)),\n callState: handle.callState$,\n error: handle.error$,\n isError: handle.isError$,\n isInit: handle.isInit$,\n isLoading: handle.isLoading$,\n isSuccess: handle.isSuccess$,\n response: handle.response$,\n timestamp: handle.timestamp$,\n }).pipe(\n map((values) => ({\n ...values,\n refresh: handle.refresh,\n remove: handle.remove,\n startPolling: handle.startPolling,\n stopPolling: handle.stopPolling,\n })),\n );\n\n/** Subscribes to a toolkit handle and renders its current state, like the `suspense` pipe of `@tomtomb/ngrx-toolkit`. */\n@Pipe({ name: 'suspense', pure: false })\nexport class SuspensePipe implements PipeTransform {\n transform = createToolkitPipeTransform<AnyMappedEntityState, AnySuspenseState | null>({\n initialState: DEFAULT_STATE,\n disposedState: null,\n state$: suspenseState$,\n }) as <T extends AnyMappedEntityState>(value: T | null | undefined) => ToolkitSuspenseState<T>;\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { combineLatest, map } from 'rxjs';\nimport { suspenseState$, ToolkitSuspenseState } from './suspense.pipe';\nimport { createToolkitPipeTransform } from './toolkit-pipe-transform';\nimport { AnyMappedEntityState } from './toolkit-types';\n\ntype AnyHandleRecord = Record<string, AnyMappedEntityState | null | undefined>;\n\nexport type ToolkitSuspenseMultiState<T extends AnyHandleRecord> = {\n [K in keyof T]: ToolkitSuspenseState<T[K]>;\n};\n\nconst suspenseMultiState$ = (handles: AnyHandleRecord) =>\n combineLatest(\n Object.entries(handles).flatMap(([key, handle]) =>\n handle ? [suspenseState$(handle).pipe(map((state) => [key, state] as const))] : [],\n ),\n ).pipe(map((states) => Object.fromEntries(states)));\n\n/**\n * Subscribes to a record of toolkit handles and renders each one's current state, like the `suspenseMulti` pipe of\n * `@tomtomb/ngrx-toolkit`. Nothing renders until every non-null handle has emitted.\n */\n@Pipe({ name: 'suspenseMulti', pure: false })\nexport class SuspenseMultiPipe implements PipeTransform {\n transform = createToolkitPipeTransform<AnyHandleRecord, Record<string, unknown>>({\n initialState: {},\n disposedState: {},\n state$: suspenseMultiState$,\n }) as <T extends AnyHandleRecord>(value: T | null | undefined) => ToolkitSuspenseMultiState<T>;\n}\n","import { NgModule } from '@angular/core';\nimport { SuspenseMultiPipe } from './suspense-multi.pipe';\nimport { SuspensePipe } from './suspense.pipe';\n\n/** Exports the `suspense` and `suspenseMulti` pipes, like the `NgRxToolkitModule` of `@tomtomb/ngrx-toolkit`. */\n@NgModule({\n imports: [SuspensePipe, SuspenseMultiPipe],\n exports: [SuspensePipe, SuspenseMultiPipe],\n})\nexport class NgRxToolkitModule {}\n","import { AnyQueryCreator, QueryArgsOf, QueryHeaders, ResponseType } from '@ethlete/query';\nimport { Observable, Subject } from 'rxjs';\n\n/** The call state of a toolkit handle, as `@tomtomb/ngrx-toolkit` names it. */\nexport const CallState = {\n INIT: 'INIT',\n LOADING: 'LOADING',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n} as const;\n\nexport type CallState = (typeof CallState)[keyof typeof CallState];\n\n/** The error shape of `@tomtomb/ngrx-toolkit`: the HTTP status, the error message and the response body. */\nexport type ToolkitError<T = unknown> = {\n status: number | string;\n message: string;\n data: T | null;\n};\n\nexport type ToolkitActionOptions = {\n headers?: QueryHeaders;\n extras?: { skipCache?: boolean };\n};\n\n/**\n * The toolkit-shaped args of a query creator: `queryParams` holds the path params, `params` the query string and\n * `body` the body, the way `@tomtomb/ngrx-toolkit` action groups named them.\n */\nexport type ActionCallArgs<TCreator extends AnyQueryCreator> = {\n [\n K in keyof QueryArgsOf<TCreator> as K extends 'pathParams'\n ? 'queryParams'\n : K extends 'queryParams'\n ? 'params'\n : K extends 'body'\n ? 'body'\n : never\n ]: QueryArgsOf<TCreator>[K];\n} & { actionOptions?: ToolkitActionOptions };\n\nexport type ToolkitPollingOptions = {\n intervalDuration: number;\n killSwitch: Subject<boolean>;\n};\n\n/** The handle `toolkitCall` returns, shaped like the `MappedEntityState` of `@tomtomb/ngrx-toolkit`. */\nexport type MappedEntityState<TCreator extends AnyQueryCreator> = {\n response$: Observable<ResponseType<QueryArgsOf<TCreator>> | null>;\n cachedResponse$: Observable<ResponseType<QueryArgsOf<TCreator>>>;\n error$: Observable<ToolkitError | null>;\n args$: Observable<ActionCallArgs<TCreator> | null>;\n isInit$: Observable<boolean | null>;\n isLoading$: Observable<boolean | null>;\n isSuccess$: Observable<boolean | null>;\n isError$: Observable<boolean | null>;\n timestamp$: Observable<number | null>;\n callState$: Observable<CallState | null>;\n refresh: () => void;\n remove: () => void;\n startPolling: (options: ToolkitPollingOptions) => void;\n stopPolling: () => void;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyMappedEntityState = MappedEntityState<any>;\n","import { computed, DestroyRef, effect, EnvironmentInjector, isDevMode, signal, untracked } from '@angular/core';\nimport {\n AnyQueryCreator,\n QueryArgsOf,\n QueryErrorResponse,\n QueryExecutionState,\n RequestArgs,\n ResponseType,\n} from '@ethlete/query';\nimport {\n defer,\n distinctUntilChanged,\n filter,\n finalize,\n interval,\n map,\n Observable,\n of,\n startWith,\n Subject,\n Subscription,\n takeUntil,\n} from 'rxjs';\nimport {\n ActionCallArgs,\n AnyMappedEntityState,\n CallState,\n MappedEntityState,\n ToolkitError,\n ToolkitPollingOptions,\n} from './toolkit-types';\n\ntype ToolkitHandleSnapshot = {\n args: unknown;\n callState: CallState | null;\n response: unknown;\n error: ToolkitError | null;\n timestamp: number | null;\n};\n\nexport type ToolkitHandleEntry = {\n handle: AnyMappedEntityState;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n call: (args: ActionCallArgs<any>) => void;\n releaseWhenSettled: () => void;\n};\n\nconst EMPTY_SNAPSHOT: ToolkitHandleSnapshot = {\n args: null,\n callState: null,\n response: null,\n error: null,\n timestamp: null,\n};\n\nconst toCallState = (state: QueryExecutionState<never> | null): CallState => {\n switch (state?.type) {\n case 'success':\n return CallState.SUCCESS;\n case 'failure':\n return CallState.ERROR;\n default:\n return CallState.LOADING;\n }\n};\n\nconst toToolkitError = (error: QueryErrorResponse): ToolkitError => ({\n status: error.raw.status,\n message: error.raw.message,\n data: error.raw.error ?? null,\n});\n\nconst handleReleasedMessage = (method: 'refresh' | 'startPolling') =>\n `${method}() was called on a toolkit handle that a newer toolkitCall() released. Args that cannot be hashed ` +\n `(FormData, Blob, Map, ...) never share a handle, so the next call for the same creator releases the previous ` +\n `handle once its request settles. The call was ignored - call toolkitCall() again with the args instead of ` +\n `reusing the old handle. This warning is shown once per handle.`;\n\nexport const toQueryArgs = (args: Record<string, unknown>) => {\n const actionOptions = args['actionOptions'] as { headers?: unknown } | undefined;\n const queryArgs: Record<string, unknown> = {};\n\n if (args['queryParams'] !== undefined) queryArgs['pathParams'] = args['queryParams'];\n if (args['params'] !== undefined) queryArgs['queryParams'] = args['params'];\n if (args['body'] !== undefined) queryArgs['body'] = args['body'];\n if (actionOptions?.headers !== undefined) queryArgs['headers'] = actionOptions.headers;\n\n return queryArgs as RequestArgs<never>;\n};\n\nexport const createToolkitHandle = <TCreator extends AnyQueryCreator>(\n creator: TCreator,\n injector: EnvironmentInjector,\n): ToolkitHandleEntry => {\n const query = creator({ injector, onlyManualExecution: true, silenceMissingWithArgsFeatureError: true });\n\n const calledArgs = signal<ActionCallArgs<TCreator> | null>(null);\n const toolkitError = computed(() => {\n const error = query.error();\n\n return error ? toToolkitError(error) : null;\n });\n const snapshot = computed<ToolkitHandleSnapshot>(() => {\n const currentArgs = calledArgs();\n\n if (!currentArgs) return EMPTY_SNAPSHOT;\n\n const state = query.executionState();\n const callState = toCallState(state);\n\n return {\n args: currentArgs,\n callState,\n response: state?.type === 'success' ? state.response : null,\n error: callState === CallState.ERROR ? toolkitError() : null,\n timestamp: Date.now(),\n };\n });\n\n const changes = new Subject<ToolkitHandleSnapshot>();\n\n const changesEffect = effect(\n () => {\n const current = snapshot();\n untracked(() => changes.next(current));\n },\n { injector },\n );\n\n let releasedSnapshot: ToolkitHandleSnapshot | null = null;\n let warnedAboutRelease = false;\n\n const ignoredAfterRelease = (method: 'refresh' | 'startPolling') => {\n if (!releasedSnapshot) return false;\n\n if (isDevMode() && !warnedAboutRelease) {\n warnedAboutRelease = true;\n console.warn(handleReleasedMessage(method));\n }\n\n return true;\n };\n\n const select = <T>(pick: (current: ToolkitHandleSnapshot) => T): Observable<T> =>\n defer(() => (releasedSnapshot ? of(releasedSnapshot) : changes.pipe(startWith(untracked(snapshot))))).pipe(\n map(pick),\n distinctUntilChanged(),\n );\n\n const call = (args: ActionCallArgs<TCreator>) => {\n calledArgs.set(args);\n query.execute({ args: toQueryArgs(args as Record<string, unknown>) });\n };\n\n const refresh = () => {\n if (ignoredAfterRelease('refresh')) return;\n\n const lastArgs = untracked(calledArgs);\n\n if (lastArgs) call(lastArgs);\n };\n\n let pollingSubscription = Subscription.EMPTY;\n\n const stopPolling = () => pollingSubscription.unsubscribe();\n\n const startPolling = ({ intervalDuration, killSwitch }: ToolkitPollingOptions) => {\n if (ignoredAfterRelease('startPolling') || !pollingSubscription.closed) return;\n\n pollingSubscription = interval(intervalDuration)\n .pipe(\n takeUntil(killSwitch),\n finalize(() => (pollingSubscription = Subscription.EMPTY)),\n )\n .subscribe(() => refresh());\n };\n\n const remove = () => {\n stopPolling();\n calledArgs.set(null);\n query.reset();\n };\n\n const removeDestroyListener = injector.get(DestroyRef).onDestroy(() => {\n stopPolling();\n changes.complete();\n });\n\n const release = () => {\n releasedSnapshot = untracked(snapshot);\n stopPolling();\n changesEffect.destroy();\n removeDestroyListener();\n changes.complete();\n query.subtle.destroy();\n };\n\n const releaseWhenSettled = () => {\n const releaseEffect = effect(\n () => {\n if (snapshot().callState === CallState.LOADING) return;\n\n releaseEffect.destroy();\n untracked(release);\n },\n { injector },\n );\n };\n\n type TResponse = ResponseType<QueryArgsOf<TCreator>>;\n\n const response$ = select((current) => current.response as TResponse | null);\n\n const handle: MappedEntityState<TCreator> = {\n response$,\n cachedResponse$: response$.pipe(filter((response): response is TResponse => !!response)),\n error$: select((current) => current.error),\n args$: select((current) => current.args as ActionCallArgs<TCreator> | null),\n isInit$: select((current) => current.callState === CallState.INIT),\n isLoading$: select((current) => current.callState === CallState.LOADING),\n isSuccess$: select((current) => current.callState === CallState.SUCCESS),\n isError$: select((current) => current.callState === CallState.ERROR),\n timestamp$: select((current) => current.timestamp),\n callState$: select((current) => current.callState),\n refresh,\n remove,\n startPolling,\n stopPolling,\n };\n\n return { handle, call, releaseWhenSettled };\n};\n","import { assertInInjectionContext, EnvironmentInjector, inject, Injector } from '@angular/core';\nimport { AnyQueryCreator, QueryHeaders, RequestArgs, resolveQueryHeaders } from '@ethlete/query';\nimport { createToolkitHandle, ToolkitHandleEntry, toQueryArgs } from './toolkit-handle';\nimport { ActionCallArgs, MappedEntityState } from './toolkit-types';\n\nexport type ToolkitCallOptions = {\n /**\n * The injector the handle's query lives in. Required outside an injection context, which is where a\n * `providedIn: 'root'` facade calls from; pass the facade's `inject(Injector)`.\n */\n injector?: Injector;\n};\n\ntype ToolkitRegistry = {\n shared: WeakMap<AnyQueryCreator, Map<string, ToolkitHandleEntry>>;\n latestUnshared: WeakMap<AnyQueryCreator, ToolkitHandleEntry>;\n};\n\nconst registries = /* @__PURE__ */ new WeakMap<EnvironmentInjector, ToolkitRegistry>();\n\nclass UnhashableValueError extends Error {}\n\nconst isPlainObject = (value: object) => {\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n};\n\nconst hashableValue = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(hashableValue);\n if (typeof value !== 'object' || value === null) return value;\n if (value instanceof Date) return { '\\u0000date': value.getTime() };\n if (!isPlainObject(value)) throw new UnhashableValueError();\n\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, hashableValue((value as Record<string, unknown>)[key])]),\n );\n};\n\nconst hashableHeaders = (headers: QueryHeaders | undefined) => {\n const resolved = resolveQueryHeaders(headers);\n\n return resolved\n ?.keys()\n .map((name) => name.toLowerCase())\n .sort()\n .map((name) => [name, resolved.getAll(name)]);\n};\n\n/**\n * Returns `null` for args holding a value JSON cannot represent (FormData, Blob, Map, ...). Those never share a handle,\n * and each one is released once the next one for the same creator starts and its own call has settled.\n */\nconst hashArgs = (args: RequestArgs<never>) => {\n const { headers, ...rest } = args as { headers?: QueryHeaders };\n\n try {\n return JSON.stringify([hashableValue(rest), hashableHeaders(headers) ?? null]);\n } catch (error) {\n if (error instanceof UnhashableValueError) return null;\n\n throw error;\n }\n};\n\nconst resolveEnvironmentInjector = (fn: (...args: never[]) => unknown, options?: ToolkitCallOptions) => {\n if (options?.injector) return options.injector.get(EnvironmentInjector);\n\n assertInInjectionContext(fn);\n\n return inject(EnvironmentInjector);\n};\n\nconst resolveEntry = <TCreator extends AnyQueryCreator>(\n creator: TCreator,\n args: ActionCallArgs<TCreator>,\n injector: EnvironmentInjector,\n) => {\n let registry = registries.get(injector);\n\n if (!registry) {\n registry = { shared: new WeakMap(), latestUnshared: new WeakMap() };\n registries.set(injector, registry);\n }\n\n const key = hashArgs(toQueryArgs(args as Record<string, unknown>));\n\n if (key === null) {\n const entry = createToolkitHandle(creator, injector);\n\n registry.latestUnshared.get(creator)?.releaseWhenSettled();\n registry.latestUnshared.set(creator, entry);\n\n return entry;\n }\n\n let entries = registry.shared.get(creator);\n\n if (!entries) {\n entries = new Map();\n registry.shared.set(creator, entries);\n }\n\n let entry = entries.get(key);\n\n if (!entry) {\n entry = createToolkitHandle(creator, injector);\n entries.set(key, entry);\n }\n\n return entry;\n};\n\n/**\n * Returns the handle for a creator and args without executing it - the `FacadeBase.select(group, actionId)` of\n * `@tomtomb/ngrx-toolkit`. Args that build the same request (in any key order, other keys ignored) give the same\n * handle `toolkitCall` returns, so `toolkitSelect(getTeam, args, { injector }).refresh()` re-runs a request another\n * component started.\n */\nexport const toolkitSelect = <TCreator extends AnyQueryCreator>(\n creator: TCreator,\n args: ActionCallArgs<TCreator>,\n options?: ToolkitCallOptions,\n): MappedEntityState<TCreator> =>\n resolveEntry(creator, args, resolveEnvironmentInjector(toolkitSelect, options)).handle;\n\n/**\n * Executes a query creator with toolkit-shaped args and returns its handle - the `FacadeBase.call(group, args)` of\n * `@tomtomb/ngrx-toolkit`. Every call sends the request again; equal args return the same handle, which lives as\n * long as the injector.\n *\n * @example\n * ```ts\n * @Injectable({ providedIn: 'root' })\n * export class TeamFacade {\n * private injector = inject(Injector);\n *\n * getTeam(args: ActionCallArgs<typeof getTeam>) {\n * return toolkitCall(getTeam, args, { injector: this.injector });\n * }\n * }\n * ```\n */\nexport const toolkitCall = <TCreator extends AnyQueryCreator>(\n creator: TCreator,\n args: ActionCallArgs<TCreator>,\n options?: ToolkitCallOptions,\n): MappedEntityState<TCreator> => {\n const entry = resolveEntry(creator, args, resolveEnvironmentInjector(toolkitCall, options));\n\n entry.call(args);\n\n return entry.handle;\n};\n","import { combineLatest, map, Observable } from 'rxjs';\nimport { ToolkitError } from './toolkit-types';\n\n/** Emits `true` while any of the given loading streams is `true`. Nullish entries are skipped. */\nexport const joinLoading = (observables: (Observable<boolean | null> | null | undefined)[]): Observable<boolean> =>\n combineLatest(observables.filter((o): o is Observable<boolean | null> => !!o)).pipe(\n map((values) => values.some((value) => !!value)),\n );\n\n/** Emits every non-null error of the given error streams, or `null` when there is none. Nullish entries are skipped. */\nexport const joinErrors = (\n observables: (Observable<ToolkitError | null> | null | undefined)[],\n): Observable<ToolkitError[] | null> =>\n combineLatest(observables.filter((o): o is Observable<ToolkitError | null> => !!o)).pipe(\n map((values) => {\n const errors = values.filter((value): value is ToolkitError => !!value);\n\n return errors.length ? errors : null;\n }),\n );\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}