@ethlete/query 0.1.0-next.9 → 1.0.1
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/esm2020/lib/auth/auth-provider.types.mjs +1 -1
- package/esm2020/lib/auth/auth-provider.utils.mjs +1 -1
- package/esm2020/lib/auth/basic-auth-provider.mjs +4 -5
- package/esm2020/lib/auth/bearer-auth-provider.mjs +117 -60
- package/esm2020/lib/auth/custom-header-auth-provider.mjs +4 -5
- package/esm2020/lib/directives/infinity-query-trigger.directive.mjs +3 -3
- package/esm2020/lib/directives/infinity-query.directive.mjs +7 -9
- package/esm2020/lib/directives/query.directive.mjs +23 -19
- package/esm2020/lib/gql/gql.mjs +2 -2
- package/esm2020/lib/infinite-query/infinity-query.mjs +15 -11
- package/esm2020/lib/query/query.mjs +111 -86
- package/esm2020/lib/query/query.types.mjs +1 -1
- package/esm2020/lib/query/query.utils.mjs +51 -4
- package/esm2020/lib/query-client/query-client.mjs +25 -13
- package/esm2020/lib/query-client/query-client.types.mjs +1 -1
- package/esm2020/lib/query-form/query-form.mjs +7 -6
- package/esm2020/lib/request/request.mjs +168 -19
- package/esm2020/lib/request/request.types.mjs +1 -1
- package/esm2020/lib/request/request.util.mjs +66 -91
- package/fesm2015/ethlete-query.mjs +673 -398
- package/fesm2015/ethlete-query.mjs.map +1 -1
- package/fesm2020/ethlete-query.mjs +657 -389
- package/fesm2020/ethlete-query.mjs.map +1 -1
- package/lib/auth/auth-provider.types.d.ts +30 -22
- package/lib/auth/auth-provider.utils.d.ts +2 -1
- package/lib/auth/basic-auth-provider.d.ts +0 -2
- package/lib/auth/bearer-auth-provider.d.ts +14 -14
- package/lib/auth/custom-header-auth-provider.d.ts +0 -2
- package/lib/directives/infinity-query.directive.d.ts +1 -2
- package/lib/directives/query.directive.d.ts +6 -5
- package/lib/gql/gql.d.ts +5 -1
- package/lib/infinite-query/infinity-query.types.d.ts +4 -4
- package/lib/query/query.d.ts +6 -6
- package/lib/query/query.types.d.ts +78 -43
- package/lib/query/query.utils.d.ts +21 -5
- package/lib/query-client/query-client.d.ts +13 -11
- package/lib/query-client/query-client.types.d.ts +22 -10
- package/lib/query-form/query-form.types.d.ts +2 -2
- package/lib/request/request.d.ts +3 -9
- package/lib/request/request.types.d.ts +63 -15
- package/lib/request/request.util.d.ts +74 -7
- package/package.json +2 -5
|
@@ -1,40 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCookie, setCookie, deleteCookie, DestroyService, equal, clone } from '@ethlete/core';
|
|
2
|
+
import { Observable, filter, takeWhile, switchMap, of, BehaviorSubject, Subject, takeUntil, interval, tap, timer, fromEvent, startWith, concat, take, debounceTime, combineLatest, map, distinctUntilChanged } from 'rxjs';
|
|
2
3
|
import * as i0 from '@angular/core';
|
|
3
4
|
import { Directive, Input, InjectionToken, inject, ChangeDetectorRef, ViewContainerRef, TemplateRef, ErrorHandler, ElementRef } from '@angular/core';
|
|
4
|
-
import * as i1 from '@ethlete/core';
|
|
5
|
-
import { DestroyDirective } from '@ethlete/core';
|
|
6
5
|
import { FormGroup } from '@angular/forms';
|
|
7
6
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
8
7
|
|
|
9
8
|
class CustomHeaderAuthProvider {
|
|
10
|
-
constructor(_config) {
|
|
11
|
-
this._config = _config;
|
|
12
|
-
this.queryClient = null;
|
|
13
|
-
}
|
|
14
9
|
get header() {
|
|
15
10
|
return { [this._config.name]: this._config.value };
|
|
16
11
|
}
|
|
12
|
+
constructor(_config) {
|
|
13
|
+
this._config = _config;
|
|
14
|
+
}
|
|
17
15
|
cleanUp() {
|
|
18
16
|
// noop
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
class BasicAuthProvider {
|
|
23
|
-
constructor(_config) {
|
|
24
|
-
this._config = _config;
|
|
25
|
-
this.queryClient = null;
|
|
26
|
-
}
|
|
27
21
|
get header() {
|
|
28
22
|
return { Authorization: `Basic ${this._basicAuthString}` };
|
|
29
23
|
}
|
|
30
24
|
get _basicAuthString() {
|
|
31
25
|
return btoa(`${this._config.username}:${this._config.password}`);
|
|
32
26
|
}
|
|
27
|
+
constructor(_config) {
|
|
28
|
+
this._config = _config;
|
|
29
|
+
}
|
|
33
30
|
cleanUp() {
|
|
34
31
|
// noop
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
|
|
35
|
+
const getOpName = /(query|mutation) ?([\w\d-_]+)? ?\(.*?\)? \{/;
|
|
36
|
+
const transformGql = (str) => {
|
|
37
|
+
str = Array.isArray(str) ? str.join('') : str;
|
|
38
|
+
const name = getOpName.exec(str);
|
|
39
|
+
return function (variables) {
|
|
40
|
+
const data = { query: str };
|
|
41
|
+
if (variables)
|
|
42
|
+
data['variables'] = JSON.stringify(variables);
|
|
43
|
+
if (name && name.length) {
|
|
44
|
+
const operationName = name[2];
|
|
45
|
+
if (operationName)
|
|
46
|
+
data['operationName'] = name[2];
|
|
47
|
+
}
|
|
48
|
+
return data;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const gql = (strings, ...values) => {
|
|
52
|
+
const str = strings.reduce((acc, cur, i) => {
|
|
53
|
+
return acc + cur + (values[i] || '');
|
|
54
|
+
}, '');
|
|
55
|
+
return str;
|
|
56
|
+
};
|
|
57
|
+
|
|
38
58
|
const buildErrorMessage = (code, message) => `[@ethlete\\query:${code}] ${message}`;
|
|
39
59
|
class QueryError extends Error {
|
|
40
60
|
constructor(code, message, data) {
|
|
@@ -52,7 +72,6 @@ const queryStateCannotTransformError = (data) => new QueryError('006', 'The quer
|
|
|
52
72
|
const invalidBodyError = (data) => new QueryError('007', 'The body is not valid or upsupported', data);
|
|
53
73
|
|
|
54
74
|
const isRequestError = (error) => error instanceof Object && 'code' in error && 'message' in error;
|
|
55
|
-
const isAbortRequestError = (error) => isRequestError(error) && error.code === -1;
|
|
56
75
|
const buildRoute = (options) => {
|
|
57
76
|
if (options.base.endsWith('/')) {
|
|
58
77
|
throw invalidBaseRouteError(options.base);
|
|
@@ -125,9 +144,9 @@ const isParamValid = (primitive) => {
|
|
|
125
144
|
return true;
|
|
126
145
|
};
|
|
127
146
|
const extractExpiresInSeconds = (headers) => {
|
|
128
|
-
const cacheControl = headers
|
|
129
|
-
const age = headers
|
|
130
|
-
const expires = headers
|
|
147
|
+
const cacheControl = headers['cache-control'];
|
|
148
|
+
const age = headers['age'];
|
|
149
|
+
const expires = headers['expires'];
|
|
131
150
|
// In seconds
|
|
132
151
|
let expiresIn = null;
|
|
133
152
|
let maxAge = null;
|
|
@@ -166,91 +185,21 @@ const buildTimestampFromSeconds = (seconds) => {
|
|
|
166
185
|
}
|
|
167
186
|
return new Date(Date.now() + seconds * 1000).getTime();
|
|
168
187
|
};
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
const err = {
|
|
172
|
-
code: -1,
|
|
173
|
-
message: 'Request aborted',
|
|
174
|
-
detail: null,
|
|
175
|
-
raw: error,
|
|
176
|
-
route,
|
|
177
|
-
requestInit,
|
|
178
|
-
};
|
|
179
|
-
return err;
|
|
180
|
-
}
|
|
181
|
-
if (error instanceof SyntaxError) {
|
|
182
|
-
const err = {
|
|
183
|
-
code: -3,
|
|
184
|
-
message: 'Syntax error',
|
|
185
|
-
detail: null,
|
|
186
|
-
raw: error,
|
|
187
|
-
route,
|
|
188
|
-
requestInit,
|
|
189
|
-
};
|
|
190
|
-
return err;
|
|
191
|
-
}
|
|
192
|
-
if (error instanceof Error) {
|
|
193
|
-
const err = {
|
|
194
|
-
code: -2,
|
|
195
|
-
message: `${error.name}: ${error.message}`,
|
|
196
|
-
detail: null,
|
|
197
|
-
raw: error,
|
|
198
|
-
route,
|
|
199
|
-
requestInit,
|
|
200
|
-
};
|
|
201
|
-
return err;
|
|
202
|
-
}
|
|
203
|
-
if (isFetchResponse(error)) {
|
|
204
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
205
|
-
let detail = null;
|
|
206
|
-
try {
|
|
207
|
-
detail = await error.json();
|
|
208
|
-
}
|
|
209
|
-
catch {
|
|
210
|
-
// noop
|
|
211
|
-
}
|
|
212
|
-
if (!detail) {
|
|
213
|
-
try {
|
|
214
|
-
detail = await error.text();
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
// noop
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
const err = {
|
|
221
|
-
code: error.status,
|
|
222
|
-
message: error.statusText,
|
|
223
|
-
detail,
|
|
224
|
-
raw: error,
|
|
225
|
-
route,
|
|
226
|
-
requestInit,
|
|
227
|
-
};
|
|
228
|
-
return err;
|
|
229
|
-
}
|
|
230
|
-
const err = {
|
|
231
|
-
code: 0,
|
|
232
|
-
message: 'Unknown error',
|
|
233
|
-
detail: null,
|
|
234
|
-
raw: error,
|
|
235
|
-
route,
|
|
236
|
-
requestInit,
|
|
237
|
-
};
|
|
238
|
-
return err;
|
|
239
|
-
};
|
|
240
|
-
const buildBody = (body) => {
|
|
241
|
-
if (body === undefined || body === null) {
|
|
188
|
+
const serializeBody = (body) => {
|
|
189
|
+
if (body === null || body === undefined) {
|
|
242
190
|
return null;
|
|
243
191
|
}
|
|
244
|
-
if (
|
|
192
|
+
if (body instanceof ArrayBuffer ||
|
|
193
|
+
body instanceof Blob ||
|
|
194
|
+
body instanceof FormData ||
|
|
195
|
+
body instanceof URLSearchParams ||
|
|
196
|
+
typeof body === 'string') {
|
|
245
197
|
return body;
|
|
246
198
|
}
|
|
247
|
-
if (typeof body === 'object') {
|
|
199
|
+
if (typeof body === 'object' || typeof body === 'boolean' || Array.isArray(body)) {
|
|
248
200
|
return JSON.stringify(body);
|
|
249
201
|
}
|
|
250
|
-
|
|
251
|
-
return body;
|
|
252
|
-
}
|
|
253
|
-
throw invalidBodyError(body);
|
|
202
|
+
return body.toString();
|
|
254
203
|
};
|
|
255
204
|
const transformMethod = (method) => {
|
|
256
205
|
if (method === 'GQL_QUERY' || method === 'GQL_MUTATE') {
|
|
@@ -258,192 +207,236 @@ const transformMethod = (method) => {
|
|
|
258
207
|
}
|
|
259
208
|
return method;
|
|
260
209
|
};
|
|
261
|
-
const
|
|
262
|
-
|
|
210
|
+
const detectContentTypeHeader = (body) => {
|
|
211
|
+
// An empty body has no content type.
|
|
212
|
+
if (body === null) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
// FormData bodies rely on the browser's content type assignment.
|
|
216
|
+
if (body instanceof FormData) {
|
|
263
217
|
return null;
|
|
264
218
|
}
|
|
219
|
+
// Blobs usually have their own content type. If it doesn't, then
|
|
220
|
+
// no type can be inferred.
|
|
221
|
+
if (body instanceof Blob) {
|
|
222
|
+
return body.type || null;
|
|
223
|
+
}
|
|
224
|
+
// Array buffers have unknown contents and thus no type can be inferred.
|
|
225
|
+
if (body instanceof ArrayBuffer) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
// Technically, strings could be a form of JSON data, but it's safe enough
|
|
229
|
+
// to assume they're plain strings.
|
|
265
230
|
if (typeof body === 'string') {
|
|
266
231
|
return 'text/plain';
|
|
267
232
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
if (typeof body === 'object') {
|
|
233
|
+
// Arrays, objects, boolean and numbers will be encoded as JSON.
|
|
234
|
+
if (typeof body === 'object' || typeof body === 'number' || typeof body === 'boolean') {
|
|
272
235
|
return 'application/json';
|
|
273
236
|
}
|
|
237
|
+
// No type could be inferred.
|
|
274
238
|
return null;
|
|
275
239
|
};
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
try {
|
|
279
|
-
const response = await fetch(options.route, options.init);
|
|
280
|
-
if (!response.ok) {
|
|
281
|
-
throw response;
|
|
282
|
-
}
|
|
283
|
-
const isJsonResponse = response.headers.get('Content-Type')?.includes('application/json');
|
|
284
|
-
const isTextResponse = response.headers.get('Content-Type')?.includes('text/plain');
|
|
285
|
-
const data = (isJsonResponse ? await response.json() : isTextResponse ? await response.text() : null);
|
|
286
|
-
const expiresInSeconds = options.cacheAdapter
|
|
287
|
-
? options.cacheAdapter(response.headers)
|
|
288
|
-
: extractExpiresInSeconds(response.headers);
|
|
289
|
-
const expiresInTimestamp = buildTimestampFromSeconds(expiresInSeconds);
|
|
290
|
-
return { data, expiresInTimestamp };
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
throw await buildRequestError(error, options.route, options.init);
|
|
294
|
-
}
|
|
240
|
+
const hasHeader = (headers, header) => {
|
|
241
|
+
return Object.keys(headers).some((key) => key.toLowerCase() === header.toLowerCase());
|
|
295
242
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const decryptBearer = (token) => {
|
|
301
|
-
try {
|
|
302
|
-
const base64Url = token.split('.')[1];
|
|
303
|
-
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
304
|
-
const jsonPayload = decodeURIComponent(atob(base64)
|
|
305
|
-
.split('')
|
|
306
|
-
.map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
|
|
307
|
-
.join(''));
|
|
308
|
-
return JSON.parse(jsonPayload);
|
|
309
|
-
}
|
|
310
|
-
catch (error) {
|
|
311
|
-
console.error(`Invalid bearer token: ${token}`, error);
|
|
312
|
-
return null;
|
|
313
|
-
}
|
|
243
|
+
const forEachHeader = (headers, callback) => {
|
|
244
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
245
|
+
callback(key, value);
|
|
246
|
+
});
|
|
314
247
|
};
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this._token = _config.token;
|
|
326
|
-
this._refreshToken = _config.refreshConfig?.token ?? null;
|
|
327
|
-
if (this._config.refreshConfig) {
|
|
328
|
-
this._setupRefresh(this._config.refreshConfig);
|
|
248
|
+
const parseAllXhrResponseHeaders = (xhr) => {
|
|
249
|
+
const headers = xhr.getAllResponseHeaders();
|
|
250
|
+
const parsedHeaders = {};
|
|
251
|
+
for (const line of headers.split('\n')) {
|
|
252
|
+
const index = line.indexOf(':');
|
|
253
|
+
if (index > 0) {
|
|
254
|
+
const name = line.slice(0, index);
|
|
255
|
+
const key = name.toLowerCase();
|
|
256
|
+
const value = line.slice(index + 1).trim();
|
|
257
|
+
parsedHeaders[key] = value;
|
|
329
258
|
}
|
|
330
259
|
}
|
|
331
|
-
|
|
332
|
-
|
|
260
|
+
return parsedHeaders;
|
|
261
|
+
};
|
|
262
|
+
const getResponseUrl = (xhr) => {
|
|
263
|
+
if ('responseURL' in xhr && xhr.responseURL) {
|
|
264
|
+
return xhr.responseURL;
|
|
333
265
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
this._refreshTimerSubscription = null;
|
|
266
|
+
if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
|
|
267
|
+
return xhr.getResponseHeader('X-Request-URL');
|
|
337
268
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
case "beforeExpiration" /* AuthBearerRefreshStrategy.BeforeExpiration */:
|
|
353
|
-
this._refreshTimerSubscription = timer(remainingTime).subscribe(() => this._refresh(config));
|
|
354
|
-
break;
|
|
269
|
+
return null;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const XSSI_PREFIX = /^\)\]\}',?\n/;
|
|
273
|
+
const request = (config) => {
|
|
274
|
+
const headers = config.headers || {};
|
|
275
|
+
const responseType = config.responseType || 'json';
|
|
276
|
+
const body = config.body || null;
|
|
277
|
+
const url = config.urlWithParams.split('?')[0];
|
|
278
|
+
return new Observable((observer) => {
|
|
279
|
+
const xhr = new XMLHttpRequest();
|
|
280
|
+
xhr.open(config.method, config.urlWithParams);
|
|
281
|
+
if (config.withCredentials) {
|
|
282
|
+
xhr.withCredentials = true;
|
|
355
283
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
throw new Error('No refresh token found');
|
|
284
|
+
forEachHeader(headers, (name, value) => xhr.setRequestHeader(name, value));
|
|
285
|
+
if (!hasHeader(headers, 'Accept')) {
|
|
286
|
+
xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
|
|
360
287
|
}
|
|
361
|
-
if (!
|
|
362
|
-
|
|
288
|
+
if (!hasHeader(headers, 'Content-Type')) {
|
|
289
|
+
const detectedType = detectContentTypeHeader(body);
|
|
290
|
+
if (detectedType) {
|
|
291
|
+
xhr.setRequestHeader('Content-Type', detectedType);
|
|
292
|
+
}
|
|
363
293
|
}
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const requestInit = { body: buildBody(body), method };
|
|
371
|
-
this.onRefreshInitiation$.next();
|
|
372
|
-
try {
|
|
373
|
-
const result = await request({
|
|
374
|
-
route: fullRoute,
|
|
375
|
-
init: requestInit,
|
|
376
|
-
});
|
|
377
|
-
const tokens = responseAdapter ? responseAdapter(result.data) : result.data;
|
|
378
|
-
if (!tokens.token) {
|
|
379
|
-
throw new Error('Token not found in response');
|
|
294
|
+
xhr.responseType = responseType !== 'json' ? responseType : 'text';
|
|
295
|
+
const reqBody = serializeBody(body);
|
|
296
|
+
let headerResponse = null;
|
|
297
|
+
const partialFromXhr = () => {
|
|
298
|
+
if (headerResponse !== null) {
|
|
299
|
+
return headerResponse;
|
|
380
300
|
}
|
|
381
|
-
|
|
382
|
-
|
|
301
|
+
const statusText = xhr.statusText || 'OK';
|
|
302
|
+
const headers = parseAllXhrResponseHeaders(xhr);
|
|
303
|
+
const _url = getResponseUrl(xhr) || url;
|
|
304
|
+
headerResponse = { headers, status: xhr.status, statusText, url: _url };
|
|
305
|
+
return headerResponse;
|
|
306
|
+
};
|
|
307
|
+
const onLoad = () => {
|
|
308
|
+
const { headers, statusText, url } = partialFromXhr();
|
|
309
|
+
let { status } = partialFromXhr();
|
|
310
|
+
let body = null;
|
|
311
|
+
if (status !== 204 /* HttpStatusCode.NoContent */) {
|
|
312
|
+
body = typeof xhr.response === 'undefined' ? xhr.responseText : xhr.response;
|
|
383
313
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
314
|
+
if (status === 0) {
|
|
315
|
+
status = body ? 200 /* HttpStatusCode.Ok */ : 0;
|
|
316
|
+
}
|
|
317
|
+
let ok = status >= 200 && status < 300;
|
|
318
|
+
if (responseType === 'json' && typeof body === 'string') {
|
|
319
|
+
const originalBody = body;
|
|
320
|
+
body = body.replace(XSSI_PREFIX, '');
|
|
321
|
+
try {
|
|
322
|
+
body = body !== '' ? JSON.parse(body) : null;
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
body = originalBody;
|
|
326
|
+
if (ok) {
|
|
327
|
+
ok = false;
|
|
328
|
+
body = { error, text: body };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (ok) {
|
|
333
|
+
const successEvent = {
|
|
334
|
+
type: 'success',
|
|
335
|
+
headers,
|
|
336
|
+
response: body,
|
|
337
|
+
};
|
|
338
|
+
const expiresInSeconds = config.cacheAdapter?.(headers) ?? extractExpiresInSeconds(headers);
|
|
339
|
+
const expiresInTimestamp = buildTimestampFromSeconds(expiresInSeconds);
|
|
340
|
+
if (expiresInTimestamp) {
|
|
341
|
+
successEvent.expiresInTimestamp = expiresInTimestamp;
|
|
342
|
+
}
|
|
343
|
+
observer.next(successEvent);
|
|
344
|
+
observer.complete();
|
|
391
345
|
}
|
|
392
346
|
else {
|
|
393
|
-
|
|
347
|
+
observer.next({
|
|
348
|
+
type: 'failure',
|
|
349
|
+
headers,
|
|
350
|
+
error: {
|
|
351
|
+
url,
|
|
352
|
+
detail: body,
|
|
353
|
+
status,
|
|
354
|
+
statusText,
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
observer.complete();
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
const onError = (error) => {
|
|
361
|
+
const { url, headers } = partialFromXhr();
|
|
362
|
+
observer.next({
|
|
363
|
+
type: 'failure',
|
|
364
|
+
headers,
|
|
365
|
+
error: {
|
|
366
|
+
url,
|
|
367
|
+
detail: error,
|
|
368
|
+
status: xhr.status || 0,
|
|
369
|
+
statusText: xhr.statusText || 'Unknown Error',
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
observer.complete();
|
|
373
|
+
};
|
|
374
|
+
const onDownProgress = (event) => {
|
|
375
|
+
const { headers } = partialFromXhr();
|
|
376
|
+
const progress = {
|
|
377
|
+
type: 'download-progress',
|
|
378
|
+
headers,
|
|
379
|
+
progress: {
|
|
380
|
+
current: event.loaded,
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
if (event.lengthComputable) {
|
|
384
|
+
const progressPercent = (event.loaded / event.total) * 100;
|
|
385
|
+
progress.progress.percentage = Math.round(progressPercent * 100) / 100;
|
|
386
|
+
progress.progress.total = event.total;
|
|
387
|
+
}
|
|
388
|
+
if (responseType === 'text' && !!xhr.responseText) {
|
|
389
|
+
progress.partialText = xhr.responseText;
|
|
390
|
+
}
|
|
391
|
+
observer.next(progress);
|
|
392
|
+
};
|
|
393
|
+
const onUpProgress = (event) => {
|
|
394
|
+
const { headers } = partialFromXhr();
|
|
395
|
+
const progress = {
|
|
396
|
+
type: 'upload-progress',
|
|
397
|
+
headers,
|
|
398
|
+
progress: {
|
|
399
|
+
current: event.loaded,
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
if (event.lengthComputable) {
|
|
403
|
+
const progressPercent = (event.loaded / event.total) * 100;
|
|
404
|
+
progress.progress.percentage = Math.round(progressPercent * 100) / 100;
|
|
405
|
+
progress.progress.total = event.total;
|
|
406
|
+
}
|
|
407
|
+
observer.next(progress);
|
|
408
|
+
};
|
|
409
|
+
xhr.addEventListener('load', onLoad);
|
|
410
|
+
xhr.addEventListener('error', onError);
|
|
411
|
+
xhr.addEventListener('timeout', onError);
|
|
412
|
+
xhr.addEventListener('abort', onError);
|
|
413
|
+
if (config.reportProgress) {
|
|
414
|
+
xhr.addEventListener('progress', onDownProgress);
|
|
415
|
+
if (reqBody !== null && xhr.upload) {
|
|
416
|
+
xhr.upload.addEventListener('progress', onUpProgress);
|
|
394
417
|
}
|
|
395
418
|
}
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
};
|
|
415
|
-
const gql = (strings, ...values) => {
|
|
416
|
-
const str = strings.reduce((acc, cur, i) => {
|
|
417
|
-
return acc + cur + (values[i] || '');
|
|
418
|
-
}, '');
|
|
419
|
-
return str;
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
const deepFreeze = (object) => {
|
|
423
|
-
// check if object is actually an object or frozen
|
|
424
|
-
if (!object || typeof object !== 'object' || Object.isFrozen(object)) {
|
|
425
|
-
return object;
|
|
426
|
-
}
|
|
427
|
-
// Retrieve the property names defined on object
|
|
428
|
-
const propNames = Object.getOwnPropertyNames(object);
|
|
429
|
-
// Freeze properties before freezing self
|
|
430
|
-
for (const name of propNames) {
|
|
431
|
-
const value = object[name];
|
|
432
|
-
if (value && typeof value === 'object') {
|
|
433
|
-
deepFreeze(value);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return Object.freeze(object);
|
|
419
|
+
xhr.send(reqBody);
|
|
420
|
+
observer.next({ type: 'start', headers });
|
|
421
|
+
return () => {
|
|
422
|
+
xhr.removeEventListener('error', onError);
|
|
423
|
+
xhr.removeEventListener('abort', onError);
|
|
424
|
+
xhr.removeEventListener('load', onLoad);
|
|
425
|
+
xhr.removeEventListener('timeout', onError);
|
|
426
|
+
if (config.reportProgress) {
|
|
427
|
+
xhr.removeEventListener('progress', onDownProgress);
|
|
428
|
+
if (reqBody !== null && xhr.upload) {
|
|
429
|
+
xhr.upload.removeEventListener('progress', onUpProgress);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (xhr.readyState !== xhr.DONE) {
|
|
433
|
+
xhr.abort();
|
|
434
|
+
}
|
|
435
|
+
observer.next({ type: 'cancel', headers });
|
|
436
|
+
};
|
|
437
|
+
});
|
|
437
438
|
};
|
|
438
439
|
|
|
439
|
-
/**
|
|
440
|
-
* Dummy function for providing types while not breaking inference.
|
|
441
|
-
* **This function always returns null.**
|
|
442
|
-
* @see https://github.com/microsoft/TypeScript/issues/26242
|
|
443
|
-
* @returns null
|
|
444
|
-
*/
|
|
445
|
-
const def = () => null;
|
|
446
|
-
|
|
447
440
|
function filterSuccess() {
|
|
448
441
|
return function (source) {
|
|
449
442
|
return source.pipe(filter((value) => isQueryStateSuccess(value)));
|
|
@@ -454,9 +447,34 @@ function filterFailure() {
|
|
|
454
447
|
return source.pipe(filter((value) => isQueryStateFailure(value)));
|
|
455
448
|
};
|
|
456
449
|
}
|
|
457
|
-
function
|
|
450
|
+
function filterQueryStates(allowedStates) {
|
|
458
451
|
return function (source) {
|
|
459
|
-
return source.pipe(
|
|
452
|
+
return source.pipe(filter((value) => value && allowedStates.includes(value.type)));
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
function takeUntilResponse(config) {
|
|
456
|
+
return function (source) {
|
|
457
|
+
return source.pipe(takeWhile((value) => {
|
|
458
|
+
if (config?.excludeNull && value === null) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
return isQueryStateLoading(value) || value === null;
|
|
462
|
+
}, true));
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function filterNull() {
|
|
466
|
+
return function (source) {
|
|
467
|
+
return source.pipe(filter((value) => value !== null));
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function switchQueryState() {
|
|
471
|
+
return function (source) {
|
|
472
|
+
return source.pipe(switchMap((value) => value?.state$ ?? of(null)));
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function switchQueryCollectionState() {
|
|
476
|
+
return function (source) {
|
|
477
|
+
return source.pipe(switchMap((value) => value?.query.state$ ?? of(null)));
|
|
460
478
|
};
|
|
461
479
|
}
|
|
462
480
|
const isQueryStateLoading = (state) => state?.type === "LOADING" /* QueryStateType.Loading */;
|
|
@@ -484,23 +502,32 @@ const isGqlQueryConfig = (config) => {
|
|
|
484
502
|
}
|
|
485
503
|
return true;
|
|
486
504
|
};
|
|
505
|
+
const isQuery = (query) => {
|
|
506
|
+
if (!query || typeof query !== 'object' || Array.isArray(query)) {
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
if (!('state$' in query)) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
return true;
|
|
513
|
+
};
|
|
514
|
+
const createQueryCollection = (
|
|
515
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
516
|
+
queryMap) => new BehaviorSubject(null);
|
|
517
|
+
const extractQuery = (v) => (isQuery(v) ? v : v?.query) ?? null;
|
|
518
|
+
const getDefaultHeaders = (headers, method) => {
|
|
519
|
+
if (!headers) {
|
|
520
|
+
return {};
|
|
521
|
+
}
|
|
522
|
+
if (method in headers) {
|
|
523
|
+
return (headers[method] ?? {});
|
|
524
|
+
}
|
|
525
|
+
return headers;
|
|
526
|
+
};
|
|
487
527
|
|
|
488
528
|
class Query {
|
|
489
|
-
constructor(_client, _queryConfig, _route, _args) {
|
|
490
|
-
this._client = _client;
|
|
491
|
-
this._queryConfig = _queryConfig;
|
|
492
|
-
this._route = _route;
|
|
493
|
-
this._args = _args;
|
|
494
|
-
this._currentId = 0;
|
|
495
|
-
this._abortController = new AbortController();
|
|
496
|
-
this._pollingSubscription = null;
|
|
497
|
-
this._state$ = new BehaviorSubject({
|
|
498
|
-
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
499
|
-
meta: { id: this._currentId },
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
529
|
get _nextId() {
|
|
503
|
-
return this._currentId
|
|
530
|
+
return ++this._currentId;
|
|
504
531
|
}
|
|
505
532
|
get state$() {
|
|
506
533
|
return this._state$.asObservable();
|
|
@@ -518,6 +545,19 @@ class Query {
|
|
|
518
545
|
}
|
|
519
546
|
return ts < Date.now();
|
|
520
547
|
}
|
|
548
|
+
constructor(_client, _queryConfig, _routeWithParams, _args) {
|
|
549
|
+
this._client = _client;
|
|
550
|
+
this._queryConfig = _queryConfig;
|
|
551
|
+
this._routeWithParams = _routeWithParams;
|
|
552
|
+
this._args = _args;
|
|
553
|
+
this._currentId = 0;
|
|
554
|
+
this._pollingSubscription = null;
|
|
555
|
+
this._onAbort$ = new Subject();
|
|
556
|
+
this._state$ = new BehaviorSubject({
|
|
557
|
+
type: "PREPARED" /* QueryStateType.Prepared */,
|
|
558
|
+
meta: { id: this._currentId },
|
|
559
|
+
});
|
|
560
|
+
}
|
|
521
561
|
clone() {
|
|
522
562
|
return this._client.fetch(this._queryConfig);
|
|
523
563
|
}
|
|
@@ -532,22 +572,20 @@ class Query {
|
|
|
532
572
|
if (isQueryStateLoading(this._state$.value)) {
|
|
533
573
|
this.abort();
|
|
534
574
|
}
|
|
535
|
-
const meta =
|
|
575
|
+
const meta = { id };
|
|
536
576
|
this._state$.next({
|
|
537
577
|
type: "LOADING" /* QueryStateType.Loading */,
|
|
538
578
|
meta,
|
|
539
579
|
});
|
|
540
|
-
|
|
541
|
-
let
|
|
580
|
+
this._updateUseResultInDependencies();
|
|
581
|
+
let body;
|
|
542
582
|
if (isGqlQueryConfig(this._queryConfig)) {
|
|
543
583
|
const queryTemplate = this._queryConfig.query;
|
|
544
584
|
const query = transformGql(queryTemplate);
|
|
545
|
-
contentType = 'application/json';
|
|
546
585
|
body = query(this._args?.variables);
|
|
547
586
|
}
|
|
548
587
|
else {
|
|
549
|
-
body =
|
|
550
|
-
contentType = guessContentType(this._args?.body);
|
|
588
|
+
body = this._args?.body;
|
|
551
589
|
}
|
|
552
590
|
let authHeader = null;
|
|
553
591
|
if (this._queryConfig.secure) {
|
|
@@ -561,57 +599,83 @@ class Query {
|
|
|
561
599
|
authHeader = this._client.authProvider.header;
|
|
562
600
|
}
|
|
563
601
|
}
|
|
564
|
-
let headers = mergeHeaders(authHeader, this._args?.headers);
|
|
565
|
-
if (contentType && !headers?.['Content-Type'] && !headers?.['content-type']) {
|
|
566
|
-
if (headers) {
|
|
567
|
-
headers['Content-Type'] = contentType;
|
|
568
|
-
}
|
|
569
|
-
else {
|
|
570
|
-
headers = {
|
|
571
|
-
'Content-Type': contentType,
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
602
|
request({
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
body,
|
|
581
|
-
headers: headers || undefined,
|
|
582
|
-
},
|
|
603
|
+
urlWithParams: this._routeWithParams,
|
|
604
|
+
method: transformMethod(this._queryConfig.method),
|
|
605
|
+
body,
|
|
606
|
+
headers: mergeHeaders(getDefaultHeaders(this._client.config.request?.headers, this._queryConfig.method), authHeader, this._args?.headers) || undefined,
|
|
583
607
|
cacheAdapter: this._client.config.request?.cacheAdapter,
|
|
608
|
+
reportProgress: this._queryConfig.reportProgress,
|
|
609
|
+
responseType: this._queryConfig.responseType,
|
|
610
|
+
withCredentials: this._queryConfig.withCredentials,
|
|
584
611
|
})
|
|
585
|
-
.
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
612
|
+
.pipe(takeUntil(this._onAbort$))
|
|
613
|
+
.subscribe({
|
|
614
|
+
next: (state) => {
|
|
615
|
+
if (state.type === 'start') {
|
|
616
|
+
this._state$.next({
|
|
617
|
+
type: "LOADING" /* QueryStateType.Loading */,
|
|
618
|
+
meta,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
else if (state.type === 'download-progress') {
|
|
622
|
+
this._state$.next({
|
|
623
|
+
type: "LOADING" /* QueryStateType.Loading */,
|
|
624
|
+
progress: state.progress,
|
|
625
|
+
partialText: state.partialText,
|
|
626
|
+
meta,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
else if (state.type === 'upload-progress') {
|
|
630
|
+
this._state$.next({
|
|
631
|
+
type: "LOADING" /* QueryStateType.Loading */,
|
|
632
|
+
progress: state.progress,
|
|
633
|
+
meta,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
else if (state.type === 'success') {
|
|
637
|
+
const isResponseObject = typeof state.response === 'object';
|
|
638
|
+
const isGql = isGqlQueryConfig(this._queryConfig);
|
|
639
|
+
let responseData = null;
|
|
640
|
+
if (isGql &&
|
|
641
|
+
isResponseObject &&
|
|
642
|
+
!!state.response &&
|
|
643
|
+
typeof state.response === 'object' &&
|
|
644
|
+
'data' in state.response) {
|
|
645
|
+
responseData = state.response['data'];
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
responseData = state.response;
|
|
649
|
+
}
|
|
650
|
+
const transformedResponse = this._queryConfig.responseTransformer
|
|
651
|
+
? this._queryConfig.responseTransformer(responseData)
|
|
652
|
+
: responseData;
|
|
653
|
+
this._state$.next({
|
|
654
|
+
type: "SUCCESS" /* QueryStateType.Success */,
|
|
655
|
+
rawResponse: state.response,
|
|
656
|
+
response: transformedResponse,
|
|
657
|
+
meta: { ...meta, expiresAt: state.expiresInTimestamp },
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
else if (state.type === 'failure') {
|
|
661
|
+
this._state$.next({
|
|
662
|
+
type: "FAILURE" /* QueryStateType.Failure */,
|
|
663
|
+
error: state.error,
|
|
664
|
+
meta,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
else if (state.type === 'cancel') {
|
|
668
|
+
this._state$.next({
|
|
669
|
+
type: "CANCELLED" /* QueryStateType.Cancelled */,
|
|
670
|
+
meta,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
});
|
|
610
675
|
return this;
|
|
611
676
|
}
|
|
612
677
|
abort() {
|
|
613
|
-
this.
|
|
614
|
-
this._abortController = new AbortController();
|
|
678
|
+
this._onAbort$.next();
|
|
615
679
|
return this;
|
|
616
680
|
}
|
|
617
681
|
poll(config) {
|
|
@@ -628,27 +692,200 @@ class Query {
|
|
|
628
692
|
this._pollingSubscription = null;
|
|
629
693
|
return this;
|
|
630
694
|
}
|
|
631
|
-
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
type: "CANCELLED" /* QueryStateType.Cancelled */,
|
|
635
|
-
meta,
|
|
636
|
-
});
|
|
695
|
+
_updateUseResultInDependencies() {
|
|
696
|
+
if (!this._args?.useResultIn?.length) {
|
|
697
|
+
return;
|
|
637
698
|
}
|
|
638
|
-
|
|
639
|
-
this.
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
699
|
+
this.state$
|
|
700
|
+
.pipe(filterSuccess(), takeUntil(this._onAbort$), takeUntilResponse(), tap((state) => {
|
|
701
|
+
if (!this._args?.useResultIn) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
for (const query of this._args.useResultIn) {
|
|
705
|
+
query._state$.next({
|
|
706
|
+
type: "SUCCESS" /* QueryStateType.Success */,
|
|
707
|
+
meta: { ...state.meta, id: query._nextId },
|
|
708
|
+
rawResponse: state.rawResponse,
|
|
709
|
+
response: state.response,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}))
|
|
713
|
+
.subscribe();
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const isBasicAuthProvider = (authProvider) => authProvider instanceof BasicAuthProvider;
|
|
718
|
+
const isBearerAuthProvider = (authProvider) => authProvider instanceof BearerAuthProvider;
|
|
719
|
+
const isCustomHeaderAuthProvider = (authProvider) => authProvider instanceof CustomHeaderAuthProvider;
|
|
720
|
+
const decryptBearer = (token) => {
|
|
721
|
+
try {
|
|
722
|
+
const base64Url = token.split('.')[1];
|
|
723
|
+
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
724
|
+
const jsonPayload = decodeURIComponent(atob(base64)
|
|
725
|
+
.split('')
|
|
726
|
+
.map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
|
|
727
|
+
.join(''));
|
|
728
|
+
return JSON.parse(jsonPayload);
|
|
729
|
+
}
|
|
730
|
+
catch (error) {
|
|
731
|
+
console.error(`Invalid bearer token: ${token}`, error);
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
class BearerAuthProvider {
|
|
737
|
+
get header() {
|
|
738
|
+
return { Authorization: `Bearer ${this._tokens$.getValue().token}` };
|
|
739
|
+
}
|
|
740
|
+
get tokens$() {
|
|
741
|
+
return this._tokens$.asObservable();
|
|
742
|
+
}
|
|
743
|
+
get tokens() {
|
|
744
|
+
return this._tokens$.getValue();
|
|
745
|
+
}
|
|
746
|
+
get currentRefreshQuery$() {
|
|
747
|
+
return this._currentRefreshQuery$.asObservable();
|
|
748
|
+
}
|
|
749
|
+
get currentRefreshQuery() {
|
|
750
|
+
return this._currentRefreshQuery$.getValue();
|
|
751
|
+
}
|
|
752
|
+
constructor(_config) {
|
|
753
|
+
this._config = _config;
|
|
754
|
+
this._destroy$ = new Subject();
|
|
755
|
+
this._currentRefreshQuery$ = new BehaviorSubject(null);
|
|
756
|
+
this._tokens$ = new BehaviorSubject({
|
|
757
|
+
token: null,
|
|
758
|
+
refreshToken: null,
|
|
759
|
+
});
|
|
760
|
+
const cookieEnabled = _config.refreshConfig?.cookieEnabled ?? true;
|
|
761
|
+
const cookieToken = _config.refreshConfig?.cookieName && cookieEnabled ? getCookie(_config.refreshConfig.cookieName) ?? null : null;
|
|
762
|
+
this._tokens$.next({
|
|
763
|
+
token: _config.token || null,
|
|
764
|
+
refreshToken: _config.refreshConfig?.token || cookieToken || null,
|
|
765
|
+
});
|
|
766
|
+
if (!this.tokens.token && !this.tokens.refreshToken) {
|
|
767
|
+
if (!_config.refreshConfig?.cookieName) {
|
|
768
|
+
console.error('A BearerAuthProvider was created without token or refresh token. You should provide at least a cookieName where the refresh token might be stored.');
|
|
769
|
+
}
|
|
770
|
+
return;
|
|
644
771
|
}
|
|
645
|
-
|
|
646
|
-
|
|
772
|
+
if (this.tokens.token) {
|
|
773
|
+
this._prepareForRefresh();
|
|
774
|
+
if (this.tokens.refreshToken && this._config.refreshConfig?.cookieName) {
|
|
775
|
+
setCookie(this._config.refreshConfig.cookieName, this.tokens.refreshToken);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
else if (this.tokens.refreshToken) {
|
|
779
|
+
this._refreshQuery();
|
|
647
780
|
}
|
|
648
781
|
}
|
|
782
|
+
cleanUp() {
|
|
783
|
+
this._destroy$.next(true);
|
|
784
|
+
this._destroy$.unsubscribe();
|
|
785
|
+
this._currentRefreshQuery$.next(null);
|
|
786
|
+
if (this._config.refreshConfig?.cookieName) {
|
|
787
|
+
deleteCookie(this._config.refreshConfig.cookieName, '/');
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
enableCookie() {
|
|
791
|
+
if (!this._config.refreshConfig?.cookieName) {
|
|
792
|
+
throw new Error('No cookie name was provided');
|
|
793
|
+
}
|
|
794
|
+
if (!this.tokens.refreshToken) {
|
|
795
|
+
throw new Error('No refresh token was provided');
|
|
796
|
+
}
|
|
797
|
+
this._config.refreshConfig.cookieEnabled = true;
|
|
798
|
+
setCookie(this._config.refreshConfig.cookieName, this.tokens.refreshToken);
|
|
799
|
+
}
|
|
800
|
+
disableCookie() {
|
|
801
|
+
if (!this._config.refreshConfig?.cookieName) {
|
|
802
|
+
throw new Error('No cookie name was provided');
|
|
803
|
+
}
|
|
804
|
+
this._config.refreshConfig.cookieEnabled = false;
|
|
805
|
+
deleteCookie(this._config.refreshConfig.cookieName, '/');
|
|
806
|
+
}
|
|
807
|
+
_prepareForRefresh() {
|
|
808
|
+
if (!this.tokens.token || !this._config.refreshConfig) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const bearer = decryptBearer(this.tokens.token);
|
|
812
|
+
if (!bearer) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const expiresInPropertyName = this._config.refreshConfig.expiresInPropertyName || 'exp';
|
|
816
|
+
const expiresIn = bearer[expiresInPropertyName];
|
|
817
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
818
|
+
const refreshBuffer = this._config.refreshConfig.refreshBuffer ?? fiveMinutes;
|
|
819
|
+
if (expiresIn === undefined) {
|
|
820
|
+
throw new Error(`Bearer token does not contain an '${expiresInPropertyName}' property`);
|
|
821
|
+
}
|
|
822
|
+
const remainingTime = new Date(expiresIn * 1000).getTime() - refreshBuffer - new Date().getTime();
|
|
823
|
+
const strategy = this._config.refreshConfig.strategy ?? "beforeExpiration" /* AuthBearerRefreshStrategy.BeforeExpiration */;
|
|
824
|
+
switch (strategy) {
|
|
825
|
+
case "beforeExpiration" /* AuthBearerRefreshStrategy.BeforeExpiration */:
|
|
826
|
+
timer(remainingTime)
|
|
827
|
+
.pipe(takeUntil(this._destroy$))
|
|
828
|
+
.subscribe(() => this._refreshQuery());
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
_refreshQuery() {
|
|
833
|
+
const currentRefreshToken = this.tokens.refreshToken;
|
|
834
|
+
if (!currentRefreshToken || !this._config.refreshConfig) {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
const args = this._config.refreshConfig.requestArgsAdapter?.({
|
|
838
|
+
token: this.tokens.token,
|
|
839
|
+
refreshToken: currentRefreshToken,
|
|
840
|
+
}) ?? {
|
|
841
|
+
body: { refreshToken: currentRefreshToken },
|
|
842
|
+
};
|
|
843
|
+
const query = this._config.refreshConfig.queryCreator.prepare(args).execute({ skipCache: true });
|
|
844
|
+
this._currentRefreshQuery$.next(query);
|
|
845
|
+
this._currentRefreshQuery$
|
|
846
|
+
.pipe(switchQueryState(), tap((state) => {
|
|
847
|
+
if (isQueryStateSuccess(state)) {
|
|
848
|
+
if (this._config.refreshConfig?.responseAdapter) {
|
|
849
|
+
const tokens = this._config.refreshConfig.responseAdapter(state.response);
|
|
850
|
+
this._tokens$.next(tokens);
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
this._tokens$.next({
|
|
854
|
+
token: state.response['token'],
|
|
855
|
+
refreshToken: state.response['refreshToken'],
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
const cookieEnabled = this._config.refreshConfig?.cookieEnabled ?? true;
|
|
859
|
+
if (this._config.refreshConfig?.cookieName && this.tokens.refreshToken && cookieEnabled) {
|
|
860
|
+
setCookie(this._config.refreshConfig.cookieName, this.tokens.refreshToken);
|
|
861
|
+
}
|
|
862
|
+
this._prepareForRefresh();
|
|
863
|
+
}
|
|
864
|
+
else if (isQueryStateFailure(state)) {
|
|
865
|
+
this._tokens$.next({ token: null, refreshToken: null });
|
|
866
|
+
if (this._config.refreshConfig?.cookieName) {
|
|
867
|
+
deleteCookie(this._config.refreshConfig.cookieName, '/');
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}), takeUntilResponse(), takeUntil(this._destroy$))
|
|
871
|
+
.subscribe();
|
|
872
|
+
}
|
|
649
873
|
}
|
|
650
874
|
|
|
651
875
|
class QueryDirective {
|
|
876
|
+
get query() {
|
|
877
|
+
return this._query;
|
|
878
|
+
}
|
|
879
|
+
set query(v) {
|
|
880
|
+
this._query = v;
|
|
881
|
+
this._subscribeToQuery();
|
|
882
|
+
}
|
|
883
|
+
get cache() {
|
|
884
|
+
return this._cache;
|
|
885
|
+
}
|
|
886
|
+
set cache(v) {
|
|
887
|
+
this._cache = v;
|
|
888
|
+
}
|
|
652
889
|
constructor(_mainTemplateRef, _viewContainerRef, _errorHandler, _cdr) {
|
|
653
890
|
this._mainTemplateRef = _mainTemplateRef;
|
|
654
891
|
this._viewContainerRef = _viewContainerRef;
|
|
@@ -662,22 +899,10 @@ class QueryDirective {
|
|
|
662
899
|
raw: null,
|
|
663
900
|
loading: false,
|
|
664
901
|
error: null,
|
|
902
|
+
progress: null,
|
|
665
903
|
};
|
|
666
904
|
this._cache = false;
|
|
667
905
|
}
|
|
668
|
-
get query() {
|
|
669
|
-
return this._query;
|
|
670
|
-
}
|
|
671
|
-
set query(v) {
|
|
672
|
-
this._query = v;
|
|
673
|
-
this._subscribeToQuery();
|
|
674
|
-
}
|
|
675
|
-
get cache() {
|
|
676
|
-
return this._cache;
|
|
677
|
-
}
|
|
678
|
-
set cache(v) {
|
|
679
|
-
this._cache = v;
|
|
680
|
-
}
|
|
681
906
|
static ngTemplateContextGuard(dir, ctx) {
|
|
682
907
|
return true;
|
|
683
908
|
}
|
|
@@ -693,15 +918,18 @@ class QueryDirective {
|
|
|
693
918
|
if (!this.query) {
|
|
694
919
|
return;
|
|
695
920
|
}
|
|
696
|
-
const
|
|
921
|
+
const query = isQuery(this.query) ? this.query : this.query.query;
|
|
922
|
+
const sub = query.state$.pipe(tap((state) => this._updateView(state))).subscribe();
|
|
697
923
|
this._subscription = sub;
|
|
698
924
|
}
|
|
699
925
|
_updateView(state) {
|
|
700
926
|
if (isQueryStateLoading(state)) {
|
|
701
927
|
this._viewContext.loading = true;
|
|
928
|
+
this._viewContext.progress = state.progress ?? null;
|
|
702
929
|
}
|
|
703
930
|
else {
|
|
704
931
|
this._viewContext.loading = false;
|
|
932
|
+
this._viewContext.progress = null;
|
|
705
933
|
}
|
|
706
934
|
if (isQueryStateSuccess(state)) {
|
|
707
935
|
this._viewContext.query = state.response;
|
|
@@ -729,9 +957,9 @@ class QueryDirective {
|
|
|
729
957
|
}
|
|
730
958
|
}
|
|
731
959
|
}
|
|
732
|
-
QueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
733
|
-
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.
|
|
734
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
960
|
+
QueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: QueryDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i0.ErrorHandler }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
961
|
+
QueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: QueryDirective, isStandalone: true, selector: "[query]", inputs: { query: "query", cache: ["queryCache", "cache"] }, ngImport: i0 });
|
|
962
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: QueryDirective, decorators: [{
|
|
735
963
|
type: Directive,
|
|
736
964
|
args: [{
|
|
737
965
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
@@ -747,16 +975,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImpor
|
|
|
747
975
|
|
|
748
976
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
749
977
|
class InfinityQuery {
|
|
750
|
-
constructor(_config) {
|
|
751
|
-
this._config = _config;
|
|
752
|
-
this._currentPage$ = new BehaviorSubject(null);
|
|
753
|
-
this._currentCalculatedPage$ = new BehaviorSubject(null);
|
|
754
|
-
this._totalPages$ = new BehaviorSubject(null);
|
|
755
|
-
this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
|
|
756
|
-
this._currentQuery$ = new BehaviorSubject(null);
|
|
757
|
-
this._data$ = new BehaviorSubject([]);
|
|
758
|
-
this._subscriptions = [];
|
|
759
|
-
}
|
|
760
978
|
get currentPage$() {
|
|
761
979
|
return this._currentPage$.asObservable();
|
|
762
980
|
}
|
|
@@ -793,6 +1011,16 @@ class InfinityQuery {
|
|
|
793
1011
|
get data() {
|
|
794
1012
|
return this._data$.getValue();
|
|
795
1013
|
}
|
|
1014
|
+
constructor(_config) {
|
|
1015
|
+
this._config = _config;
|
|
1016
|
+
this._currentPage$ = new BehaviorSubject(null);
|
|
1017
|
+
this._currentCalculatedPage$ = new BehaviorSubject(null);
|
|
1018
|
+
this._totalPages$ = new BehaviorSubject(null);
|
|
1019
|
+
this._itemsPerPage$ = new BehaviorSubject(this._config.limitParam?.value ?? 10);
|
|
1020
|
+
this._currentQuery$ = new BehaviorSubject(null);
|
|
1021
|
+
this._data$ = new BehaviorSubject([]);
|
|
1022
|
+
this._subscriptions = [];
|
|
1023
|
+
}
|
|
796
1024
|
nextPage() {
|
|
797
1025
|
const newPage = (this._currentPage$.value ?? 0) + 1;
|
|
798
1026
|
const calculatedPage = this._config?.pageParam?.valueCalculator?.({
|
|
@@ -800,6 +1028,10 @@ class InfinityQuery {
|
|
|
800
1028
|
totalPages: this.totalPages,
|
|
801
1029
|
itemsPerPage: this.itemsPerPage,
|
|
802
1030
|
}) ?? newPage;
|
|
1031
|
+
if (this.totalPages !== null && calculatedPage > this.totalPages) {
|
|
1032
|
+
console.error('Cannot load more pages, already at the end. Make sure to not render the infinity query trigger using *ngIf canLoadMore');
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
803
1035
|
const args = this._prepareArgs(this._config, calculatedPage);
|
|
804
1036
|
const query = this._config.queryCreator.prepare(args).execute();
|
|
805
1037
|
this._handleNewQuery(query);
|
|
@@ -925,7 +1157,7 @@ class InfinityQueryDirective {
|
|
|
925
1157
|
itemsPerPage: null,
|
|
926
1158
|
};
|
|
927
1159
|
this._infinityQueryInstance = null;
|
|
928
|
-
this._destroy$ = inject(
|
|
1160
|
+
this._destroy$ = inject(DestroyService, { host: true }).destroy$;
|
|
929
1161
|
this._cdr = inject(ChangeDetectorRef);
|
|
930
1162
|
this._viewContainerRef = inject(ViewContainerRef);
|
|
931
1163
|
this._mainTemplateRef = inject((TemplateRef));
|
|
@@ -1040,17 +1272,16 @@ class InfinityQueryDirective {
|
|
|
1040
1272
|
this._data$.next([]);
|
|
1041
1273
|
}
|
|
1042
1274
|
}
|
|
1043
|
-
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
1044
|
-
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.
|
|
1045
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
1275
|
+
InfinityQueryDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: InfinityQueryDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1276
|
+
InfinityQueryDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: InfinityQueryDirective, isStandalone: true, selector: "[infinityQuery]", inputs: { infinityQuery: "infinityQuery" }, providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService], exportAs: ["infinityQuery"], ngImport: i0 });
|
|
1277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: InfinityQueryDirective, decorators: [{
|
|
1046
1278
|
type: Directive,
|
|
1047
1279
|
args: [{
|
|
1048
1280
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
1049
1281
|
selector: '[infinityQuery]',
|
|
1050
1282
|
exportAs: 'infinityQuery',
|
|
1051
1283
|
standalone: true,
|
|
1052
|
-
providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }],
|
|
1053
|
-
hostDirectives: [DestroyDirective],
|
|
1284
|
+
providers: [{ provide: INFINITY_QUERY_TOKEN, useExisting: InfinityQueryDirective }, DestroyService],
|
|
1054
1285
|
}]
|
|
1055
1286
|
}], propDecorators: { infinityQuery: [{
|
|
1056
1287
|
type: Input
|
|
@@ -1093,9 +1324,9 @@ class InfinityQueryTriggerDirective {
|
|
|
1093
1324
|
this._observer.observe(this._elementRef.nativeElement);
|
|
1094
1325
|
}
|
|
1095
1326
|
}
|
|
1096
|
-
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.
|
|
1097
|
-
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.
|
|
1098
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.
|
|
1327
|
+
InfinityQueryTriggerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1328
|
+
InfinityQueryTriggerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.4", type: InfinityQueryTriggerDirective, isStandalone: true, selector: "[infinityQueryTrigger], infinity-query-trigger", inputs: { scrollContainerSelector: "scrollContainerSelector" }, ngImport: i0 });
|
|
1329
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: InfinityQueryTriggerDirective, decorators: [{
|
|
1099
1330
|
type: Directive,
|
|
1100
1331
|
args: [{
|
|
1101
1332
|
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
@@ -1187,9 +1418,18 @@ config, args) => {
|
|
|
1187
1418
|
};
|
|
1188
1419
|
|
|
1189
1420
|
class QueryClient {
|
|
1421
|
+
get config() {
|
|
1422
|
+
return this._clientConfig;
|
|
1423
|
+
}
|
|
1424
|
+
get authProvider() {
|
|
1425
|
+
return this._authProvider$.getValue() ?? this._clientConfig.parent?._authProvider$.getValue() ?? null;
|
|
1426
|
+
}
|
|
1427
|
+
get authProvider$() {
|
|
1428
|
+
return this._authProvider$.asObservable() ?? this._clientConfig.parent?._authProvider$.asObservable() ?? null;
|
|
1429
|
+
}
|
|
1190
1430
|
constructor(_clientConfig) {
|
|
1191
1431
|
this._clientConfig = _clientConfig;
|
|
1192
|
-
this._authProvider = null;
|
|
1432
|
+
this._authProvider$ = new BehaviorSubject(null);
|
|
1193
1433
|
this.get = (queryConfig) => this.fetch({
|
|
1194
1434
|
...queryConfig,
|
|
1195
1435
|
method: 'GET',
|
|
@@ -1246,38 +1486,41 @@ class QueryClient {
|
|
|
1246
1486
|
};
|
|
1247
1487
|
};
|
|
1248
1488
|
this.setAuthProvider = (authProvider) => {
|
|
1249
|
-
if (this.
|
|
1489
|
+
if (this.authProvider) {
|
|
1250
1490
|
throw new Error('The auth provider is already set. Please call clearAuthProvider() first.');
|
|
1251
1491
|
}
|
|
1252
|
-
this._authProvider
|
|
1253
|
-
|
|
1492
|
+
this._authProvider$.next(authProvider);
|
|
1493
|
+
};
|
|
1494
|
+
this.setDefaultHeaders = (headers) => {
|
|
1495
|
+
if (!this._clientConfig.request) {
|
|
1496
|
+
this._clientConfig.request = {
|
|
1497
|
+
headers: headers ?? undefined,
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
this._clientConfig.request.headers = headers ?? undefined;
|
|
1502
|
+
}
|
|
1254
1503
|
};
|
|
1255
1504
|
this.clearAuthProvider = () => {
|
|
1256
|
-
this.
|
|
1257
|
-
this._authProvider
|
|
1505
|
+
this.authProvider?.cleanUp();
|
|
1506
|
+
this._authProvider$.next(null);
|
|
1258
1507
|
};
|
|
1259
1508
|
this._store = new QueryStore({
|
|
1260
1509
|
enableChangeLogging: _clientConfig.logging?.queryStateChanges,
|
|
1261
1510
|
enableGarbageCollectorLogging: _clientConfig.logging?.queryStateGarbageCollector,
|
|
1262
1511
|
});
|
|
1263
1512
|
}
|
|
1264
|
-
get config() {
|
|
1265
|
-
return this._clientConfig;
|
|
1266
|
-
}
|
|
1267
|
-
get authProvider() {
|
|
1268
|
-
return this._authProvider;
|
|
1269
|
-
}
|
|
1270
1513
|
}
|
|
1271
1514
|
|
|
1272
1515
|
class QueryField {
|
|
1516
|
+
get control() {
|
|
1517
|
+
return this.data.control;
|
|
1518
|
+
}
|
|
1273
1519
|
constructor(data) {
|
|
1274
1520
|
this.data = data;
|
|
1275
1521
|
this.changes$ = this._setupChangesObservable();
|
|
1276
1522
|
this._currentDebounceTimeout = null;
|
|
1277
1523
|
}
|
|
1278
|
-
get control() {
|
|
1279
|
-
return this.data.control;
|
|
1280
|
-
}
|
|
1281
1524
|
setValue(value) {
|
|
1282
1525
|
if (this._currentDebounceTimeout !== null) {
|
|
1283
1526
|
clearTimeout(this._currentDebounceTimeout);
|
|
@@ -1311,7 +1554,7 @@ class QueryForm {
|
|
|
1311
1554
|
this.form = this._setupFormGroup();
|
|
1312
1555
|
}
|
|
1313
1556
|
observe(options) {
|
|
1314
|
-
return combineLatest(Object.values(this._fields).map((field) => field.changes$)).pipe(map(() => this.form.getRawValue()), distinctUntilChanged((a, b) =>
|
|
1557
|
+
return combineLatest(Object.values(this._fields).map((field) => field.changes$)).pipe(map(() => this.form.getRawValue()), distinctUntilChanged((a, b) => equal(a, b)), tap((values) => {
|
|
1315
1558
|
if (options?.syncViaUrlQueryParams !== false) {
|
|
1316
1559
|
this._syncViaUrlQueryParams(values);
|
|
1317
1560
|
}
|
|
@@ -1372,7 +1615,7 @@ class QueryForm {
|
|
|
1372
1615
|
if (!this._router || !this._activatedRoute) {
|
|
1373
1616
|
return;
|
|
1374
1617
|
}
|
|
1375
|
-
const queryParams =
|
|
1618
|
+
const queryParams = { ...clone(this._activatedRoute.snapshot.queryParams) };
|
|
1376
1619
|
for (const [key, value] of Object.entries(values)) {
|
|
1377
1620
|
if (this._isDefaultValue(key, value) || this._fields[key].data.appendToUrl === false) {
|
|
1378
1621
|
delete queryParams[key];
|
|
@@ -1483,9 +1726,34 @@ const transformToSortQueryParam = (value) => {
|
|
|
1483
1726
|
return null;
|
|
1484
1727
|
};
|
|
1485
1728
|
|
|
1729
|
+
const deepFreeze = (object) => {
|
|
1730
|
+
// check if object is actually an object or frozen
|
|
1731
|
+
if (!object || typeof object !== 'object' || Object.isFrozen(object)) {
|
|
1732
|
+
return object;
|
|
1733
|
+
}
|
|
1734
|
+
// Retrieve the property names defined on object
|
|
1735
|
+
const propNames = Object.getOwnPropertyNames(object);
|
|
1736
|
+
// Freeze properties before freezing self
|
|
1737
|
+
for (const name of propNames) {
|
|
1738
|
+
const value = object[name];
|
|
1739
|
+
if (value && typeof value === 'object') {
|
|
1740
|
+
deepFreeze(value);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
return Object.freeze(object);
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Dummy function for providing types while not breaking inference.
|
|
1748
|
+
* **This function always returns null.**
|
|
1749
|
+
* @see https://github.com/microsoft/TypeScript/issues/26242
|
|
1750
|
+
* @returns null
|
|
1751
|
+
*/
|
|
1752
|
+
const def = () => null;
|
|
1753
|
+
|
|
1486
1754
|
/**
|
|
1487
1755
|
* Generated bundle index. Do not edit.
|
|
1488
1756
|
*/
|
|
1489
1757
|
|
|
1490
|
-
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryDirective, QueryError, QueryField, QueryForm, QueryStore,
|
|
1758
|
+
export { BasicAuthProvider, BearerAuthProvider, CustomHeaderAuthProvider, INFINITY_QUERY_TOKEN, InfinityQuery, InfinityQueryDirective, InfinityQueryTriggerDirective, Query, QueryClient, QueryDirective, QueryError, QueryField, QueryForm, QueryStore, buildErrorMessage, buildGqlCacheKey, buildQueryArrayString, buildQueryString, buildRoute, buildTimestampFromSeconds, createInfinityQueryConfig, createQueryCollection, decryptBearer, deepFreeze, def, detectContentTypeHeader, extractExpiresInSeconds, extractQuery, filterFailure, filterInvalidParams, filterNull, filterQueryStates, filterSuccess, forEachHeader, getDefaultHeaders, getResponseUrl, gql, hasHeader, invalidBaseRouteError, invalidBodyError, invalidRouteError, isBasicAuthProvider, isBearerAuthProvider, isCustomHeaderAuthProvider, isFetchResponse, isGqlQueryConfig, isParamValid, isQuery, isQueryStateCancelled, isQueryStateFailure, isQueryStateLoading, isQueryStatePrepared, isQueryStateSuccess, isRequestError, mergeHeaders, parseAllXhrResponseHeaders, pathParamsMissingInRouteFunctionError, queryStateAlreadyHasKeyError, queryStateCannotTransformError, queryStateDoesNotContainKeyError, request, serializeBody, shouldCacheQuery, skipPaginationPageParamCalculator, switchQueryCollectionState, switchQueryState, takeUntilResponse, transformGql, transformMethod, transformToBoolean, transformToBooleanArray, transformToDate, transformToDateArray, transformToNumber, transformToNumberArray, transformToSort, transformToSortQueryParam, transformToString, transformToStringArray };
|
|
1491
1759
|
//# sourceMappingURL=ethlete-query.mjs.map
|