module license import { ModuleRpcCommon } from '../../common' ; import { ModuleRpcClient } from '../../client' ; import * as moment from 'moment' ; import { ModuleRpcContextCommon } from '../common' ; /**
 * Takes a refresh token and returns a brand new token info.
 */ export type RefreshTokenHandler = ( refreshToken : string ) => Promise < ModuleRpcContextCommon . TokenInfo > ; /**
 * Provide a client context connector that adds an 'authorization' header.
 *
 * The bearer token to put can be given and refreshed through the `authenticate` method
 * (when initialized, the `TokenAuthClientContextConnector` operates without any token
 * and so no 'authorization' header is added).  Additionally, it is possible to specify
 * an optional `refreshTokenHandler` that is automatically called `expiryDateOffsetMs`
 * milliseconds before the current token expires.
 */ export class TokenAuthClientContextConnector implements ModuleRpcClient . ClientContextConnector < ModuleRpcContextCommon . TokenAuthResponseContext > { private tokenInfo : ModuleRpcContextCommon . TokenInfo ; private timeout : NodeJS . Timer ; /**
     * Constructs a token auth client context connector.
     * The initial token must be provided with [[TokenAuthClientContextConnector.authenticate]].
     */ constructor ( ) ; param refreshTokenHandler param expiryDateOffsetMs param reportRefreshError constructor ( refreshTokenHandler , expiryDateOffsetMs ? , reportRefreshError ? ) ; constructor ( private readonly refreshTokenHandler = undefined , private readonly expiryDateOffsetMs = 10000 , private readonly reportRefreshError = console . error ) { } /**
     * Provides an initial token info.
     *
     * This function also sets up a `setInterval` to refresh the token periodically,
     * unless `autoRefresh` is set to `false`.
     */ authenticate ( tokenInfo , autoRefresh = true ) { this . tokenInfo = tokenInfo ; this . clearAutoRefresh ( ) ; if ( autoRefresh ) { const setRefreshTimeout = ( ) => { if ( ! this . tokenInfo . expiryDate ) { return ; } const duration = moment . utc ( ) . diff ( moment ( this . tokenInfo . expiryDate ) . subtract ( this . expiryDateOffsetMs , 'ms' ) ) ; this . timeout = setTimeout ( async ( ) => { try { await this . refreshToken ( ) ; setRefreshTimeout ( ) ; } catch ( err ) { this . reportRefreshError ( err ) ; } } , duration ) ; } ; setRefreshTimeout ( ) ; } } /**
     * Clear the auto refresh.
     *
     * If the function is not called when one is finished with the connector,
     * the auto refresh keeps happening in the background.
     */ clearAutoRefresh ( ) { clearTimeout ( this . timeout ) ; } /**
     * Forces a token refresh.  This function does nothing if no refresh handler or
     * no refresh token was specified.
     */ async forceRefreshToken ( ) { if ( ! this . refreshTokenHandler || ! this . tokenInfo . refreshToken ) { return ; } if ( ! this . timeout ) { this . refreshToken ( ) ; } else { this . authenticate ( await this . refreshTokenHandler ( this . tokenInfo . refreshToken ) ) ; } } private async refreshToken ( ) { if ( ! this . refreshTokenHandler || ! this . tokenInfo . refreshToken ) { return ; } this . tokenInfo = await this . refreshTokenHandler ( this . tokenInfo . refreshToken ) ; } async provideRequestContext ( ) { if ( ! this . tokenInfo ) { throw new ModuleRpcClient . RequestContextError ( 'principal has not yet been authenticated' ) ; } if ( this . tokenInfo . expiryDate && moment . utc ( ) . isAfter ( moment ( this . tokenInfo . expiryDate ) . subtract ( this . expiryDateOffsetMs , 'ms' ) ) ) { if ( ! this . refreshTokenHandler || ! this . tokenInfo . refreshToken ) { throw new ModuleRpcClient . RequestContextError ( 'session has expired and no refresh token was provided' ) ; } this . tokenInfo = await this . refreshTokenHandler ( this . tokenInfo . refreshToken ) ; } const token = this . tokenInfo . token ; if ( ! token ) { throw new ModuleRpcClient . RequestContextError ( 'unexpected shape of tokenInfo: token field is missing' ) ; } return { [ ModuleRpcContextCommon . tokenAuthContextKeys . authorization ] : `Bearer ${ token }` , } ; } async decodeResponseContext ( _encodedResponseContext ) { return { } ; } }