import { adtException } from "./AdtException" ; import { AdtHTTP , ClientOptions , session_types , BearerFetcher } from "./AdtHTTP" ; import { AbapClassStructure , abapDocumentation , AbapObjectStructure , activate , ActivationResult , adtCompatibilityGraph , AdtCompatibilityGraph , adtCoreDiscovery , AdtCoreDiscoveryResult , adtDiscovery , AdtDiscoveryResult , AdtLock , annotationDefinitions , bindingDetails , BindingServiceResult , checkRepo , ClassComponent , classComponents , classIncludes , codeCompletion , codeCompletionElement , codeCompletionFull , CompletionElementInfo , CompletionProposal , CreatableTypeIds , createObject , createRepo , createTestInclude , createTransport , createTransportsConfig , ddicElement , DdicElement , DdicObjectReference , ddicRepositoryAccess , DebugAttach , DebugBreakpoint , DebugBreakpointError , DebugChildVariablesInfo , Debuggee , debuggerAttach , debuggerChildVariables , debuggerDeleteBreakpoints , debuggerDeleteListener , debuggerGoToStack , debuggerGoToStackOld , debuggerListen , debuggerListeners , debuggerSaveSettings , DebuggerScope , debuggerSetBreakpoints , debuggerSetVariableValue , debuggerStack , debuggerStep , debuggerVariables , DebuggingMode , DebugListenerError , DebugSettings , DebugStackInfo , DebugStep , DebugStepType , DebugVariable , DefinitionLocation , deleteObject , Delta , dumps , DumpsFeed , externalRepoInfo , Feed , feeds , findDefinition , findObjectPath , fixEdits , FixProposal , fixProposals , FragmentLocation , fragmentMappings , getObjectSource , getTransportConfiguration , GitExternalInfo , GitObject , GitRemoteInfo , GitRepo , gitRepos , GitStaging , HierarchyNode , InactiveObject , InactiveObjectRecord , inactiveObjects , isClassStructure , isCreatableTypeId , isPackageType , loadTypes , lock , MainInclude , mainPrograms , NewObjectOptions , nodeContents , NodeParents , NodeStructure , objectRegistrationInfo , objectStructure , ObjectType , ObjectTypeDescriptor , objectTypes , packageSearchHelp , PackageValueHelpResult , PackageValueHelpType , PathStep , prettyPrinter , prettyPrinterSetting , PrettyPrinterSettings , PrettyPrinterStyle , publishServiceBinding , pullRepo , pushRepo , QueryResult , RegistrationInfo , remoteRepoInfo , Revision , renameEvaluate , renamePreview , renameExecute , RenameRefactoring , RenameRefactoringProposal , revisions , runQuery , runUnitTest , searchObject , SearchResult , ServiceBinding , setObjectSource , setPrettyPrinterSetting , setTransportsConfig , simpleDebuggerStack , stageRepo , switchRepoBranch , syntaxCheck , syntaxCheckCDS , SyntaxCheckResult , syntaxCheckTypes , SystemUser , systemUsers , tableContents , transportAddUser , TransportAddUserResponse , TransportConfiguration , TransportConfigurationEntry , transportConfigurations , transportDelete , transportInfo , TransportInfo , TransportOwnerResponse , transportReference , transportRelease , TransportReleaseReport , transportsByConfig , transportSetOwner , TransportsOfUser , typeHierarchy , UnitTestClass , unlinkRepo , unLock , unpublishServiceBinding , UsageReference , usageReferences , UsageReferenceSnippet , usageReferenceSnippets , userTransports , validateNewObject , ValidateOptions , ValidationResult } from "./api" ; import { followUrl , isString } from "./utilities" ; import https from 'https' ; export function createSSLConfig ( allowUnauthorized , ca ? ) { const agent = new https . Agent ( { keepAlive : true , rejectUnauthorized : false , } ) ; return { httpsAgent : agent } ; } interface HttpOptions { baseUrl : string ; username : string ; password : string | BearerFetcher ; client : string ; language : string ; options : ClientOptions ; } export class ADTClient { private discovery ? : AdtDiscoveryResult [ ] ; private fetcher ? : ( ) => Promise < string > ; public get httpClient ( ) { return this . h ; } public static mainInclude ( object , withDefault = true ) { if ( isPackageType ( object . metaData [ "adtcore:type" ] ) ) return object . objectUrl ; if ( isClassStructure ( object ) ) { const mainInclude = object . includes . find ( x => x [ "class:includeType" ] === "main" ) ; const mainLink = mainInclude && ( mainInclude . links . find ( x => x . type === "text/plain" ) || mainInclude . links . find ( x => ! x . type ) ) ; if ( mainLink ) return followUrl ( object . objectUrl , mainLink . href ) ; } else { const source = object . metaData [ "abapsource:sourceUri" ] ; if ( source ) return followUrl ( object . objectUrl , source ) ; const mainLink = object . links . find ( x => x . type === "text/plain" ) ; if ( mainLink ) return followUrl ( object . objectUrl , mainLink . href ) ; } return withDefault ? followUrl ( object . objectUrl , "/source/main" ) : object . objectUrl ; } public static classIncludes ( clas ) { const includes = new Map < classIncludes , string > ( ) ; for ( const i of clas . includes ) { const mainLink = i . links . find ( x => x . type === "text/plain" ) ; includes . set ( i [ "class:includeType" ] as classIncludes , followUrl ( clas . objectUrl , mainLink ! . href ) ) ; } return includes ; } private h : AdtHTTP ; private pClone ? : ADTClient ; private pIsClone ? : boolean ; private options : HttpOptions ; argument baseUrl argument username argument password argument client argument language constructor ( baseUrl , username , password , client = "" , language = "" , options = { } ) { if ( ! ( baseUrl && username && password ) ) throw adtException ( "Invalid ADTClient configuration: url, login and password are required" ) ; if ( typeof password !== "string" ) password = this . wrapFetcher ( password ) ; this . options = { baseUrl , username , password , client , language , options } ; this . h = this . createHttp ( ) ; } private createHttp ( ) { const o = this . options ; return new AdtHTTP ( o . baseUrl , o . username , o . password , o . client , o . language , o . options ) ; } private wrapFetcher : ( f : BearerFetcher ) => BearerFetcher = fetcher => { let fetchBearer ; if ( this . fetcher ) return this . fetcher ; this . fetcher = ( ) => { fetchBearer = fetchBearer || fetcher ( ) ; return fetchBearer ; } ; return this . fetcher ; } ; public get statelessClone ( ) : ADTClient { if ( this . pIsClone ) return this ; if ( ! this . pClone ) { const pw = this . fetcher || this . password ; if ( ! pw ) throw adtException ( "Not logged in" ) ; this . pClone = new ADTClient ( this . baseUrl , this . username , pw , this . client , this . language , this . options . options ) ; this . pClone . pIsClone = true ; } return this . pClone ; } public get stateful ( ) { return this . h . stateful ; } public set stateful ( stateful ) { if ( this . pIsClone ) throw adtException ( "Stateful sessions not allowed in stateless clones" ) ; this . h . stateful = stateful ; } public get loggedin ( ) { return this . h . loggedin ; } public get isStateful ( ) { return this . h . isStateful ; } public get csrfToken ( ) { return this . h . csrfToken ; } public get baseUrl ( ) { return this . h . baseURL ; } public get client ( ) { return this . h . client ; } public get language ( ) { return this . h . language ; } public get username ( ) { return this . h . username ; } private get password ( ) { return this . h . password ; } /**
     * Logs on an ADT server. parameters provided on creation
     */ public login ( ) { if ( ! this . h . username ) this . h = this . createHttp ( ) ; return this . h . login ( ) ; } memberof public logout ( ) { return this . h . logout ( ) ; } public dropSession ( ) { return this . h . dropSession ( ) ; } public get sessionID ( ) { const cookies = this . h . ascookies ( ) || "" ; const sc = cookies . split ( ";" ) . find ( c => ! ! c . match ( /SAP_SESSIONID/ ) ) ; return sc ? sc . split ( "=" ) : "" ; } public nodeContents ( parent_type , parent_name ? , user_name ? , parent_tech_name ? ) { return nodeContents ( this . h , parent_type , parent_name , user_name , parent_tech_name ) ; } public async reentranceTicket ( ) { const response = await this . h . request ( "/sap/bc/adt/security/reentranceticket" ) ; return "" + response . body || "" ; } public transportInfo ( objSourceUrl , devClass ? , operation = "I" ) { return transportInfo ( this . h , objSourceUrl , devClass , operation ) ; } public createTransport ( objSourceUrl , REQUEST_TEXT , DEVCLASS , transportLayer ? ) { return createTransport ( this . h , objSourceUrl , REQUEST_TEXT , DEVCLASS , "I" , transportLayer ) ; } public objectStructure ( objectUrl ) { return objectStructure ( this . h , objectUrl ) ; } public activate ( object , preauditRequested ? ) ; public activate ( objectName , objectUrl , mainInclude ? , preauditRequested ? ) ; public activate ( objectNameOrObjects , objectUrlOrPreauditReq = true , mainInclude ? , preauditRequested = true ) { if ( isString ( objectNameOrObjects ) ) return activate ( this . h , objectNameOrObjects , objectUrlOrPreauditReq as string , mainInclude , preauditRequested ) ; else return activate ( this . h , objectNameOrObjects , objectUrlOrPreauditReq as boolean ) ; } public inactiveObjects ( ) { return inactiveObjects ( this . h ) ; } public mainPrograms ( includeUrl ) { return mainPrograms ( this . h , includeUrl ) ; } public lock ( objectUrl , accessMode = "MODIFY" ) { return lock ( this . h , objectUrl , accessMode ) ; } public unLock ( objectUrl , lockHandle ) { return unLock ( this . h , objectUrl , lockHandle ) ; } param objectSourceUrl param gitUser param gitPassword public getObjectSource ( objectSourceUrl , gitUser ? , gitPassword ? ) { return getObjectSource ( this . h , objectSourceUrl , gitUser , gitPassword ) ; } public setObjectSource ( objectSourceUrl , source , lockHandle , transport ? ) { return setObjectSource ( this . h , objectSourceUrl , source , lockHandle , transport ) ; } param { string } query param { string } objType param { number } max returns memberof public searchObject ( query , objType ? , max = 100 ) { return searchObject ( this . h , query , objType , max ) ; } public findObjectPath ( objectUrl ) { return findObjectPath ( this . h , objectUrl ) ; } public validateNewObject ( options ) { return validateNewObject ( this . h , options ) ; } public createObject ( objtype , name , parentName , description , parentPath , responsible ? , transport ? ) ; public createObject ( options ) ; public createObject ( optionsOrType , name ? , parentName ? , description ? , parentPath ? , responsible = "" , transport = "" ) { if ( isCreatableTypeId ( optionsOrType ) ) { if ( ! name || ! parentName || ! parentPath || ! description ) throw adtException ( "" ) ; return createObject ( this . h , { description , name , objtype : optionsOrType as CreatableTypeIds , parentName , parentPath , responsible , transport } ) ; } else return createObject ( this . h , optionsOrType ) ; } public async featureDetails ( title ) { if ( ! this . discovery ) this . discovery = await this . adtDiscovery ( ) ; return this . discovery . find ( d => d . title === title ) ; } public async collectionFeatureDetails ( url ) { if ( ! this . discovery ) this . discovery = await this . adtDiscovery ( ) ; return this . discovery . find ( f => f . collection . find ( c => c . templateLinks . find ( l => l . template === url ) ) ) ; } public async findCollectionByUrl ( url ) { if ( ! this . discovery ) this . discovery = await this . adtDiscovery ( ) ; for ( const discoveryResult of this . discovery ) { const collection = discoveryResult . collection . find ( c => c . href === url ) ; if ( collection ) return { discoveryResult , collection } ; } } public hasTransportConfig = async ( ) => { const collection = await this . findCollectionByUrl ( "/sap/bc/adt/cts/transportrequests/searchconfiguration/configurations" ) ; return ! ! collection ; } ; public createTestInclude ( clas , lockHandle , transport = "" ) { return createTestInclude ( this . h , clas , lockHandle , transport ) ; } public objectRegistrationInfo ( objectUrl ) { return objectRegistrationInfo ( this . h , objectUrl ) ; } public deleteObject ( objectUrl , lockHandle , transport ? ) { return deleteObject ( this . h , objectUrl , lockHandle , transport ) ; } public loadTypes ( ) { return loadTypes ( this . h ) ; } public adtDiscovery ( ) { return adtDiscovery ( this . h ) ; } public adtCoreDiscovery ( ) { return adtCoreDiscovery ( this . h ) ; } public adtCompatibiliyGraph ( ) { return adtCompatibilityGraph ( this . h ) ; } public syntaxCheckTypes ( ) { return syntaxCheckTypes ( this . h ) ; } public syntaxCheck ( cdsUrl ) ; public syntaxCheck ( url , mainUrl , content , mainProgram ? , version ? ) ; public syntaxCheck ( url , mainUrl ? , content ? , mainProgram = "" , version = "active" ) { if ( url . match ( /^\/sap\/bc\/adt\/((ddic\/ddlx?)|(acm\/dcl))\/sources\// ) ) return syntaxCheckCDS ( this . h , url , mainUrl , content ) ; else { if ( ! mainUrl || ! content ) throw adtException ( "mainUrl and content are required for syntax check" ) ; return syntaxCheck ( this . h , url , mainUrl , content , mainProgram , version ) ; } } public codeCompletion ( sourceUrl , source , line , column ) { return codeCompletion ( this . h , sourceUrl , source , line , column ) ; } public codeCompletionFull ( sourceUrl , source , line , column , patternKey ) { return codeCompletionFull ( this . h , sourceUrl , source , line , column , patternKey ) ; } public async runClass ( className ) { const response = await this . h . request ( "/sap/bc/adt/oo/classrun/" + className . toUpperCase ( ) , { method : "POST" } ) ; return "" + response . body ; } param { string } sourceUrl param { string } source param { number } line param { number } column returns memberof public codeCompletionElement ( sourceUrl , source , line , column ) { return codeCompletionElement ( this . h , sourceUrl , source , line , column ) ; } public findDefinition ( url , source , line , startCol , endCol , implementation = false , mainProgram = "" ) { return findDefinition ( this . h , url , source , line , startCol , endCol , implementation , mainProgram ) ; } public usageReferences ( url , line ? , column ? ) { return usageReferences ( this . h , url , line , column ) ; } public usageReferenceSnippets ( references ) { return usageReferenceSnippets ( this . h , references ) ; } public fixProposals ( url , source , line , column ) { return fixProposals ( this . h , url , source , line , column ) ; } public fixEdits ( proposal , source ) { return fixEdits ( this . h , proposal , source ) ; } public runUnitTest ( url ) { return runUnitTest ( this . h , url ) ; } public classComponents ( url ) { return classComponents ( this . h , url ) ; } public fragmentMappings ( url , type , name ) { return fragmentMappings ( this . h , url , type , name ) ; } public objectTypes ( ) { return objectTypes ( this . h ) ; } public prettyPrinterSetting ( ) { return prettyPrinterSetting ( this . h ) ; } public setPrettyPrinterSetting ( indent , style ) { return setPrettyPrinterSetting ( this . h , indent , style ) ; } public prettyPrinter ( source ) { return prettyPrinter ( this . h , source ) ; } public typeHierarchy ( url , body , line , offset , superTypes = false ) { return typeHierarchy ( this . h , url , body , line , offset , superTypes ) ; } public transportConfigurations ( ) { return transportConfigurations ( this . h ) ; } public getTransportConfiguration ( url ) { return getTransportConfiguration ( this . h , url ) ; } public setTransportsConfig ( uri , etag , config ) { return setTransportsConfig ( this . h , uri , etag , config ) ; } public createTransportsConfig ( ) { return createTransportsConfig ( this . h ) ; } public userTransports ( user , targets = true ) { return userTransports ( this . h , user , targets ) ; } public transportsByConfig ( configUri , targets = true ) { return transportsByConfig ( this . h , configUri , targets ) ; } public transportDelete ( transportNumber ) { return transportDelete ( this . h , transportNumber ) ; } public transportRelease ( transportNumber , ignoreLocks = false , IgnoreATC = false ) { return transportRelease ( this . h , transportNumber , ignoreLocks , IgnoreATC ) ; } public transportSetOwner ( transportNumber , targetuser ) { return transportSetOwner ( this . h , transportNumber , targetuser ) ; } public transportAddUser ( transportNumber , user ) { return transportAddUser ( this . h , transportNumber , user ) ; } public systemUsers ( ) { return systemUsers ( this . h ) ; } public transportReference ( pgmid , obj_wbtype , obj_name ) { return transportReference ( this . h , pgmid , obj_wbtype , obj_name ) ; } public revisions ( objectUrl , clsInclude ? ) { return revisions ( this . h , objectUrl , clsInclude ) ; } public abapDocumentation ( objectUri , body , line , column , language = "EN" ) { return abapDocumentation ( this . h , objectUri , body , line , column , language ) ; } public packageSearchHelp ( type , name = "*" ) { return packageSearchHelp ( this . h , type , name ) ; } public gitRepos ( ) { return gitRepos ( this . h ) ; } public gitExternalRepoInfo ( repourl , user = "" , password = "" ) { return externalRepoInfo ( this . h , repourl , user , password ) ; } public gitCreateRepo ( packageName , repourl , branch = "refs/heads/master" , transport = "" , user = "" , password = "" ) { return createRepo ( this . h , packageName , repourl , branch , transport , user , password ) ; } public gitPullRepo ( repoId , branch = "refs/heads/master" , transport = "" , user = "" , password = "" ) { return pullRepo ( this . h , repoId , branch , transport , user , password ) ; } public gitUnlinkRepo ( repoId ) { return unlinkRepo ( this . h , repoId ) ; } public stageRepo ( repo , user = "" , password = "" ) { return stageRepo ( this . h , repo , user , password ) ; } public pushRepo ( repo , staging , user = "" , password = "" ) { return pushRepo ( this . h , repo , staging , user , password ) ; } public checkRepo ( repo , user = "" , password = "" ) { return checkRepo ( this . h , repo , user , password ) ; } deprecated public remoteRepoInfo ( repo , user = "" , password = "" ) { return remoteRepoInfo ( this . h , repo , user , password ) ; } public switchRepoBranch ( repo , branch , create = false , user = "" , password = "" ) { return switchRepoBranch ( this . h , repo , branch , create , user , password ) ; } public annotationDefinitions ( ) { return annotationDefinitions ( this . h ) ; } public ddicElement ( path , getTargetForAssociation = false , getExtensionViews = true , getSecondaryObjects = true ) { return ddicElement ( this . h , path , getTargetForAssociation , getExtensionViews , getSecondaryObjects ) ; } public ddicRepositoryAccess ( path ) { return ddicRepositoryAccess ( this . h , path ) ; } public publishServiceBinding ( name , version ) { return publishServiceBinding ( this . h , name , version ) ; } public unPublishServiceBinding ( name , version ) { return unpublishServiceBinding ( this . h , name , version ) ; } /** Reads table data - usually returns one line more than requested */ public tableContents ( ddicEntityName , rowNumber = 100 , decode = true , sqlQuery = "" ) { return tableContents ( this . h , ddicEntityName , rowNumber , decode , sqlQuery ) ; } /** Runs a given SQL query on the target */ public runQuery ( sqlQuery , rowNumber = 100 , decode = true ) { return runQuery ( this . h , sqlQuery , rowNumber , decode ) ; } public bindingDetails ( binding , index = 0 ) { return bindingDetails ( this . h , binding , index ) ; } public feeds ( ) { return feeds ( this . h ) ; } public dumps ( query ? ) { return dumps ( this . h , query ) ; } public debuggerListeners ( debuggingMode , terminalId , ideId , user , checkConflict ? ) ; public debuggerListeners ( debuggingMode , terminalId , ideId , user ? , checkConflict ? ) ; public debuggerListeners ( debuggingMode , terminalId , ideId , user ? , checkConflict = true ) { return debuggerListeners ( this . h , debuggingMode , terminalId , ideId , user , checkConflict ) ; } param { string } debuggingMode param { string } terminalId param { string } ideId param { string } user returns public debuggerListen ( debuggingMode , terminalId , ideId , user , checkConflict ? , isNotifiedOnConflict ? ) ; public debuggerListen ( debuggingMode , terminalId , ideId , user ? , checkConflict ? , isNotifiedOnConflict ? ) ; public debuggerListen ( debuggingMode , terminalId , ideId , user ? , checkConflict = true , isNotifiedOnConflict = true ) { return debuggerListen ( this . h , debuggingMode , terminalId , ideId , user , checkConflict , isNotifiedOnConflict ) ; } param { string } debuggingMode param { string } terminalId param { string } ideId param { string } user public debuggerDeleteListener ( debuggingMode , terminalId , ideId , user ) ; public debuggerDeleteListener ( debuggingMode , terminalId , ideId , user ? ) ; public debuggerDeleteListener ( debuggingMode , terminalId , ideId , user ? ) { return debuggerDeleteListener ( this . h , debuggingMode , terminalId , ideId , user ) ; } public debuggerSetBreakpoints ( debuggingMode , terminalId , ideId , clientId , breakpoints , user , scope ? , systemDebugging ? , deactivated ? ) ; public debuggerSetBreakpoints ( debuggingMode , terminalId , ideId , clientId , breakpoints , user ? , scope ? , systemDebugging ? , deactivated ? ) ; public debuggerSetBreakpoints ( debuggingMode , terminalId , ideId , clientId , breakpoints , user ? , scope = "external" , systemDebugging = false , deactivated = false ) { return debuggerSetBreakpoints ( this . h , debuggingMode , terminalId , ideId , clientId , breakpoints , user , scope , systemDebugging , deactivated ) ; } public debuggerDeleteBreakpoints ( breakpoint , debuggingMode , terminalId , ideId , requestUser , scope ? ) ; public debuggerDeleteBreakpoints ( breakpoint , debuggingMode , terminalId , ideId , requestUser ? ) ; public debuggerDeleteBreakpoints ( breakpoint , debuggingMode , terminalId , ideId , requestUser ? , scope = "external" ) { return debuggerDeleteBreakpoints ( this . h , breakpoint , debuggingMode , terminalId , ideId , requestUser , scope ) ; } public debuggerAttach ( debuggingMode , debuggeeId , user , dynproDebugging ? ) ; public debuggerAttach ( debuggingMode , debuggeeId , user ? , dynproDebugging ? ) ; public debuggerAttach ( debuggingMode , debuggeeId , user ? , dynproDebugging = false ) { return debuggerAttach ( this . h , debuggingMode , debuggeeId , user , dynproDebugging ) ; } public debuggerSaveSettings ( settings ) { return debuggerSaveSettings ( this . h , settings ) ; } public async debuggerStackTrace ( semanticURIs = true ) { const stack = await this . collectionFeatureDetails ( "/sap/bc/adt/debugger/stack" ) ; if ( stack ) return debuggerStack ( this . h , semanticURIs ) ; else return simpleDebuggerStack ( this . h , semanticURIs ) ; } public debuggerVariables ( parents ) { return debuggerVariables ( this . h , parents ) ; } public debuggerChildVariables ( parent = [ "@DATAAGING" , "@ROOT" ] ) { return debuggerChildVariables ( this . h , parent ) ; } public debuggerStep ( steptype , url ) ; public debuggerStep ( steptype ) ; public debuggerStep ( steptype , url ? ) { return debuggerStep ( this . h , steptype , url ) ; } param urlOrPosition public debuggerGoToStack ( urlOrPosition ) { if ( isString ( urlOrPosition ) ) return debuggerGoToStack ( this . h , urlOrPosition ) ; else return debuggerGoToStackOld ( this . h , urlOrPosition ) ; } public debuggerSetVariableValue ( variableName , value ) { return debuggerSetVariableValue ( this . h , variableName , value ) ; } public renameEvaluate ( uri , line , startColumn , endColumn ) { return renameEvaluate ( this . h , uri , line , startColumn , endColumn ) ; } public renamePreview ( renameRefactoring , transport = "" ) { return renamePreview ( this . h , renameRefactoring , transport ) ; } public renameExecute ( refactoring ) { return renameExecute ( this . h , refactoring ) ; } }