@ethlete/query 0.1.0-next.8 → 1.0.0

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