@ethlete/query 5.16.0 → 5.16.2

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 (184) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/esm2022/ethlete-query.mjs +5 -0
  3. package/esm2022/index.mjs +20 -0
  4. package/esm2022/lib/auth/auth-provider.types.mjs +2 -0
  5. package/esm2022/lib/auth/auth-provider.utils.mjs +25 -0
  6. package/esm2022/lib/auth/basic-auth-provider.mjs +15 -0
  7. package/esm2022/lib/auth/bearer-auth-provider.mjs +168 -0
  8. package/esm2022/lib/auth/custom-header-auth-provider.mjs +12 -0
  9. package/esm2022/lib/auth/index.mjs +6 -0
  10. package/esm2022/lib/class-validator/class-validator.types.mjs +2 -0
  11. package/esm2022/lib/class-validator/class-validator.utils.mjs +4 -0
  12. package/esm2022/lib/class-validator/index.mjs +3 -0
  13. package/esm2022/lib/devtools/components/query-devtools/index.mjs +2 -0
  14. package/esm2022/lib/devtools/components/query-devtools/query-devtools.component.mjs +297 -0
  15. package/esm2022/lib/devtools/pipes/index.mjs +2 -0
  16. package/esm2022/lib/devtools/pipes/query-short-name.pipe.mjs +24 -0
  17. package/esm2022/lib/devtools/utils/index.mjs +2 -0
  18. package/esm2022/lib/devtools/utils/query-client.utils.mjs +13 -0
  19. package/esm2022/lib/directives/index.mjs +4 -0
  20. package/esm2022/lib/directives/infinity-query-trigger.directive.mjs +56 -0
  21. package/esm2022/lib/directives/infinity-query.directive.mjs +147 -0
  22. package/esm2022/lib/directives/query.directive.mjs +123 -0
  23. package/esm2022/lib/entity/entity-store.mjs +127 -0
  24. package/esm2022/lib/entity/entity.types.mjs +2 -0
  25. package/esm2022/lib/entity/entity.utils.mjs +29 -0
  26. package/esm2022/lib/entity/index.mjs +4 -0
  27. package/esm2022/lib/gql/gql.mjs +23 -0
  28. package/esm2022/lib/gql/index.mjs +2 -0
  29. package/esm2022/lib/infinite-query/index.mjs +4 -0
  30. package/esm2022/lib/infinite-query/infinity-query.mjs +171 -0
  31. package/esm2022/lib/infinite-query/infinity-query.types.mjs +2 -0
  32. package/esm2022/lib/infinite-query/infinity-query.utils.mjs +3 -0
  33. package/esm2022/lib/logger/index.mjs +2 -0
  34. package/esm2022/lib/logger/logger.mjs +16 -0
  35. package/esm2022/lib/query/index.mjs +4 -0
  36. package/esm2022/lib/query/query.mjs +430 -0
  37. package/esm2022/lib/query/query.types.mjs +2 -0
  38. package/esm2022/lib/query/query.utils.mjs +253 -0
  39. package/esm2022/lib/query-client/index.mjs +4 -0
  40. package/esm2022/lib/query-client/query-client.mjs +80 -0
  41. package/esm2022/lib/query-client/query-client.types.mjs +2 -0
  42. package/esm2022/lib/query-client/query-client.utils.mjs +20 -0
  43. package/esm2022/lib/query-creator/index.mjs +3 -0
  44. package/esm2022/lib/query-creator/query-creator.mjs +55 -0
  45. package/esm2022/lib/query-creator/query-creator.types.mjs +2 -0
  46. package/esm2022/lib/query-form/index.mjs +4 -0
  47. package/esm2022/lib/query-form/query-form.mjs +379 -0
  48. package/esm2022/lib/query-form/query-form.types.mjs +2 -0
  49. package/esm2022/lib/query-form/query-form.utils.mjs +97 -0
  50. package/esm2022/lib/query-store/index.mjs +2 -0
  51. package/esm2022/lib/query-store/query-store.mjs +144 -0
  52. package/esm2022/lib/request/index.mjs +4 -0
  53. package/esm2022/lib/request/request.mjs +196 -0
  54. package/esm2022/lib/request/request.types.mjs +2 -0
  55. package/esm2022/lib/request/request.util.mjs +252 -0
  56. package/esm2022/lib/symfony/index.mjs +3 -0
  57. package/esm2022/lib/symfony/symfony.types.mjs +2 -0
  58. package/esm2022/lib/symfony/symfony.utils.mjs +31 -0
  59. package/esm2022/lib/utils/data.utils.mjs +138 -0
  60. package/esm2022/lib/utils/deep-freeze.util.mjs +17 -0
  61. package/esm2022/lib/utils/def.util.mjs +8 -0
  62. package/esm2022/lib/utils/index.mjs +4 -0
  63. package/fesm2022/ethlete-query.mjs +3289 -0
  64. package/fesm2022/ethlete-query.mjs.map +1 -0
  65. package/{src/index.ts → index.d.ts} +0 -2
  66. package/lib/auth/auth-provider.types.d.ts +133 -0
  67. package/lib/auth/auth-provider.utils.d.ts +9 -0
  68. package/lib/auth/basic-auth-provider.d.ts +10 -0
  69. package/lib/auth/bearer-auth-provider.d.ts +23 -0
  70. package/lib/auth/custom-header-auth-provider.d.ts +9 -0
  71. package/{src/lib/class-validator/class-validator.types.ts → lib/class-validator/class-validator.types.d.ts} +3 -4
  72. package/lib/class-validator/class-validator.utils.d.ts +2 -0
  73. package/lib/devtools/components/query-devtools/query-devtools.component.d.ts +151 -0
  74. package/lib/devtools/pipes/query-short-name.pipe.d.ts +8 -0
  75. package/lib/devtools/utils/query-client.utils.d.ts +12 -0
  76. package/lib/directives/infinity-query-trigger.directive.d.ts +15 -0
  77. package/lib/directives/infinity-query.directive.d.ts +49 -0
  78. package/lib/directives/query.directive.d.ts +63 -0
  79. package/lib/entity/entity-store.d.ts +25 -0
  80. package/lib/entity/entity.types.d.ts +25 -0
  81. package/lib/entity/entity.utils.d.ts +12 -0
  82. package/lib/gql/gql.d.ts +6 -0
  83. package/lib/infinite-query/infinity-query.d.ts +29 -0
  84. package/lib/infinite-query/infinity-query.types.d.ts +104 -0
  85. package/lib/infinite-query/infinity-query.utils.d.ts +4 -0
  86. package/lib/logger/logger.d.ts +12 -0
  87. package/lib/query/query.d.ts +60 -0
  88. package/lib/query/query.types.d.ts +388 -0
  89. package/lib/query/query.utils.d.ts +82 -0
  90. package/lib/query-client/query-client.d.ts +29 -0
  91. package/lib/query-client/query-client.types.d.ts +82 -0
  92. package/lib/query-client/query-client.utils.d.ts +4 -0
  93. package/lib/query-creator/query-creator.d.ts +20 -0
  94. package/lib/query-creator/query-creator.types.d.ts +13 -0
  95. package/lib/query-form/query-form.d.ts +91 -0
  96. package/lib/query-form/query-form.types.d.ts +145 -0
  97. package/lib/query-form/query-form.utils.d.ts +13 -0
  98. package/lib/query-store/query-store.d.ts +31 -0
  99. package/lib/request/request.d.ts +3 -0
  100. package/lib/request/request.types.d.ts +126 -0
  101. package/lib/request/request.util.d.ts +92 -0
  102. package/lib/symfony/symfony.types.d.ts +19 -0
  103. package/lib/symfony/symfony.utils.d.ts +6 -0
  104. package/lib/utils/data.utils.d.ts +59 -0
  105. package/lib/utils/deep-freeze.util.d.ts +1 -0
  106. package/{src/lib/utils/def.util.ts → lib/utils/def.util.d.ts} +1 -1
  107. package/package.json +23 -6
  108. package/.eslintrc.json +0 -40
  109. package/jest.config.ts +0 -23
  110. package/ng-package.json +0 -8
  111. package/project.json +0 -37
  112. package/src/lib/auth/auth-provider.types.ts +0 -160
  113. package/src/lib/auth/auth-provider.utils.ts +0 -39
  114. package/src/lib/auth/basic-auth-provider.ts +0 -17
  115. package/src/lib/auth/bearer-auth-provider.ts +0 -243
  116. package/src/lib/auth/custom-header-auth-provider.ts +0 -13
  117. package/src/lib/class-validator/class-validator.utils.ts +0 -5
  118. package/src/lib/devtools/components/query-devtools/query-devtools.component.html +0 -402
  119. package/src/lib/devtools/components/query-devtools/query-devtools.component.scss +0 -360
  120. package/src/lib/devtools/components/query-devtools/query-devtools.component.ts +0 -427
  121. package/src/lib/devtools/pipes/query-short-name.pipe.ts +0 -24
  122. package/src/lib/devtools/utils/query-client.utils.ts +0 -25
  123. package/src/lib/directives/infinity-query-trigger.directive.ts +0 -58
  124. package/src/lib/directives/infinity-query.directive.ts +0 -208
  125. package/src/lib/directives/query.directive.ts +0 -201
  126. package/src/lib/entity/entity-store.ts +0 -180
  127. package/src/lib/entity/entity.types.ts +0 -34
  128. package/src/lib/entity/entity.utils.ts +0 -51
  129. package/src/lib/gql/gql.ts +0 -22
  130. package/src/lib/infinite-query/infinity-query.ts +0 -245
  131. package/src/lib/infinite-query/infinity-query.types.ts +0 -149
  132. package/src/lib/infinite-query/infinity-query.utils.ts +0 -14
  133. package/src/lib/logger/logger.ts +0 -30
  134. package/src/lib/query/query.ts +0 -631
  135. package/src/lib/query/query.types.ts +0 -532
  136. package/src/lib/query/query.utils.spec.ts +0 -92
  137. package/src/lib/query/query.utils.ts +0 -450
  138. package/src/lib/query-client/query-client.spec.ts +0 -77
  139. package/src/lib/query-client/query-client.ts +0 -195
  140. package/src/lib/query-client/query-client.types.ts +0 -101
  141. package/src/lib/query-client/query-client.utils.spec.ts +0 -61
  142. package/src/lib/query-client/query-client.utils.ts +0 -28
  143. package/src/lib/query-creator/query-creator.ts +0 -103
  144. package/src/lib/query-creator/query-creator.types.ts +0 -74
  145. package/src/lib/query-form/query-form.ts +0 -526
  146. package/src/lib/query-form/query-form.types.ts +0 -169
  147. package/src/lib/query-form/query-form.utils.ts +0 -116
  148. package/src/lib/query-store/query-store.ts +0 -192
  149. package/src/lib/request/request.ts +0 -253
  150. package/src/lib/request/request.types.ts +0 -164
  151. package/src/lib/request/request.util.spec.ts +0 -177
  152. package/src/lib/request/request.util.ts +0 -399
  153. package/src/lib/stories/angular-example-page.mdx +0 -85
  154. package/src/lib/stories/authentication-page.mdx +0 -35
  155. package/src/lib/stories/changelog-page.mdx +0 -9
  156. package/src/lib/stories/client-page.mdx +0 -100
  157. package/src/lib/stories/queries-page.mdx +0 -117
  158. package/src/lib/symfony/symfony.types.ts +0 -21
  159. package/src/lib/symfony/symfony.utils.ts +0 -43
  160. package/src/lib/utils/data.utils.ts +0 -280
  161. package/src/lib/utils/deep-freeze.util.ts +0 -21
  162. package/src/test-setup.ts +0 -1
  163. package/tsconfig.json +0 -29
  164. package/tsconfig.lib.json +0 -12
  165. package/tsconfig.lib.prod.json +0 -10
  166. package/tsconfig.spec.json +0 -11
  167. /package/{src/lib/auth/index.ts → lib/auth/index.d.ts} +0 -0
  168. /package/{src/lib/class-validator/index.ts → lib/class-validator/index.d.ts} +0 -0
  169. /package/{src/lib/devtools/components/query-devtools/index.ts → lib/devtools/components/query-devtools/index.d.ts} +0 -0
  170. /package/{src/lib/devtools/pipes/index.ts → lib/devtools/pipes/index.d.ts} +0 -0
  171. /package/{src/lib/devtools/utils/index.ts → lib/devtools/utils/index.d.ts} +0 -0
  172. /package/{src/lib/directives/index.ts → lib/directives/index.d.ts} +0 -0
  173. /package/{src/lib/entity/index.ts → lib/entity/index.d.ts} +0 -0
  174. /package/{src/lib/gql/index.ts → lib/gql/index.d.ts} +0 -0
  175. /package/{src/lib/infinite-query/index.ts → lib/infinite-query/index.d.ts} +0 -0
  176. /package/{src/lib/logger/index.ts → lib/logger/index.d.ts} +0 -0
  177. /package/{src/lib/query/index.ts → lib/query/index.d.ts} +0 -0
  178. /package/{src/lib/query-client/index.ts → lib/query-client/index.d.ts} +0 -0
  179. /package/{src/lib/query-creator/index.ts → lib/query-creator/index.d.ts} +0 -0
  180. /package/{src/lib/query-form/index.ts → lib/query-form/index.d.ts} +0 -0
  181. /package/{src/lib/query-store/index.ts → lib/query-store/index.d.ts} +0 -0
  182. /package/{src/lib/request/index.ts → lib/request/index.d.ts} +0 -0
  183. /package/{src/lib/symfony/index.ts → lib/symfony/index.d.ts} +0 -0
  184. /package/{src/lib/utils/index.ts → lib/utils/index.d.ts} +0 -0
