@tstdl/base 0.93.144 → 0.93.145

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.
@@ -126,6 +126,9 @@ export declare const authenticationApiDefinition: {
126
126
  timestamp: {
127
127
  resource: string;
128
128
  result: import("../schema/index.js").NumberSchema;
129
+ data: {
130
+ [dontWaitForValidToken]: boolean;
131
+ };
129
132
  };
130
133
  };
131
134
  };
@@ -248,6 +251,9 @@ export declare function getAuthenticationApiDefinition<AdditionalTokenPayload ex
248
251
  timestamp: {
249
252
  resource: string;
250
253
  result: import("../schema/index.js").NumberSchema;
254
+ data: {
255
+ [dontWaitForValidToken]: boolean;
256
+ };
251
257
  };
252
258
  };
253
259
  };
@@ -365,6 +371,9 @@ export declare function getAuthenticationApiEndpointsDefinition<AdditionalTokenP
365
371
  timestamp: {
366
372
  resource: string;
367
373
  result: import("../schema/index.js").NumberSchema;
374
+ data: {
375
+ [dontWaitForValidToken]: boolean;
376
+ };
368
377
  };
369
378
  };
370
379
  export {};
@@ -147,6 +147,9 @@ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSc
147
147
  timestamp: {
148
148
  resource: 'timestamp',
149
149
  result: number(),
150
+ data: {
151
+ [dontWaitForValidToken]: true,
152
+ },
150
153
  },
151
154
  };
152
155
  }
@@ -420,7 +420,7 @@ let AuthenticationClientService = class AuthenticationClientService {
420
420
  if (stillNeedsRefresh) {
421
421
  await this.refresh();
422
422
  }
423
- if (this.forceRefreshRequested() && (this.token() != currentToken)) {
423
+ if (this.forceRefreshRequested() && (this.token()?.jti != currentToken?.jti)) {
424
424
  this.forceRefreshRequested.set(false);
425
425
  }
426
426
  });
