@ethlete/query 6.0.0-next.51 → 6.0.0-next.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/fesm2022/ethlete-query-ngrx-toolkit.mjs +321 -0
- package/fesm2022/ethlete-query-ngrx-toolkit.mjs.map +1 -0
- package/fesm2022/ethlete-query.mjs +340 -136
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/generators/generators.json +5 -0
- package/generators/migrate-from-ngrx-toolkit/args-assignability.js +140 -0
- package/generators/migrate-from-ngrx-toolkit/consumers.js +453 -0
- package/generators/migrate-from-ngrx-toolkit/creators.js +301 -0
- package/generators/migrate-from-ngrx-toolkit/facade.js +295 -0
- package/generators/migrate-from-ngrx-toolkit/feature.js +513 -0
- package/generators/migrate-from-ngrx-toolkit/migration.js +139 -0
- package/generators/migrate-from-ngrx-toolkit/report.js +154 -0
- package/generators/migrate-from-ngrx-toolkit/schema.json +42 -0
- package/generators/migrate-from-ngrx-toolkit/store-removal.js +633 -0
- package/generators/migrate-from-ngrx-toolkit/ts-edits.js +128 -0
- package/generators/migrate-query-opt-in-features/migration.js +10 -9
- package/generators/migrate-to-query-v3/auth-provider-scaffold.js +29 -2
- package/generators/migrate-to-query-v3/cleanup-migration.js +22 -1
- package/generators/migrate-to-query-v3/legacy-query-creator-migration.js +39 -2
- package/generators/migrate-to-query-v3/migration.js +2 -1
- package/generators/migrate-to-query-v3/module-graph.js +2 -0
- package/generators/migrate-to-query-v3/query-client-migration.js +71 -2
- package/generators/migrate-to-query-v3/shared.js +27 -0
- package/generators/prep-for-query-v3/migration.js +83 -1
- package/migrations/query-field-default-types.md +43 -0
- package/migrations/search-query-field-string.md +43 -0
- package/migrations.json +16 -0
- package/package.json +5 -1
- package/types/ethlete-query-ngrx-toolkit.d.ts +143 -0
- package/types/ethlete-query.d.ts +129 -34
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @ethlete/query
|
|
2
2
|
|
|
3
|
+
## 6.0.0-next.52
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- **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`.
|
|
8
|
+
- **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`.
|
|
9
|
+
|
|
10
|
+
### Minor Changes
|
|
11
|
+
|
|
12
|
+
- Add `query.abort()`, which stops the execution in flight and puts `response()`, `error()` and `executionState()` back to where they were before it.
|
|
13
|
+
- `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`.
|
|
14
|
+
- 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.
|
|
15
|
+
- Every query request now carries the exported `IS_QUERY_REQUEST` `HttpContextToken`, so an app `HttpInterceptor` can skip requests sent by `@ethlete/query`.
|
|
16
|
+
- 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`.
|
|
17
|
+
- 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`.
|
|
18
|
+
- 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`.
|
|
19
|
+
- Query: `withPolling`, `withLongPolling` and `withAutoRefresh` take an `enabled` signal and run only while it is `true`, which replaces stopping a poll with `takeUntil`.
|
|
20
|
+
- `activeFilterCount` no longer counts a `searchQueryField()` or `sortQueryField()`, whatever its key.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- `*etQuery` over an interop legacy query no longer reports each failed request to the `ErrorHandler` a second time.
|
|
25
|
+
- `*etInfinityQuery` over an interop legacy query no longer reports each failed page to the `ErrorHandler` a second time.
|
|
26
|
+
- 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.
|
|
27
|
+
- Legacy `queryComputed` no longer runs its computation twice on creation, which sent a mutation twice and replaced the query it returned synchronously.
|
|
28
|
+
- 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()`.
|
|
29
|
+
- 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.
|
|
30
|
+
- Calling `execute()` or `reset()` on a query inside an `effect` no longer re-runs the effect in an endless request loop.
|
|
31
|
+
- `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.
|
|
32
|
+
- `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.
|
|
33
|
+
- 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`.
|
|
34
|
+
- A migration task covers the `searchQueryField()` change from `null` to `''`.
|
|
35
|
+
- `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.
|
|
36
|
+
- The `ET100` error now says mutations need `withArgs` too and calls `silenceMissingWithArgsFeatureError` an escape hatch; the query skill recommends `withArgs` for mutations.
|
|
37
|
+
|
|
3
38
|
## 6.0.0-next.51
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ChangeDetectorRef, DestroyRef, Pipe, NgModule, signal, computed, effect, untracked, EnvironmentInjector, assertInInjectionContext } from '@angular/core';
|
|
3
|
+
import { Subscription, combineLatest, startWith, map, Subject, defer, distinctUntilChanged, interval, takeUntil, finalize, filter } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
const createToolkitPipeTransform = (options) => {
|
|
6
|
+
const cdr = inject(ChangeDetectorRef);
|
|
7
|
+
let subscription = Subscription.EMPTY;
|
|
8
|
+
let current = null;
|
|
9
|
+
let state = options.initialState;
|
|
10
|
+
const dispose = () => {
|
|
11
|
+
subscription.unsubscribe();
|
|
12
|
+
current = null;
|
|
13
|
+
state = options.disposedState;
|
|
14
|
+
};
|
|
15
|
+
const subscribe = (value) => {
|
|
16
|
+
current = value;
|
|
17
|
+
subscription = options.state$(value).subscribe((next) => {
|
|
18
|
+
state = next;
|
|
19
|
+
cdr.markForCheck();
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
inject(DestroyRef).onDestroy(dispose);
|
|
23
|
+
return (value) => {
|
|
24
|
+
if (!current && value)
|
|
25
|
+
subscribe(value);
|
|
26
|
+
if (current !== value) {
|
|
27
|
+
dispose();
|
|
28
|
+
if (value)
|
|
29
|
+
subscribe(value);
|
|
30
|
+
}
|
|
31
|
+
return state;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const noop = () => undefined;
|
|
36
|
+
const DEFAULT_STATE = {
|
|
37
|
+
args: null,
|
|
38
|
+
cachedResponse: null,
|
|
39
|
+
callState: null,
|
|
40
|
+
error: null,
|
|
41
|
+
isError: false,
|
|
42
|
+
isInit: false,
|
|
43
|
+
isLoading: false,
|
|
44
|
+
isSuccess: false,
|
|
45
|
+
response: null,
|
|
46
|
+
timestamp: null,
|
|
47
|
+
refresh: noop,
|
|
48
|
+
remove: noop,
|
|
49
|
+
startPolling: noop,
|
|
50
|
+
stopPolling: noop,
|
|
51
|
+
};
|
|
52
|
+
const suspenseState$ = (handle) => combineLatest({
|
|
53
|
+
args: handle.args$,
|
|
54
|
+
cachedResponse: handle.cachedResponse$.pipe(startWith(null)),
|
|
55
|
+
callState: handle.callState$,
|
|
56
|
+
error: handle.error$,
|
|
57
|
+
isError: handle.isError$,
|
|
58
|
+
isInit: handle.isInit$,
|
|
59
|
+
isLoading: handle.isLoading$,
|
|
60
|
+
isSuccess: handle.isSuccess$,
|
|
61
|
+
response: handle.response$,
|
|
62
|
+
timestamp: handle.timestamp$,
|
|
63
|
+
}).pipe(map((values) => ({
|
|
64
|
+
...values,
|
|
65
|
+
refresh: handle.refresh,
|
|
66
|
+
remove: handle.remove,
|
|
67
|
+
startPolling: handle.startPolling,
|
|
68
|
+
stopPolling: handle.stopPolling,
|
|
69
|
+
})));
|
|
70
|
+
/** Subscribes to a toolkit handle and renders its current state, like the `suspense` pipe of `@tomtomb/ngrx-toolkit`. */
|
|
71
|
+
class SuspensePipe {
|
|
72
|
+
constructor() {
|
|
73
|
+
this.transform = createToolkitPipeTransform({
|
|
74
|
+
initialState: DEFAULT_STATE,
|
|
75
|
+
disposedState: null,
|
|
76
|
+
state$: suspenseState$,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
80
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, isStandalone: true, name: "suspense", pure: false }); }
|
|
81
|
+
}
|
|
82
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspensePipe, decorators: [{
|
|
83
|
+
type: Pipe,
|
|
84
|
+
args: [{ name: 'suspense', pure: false }]
|
|
85
|
+
}] });
|
|
86
|
+
|
|
87
|
+
const suspenseMultiState$ = (handles) => combineLatest(Object.entries(handles).flatMap(([key, handle]) => handle ? [suspenseState$(handle).pipe(map((state) => [key, state]))] : [])).pipe(map((states) => Object.fromEntries(states)));
|
|
88
|
+
/**
|
|
89
|
+
* Subscribes to a record of toolkit handles and renders each one's current state, like the `suspenseMulti` pipe of
|
|
90
|
+
* `@tomtomb/ngrx-toolkit`. Nothing renders until every non-null handle has emitted.
|
|
91
|
+
*/
|
|
92
|
+
class SuspenseMultiPipe {
|
|
93
|
+
constructor() {
|
|
94
|
+
this.transform = createToolkitPipeTransform({
|
|
95
|
+
initialState: {},
|
|
96
|
+
disposedState: {},
|
|
97
|
+
state$: suspenseMultiState$,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
101
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, isStandalone: true, name: "suspenseMulti", pure: false }); }
|
|
102
|
+
}
|
|
103
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SuspenseMultiPipe, decorators: [{
|
|
104
|
+
type: Pipe,
|
|
105
|
+
args: [{ name: 'suspenseMulti', pure: false }]
|
|
106
|
+
}] });
|
|
107
|
+
|
|
108
|
+
/** Exports the `suspense` and `suspenseMulti` pipes, like the `NgRxToolkitModule` of `@tomtomb/ngrx-toolkit`. */
|
|
109
|
+
class NgRxToolkitModule {
|
|
110
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
111
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, imports: [SuspensePipe, SuspenseMultiPipe], exports: [SuspensePipe, SuspenseMultiPipe] }); }
|
|
112
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule }); }
|
|
113
|
+
}
|
|
114
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NgRxToolkitModule, decorators: [{
|
|
115
|
+
type: NgModule,
|
|
116
|
+
args: [{
|
|
117
|
+
imports: [SuspensePipe, SuspenseMultiPipe],
|
|
118
|
+
exports: [SuspensePipe, SuspenseMultiPipe],
|
|
119
|
+
}]
|
|
120
|
+
}] });
|
|
121
|
+
|
|
122
|
+
/** The call state of a toolkit handle, as `@tomtomb/ngrx-toolkit` names it. */
|
|
123
|
+
const CallState = {
|
|
124
|
+
INIT: 'INIT',
|
|
125
|
+
LOADING: 'LOADING',
|
|
126
|
+
SUCCESS: 'SUCCESS',
|
|
127
|
+
ERROR: 'ERROR',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const EMPTY_SNAPSHOT = {
|
|
131
|
+
args: null,
|
|
132
|
+
callState: null,
|
|
133
|
+
response: null,
|
|
134
|
+
error: null,
|
|
135
|
+
timestamp: null,
|
|
136
|
+
};
|
|
137
|
+
const toCallState = (state) => {
|
|
138
|
+
switch (state?.type) {
|
|
139
|
+
case 'success':
|
|
140
|
+
return CallState.SUCCESS;
|
|
141
|
+
case 'failure':
|
|
142
|
+
return CallState.ERROR;
|
|
143
|
+
default:
|
|
144
|
+
return CallState.LOADING;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const toToolkitError = (error) => ({
|
|
148
|
+
status: error.raw.status,
|
|
149
|
+
message: error.raw.message,
|
|
150
|
+
data: error.raw.error ?? null,
|
|
151
|
+
});
|
|
152
|
+
const toQueryArgs = (args) => {
|
|
153
|
+
const actionOptions = args['actionOptions'];
|
|
154
|
+
const queryArgs = {};
|
|
155
|
+
if (args['queryParams'] !== undefined)
|
|
156
|
+
queryArgs['pathParams'] = args['queryParams'];
|
|
157
|
+
if (args['params'] !== undefined)
|
|
158
|
+
queryArgs['queryParams'] = args['params'];
|
|
159
|
+
if (args['body'] !== undefined)
|
|
160
|
+
queryArgs['body'] = args['body'];
|
|
161
|
+
if (actionOptions?.headers !== undefined)
|
|
162
|
+
queryArgs['headers'] = actionOptions.headers;
|
|
163
|
+
return queryArgs;
|
|
164
|
+
};
|
|
165
|
+
const createToolkitHandle = (creator, args, injector) => {
|
|
166
|
+
const query = creator({ injector, onlyManualExecution: true, silenceMissingWithArgsFeatureError: true });
|
|
167
|
+
const queryArgs = toQueryArgs(args);
|
|
168
|
+
const calledArgs = signal(null, /* @ts-ignore */
|
|
169
|
+
...(ngDevMode ? [{ debugName: "calledArgs" }] : /* istanbul ignore next */ []));
|
|
170
|
+
const toolkitError = computed(() => {
|
|
171
|
+
const error = query.error();
|
|
172
|
+
return error ? toToolkitError(error) : null;
|
|
173
|
+
}, /* @ts-ignore */
|
|
174
|
+
...(ngDevMode ? [{ debugName: "toolkitError" }] : /* istanbul ignore next */ []));
|
|
175
|
+
const snapshot = computed(() => {
|
|
176
|
+
const currentArgs = calledArgs();
|
|
177
|
+
if (!currentArgs)
|
|
178
|
+
return EMPTY_SNAPSHOT;
|
|
179
|
+
const state = query.executionState();
|
|
180
|
+
const callState = toCallState(state);
|
|
181
|
+
return {
|
|
182
|
+
args: currentArgs,
|
|
183
|
+
callState,
|
|
184
|
+
response: state?.type === 'success' ? state.response : null,
|
|
185
|
+
error: callState === CallState.ERROR ? toolkitError() : null,
|
|
186
|
+
timestamp: Date.now(),
|
|
187
|
+
};
|
|
188
|
+
}, /* @ts-ignore */
|
|
189
|
+
...(ngDevMode ? [{ debugName: "snapshot" }] : /* istanbul ignore next */ []));
|
|
190
|
+
const changes = new Subject();
|
|
191
|
+
effect(() => {
|
|
192
|
+
const current = snapshot();
|
|
193
|
+
untracked(() => changes.next(current));
|
|
194
|
+
}, { injector });
|
|
195
|
+
const select = (pick) => defer(() => changes.pipe(startWith(untracked(snapshot)))).pipe(map(pick), distinctUntilChanged());
|
|
196
|
+
const call = () => {
|
|
197
|
+
calledArgs.set(args);
|
|
198
|
+
query.execute({ args: queryArgs });
|
|
199
|
+
};
|
|
200
|
+
const refresh = () => {
|
|
201
|
+
if (untracked(calledArgs))
|
|
202
|
+
call();
|
|
203
|
+
};
|
|
204
|
+
let pollingSubscription = Subscription.EMPTY;
|
|
205
|
+
const stopPolling = () => pollingSubscription.unsubscribe();
|
|
206
|
+
const startPolling = ({ intervalDuration, killSwitch }) => {
|
|
207
|
+
if (!pollingSubscription.closed)
|
|
208
|
+
return;
|
|
209
|
+
pollingSubscription = interval(intervalDuration)
|
|
210
|
+
.pipe(takeUntil(killSwitch), finalize(() => (pollingSubscription = Subscription.EMPTY)))
|
|
211
|
+
.subscribe(() => refresh());
|
|
212
|
+
};
|
|
213
|
+
const remove = () => {
|
|
214
|
+
stopPolling();
|
|
215
|
+
calledArgs.set(null);
|
|
216
|
+
query.reset();
|
|
217
|
+
};
|
|
218
|
+
injector.get(DestroyRef).onDestroy(() => {
|
|
219
|
+
stopPolling();
|
|
220
|
+
changes.complete();
|
|
221
|
+
});
|
|
222
|
+
const response$ = select((current) => current.response);
|
|
223
|
+
const handle = {
|
|
224
|
+
response$,
|
|
225
|
+
cachedResponse$: response$.pipe(filter((response) => !!response)),
|
|
226
|
+
error$: select((current) => current.error),
|
|
227
|
+
args$: select((current) => current.args),
|
|
228
|
+
isInit$: select((current) => current.callState === CallState.INIT),
|
|
229
|
+
isLoading$: select((current) => current.callState === CallState.LOADING),
|
|
230
|
+
isSuccess$: select((current) => current.callState === CallState.SUCCESS),
|
|
231
|
+
isError$: select((current) => current.callState === CallState.ERROR),
|
|
232
|
+
timestamp$: select((current) => current.timestamp),
|
|
233
|
+
callState$: select((current) => current.callState),
|
|
234
|
+
refresh,
|
|
235
|
+
remove,
|
|
236
|
+
startPolling,
|
|
237
|
+
stopPolling,
|
|
238
|
+
};
|
|
239
|
+
return { handle, call };
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const registries = /* @__PURE__ */ new WeakMap();
|
|
243
|
+
const sortedValue = (value) => {
|
|
244
|
+
if (Array.isArray(value))
|
|
245
|
+
return value.map(sortedValue);
|
|
246
|
+
if (typeof value !== 'object' || value === null)
|
|
247
|
+
return value;
|
|
248
|
+
return Object.fromEntries(Object.keys(value)
|
|
249
|
+
.sort()
|
|
250
|
+
.map((key) => [key, sortedValue(value[key])]));
|
|
251
|
+
};
|
|
252
|
+
const hashArgs = (args) => JSON.stringify(sortedValue(args ?? null));
|
|
253
|
+
const resolveEnvironmentInjector = (fn, options) => {
|
|
254
|
+
if (options?.injector)
|
|
255
|
+
return options.injector.get(EnvironmentInjector);
|
|
256
|
+
assertInInjectionContext(fn);
|
|
257
|
+
return inject(EnvironmentInjector);
|
|
258
|
+
};
|
|
259
|
+
const resolveEntry = (creator, args, injector) => {
|
|
260
|
+
let registry = registries.get(injector);
|
|
261
|
+
if (!registry) {
|
|
262
|
+
registry = new WeakMap();
|
|
263
|
+
registries.set(injector, registry);
|
|
264
|
+
}
|
|
265
|
+
let entries = registry.get(creator);
|
|
266
|
+
if (!entries) {
|
|
267
|
+
entries = new Map();
|
|
268
|
+
registry.set(creator, entries);
|
|
269
|
+
}
|
|
270
|
+
const key = hashArgs(toQueryArgs(args));
|
|
271
|
+
let entry = entries.get(key);
|
|
272
|
+
if (!entry) {
|
|
273
|
+
entry = createToolkitHandle(creator, args, injector);
|
|
274
|
+
entries.set(key, entry);
|
|
275
|
+
}
|
|
276
|
+
return entry;
|
|
277
|
+
};
|
|
278
|
+
/**
|
|
279
|
+
* Returns the handle for a creator and args without executing it - the `FacadeBase.select(group, actionId)` of
|
|
280
|
+
* `@tomtomb/ngrx-toolkit`. Args that build the same request (in any key order, other keys ignored) give the same
|
|
281
|
+
* handle `toolkitCall` returns, so `toolkitSelect(getTeam, args, { injector }).refresh()` re-runs a request another
|
|
282
|
+
* component started.
|
|
283
|
+
*/
|
|
284
|
+
const toolkitSelect = (creator, args, options) => resolveEntry(creator, args, resolveEnvironmentInjector(toolkitSelect, options)).handle;
|
|
285
|
+
/**
|
|
286
|
+
* Executes a query creator with toolkit-shaped args and returns its handle - the `FacadeBase.call(group, args)` of
|
|
287
|
+
* `@tomtomb/ngrx-toolkit`. Every call sends the request again; equal args return the same handle, which lives as
|
|
288
|
+
* long as the injector.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* @Injectable({ providedIn: 'root' })
|
|
293
|
+
* export class TeamFacade {
|
|
294
|
+
* private injector = inject(Injector);
|
|
295
|
+
*
|
|
296
|
+
* getTeam(args: ActionCallArgs<typeof getTeam>) {
|
|
297
|
+
* return toolkitCall(getTeam, args, { injector: this.injector });
|
|
298
|
+
* }
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
const toolkitCall = (creator, args, options) => {
|
|
303
|
+
const entry = resolveEntry(creator, args, resolveEnvironmentInjector(toolkitCall, options));
|
|
304
|
+
entry.call();
|
|
305
|
+
return entry.handle;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
/** Emits `true` while any of the given loading streams is `true`. Nullish entries are skipped. */
|
|
309
|
+
const joinLoading = (observables) => combineLatest(observables.filter((o) => !!o)).pipe(map((values) => values.some((value) => !!value)));
|
|
310
|
+
/** Emits every non-null error of the given error streams, or `null` when there is none. Nullish entries are skipped. */
|
|
311
|
+
const joinErrors = (observables) => combineLatest(observables.filter((o) => !!o)).pipe(map((values) => {
|
|
312
|
+
const errors = values.filter((value) => !!value);
|
|
313
|
+
return errors.length ? errors : null;
|
|
314
|
+
}));
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Generated bundle index. Do not edit.
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
export { CallState, NgRxToolkitModule, SuspenseMultiPipe, SuspensePipe, joinErrors, joinLoading, toolkitCall, toolkitSelect };
|
|
321
|
+
//# 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, 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 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 call: () => 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\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 args: ActionCallArgs<TCreator>,\n injector: EnvironmentInjector,\n): ToolkitHandleEntry => {\n const query = creator({ injector, onlyManualExecution: true, silenceMissingWithArgsFeatureError: true });\n const queryArgs = toQueryArgs(args as Record<string, unknown>);\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 effect(\n () => {\n const current = snapshot();\n untracked(() => changes.next(current));\n },\n { injector },\n );\n\n const select = <T>(pick: (current: ToolkitHandleSnapshot) => T): Observable<T> =>\n defer(() => changes.pipe(startWith(untracked(snapshot)))).pipe(map(pick), distinctUntilChanged());\n\n const call = () => {\n calledArgs.set(args);\n query.execute({ args: queryArgs });\n };\n\n const refresh = () => {\n if (untracked(calledArgs)) call();\n };\n\n let pollingSubscription = Subscription.EMPTY;\n\n const stopPolling = () => pollingSubscription.unsubscribe();\n\n const startPolling = ({ intervalDuration, killSwitch }: ToolkitPollingOptions) => {\n if (!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 injector.get(DestroyRef).onDestroy(() => {\n stopPolling();\n changes.complete();\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 };\n};\n","import { assertInInjectionContext, EnvironmentInjector, inject, Injector } from '@angular/core';\nimport { AnyQueryCreator } 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 = WeakMap<AnyQueryCreator, Map<string, ToolkitHandleEntry>>;\n\nconst registries = /* @__PURE__ */ new WeakMap<EnvironmentInjector, ToolkitRegistry>();\n\nconst sortedValue = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(sortedValue);\n if (typeof value !== 'object' || value === null) return value;\n\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, sortedValue((value as Record<string, unknown>)[key])]),\n );\n};\n\nconst hashArgs = (args: unknown) => JSON.stringify(sortedValue(args ?? null));\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 = new WeakMap();\n registries.set(injector, registry);\n }\n\n let entries = registry.get(creator);\n\n if (!entries) {\n entries = new Map();\n registry.set(creator, entries);\n }\n\n const key = hashArgs(toQueryArgs(args as Record<string, unknown>));\n let entry = entries.get(key);\n\n if (!entry) {\n entry = createToolkitHandle(creator, args, 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();\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":";;;;AASO,MAAM,0BAA0B,GAAG,CACxC,OAA0D,KACxD;AACF,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACrC,IAAA,IAAI,YAAY,GAAG,YAAY,CAAC,KAAK;IACrC,IAAI,OAAO,GAAkB,IAAI;AACjC,IAAA,IAAI,KAAK,GAAG,OAAO,CAAC,YAAY;IAEhC,MAAM,OAAO,GAAG,MAAK;QACnB,YAAY,CAAC,WAAW,EAAE;QAC1B,OAAO,GAAG,IAAI;AACd,QAAA,KAAK,GAAG,OAAO,CAAC,aAAa;AAC/B,IAAA,CAAC;AAED,IAAA,MAAM,SAAS,GAAG,CAAC,KAAa,KAAI;QAClC,OAAO,GAAG,KAAK;AACf,QAAA,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,KAAI;YACtD,KAAK,GAAG,IAAI;YACZ,GAAG,CAAC,YAAY,EAAE;AACpB,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;IAErC,OAAO,CAAC,KAAgC,KAAI;QAC1C,IAAI,CAAC,OAAO,IAAI,KAAK;YAAE,SAAS,CAAC,KAAK,CAAC;AAEvC,QAAA,IAAI,OAAO,KAAK,KAAK,EAAE;AACrB,YAAA,OAAO,EAAE;AACT,YAAA,IAAI,KAAK;gBAAE,SAAS,CAAC,KAAK,CAAC;QAC7B;AAEA,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AACH,CAAC;;ACdD,MAAM,IAAI,GAAG,MAAM,SAAS;AAE5B,MAAM,aAAa,GAAqB;AACtC,IAAA,IAAI,EAAE,IAAI;AACV,IAAA,cAAc,EAAE,IAAI;AACpB,IAAA,SAAS,EAAE,IAAI;AACf,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,OAAO,EAAE,KAAK;AACd,IAAA,MAAM,EAAE,KAAK;AACb,IAAA,SAAS,EAAE,KAAK;AAChB,IAAA,SAAS,EAAE,KAAK;AAChB,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,SAAS,EAAE,IAAI;AACf,IAAA,OAAO,EAAE,IAAI;AACb,IAAA,MAAM,EAAE,IAAI;AACZ,IAAA,YAAY,EAAE,IAAI;AAClB,IAAA,WAAW,EAAE,IAAI;CAClB;AAEM,MAAM,cAAc,GAAG,CAAC,MAA4B,KACzD,aAAa,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,KAAK;IAClB,cAAc,EAAE,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC,UAAU;IAC5B,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,OAAO,EAAE,MAAM,CAAC,QAAQ;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC,UAAU;IAC5B,SAAS,EAAE,MAAM,CAAC,UAAU;IAC5B,QAAQ,EAAE,MAAM,CAAC,SAAS;IAC1B,SAAS,EAAE,MAAM,CAAC,UAAU;CAC7B,CAAC,CAAC,IAAI,CACL,GAAG,CAAC,CAAC,MAAM,MAAM;AACf,IAAA,GAAG,MAAM;IACT,OAAO,EAAE,MAAM,CAAC,OAAO;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,YAAY,EAAE,MAAM,CAAC,YAAY;IACjC,WAAW,EAAE,MAAM,CAAC,WAAW;CAChC,CAAC,CAAC,CACJ;AAEH;MAEa,YAAY,CAAA;AADzB,IAAA,WAAA,GAAA;QAEE,IAAA,CAAA,SAAS,GAAG,0BAA0B,CAAgD;AACpF,YAAA,YAAY,EAAE,aAAa;AAC3B,YAAA,aAAa,EAAE,IAAI;AACnB,YAAA,MAAM,EAAE,cAAc;AACvB,SAAA,CAA6F;AAC/F,IAAA;8GANY,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA,CAAA;4GAAZ,YAAY,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,KAAA,EAAA,CAAA,CAAA;;2FAAZ,YAAY,EAAA,UAAA,EAAA,CAAA;kBADxB,IAAI;AAAC,YAAA,IAAA,EAAA,CAAA,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE;;;AC3DvC,MAAM,mBAAmB,GAAG,CAAC,OAAwB,KACnD,aAAa,CACX,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAC5C,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,GAAG,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC,GAAG,EAAE,CACnF,CACF,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAErD;;;AAGG;MAEU,iBAAiB,CAAA;AAD9B,IAAA,WAAA,GAAA;QAEE,IAAA,CAAA,SAAS,GAAG,0BAA0B,CAA2C;AAC/E,YAAA,YAAY,EAAE,EAAE;AAChB,YAAA,aAAa,EAAE,EAAE;AACjB,YAAA,MAAM,EAAE,mBAAmB;AAC5B,SAAA,CAA6F;AAC/F,IAAA;8GANY,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA,CAAA;4GAAjB,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,eAAA,EAAA,IAAA,EAAA,KAAA,EAAA,CAAA,CAAA;;2FAAjB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,IAAI;AAAC,YAAA,IAAA,EAAA,CAAA,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE;;;ACnB5C;MAKa,iBAAiB,CAAA;8GAAjB,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA,CAAA;AAAjB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,YAHlB,YAAY,EAAE,iBAAiB,CAAA,EAAA,OAAA,EAAA,CAC/B,YAAY,EAAE,iBAAiB,CAAA,EAAA,CAAA,CAAA;+GAE9B,iBAAiB,EAAA,CAAA,CAAA;;2FAAjB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAJ7B,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;AACR,oBAAA,OAAO,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC;AAC1C,oBAAA,OAAO,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC;AAC3C,iBAAA;;;ACLD;AACO,MAAM,SAAS,GAAG;AACvB,IAAA,IAAI,EAAE,MAAM;AACZ,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,KAAK,EAAE,OAAO;;;ACoChB,MAAM,cAAc,GAA0B;AAC5C,IAAA,IAAI,EAAE,IAAI;AACV,IAAA,SAAS,EAAE,IAAI;AACf,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,SAAS,EAAE,IAAI;CAChB;AAED,MAAM,WAAW,GAAG,CAAC,KAAwC,KAAe;AAC1E,IAAA,QAAQ,KAAK,EAAE,IAAI;AACjB,QAAA,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC,OAAO;AAC1B,QAAA,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC,KAAK;AACxB,QAAA;YACE,OAAO,SAAS,CAAC,OAAO;;AAE9B,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,KAAyB,MAAoB;AACnE,IAAA,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM;AACxB,IAAA,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO;AAC1B,IAAA,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI;AAC9B,CAAA,CAAC;AAEK,MAAM,WAAW,GAAG,CAAC,IAA6B,KAAI;AAC3D,IAAA,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAsC;IAChF,MAAM,SAAS,GAA4B,EAAE;AAE7C,IAAA,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,SAAS;QAAE,SAAS,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;AACpF,IAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,SAAS;QAAE,SAAS,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;AAC3E,IAAA,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,SAAS;QAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AAChE,IAAA,IAAI,aAAa,EAAE,OAAO,KAAK,SAAS;AAAE,QAAA,SAAS,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,OAAO;AAEtF,IAAA,OAAO,SAA+B;AACxC,CAAC;AAEM,MAAM,mBAAmB,GAAG,CACjC,OAAiB,EACjB,IAA8B,EAC9B,QAA6B,KACP;AACtB,IAAA,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,kCAAkC,EAAE,IAAI,EAAE,CAAC;AACxG,IAAA,MAAM,SAAS,GAAG,WAAW,CAAC,IAA+B,CAAC;AAE9D,IAAA,MAAM,UAAU,GAAG,MAAM,CAAkC,IAAI;mFAAC;AAChE,IAAA,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAK;AACjC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE;AAE3B,QAAA,OAAO,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI;IAC7C,CAAC;qFAAC;AACF,IAAA,MAAM,QAAQ,GAAG,QAAQ,CAAwB,MAAK;AACpD,QAAA,MAAM,WAAW,GAAG,UAAU,EAAE;AAEhC,QAAA,IAAI,CAAC,WAAW;AAAE,YAAA,OAAO,cAAc;AAEvC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE;AACpC,QAAA,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC;QAEpC,OAAO;AACL,YAAA,IAAI,EAAE,WAAW;YACjB,SAAS;AACT,YAAA,QAAQ,EAAE,KAAK,EAAE,IAAI,KAAK,SAAS,GAAG,KAAK,CAAC,QAAQ,GAAG,IAAI;AAC3D,YAAA,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC,KAAK,GAAG,YAAY,EAAE,GAAG,IAAI;AAC5D,YAAA,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB;IACH,CAAC;iFAAC;AAEF,IAAA,MAAM,OAAO,GAAG,IAAI,OAAO,EAAyB;IAEpD,MAAM,CACJ,MAAK;AACH,QAAA,MAAM,OAAO,GAAG,QAAQ,EAAE;QAC1B,SAAS,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,IAAA,CAAC,EACD,EAAE,QAAQ,EAAE,CACb;AAED,IAAA,MAAM,MAAM,GAAG,CAAI,IAA2C,KAC5D,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAEnG,MAAM,IAAI,GAAG,MAAK;AAChB,QAAA,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QACpB,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACpC,IAAA,CAAC;IAED,MAAM,OAAO,GAAG,MAAK;QACnB,IAAI,SAAS,CAAC,UAAU,CAAC;AAAE,YAAA,IAAI,EAAE;AACnC,IAAA,CAAC;AAED,IAAA,IAAI,mBAAmB,GAAG,YAAY,CAAC,KAAK;IAE5C,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE;IAE3D,MAAM,YAAY,GAAG,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAyB,KAAI;QAC/E,IAAI,CAAC,mBAAmB,CAAC,MAAM;YAAE;AAEjC,QAAA,mBAAmB,GAAG,QAAQ,CAAC,gBAAgB;AAC5C,aAAA,IAAI,CACH,SAAS,CAAC,UAAU,CAAC,EACrB,QAAQ,CAAC,OAAO,mBAAmB,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAE3D,aAAA,SAAS,CAAC,MAAM,OAAO,EAAE,CAAC;AAC/B,IAAA,CAAC;IAED,MAAM,MAAM,GAAG,MAAK;AAClB,QAAA,WAAW,EAAE;AACb,QAAA,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QACpB,KAAK,CAAC,KAAK,EAAE;AACf,IAAA,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAK;AACtC,QAAA,WAAW,EAAE;QACb,OAAO,CAAC,QAAQ,EAAE;AACpB,IAAA,CAAC,CAAC;AAIF,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,QAA4B,CAAC;AAE3E,IAAA,MAAM,MAAM,GAAgC;QAC1C,SAAS;AACT,QAAA,eAAe,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,KAA4B,CAAC,CAAC,QAAQ,CAAC,CAAC;QACxF,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC;QAC1C,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,IAAuC,CAAC;AAC3E,QAAA,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC;AAClE,QAAA,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,OAAO,CAAC;AACxE,QAAA,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,OAAO,CAAC;AACxE,QAAA,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,KAAK,CAAC;QACpE,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC;QAClD,UAAU,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC;QAClD,OAAO;QACP,MAAM;QACN,YAAY;QACZ,WAAW;KACZ;AAED,IAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;AACzB,CAAC;;ACvKD,MAAM,UAAU,mBAAmB,IAAI,OAAO,EAAwC;AAEtF,MAAM,WAAW,GAAG,CAAC,KAAc,KAAa;AAC9C,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC;AACvD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;AAAE,QAAA,OAAO,KAAK;IAE7D,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,IAAI,CAAC,KAAK;AACd,SAAA,IAAI;AACJ,SAAA,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,WAAW,CAAE,KAAiC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAC7E;AACH,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,IAAa,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AAE7E,MAAM,0BAA0B,GAAG,CAAC,EAAiC,EAAE,OAA4B,KAAI;IACrG,IAAI,OAAO,EAAE,QAAQ;QAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAEvE,wBAAwB,CAAC,EAAE,CAAC;AAE5B,IAAA,OAAO,MAAM,CAAC,mBAAmB,CAAC;AACpC,CAAC;AAED,MAAM,YAAY,GAAG,CACnB,OAAiB,EACjB,IAA8B,EAC9B,QAA6B,KAC3B;IACF,IAAI,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;IAEvC,IAAI,CAAC,QAAQ,EAAE;AACb,QAAA,QAAQ,GAAG,IAAI,OAAO,EAAE;AACxB,QAAA,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC;IACpC;IAEA,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IAEnC,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,GAAG,IAAI,GAAG,EAAE;AACnB,QAAA,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;IAChC;IAEA,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,IAA+B,CAAC,CAAC;IAClE,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IAE5B,IAAI,CAAC,KAAK,EAAE;QACV,KAAK,GAAG,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC;AACpD,QAAA,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;IACzB;AAEA,IAAA,OAAO,KAAK;AACd,CAAC;AAED;;;;;AAKG;AACI,MAAM,aAAa,GAAG,CAC3B,OAAiB,EACjB,IAA8B,EAC9B,OAA4B,KAE5B,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,0BAA0B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;AAElF;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,WAAW,GAAG,CACzB,OAAiB,EACjB,IAA8B,EAC9B,OAA4B,KACG;AAC/B,IAAA,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,0BAA0B,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE3F,KAAK,CAAC,IAAI,EAAE;IAEZ,OAAO,KAAK,CAAC,MAAM;AACrB;;ACzGA;MACa,WAAW,GAAG,CAAC,WAA8D,KACxF,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAsC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACjF,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;AAGpD;AACO,MAAM,UAAU,GAAG,CACxB,WAAmE,KAEnE,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAA2C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACtF,GAAG,CAAC,CAAC,MAAM,KAAI;AACb,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,KAA4B,CAAC,CAAC,KAAK,CAAC;IAEvE,OAAO,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI;AACtC,CAAC,CAAC;;AClBN;;AAEG;;;;"}
|