|
1 | 1 | import type { ClientOptions, ClientResponse, NgsiError } from "./types.js"; |
2 | 2 | import { clientCredentialsGrant } from "./oauth.js"; |
| 3 | +import { getTokenStatus } from "./token.js"; |
3 | 4 |
|
4 | 5 | export class DryRunSignal extends Error { |
5 | 6 | constructor() { |
@@ -163,7 +164,19 @@ export class GdbClient { |
163 | 164 | } |
164 | 165 |
|
165 | 166 | private canRefresh(): boolean { |
166 | | - return (!!this.refreshToken || (!!this.clientId && !!this.clientSecret)) && !this.apiKey; |
| 167 | + if (!this.refreshToken && !(this.clientId && this.clientSecret)) return false; |
| 168 | + // When authenticating solely via apiKey (no token), token refresh is unnecessary |
| 169 | + if (!this.token && this.apiKey) return false; |
| 170 | + return true; |
| 171 | + } |
| 172 | + |
| 173 | + /** Proactively refresh the token before making a request if it is expired or about to expire. */ |
| 174 | + private async proactiveRefresh(): Promise<void> { |
| 175 | + if (!this.token || !this.canRefresh()) return; |
| 176 | + const status = getTokenStatus(this.token); |
| 177 | + if (status.isExpired || status.isExpiringSoon) { |
| 178 | + await this.performTokenRefresh(); |
| 179 | + } |
167 | 180 | } |
168 | 181 |
|
169 | 182 | /** Check whether an error indicates an authentication/token problem that may be resolved by refreshing. */ |
@@ -341,6 +354,7 @@ export class GdbClient { |
341 | 354 | headers?: Record<string, string>; |
342 | 355 | }, |
343 | 356 | ): Promise<ClientResponse<T>> { |
| 357 | + await this.proactiveRefresh(); |
344 | 358 | try { |
345 | 359 | return await this.executeRequest<T>(method, path, options); |
346 | 360 | } catch (err) { |
@@ -404,6 +418,7 @@ export class GdbClient { |
404 | 418 | skipTenantHeader?: boolean; |
405 | 419 | }, |
406 | 420 | ): Promise<ClientResponse<T>> { |
| 421 | + await this.proactiveRefresh(); |
407 | 422 | try { |
408 | 423 | return await this.executeRawRequest<T>(method, path, options); |
409 | 424 | } catch (err) { |
|
0 commit comments