@@ -428,7 +428,7 @@ let AuthenticationClientService = class AuthenticationClientService {
428
428
  // Lock held by another instance, wait 5 seconds or until token changes (Passive Sync)
429
429
  const changeReason = await firstValueFrom(race([
430
430
  timer(5000).pipe(map(() => 'timer')),
431
- this.token$.pipe(filter((t) => t != token), map(() => 'token')),
431
+ this.token$.pipe(filter((t) => t?.jti != token.jti), map(() => 'token')),
432
432
  from(this.disposeSignal),
433
433
  ]), { defaultValue: undefined });
434
434
  if (changeReason == 'token') {
@@ -442,7 +442,7 @@ let AuthenticationClientService = class AuthenticationClientService {
442
442
  const delay = Math.min(maxRefreshDelay, ((currentToken?.exp ?? 0) - this.estimatedServerTimestampSeconds() - currentRefreshBufferSeconds) * millisecondsPerSecond);
443
443
  const wakeUpSignals = [
444
444
  from(this.disposeSignal),
445
- this.token$.pipe(filter((t) => t != currentToken)),
445
+ this.token$.pipe(filter((t) => t?.jti != currentToken?.jti)),
446
446
  ];
447
447
  if (!forceRefresh) {
448
448
  wakeUpSignals.push(this.forceRefreshRequested$.pipe(filter((requested) => requested)));
@@ -451,7 +451,7 @@ let AuthenticationClientService = class AuthenticationClientService {
451
451
  await firstValueFrom(race([timer(delay), ...wakeUpSignals]), { defaultValue: undefined });
452
452
  }
453
453
  else {
454
- await firstValueFrom(race([timer(5000), ...wakeUpSignals]), { defaultValue: undefined });
454
+ await firstValueFrom(race([timer(2500), ...wakeUpSignals]), { defaultValue: undefined });
455
455
  }
456
456
  }
457
457
  catch (error) {
@@ -460,7 +460,7 @@ let AuthenticationClientService = class AuthenticationClientService {
460
460
  await firstValueFrom(race([
461
461
  timer(2500),
462
462
  from(this.disposeSignal),
463
- this.token$.pipe(filter((t) => t != currentToken)),
463
+ this.token$.pipe(filter((t) => t?.jti != currentToken?.jti)),
464
464
  this.forceRefreshRequested$.pipe(filter((requested) => requested), skip(this.forceRefreshRequested() ? 1 : 0)),
465
465
  ]), { defaultValue: undefined });
466
466
  }
@@ -1,5 +1,6 @@
1
- import { firstValueFrom, race, timeout } from 'rxjs';
1
+ import { firstValueFrom, race, timeout as rxjsTimeout } from 'rxjs';
2
2
  import { HttpError } from '../../http/index.js';
3
+ import { timeout } from '../../utils/timing.js';
3
4
  import { isDefined } from '../../utils/type-guards.js';
4
5
  import { cacheValueOrAsyncProvider } from '../../utils/value-or-provider.js';
5
6
  import { dontWaitForValidToken } from '../authentication.api.js';
@@ -19,10 +20,13 @@ export function waitForAuthenticationCredentialsMiddleware(authenticationService
19
20
  authenticationService.validToken$,
20
21
  request.cancellationSignal,
21
22
  ]);
22
- await firstValueFrom(race$.pipe(timeout(30000))).catch(() => undefined);
23
+ await firstValueFrom(race$.pipe(rxjsTimeout(30000))).catch(() => undefined);
23
24
  if (request.cancellationSignal.isSet) {
24
25
  break;
25
26
  }
27
+ if (!authenticationService.hasValidToken && authenticationService.isLoggedIn()) {
28
+ await timeout(100);
29
+ }
26
30
  }
27
31
  }
28
32
  await next();
@@ -21,6 +21,41 @@ describe('waitForAuthenticationCredentialsMiddleware', () => {
21
21
  await middleware({ request }, next);
22
22
  expect(next).toHaveBeenCalled();
23
23
  });
24
+ test('should NOT wait if endpoint has dontWaitForValidToken', async () => {
25
+ const authenticationServiceMock = {
26
+ isLoggedIn: vi.fn().mockReturnValue(true),
27
+ hasValidToken: false,
28
+ };
29
+ const middleware = waitForAuthenticationCredentialsMiddleware(authenticationServiceMock);
30
+ const request = new HttpClientRequest('http://localhost');
31
+ request.context = {
32
+ endpoint: {
33
+ credentials: true,
34
+ data: {
35
+ [dontWaitForValidToken]: true,
36
+ },
37
+ },
38
+ };
39
+ const next = vi.fn().mockResolvedValue(undefined);
40
+ await middleware({ request }, next);
41
+ expect(next).toHaveBeenCalled();
42
+ });
43
+ test('should NOT wait if credentials is NOT true', async () => {
44
+ const authenticationServiceMock = {
45
+ isLoggedIn: vi.fn().mockReturnValue(true),
46
+ hasValidToken: false,
47
+ };
48
+ const middleware = waitForAuthenticationCredentialsMiddleware(authenticationServiceMock);
49
+ const request = new HttpClientRequest('http://localhost');
50
+ request.context = {
51
+ endpoint: {
52
+ credentials: false,
53
+ },
54
+ };
55
+ const next = vi.fn().mockResolvedValue(undefined);
56
+ await middleware({ request }, next);
57
+ expect(next).toHaveBeenCalled();
58
+ });
24
59
  });
25
60
  describe('logoutOnUnauthorizedMiddleware', () => {
26
61
  test('should call logout on 401 error', async () => {
@@ -123,4 +123,11 @@ describe('AuthenticationClientService Refresh Loop Reproduction', () => {
123
123
  // If it busy loops, this will be much higher than 1.
124
124
  expect(mockLock.tryUse.mock.calls.length).toBeLessThan(5);
125
125
  });
126
+ test('refresh() should call timestamp() to sync clock', async () => {
127
+ service = injector.resolve(AuthenticationClientService);
128
+ const newToken = { iat: 1000, exp: 2000, jti: 'new' };
129
+ mockApiClient.refresh.mockResolvedValue(newToken);
130
+ await service.refresh();
131
+ expect(mockApiClient.timestamp).toHaveBeenCalled();
132
+ });
126
133
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.144",
3
+ "version": "0.93.145",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"