@@ -1,631 +0,0 @@
1
- import { untracked } from '@angular/core';
2
- import {
3
- BehaviorSubject,
4
- combineLatest,
5
- filter,
6
- interval,
7
- map,
8
- Observable,
9
- of,
10
- ReplaySubject,
11
- shareReplay,
12
- skip,
13
- Subject,
14
- Subscription,
15
- switchMap,
16
- take,
17
- takeUntil,
18
- takeWhile,
19
- tap,
20
- timer,
21
- } from 'rxjs';
22
- import { isBearerAuthProvider } from '../auth';
23
- import { EntityStore } from '../entity';
24
- import { QueryClient, shouldCacheQuery } from '../query-client';
25
- import { HttpStatusCode, request, RequestError, RequestEvent, RequestHeaders } from '../request';
26
- import {
27
- BaseArguments,
28
- ExecuteQueryOptions,
29
- GqlQueryConfig,
30
- PollConfig,
31
- QueryAutoRefreshConfig,
32
- QueryState,
33
- QueryStateMeta,
34
- QueryStateType,
35
- RestQueryConfig,
36
- RouteType,
37
- } from './query.types';
38
- import {
39
- computeQueryBody,
40
- computeQueryHeaders,
41
- computeQueryMethod,
42
- filterFailure,
43
- filterSuccess,
44
- isGqlQueryConfig,
45
- isQueryStateCancelled,
46
- isQueryStateFailure,
47
- isQueryStateLoading,
48
- isQueryStatePrepared,
49
- isQueryStateSuccess,
50
- switchQueryState,
51
- takeUntilResponse,
52
- } from './query.utils';
53
-
54
- let _nextQueryId = 0;
55
-
56
- export class Query<
57
- Response,
58
- Arguments extends BaseArguments | undefined,
59
- Route extends RouteType<Arguments>,
60
- Store extends EntityStore<unknown>,
61
- Data,
62
- Id,
63
- > {
64
- readonly _id = _nextQueryId++;
65
-
66
- private _currentLocalId = 0;
67
- private _pollingSubscription: Subscription | null = null;
68
- private _onAbort$ = new Subject<void>();
69
- private _currentPollConfig: PollConfig | null = null;
70
-
71
- /**
72
- * @internal
73
- * Used to track which components depend on this query.
74
- * The key is the component's _tNode index.
75
- * The value is the number of times the component has subscribed to this query.
76
- * The value might increase since we cant distinguish between a component and a host directive applied to it.
77
- */
78
- _dependents: Record<number, number> = {};
79
-
80
- /**
81
- * @internal
82
- */
83
- _dependentsChanged$ = new ReplaySubject<Record<number, number>>();
84
-
85
- /**
86
- * @internal
87
- */
88
- _isPollingPaused = false;
89
-
90
- private readonly _state$ = new BehaviorSubject<QueryState<Response>>({
91
- type: QueryStateType.Prepared,
92
- meta: { id: this._currentLocalId, triggeredVia: 'program' },
93
- });
94
-
95
- private get _nextId() {
96
- return ++this._currentLocalId;
97
- }
98
-
99
- get state$(): Observable<QueryState<Data>> {
100
- return this._state$.pipe(
101
- tap((s) => {
102
- if (!this._client.config.logging?.preparedQuerySubscriptions) return;
103
-
104
- if (isQueryStatePrepared(s)) {
105
- console.warn(
106
- `Query ${this._routeWithParams} was subscribed to in the prepared state. Did you forget to call .execute()?`,
107
- );
108
- }
109
- }),
110
- switchMap((s) => this._transformState(s)),
111
- shareReplay({ bufferSize: 1, refCount: true }),
112
- );
113
- }
114
-
115
- /**
116
- * The current state of the query.
117
- *
118
- * **Warning!** This differs from the `state$` observable in that it does not use the query store. Thus, the response data might be outdated.
119
- * Use `state$` (or `firstValueFrom(state$)`) the most up-to-date data.
120
- */
121
- get rawState() {
122
- return this._state$.value;
123
- }
124
-
125
- get isExpired() {
126
- if (isQueryStateLoading(this.rawState)) {
127
- return false;
128
- }
129
-
130
- if (
131
- isQueryStatePrepared(this.rawState) ||
132
- isQueryStateCancelled(this.rawState) ||
133
- isQueryStateFailure(this.rawState)
134
- ) {
135
- return true;
136
- }
137
-
138
- const ts = this.rawState.meta.expiresAt;
139
-
140
- if (!ts) {
141
- return true;
142
- }
143
-
144
- return ts < Date.now();
145
- }
146
-
147
- get isInUse() {
148
- return this._state$.observed || Object.keys(this._dependents).length > 0;
149
- }
150
-
151
- /**
152
- * @internal
153
- */
154
- get _subscriberCount() {
155
- return this._state$.observers.length;
156
- }
157
-
158
- get isPolling() {
159
- return !!this._pollingSubscription;
160
- }
161
-
162
- get autoRefreshOnConfig() {
163
- const base = this._queryConfig.autoRefreshOn ?? {};
164
-
165
- const transformed: Readonly<QueryAutoRefreshConfig> = {
166
- queryClientDefaultHeadersChange: base.queryClientDefaultHeadersChange ?? true,
167
- windowFocus: base.windowFocus ?? true,
168
- };
169
-
170
- return transformed;
171
- }
172
-
173
- /**
174
- * @internal
175
- */
176
- get _enableSmartPolling() {
177
- return this._queryConfig.enableSmartPolling ?? true;
178
- }
179
-
180
- get store() {
181
- return this._queryConfig.entity?.store ?? null;
182
- }
183
-
184
- get canBeCached() {
185
- return shouldCacheQuery(this._queryConfig.method);
186
- }
187
-
188
- get _isInMockMode() {
189
- return !!this._arguments?.mock;
190
- }
191
-
192
- constructor(
193
- private readonly _client: QueryClient,
194
-
195
- /**
196
- * @internal
197
- */
198
- public readonly _queryConfig:
199
- | RestQueryConfig<Route, Response, Arguments, Store, Data, Id>
200
- | GqlQueryConfig<Route, Response, Arguments, Store, Data, Id>,
201
-
202
- /**
203
- * @internal
204
- */
205
- public readonly _routeWithParams: Route,
206
-
207
- /**
208
- * @internal
209
- */
210
- public readonly _arguments: Arguments,
211
-
212
- /**
213
- * @internal
214
- */
215
- public readonly _queryStoreKey: string,
216
- ) {}
217
-
218
- execute(options: ExecuteQueryOptions = {}) {
219
- const { skipCache = false, _triggeredVia: triggeredVia = 'program', cancelPrevious = false } = options;
220
- const { authProvider } = this._client;
221
- const queryConfig = this._queryConfig;
222
-
223
- if (!this.isExpired && !skipCache && isQueryStateSuccess(this.rawState)) {
224
- return this;
225
- }
226
-
227
- if (queryConfig.secure && !authProvider && !this._isInMockMode) {
228
- throw new Error('Cannot execute secure query without auth provider');
229
- }
230
-
231
- const id = this._nextId;
232
- const meta: QueryStateMeta = { id, triggeredVia };
233
-
234
- if (isQueryStateLoading(this.rawState)) {
235
- if (cancelPrevious) {
236
- this.abort();
237
- } else {
238
- return this;
239
- }
240
- }
241
-
242
- this._updateState({ type: QueryStateType.Loading, meta });
243
-
244
- if (this._isInMockMode) {
245
- this._mockRequest({}, meta, options);
246
- } else {
247
- let goSignal = of(true);
248
-
249
- if (
250
- authProvider &&
251
- isBearerAuthProvider(authProvider) &&
252
- queryConfig.secure &&
253
- !isQueryStateSuccess(authProvider.currentRefreshQuery?.rawState)
254
- ) {
255
- // On page load the query might be executed before the auth provider has been initialized.
256
- // In this case we need to wait for the auth provider to be ready before we can execute the query.
257
- goSignal = combineLatest([
258
- // The tokens might get set without a refresh query being created (e.g.) directly after login.
259
- authProvider.currentRefreshQuery$.pipe(switchQueryState(), takeUntilResponse()),
260
- authProvider.tokens$.pipe(take(1)),
261
- ]).pipe(
262
- takeUntil(this._onAbort$),
263
- filter(([state, tokens]) => {
264
- if (state) {
265
- return !isQueryStateLoading(state);
266
- }
267
-
268
- return !!tokens;
269
- }),
270
- tap(([state]) => {
271
- if (isQueryStateFailure(state)) {
272
- this._updateEntityState({ type: 'failure', error: state.error, headers: {} }, meta, options);
273
- }
274
- }),
275
- map(() => true),
276
- take(1),
277
- );
278
- }
279
-
280
- goSignal
281
- .pipe(
282
- switchMap(() => {
283
- const method = computeQueryMethod({ config: queryConfig, client: this._client });
284
- const body = computeQueryBody({ config: queryConfig, client: this._client, args: this._arguments, method });
285
- const headers = computeQueryHeaders({ client: this._client, config: queryConfig, args: this._arguments });
286
-
287
- return request<Response>({
288
- urlWithParams: this._routeWithParams as string,
289
- method,
290
- body,
291
- headers,
292
- reportProgress: queryConfig.reportProgress,
293
- responseType: queryConfig.responseType,
294
- withCredentials: queryConfig.withCredentials,
295
- cacheAdapter: this._client.config.request?.cacheAdapter,
296
- retryFn: this._client.config.request?.retryFn,
297
- }).pipe(
298
- tap((state) => this._updateEntityState(state, meta, options)),
299
- takeUntil(this._onAbort$),
300
- );
301
- }),
302
- )
303
-
304
- .subscribe();
305
- }
306
-
307
- return this;
308
- }
309
-
310
- abort() {
311
- if (!isQueryStateLoading(this.rawState)) {
312
- return this;
313
- }
314
-
315
- this._onAbort$.next();
316
-
317
- this._updateState({
318
- type: QueryStateType.Cancelled,
319
- meta: { id: this.rawState.meta.id, triggeredVia: this.rawState.meta.triggeredVia },
320
- });
321
-
322
- return this;
323
- }
324
-
325
- poll(config: PollConfig) {
326
- if (this._pollingSubscription) {
327
- return this;
328
- }
329
-
330
- this._currentPollConfig = config;
331
-
332
- const interval$ = interval(config.interval);
333
- const poll$ = interval$.pipe(
334
- skip(config.triggerImmediately ? 0 : 1),
335
- takeUntil(config.takeUntil),
336
- takeWhile(() => !this._isPollingPaused),
337
- filter(() => !isQueryStateLoading(this._state$.value)),
338
- );
339
-
340
- this._pollingSubscription = poll$.subscribe({
341
- next: () => this.execute({ skipCache: true, _triggeredVia: 'poll' }),
342
- complete: () => this.stopPolling(),
343
- });
344
-
345
- return this;
346
- }
347
-
348
- stopPolling() {
349
- this._pollingSubscription?.unsubscribe();
350
- this._pollingSubscription = null;
351
- this._currentPollConfig = null;
352
-
353
- return this;
354
- }
355
-
356
- pausePolling() {
357
- this._pollingSubscription?.unsubscribe();
358
- this._pollingSubscription = null;
359
-
360
- this._isPollingPaused = true;
361
-
362
- return this;
363
- }
364
-
365
- resumePolling() {
366
- if (!this._isPollingPaused || !this._currentPollConfig) {
367
- return this;
368
- }
369
-
370
- this._isPollingPaused = false;
371
-
372
- return this.poll({ ...this._currentPollConfig, triggerImmediately: true });
373
- }
374
-
375
- onSuccess(callback: (response: Data) => void) {
376
- this.state$.pipe(takeUntilResponse(), filterSuccess()).subscribe((state) => callback(state.response));
377
- return this;
378
- }
379
-
380
- onFailure(callback: (error: RequestError<unknown>) => void) {
381
- this.state$.pipe(takeUntilResponse(), filterFailure()).subscribe((state) => callback(state.error));
382
- return this;
383
- }
384
-
385
- private _getBearerAuthProvider() {
386
- const authProvider = this._client.authProvider;
387
-
388
- if (authProvider && isBearerAuthProvider(authProvider)) {
389
- return authProvider;
390
- }
391
-
392
- return null;
393
- }
394
-
395
- private _updateEntityState(
396
- requestEvent: RequestEvent<Response>,
397
- meta: QueryStateMeta,
398
- options?: ExecuteQueryOptions,
399
- ) {
400
- switch (requestEvent.type) {
401
- case 'start':
402
- case 'delay-retry': {
403
- const { type, retryDelay, retryNumber } = requestEvent;
404
- const newMeta: QueryStateMeta = { ...meta, isWaitingForRetry: type === 'delay-retry', retryDelay, retryNumber };
405
-
406
- this._updateState({
407
- type: QueryStateType.Loading,
408
- meta: newMeta,
409
- });
410
- break;
411
- }
412
-
413
- case 'upload-progress':
414
- case 'download-progress': {
415
- this._updateState({
416
- type: QueryStateType.Loading,
417
- progress: requestEvent.progress,
418
- partialText: 'partialText' in requestEvent ? requestEvent.partialText : undefined,
419
- meta,
420
- });
421
-
422
- break;
423
- }
424
-
425
- case 'success': {
426
- const { response, expiresInTimestamp } = requestEvent;
427
- const isGql = isGqlQueryConfig(this._queryConfig);
428
- const responseData =
429
- isGql && typeof response === 'object' && !!response && 'data' in response
430
- ? (response['data'] as Response)
431
- : (response as Response);
432
-
433
- if (this._queryConfig.entity && this._queryConfig.entity.set) {
434
- const id = this._queryConfig.entity?.id({ args: this._arguments, response: responseData });
435
-
436
- this._queryConfig.entity?.set({
437
- args: this._arguments,
438
- response: responseData,
439
- id,
440
- store: this._queryConfig.entity.store,
441
- });
442
- }
443
-
444
- this._updateState({
445
- type: QueryStateType.Success,
446
- response: responseData,
447
- meta: { ...meta, expiresAt: expiresInTimestamp },
448
- });
449
-
450
- break;
451
- }
452
-
453
- case 'failure': {
454
- const { error } = requestEvent;
455
- const failure = () => this._updateState({ type: QueryStateType.Failure, error, meta });
456
- const bearerAuthProvider = this._getBearerAuthProvider();
457
-
458
- if (
459
- !bearerAuthProvider ||
460
- options?._isUnauthorizedRetry ||
461
- error.status !== HttpStatusCode.Unauthorized ||
462
- !bearerAuthProvider.shouldRefreshOnUnauthorizedResponse
463
- ) {
464
- return failure();
465
- }
466
-
467
- const query = bearerAuthProvider._refreshQuery();
468
- if (!query) return failure();
469
-
470
- query.state$
471
- .pipe(
472
- takeUntilResponse(),
473
- takeUntil(this._onAbort$),
474
- tap((state) =>
475
- isQueryStateSuccess(state) ? this.execute({ ...options, _isUnauthorizedRetry: true }) : failure(),
476
- ),
477
- )
478
- .subscribe();
479
-
480
- break;
481
- }
482
-
483
- case 'cancel': {
484
- this._updateState({
485
- type: QueryStateType.Cancelled,
486
- meta,
487
- });
488
-
489
- break;
490
- }
491
- }
492
- }
493
-
494
- private _transformState(s: QueryState<Response>): Observable<QueryState<Data>> {
495
- if (!isQueryStateSuccess(s) || !this._queryConfig.entity?.get) {
496
- return of(s) as Observable<QueryState<Data>>;
497
- }
498
-
499
- const id = this._queryConfig.entity.id({ args: this._arguments, response: s.response });
500
-
501
- return this._queryConfig.entity
502
- .get({ args: this._arguments, id, response: s.response, store: this._queryConfig.entity.store })
503
- .pipe(map((v) => ({ ...s, response: v })));
504
- }
505
-
506
- private _updateState(s: QueryState<Response>) {
507
- // We need to use untracked here to avoid Angular's "allowSignalWrites is false" error when executing queries inside Angular's computed/effect signal functions.
508
- untracked(() => this._state$.next(s));
509
- }
510
-
511
- private _mockRequest(headers: RequestHeaders | undefined, meta: QueryStateMeta, options: ExecuteQueryOptions) {
512
- if (!this._arguments?.mock) return;
513
-
514
- const { delay = 200, error, response, retryIntoResponse = false, progress } = this._arguments.mock;
515
- const progressFileSize = progress?.fileSize ?? 1000000;
516
- const progressEventType = progress?.eventType ?? 'upload';
517
- const progressEventCount = progress?.eventCount ?? 5;
518
- const progressOmitTotal = progress?.omitTotal ?? false;
519
- const omitPartialText = progress?.omitPartialText ?? false;
520
-
521
- const finalResolveMock = () => {
522
- if (error) {
523
- this._updateEntityState({ error, headers: headers ?? {}, type: 'failure' }, meta, options);
524
- return;
525
- }
526
-
527
- this._updateEntityState(
528
- { response: response as Response, headers: headers ?? {}, type: 'success' },
529
- meta,
530
- options,
531
- );
532
- };
533
-
534
- if (progress) {
535
- interval(delay)
536
- .pipe(
537
- tap((a) => {
538
- if (a === progressEventCount + 1) {
539
- finalResolveMock();
540
- } else {
541
- const current = Math.min(progressFileSize * a, progressFileSize * progressEventCount);
542
- const percentage = (current / (progressFileSize * progressEventCount)) * 100;
543
-
544
- this._updateEntityState(
545
- {
546
- type: progressEventType === 'upload' ? 'upload-progress' : 'download-progress',
547
- headers: headers ?? {},
548
- progress: { current, ...(progressOmitTotal ? {} : { percentage, total: progressFileSize }) },
549
- partialText: omitPartialText ? undefined : `Partial text ${a}`,
550
- },
551
- meta,
552
- options,
553
- );
554
- }
555
- }),
556
- takeUntil(this._onAbort$),
557
- takeWhile((a) => a < progressEventCount + 1, true),
558
- )
559
- .subscribe();
560
- } else if (retryIntoResponse) {
561
- interval(delay)
562
- .pipe(
563
- tap((a) => {
564
- if (a === 3) {
565
- finalResolveMock();
566
- } else {
567
- const aModified = a + 1;
568
- this._updateEntityState(
569
- {
570
- type: 'delay-retry',
571
- headers: headers ?? {},
572
- retryDelay: 1000 + 1000 * aModified,
573
- retryNumber: aModified,
574
- },
575
- meta,
576
- options,
577
- );
578
- }
579
- }),
580
- takeUntil(this._onAbort$),
581
- takeWhile((a) => a < 3, true),
582
- )
583
- .subscribe();
584
- } else {
585
- timer(delay)
586
- .pipe(
587
- tap(() => finalResolveMock()),
588
- takeUntil(this._onAbort$),
589
- )
590
- .subscribe();
591
- }
592
- }
593
-
594
- /**
595
- * @internal
596
- */
597
- _addDependent(tNodeIndex: number) {
598
- if (!this._dependents[tNodeIndex]) {
599
- this._dependents[tNodeIndex] = 0;
600
- }
601
-
602
- this._dependents[tNodeIndex]++;
603
-
604
- this._dependentsChanged$.next(this._dependents);
605
- }
606
-
607
- /**
608
- * @internal
609
- */
610
- _removeDependent(tNodeIndex: number) {
611
- const count = this._dependents[tNodeIndex];
612
- if (count === undefined) {
613
- return;
614
- }
615
-
616
- this._dependents[tNodeIndex]--;
617
-
618
- if (count <= 1) {
619
- delete this._dependents[tNodeIndex];
620
- }
621
-
622
- this._dependentsChanged$.next(this._dependents);
623
- }
624
-
625
- /**
626
- * @internal
627
- */
628
- _hasDependents() {
629
- return Object.keys(this._dependents).length > 0;
630
- }
631
- }