import { createLogger , ErrorWithCause } from '@sap-cloud-sdk/util' ; import { decodeJwt } from '../jwt' ; import { sanitizeDestination , isDestinationConfiguration , parseDestination } from './destination' ; import { DestinationFetchOptions } from './destination-accessor-types' ; import type { Destination , DestinationAuthToken } from './destination-service-types' ; import { addProxyConfigurationInternet , ProxyStrategy , proxyStrategy } from './proxy-util' ; const logger = createLogger ( { package : 'connectivity' , messageContext : 'env-destination-accessor' } ) ; returns internal export function getDestinationsFromEnv ( ) { const destinationsEnv = getDestinationsEnvVariable ( ) ; logger . debug ( `The value for the destination environment variable is: ${ destinationsEnv }` ) ; if ( destinationsEnv ) { let destinations ; try { destinations = JSON . parse ( destinationsEnv ) ; } catch ( err ) { throw new ErrorWithCause ( 'Error in parsing the destinations from the environment variable.' , err ) ; } validateDestinations ( destinations ) ; return destinations . map ( destination => isDestinationConfiguration ( destination ) ? parseDestination ( destination ) : sanitizeDestination ( destination ) ) ; } return [ ] ; } param name returns internal export function getDestinationFromEnvByName ( name ) { const matchingDestinations = getDestinationsFromEnv ( ) . filter ( dest => dest . name === name ) ; if ( ! matchingDestinations . length ) { return null ; } if ( matchingDestinations . length > 1 ) { logger . warn ( `The 'destinations' env variable contains multiple destinations with the name '${ name }'. Only the first entry will be respected.` ) ; } const destination = matchingDestinations [ 0 ] ; return proxyStrategy ( destination ) === ProxyStrategy . INTERNET_PROXY ? addProxyConfigurationInternet ( destination ) : destination ; } internal export function getDestinationConfig ( dest = 'ErpQueryEndpoint' ) { return typeof dest === 'string' ? getDestinationFromEnvByName ( dest ) : dest ; } internal export function getDestinationsEnvVariable ( ) { return process . env [ 'destinations' ] ; } function validateDestinations ( destinations ) { destinations . forEach ( destination => { if ( typeof destination . name === 'undefined' && typeof destination . Name === 'undefined' ) { logger . warn ( "Destination from 'destinations' env variable is missing 'name' or 'Name' property." ) ; } } ) ; } internal export function searchEnvVariablesForDestination ( options ) { logger . info ( 'Attempting to retrieve destination from environment variable.' ) ; if ( getDestinationsEnvVariable ( ) ) { try { const destination = getDestinationFromEnvByName ( options . destinationName ) ; if ( destination ) { if ( destination . forwardAuthToken ) { destination . authTokens = destinationAuthToken ( options . jwt ) ; } logger . info ( `Successfully retrieved destination '${ options . destinationName }' from environment variable.` ) ; return destination ; } } catch ( error ) { logger . error ( `Error in reading the given destinations from the environment variable ${ error . message }.` ) ; } } logger . info ( 'No environment variable set.' ) ; } function destinationAuthToken ( token ? ) { if ( token ) { const decoded = decodeJwt ( token ) ; logger . info ( "Option 'forwardAuthToken' enabled on destination. Using the initial token for the destination." ) ; return [ { value : token , expiresIn : decoded . exp ! . toString ( ) , error : null , http_header : { key : 'Authorization' , value : `Bearer ${ token }` } , type : 'Bearer' } ] ; } logger . warn ( "Option 'forwardAuthToken' was set on destination but no token was provided to forward. This is most likely unintended and will lead to a authorization error on request execution." ) ; } internal export function validateNameAvailable ( destinationName , existingNames ) { if ( existingNames . has ( destinationName ) ) { throw new Error ( `Parsing destinations failed, destination with name "${ destinationName }" already exists in the "destinations" environment variables.` ) ; } } internal export function setDestinationsInEnv ( destinations ) { process . env . destinations = JSON . stringify ( destinations ) ; } type DestinationWithName = Omit < Destination , 'name' > & { name : string ; } ; function destinationHasName ( destination ) { return ! ! destination . name ; } param destination export function registerDestination ( destination ) { const currentDestinations = getDestinationsFromEnv ( ) ; const existingNames = new Set < string > ( currentDestinations . filter ( destinationHasName ) . map ( dest => dest . name ) ) ; if ( ! destination . name || ! destination . url ) { throw Error ( 'The registerDestination function requires a destination name and url.' ) ; } validateNameAvailable ( destination . name , existingNames ) ; setDestinationsInEnv ( [ ... currentDestinations , destination ] ) ; }