Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

navidev-adt-api

Package Overview
Dependencies
Maintainers
0
Versions
72
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

navidev-adt-api

API de conexión al Abap Developer Tools

  • 0.7.5
  • latest
  • npm
  • Socket score

Version published
Maintainers
0
Created
Source

Objetivo

El objetivo es disponer de una API que permita conectar con el ADT, Abap Developer Tools, para permitirnos crear programa, clases, mensajes, etc.. Desde cualquier aplicación hecha en JS/TS, ya que esta API ha sido creada en node para que pueda usarse en cualquier framework de JS, como React.

Esta herramienta o API se inspira, por no decir que algunas partes se basan en esa API, en la Abap ADT API creada por Marcello Urbani para su extensión de VS Code llamada ABAP Remote FS.

La diferencia entre ambas API , aparte que la mia tiene menos funcionalidad al menos incialmente, es que la he creado intentado usar metodología DDD, para tener una mejor estructuración. Y algunas cosas de que Marcello las hace de una manera yo las he planteado de otra manera.

Y me gustaría destacar el esfuerzo de Marcello para crear semejante API y extensión de VS Code.

Instalación

Desde el terminal solo tenemos que instalarlo con nuestro gestor de paquetes favorito:

pnpm install navidev-adt-api

o

npm install navidev-adt-api

Como usarla

En nuestro código lo primero es importarla de la siguiente manera:

import AdtAPI from "navidev-adt-api/AdtAPI"

A destacar lo siguiente:

  • Todas las llamadas devuelven siempre una Promesa que hay que tratar para recuperar los valores o los errores.
  • La clase devuelve excepciones pero no es necesario capturarla con un try..catch en caso de errores de cualquier índole.

En el siguiente apartado se explica como recuperar los valores y errores

Como recuperar valores y errores

A modo de ejemplo pongo la llamada que nos devuelve una lista con todos los objetos del ADT:

Ejemplo de llamada:

adtApi.repositoryreadTypesStructure().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as RepositoryTypesStructure;
		console.log(values);
	} else if (response.isFailure) {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

La respuesta tiene dos variables: isSucces que será true si la petición ha ido correctamente, y recuperaremos los valores a través del método getValue, y la segunda isFailure que será true si se ha producción cualquier tipo de error del proceso, el error se recuperá mediante el metodo getErrorValue. El error devuelto será siempre del tipo AdtException. Habrá que mirar los campos informados que variarán según a la API que se llame.

Este ejemplo se hace un else if para mirar si ha fallado a modo de ejemplo completo, pero realmente si isSuccess es false es que se ha producido un error que habrá que procesarlo tal como se ve en el ejemplo.

Esta manera de recuperar los valores y errores será igual para toda la API.

API

Laa funcionalidad de la API esta repartida entre varias clases. En cualquier caso, siempre se instanciará pasandole los datos de conexión:

let adtConnection = new AdtConnection({
	client: "001",
	language: "EN",
	password: "password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

En el ejemplo se usa la clase AdtConnection.

Una vez instanciada se podrá acceder a todos los método disponibles que se explican a continuación.

Login

Clase: AdtConnection

Método: Login

Este método aunque no es necesario, ya que se establece la conexión automática, si que se puede usar para dos cosas:

  1. Validar que es posible acceder al sistema con los datos proporcionados.
  2. Recuperar el token de autentificación para pasarlos en sucesivas llamadas evitando hacer login cada vez que se use una funcionalidad.

Ejemplo de llamada:

let adtConnection = new AdtConnection({
	client: "001",
	language: "EN",
	password: "password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
}).login().then((response) => {
		if( response.isSuccess){
            let values = response.getValue() as ResultConnection;
			console.log(`Bearer token: ${values.connectionAuth.bearerToken}`)
			console.log(`Cookies auth: ${values.connectionAuth.cookiesAuth}`)
        }
		else{
            let adtException = response.getErrorValue() as AdtException;
		    // Tratamiento del error
        }
	});

En el ejemplo se muestra en consola los dos campos de autentificación que se pasarán a los siguientes métodos de las clases que se quiera usar. Ejemplo:

adtConnection.login().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as ResultConnection;

		let adt = new AdtTransport({
			client: "001",
			language: "EN",
			password: "password",
			bearerToken: values.connectionAuth.bearerToken,
			cookiesAuth: values.connectionAuth.cookiesAuth,
			username: "DEVELOPER",
			urlBase: "http://vhcala4hci:50000",
		});
	}
});

Al método también se le pasa el usuario y password por si los token de autentificación ya no son validos, han caducado, para que se vuelve hacer el login.

General

Usuarios del sistema

Clase: AdtGeneral

Método: getUsers

Devuelve los usuarios del sistema. Devuelve el codigo de usuario y el nombre.

Ejemplo de llamada:

let general = new AdtGeneral({
			client: "001",
			language: "EN",
			password: "password",
			bearerToken: values.connectionAuth.bearerToken,
			cookiesAuth: values.connectionAuth.cookiesAuth,
			username: "DEVELOPER",
			urlBase: "http://vhcala4hci:50000",
		});
		general.getUsers().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as Users;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Repositorio

Listado de tipos de estructura(Arbol ADT)

Clase: AdtRepository

Método: readTypesStructure

Devuelve el listado de los tipos en el arbol de estructura en ADT. Son los nodos que podemos ver en la SE80 o Eclipse.

Ejemplo de llamada:

let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository.readTypesStructure().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as RepositoryTypesStructure;
		console.log(values);
	} else  {
		let adtException = response.getErrorValue() as AdtException;
		// Tratmiento del error
	}
});

Listado de tipos objetos

Clase: AdtRepository

Método: repositoryReadObjectTypes

Devuelve el listado de los tipos de objetos de ADT: Programa, clases, Webdynpro, etc..

Ejemplo de llamada:

let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository.readObjectTypes().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as RepositoryObjectTypes;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Listado de tipos de objetos que se pueden validar

Clase: AdtRepository

Método: repositoryReadCheckRuns

Devuelve el listado de los tipos de objetos que se pueden validar o compilar: programas, clases, funciones, diccionario, etc.

Ejemplo de llamada:

let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository.repositoryReadCheckRuns().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as RepositoryCheckRuns;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Metadatos para poder buscar objetos

Clase: AdtRepository

Método: repositorySearchMetadata

Devuelve la combinación de tipos objetos que se pueden usar para hacer búsquedas de objetos. Ejemplo: En clases nos devolverá el tipo CLASS y los subtipos: OA(atributo de clase), OC(clase), OCE(evento), etc..

Los campos destacados que devuelve el método son:

  • trobjtype -> Tipo de objeto: CLAS (clase), DEVC(paquete), etc
  • legacy_type -> Subtipo: OA(atributo de clase), OC(clase), OCE(evento), etc..
  • descriptionsingular y description_plural -> Descripción del campo _legacy_type
  • descriptionencl_object -> Descripción del campo _trobjtype

Ejemplo de llamada:

let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository.searchMetadata().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as SearchMetadatas;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Búsqueda de objetos

Clase: AdtRepository

Método: searchObjectSingleType

Realiza la busqueda individual de objetos, es decir, por un tipo y subtipo. Al método se le pasa el tipo, subtipo y el texto a buscar. El texto a buscar puede ser un patron: *zclmyclass** para que devuelva los posibles valores.

Para búsqueda rápidas, como verificar si existe una clase o devolver paquetes que tengan un patrón, es recomendable usar el método repositoryQuickSearch de la API ya que no es necesario saberse el subtipo en concreto.

Los campos que devuelve el método son:

  • uri -> URL del objeto, esta URL se usará para obtener sus contenido, activación, grabación, etc.
  • type -> Tipo de objeto
  • name -> Nombre del objeto
  • packageName -> Paquete al que esta asociado

Ejemplo de llamada:

let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository
	.repositoryIndividualSearchObjects(
		"CLAS",
		"OC",
		"zcl_zsap_tools_core_dpc_ext"
	)
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as SearchObjects;
			console.log(values);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});

En este ejemplo de llamada se le pasa el tipo "CLAS" y el subtipo "OC" (clase en si misma) y el nombre de la clase a búscar.

Búsqueda rápida de objetos

Clase: AdtRepository

Método: quickSearch

Muy parecido a la búsqueda individual de objetos pero aquí la diferencia es que solo se pasa el tipo de objeto y el texto o patrón del objeto. Este método es el más indicando para búsquedas estilo:"Dame todos los paquetes que comiencen por ZCA*".

Los campos que devuelve el método son:

  • uri -> URL del objeto, esta URL se usará para obtener sus contenido, activación, grabación, etc.
  • type -> Tipo de objeto
  • name -> Nombre del objeto
  • packageName -> Paquete al que esta asociado

Ejemplo de llamada:


let adtRepository = new AdtRepository({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtRepository.quickSearch("DEVC", "zca*").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as SearchObjects;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Paquetes

Listado de clases de desarrollo o paquetes

Clase: AdtPackage

Método: readAllPackages

Devuelve el listado todos los paquetes de desarrollo del sistema

Ejemplo de llamada:


let adtPackage = new AdtPackage({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtApi.packageReadPackages().then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as PackagesList;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Contenido de un paquete

Clase: AdtPackage

Método: packageReadContent

Devuelve el contenido de un paquete. El contenido devuelto es parecido a la estructura que vemos en el Eclipse: |- Nombre del paquete |-- categories -> Categorias de los objetos: Codigo fuente, diccionario, clases de mensaje, etc. |---- objectTypes -> Tipos de objeto clases, programas, dominios, etc. |----- objects -> Objetos del tipo: Nombre del objeto. De este nodo destacar el valor del campo objectUri, esta es la URL que se le pasará a otros servicio como el que obtiene estructuras, etc.. y el campo objectName que nos servirá en método como el de activar |-- Subpaquetes -> Objeto que contiene la misma estructura que la anterior de manera recursiva.

Ejemplo de llamada:

let adtPackage = new AdtPackage({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtPackage.readPackagesContent("ZSAP_TOOLS").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as PackageContent;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Contenido de un paquete en formato plano

Clase: AdtPackage

Método: packageReadContentFlat

Se basa en el método packageReadContent pero en vez de devolver los paquetes en subniveles los devuelve en un formato plano:

|- Nivel |- Paquete superior o padre |- Nombre del paquete |-- categories -> Categorias de los objetos: Codigo fuente, diccionario, clases de mensaje, etc. |---- objectTypes -> Tipos de objeto clases, programas, dominios, etc. |----- objects -> Objetos del tipo: Nombre del objeto. De este nodo destacar el valor del campo objectUri, esta es la URL que se le pasará a otros servicio como el que obtiene estructuras, etc.. y el campo objectName que nos servirá en método como el de activar

Ejemplo de llamada:

let adtPackage = new AdtPackage({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtPackage.readPackageReadContentFlat("ZSAP_TOOLS").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as PackageContentsFlat;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Objeto

Obtener la estructura

Clase: AdtAbapObject

Método: objectReadStructure

Devuelve la estructura de un objeto: variables, constantes, métodos, interfaces y su posición. Es decir, lo que en el eclipse se ve en el outline. Dependiendo del tipo de objeto devuelve varias posiciones dividido por secciones. Ejemplo si tenemos esta declaración:

    INTERFACES zif_spt_core_app .

Nos devolverá dos secciones: definitionIdentifier donde indica linea y columna donde comienza y finaliza el texto zif_spt_core_app. Y otro registro con el bloque definitionBlock donde indica linea y columna donde comienza y finaliza el texto INTERFACES zif_spt_core_app .

Al método se le pasa la URL del objeto que se quiere obtener los datos. Esa URL se recupera de la lectura de los objetos de los paquetes en el array objects campo objectUri.

La estructura que devuelve es:

|- Campos del objeto y tipo |-- structureElements Array con las variables, constantes, etc.. que se usa |--- blockInfo Array con la información de los bloques y su posiciones.

Ejemplo de llamada:

let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

    adtObject
	.readObjectStructure("/sap/bc/adt/oo/classes/zcl_spt_apps_base")
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectStructure;
			console.log(values);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});

Validación de sintaxis

Clase: AdtAbapObject

Método: checkRun

Hace la validación de sintaxis de un objeto. La validación de la sintaxis se puede hacer de dos maneras:

  • Pasandole la URL directamente esto hace que se valide la versión activa del objeto.

Ejemplo de como se haría la llamada en este caso:

let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject.checkRun("/sap/bc/adt/oo/classes/zcl_spt_apps_base")
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectCheckRun;
			console.log(values);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});
  • Pasandole la URL del objeto y los artifacts. El artifact son los subcomponentes del objeto y el contenido del mismo. El contenido hay que pasarlo en base64. Ejemplo de llamada en un clase:
let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject.checkRun("/sap/bc/adt/oo/classes/zcl_test_adt", [
		{
			sourceUri:
				"includes/implementations",
			artifactContent:
				"KiIqIHVzZSB0aGlzIHNvdXJjZSBmaWxlIGZvciB0aGUgZGVmaW5pdGlvbiBhbmQgaW1wbGVtZW50YXRpb24gb2YNCioiKiBsb2NhbCBoZWxwZXIgY2xhc3NlcywgaW50ZXJmYWNlIGRlZmluaXRpb25zIGFuZCB0eXBlDQoqIiogZGVjbGFyYXRpb25zDQoNCmNsYXNzIGxjbF9jb250cm9sbGVyIERFRklOSVRJT04uDQpwdWJsaWMgc2VjdGlvbi4NCm1ldGhvZHMgbWV0b2RvMi4NCg0KRU5EQ0xBU1MuDQoNCmNsYXNzIGxjbF9jb250cm9sbGVyIElNUExFTUVOVEFUSU9OLg0KRU5EQ0xBU1Mu",
		},
		{
			sourceUri:
				"source/main",
			artifactContent:
				"Y2xhc3MgWkNMX1RFU1RfQURUIGRlZmluaXRpb24NCiAgcHVibGljDQogIGZpbmFsDQogIGNyZWF0ZSBwdWJsaWMgLg0KDQpwdWJsaWMgc2VjdGlvbi4NCg0KICBkYXRhIE1WX1ZBUjIgdHlwZSBTVFJJTkcgLg0KDQogIG1ldGhvZHMgTUVUT0RPMSAuDQogIFBST1RFQ1RFRCBTRUNUSU9OLg0KICBQUklWQVRFIFNFQ1RJT04uDQpFTkRDTEFTUy4NCg0KDQoNCkNMQVNTIFpDTF9URVNUX0FEVCBJTVBMRU1FTlRBVElPTi4NCg0KDQogIE1FVEhPRCBtZXRvZG8xLg0KICAgIFdSSVRFOi8gJ2RkJy4uDQogIEVORE1FVEhPRC4NCkVORENMQVNTLg==",
		}
	])
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectCheckRun;
			console.log(values.messagesList);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});

Al ser un array se pueden pasar varios includes, tal como se ve en el ejemplo anterior. Eso si, en la versión de ABAP del trial versión que estoy usando si ambos includes tienen errores de código devuelve solo el primer error. Eso si, la API esta preparada para devolver todos los posibles mensajes que devuelta el ADT.

La URL principal del objeto viene cuando se leen los objetos de un paquete, en el array objects esta el campo objectUri con su valor.

El sourceUri de los artifacts depende del objeto que se esta procesando. En el caso de las clases se obtiene cuando se lee su contenido con el método classReadContent encontraremos el valor en el campo sourceUri en el array sourceIncludes.

En ambos tiposde llamada la estructura que devuelve es:

|- Campos de salida genericos de la validación. |-- messagesList Listado de con los mensajes devuelve en la validación. En el campo type con los valores: 'E' error y 'W' warning. shortText con el mensaje, pos posición del mensaje y quickFix si propuesta para arreglo rapido.

Bloqueo de objetos

Clase: AdtAbapObject

Método: lock

Bloquea un objeto antes de poder editarlo. Si el objeto ya esta bloqueado se recupera quien lo esta bloqueando en la excepción que se recupera.

Al método se le pasa la URL que se recupera de la lectura de los objetos de los paquetes en el array objects campo objectUri.

En la respuesta del bloqueo hay que tener en cuenta dos campos para la edición:

  • lockHandle -> Devuelve el ID del bloqueo que se pasará al grabar y desbloquear el objeto.
  • corrnr -> Orden de transporte asociado al objeto, que se pasará al grabar el objeto.

Ejemplo de llamada:


let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject.lock("/sap/bc/adt/oo/classes/zcl_spt_apps_base")
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectLock;
			console.log(`lock handle: ${values.lockHandle}`);
			console.log(`Transport order: ${values.corrnr}`);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException.message);
		}
	});

Desbloqueo de objetos

Clase: AdtAbapObject

Método: unlock

Desbloquea un objeto. Al método se le pasa la URL que se recupera de la lectura de los objetos de los paquetes en el array objects campo objectUri, y se le pasa el valor del campo lockHandle que se recupera en el bloqueo.

El método no devuelve nada si todo ha ido bien.

Ejemplo de llamada:


let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject
	.lock("/sap/bc/adt/oo/classes/zcl_spt_apps_base")
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectLock;
			console.log(`lock handle: ${values.lockHandle}`);
			console.log(`Transport order: ${values.corrnr}`);
			adtObject
				.unlock(
					"/sap/bc/adt/oo/classes/zcl_spt_apps_base",
					values.lockHandle
				)
				.then((response) => {
					if (response.isSuccess) {
					} else {
						let adtException = response.getErrorValue() as AdtException;
						console.log(adtException.message);
					}
				});
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException.message);
		}
	});

Activación de objetos

Clase: AdtAbapObject

Método: activate

Activa un objeto. Al método se le pasa la URL que se recupera de la lectura de los objetos de los paquetes en el array objects campo objectUri, y se le pasa el nombre del objeto, campo objectName que también estado en el array donde recuperamos el objectUri.

El método no devuelve nada si todo ha ido bien. Si hay errores de sintaxis en la activación los mensajes vienen en nodo messages.

Ejemplo de llamada:


let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject
	.activate("/sap/bc/adt/oo/classes/zcl_test_adt", "ZCL_TEST_ADT")
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectActivate;
			if (values.messages) console.log(values);
			else console.log("ok");
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});

Element info

Clase: AdtAbapObject

Método: elementInfo

Devuelve la información de un elemento para una línea y posición del código fuente pasado. Al método se le pasa la url del objeto más su sección (para objetos donde tiene codigo fuente en varias secciones como las clases), se le pasa la línea y posición donde esta el elemento a obtener información y se le pasa el codigo fuente a analizar.

Ejemplo de llamada:

let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtApi
	.elementInfo(
		"/sap/bc/adt/oo/classes/zcl_spt_apps_base/source/main",
		32,
		48,
		content
	)
	.then((response) => {
		if (response.isSuccess) {
			let values = response.getValue() as ObjectElementInfo;
			console.log(values);
		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException);
		}
	});

Clases

Contenido de una clase

Clase: AdtAbapObject

Método: readContent

Devuelve el contenido de una clase. Ese contenido se separa en dos partes:

  1. Metadatos: nombre de clase, tipo, datos de creación y modificación
  2. Includes con el código fuente de cada parte de la clase: definiciones/implementaciones clases locales, macros, testing y código principal. El código fuente principal esta en el include, campo includeType, "main".

Al método se le pasa la URL del objeto que se recupera al leer el contenido de los objetos de las clases de desarrollo.

Ejemplo de llamada:

let adtClass = new AdtClass({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtClass.readContent("/sap/bc/adt/oo/classes/zcl_spt_apps_base").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as ClassContent;
		console.log(values);
	} else {
		let adtException = response.getErrorValue() as AdtException;
		console.log(adtException);
	}
});

Grabar contenido

Clase: AdtAbapObject

Método: saveContent

Graba el contenido de una clase al método se le pasa:

  1. URL del objeto.
  2. Sección del objeto.
  3. Contenido de la clase
  4. Objeto del bloqueo
  5. Orden de transporte

Ejemplo de llamada:

let adtObject = new AdtAbapObject({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

let adtClass = new AdtClass({
	client: "001",
	language: "EN",
	password: "Password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
});

adtObject
	.lock("/sap/bc/adt/oo/classes/zcl_spt_apps_base")
	.then((response) => {
		if (response.isSuccess) {
			adtApi
			.classSave(
				"/sap/bc/adt/oo/classes/zcl_test_adt",
				"/source/main",
				data,
				values.lockHandle,
				values.corrnr
			)
			.then((responseSave) => {
				if (responseSave.isSuccess) {
					console.log("clase grabada");
				} else {
					let adtException = response.getErrorValue() as AdtException;
					console.log(adtException.message);
				}
				adtObject
				.unlock(
					"/sap/bc/adt/oo/classes/zcl_spt_apps_base",
					values.lockHandle
				)
				.then((response) => {
					if (response.isSuccess) {
					} else {
						let adtException = response.getErrorValue() as AdtException;
						console.log(adtException.message);
					}
				});
				})

		} else {
			let adtException = response.getErrorValue() as AdtException;
			console.log(adtException.message);
		}
	});

Transportes

La funcionalidad deque proporciona el ADT para la gestión de las ordenes de transporte dependerá de la versión del ABAP que se tenga. A mayor versión más funcionalidad se tiene.

Ejemplo, en la versión ABAP Trial Innovation Package que tiene la versión 7.51 es posible recuperar las ordenes de un usuario, añadir empleado, cambiar propietario o liberarlo. Mientras que en la versión ABAP Trial 2022 que contiene el ABAP 7.5H, la misma que en las ultimas versión del S/4 o ABAP Cloud, es posible crear ordenes, añadir objetos, borrarlos, etc..

Otro detalle importe es que hay información adicional, como en el método que recuperan las ordenes del usuario, que varia según la versión de ABAP. A mayor versión puede tener más información adicional.

Una manera que he detectado como distinguir las versiones antiguas de las más modernas es a través de la obtención de la configuración interna para obtener las ordenes del usuario, y será lo primero que se explique en los ejemplos. En los ejemplo se intentará comentar en que versión de ABAP esta disponible.

En los ejemplos que se pongan la parte de conexión se va omitir pero siempre se harán de la siguiente manera:

let adtConnection = new AdtConnection({
	client: "001",
	language: "EN",
	password: "password",
	username: "DEVELOPER",
	urlBase: "http://vhcalnplci.dummy.nodomain:8000",
}).login().then((response) => {
		if( response.isSuccess) {

			let values = response.getValue() as ResultConnection;
            let adt = new AdtTransport({
			client: "001",
			language: "EN",
			password: "password",
			bearerToken: values.connectionAuth.bearerToken,
			cookiesAuth: values.connectionAuth.cookiesAuth,
			username: "DEVELOPER",
			urlBase: "http://vhcala4hci:50000",
		});
        }
		else{
            let adtException = response.getErrorValue() as AdtException;
		    // Tratamiento del error
        }
	} else {
		let valuesError = response.getErrorValue();
		console.log(valuesError);
	}
});

Se podría llamar directamente a la clase AdtTransport sin necesidad de hacer login previamente, porque se hace login de manera automática.

Configuración

Para haceros una idea la configuración es como la pantalla inicial de la transación SE09/SE10 que nos permite buscar las ordenes en el SAPGUI. Este servicio de configuración esta en versiones modernas de ABAP, en la 7.51 no existe.

Metadata

Clase: AdtTransport

Método: getConfigurationMetadata

Obtiene los campos de selección que se usan para cambiar los valores de la configuración y devuelve el valor por defecto.

Este servicio en el ADT lo llama en la pantalla para cambiar los filtros de selección.

Ejemplo de llamada:

adt.getConfigurationMetadata().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportConfigurationMetadata;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});
Obtener ID de configuración

Clase: AdtTransport

Método: searchConfigurations

Es posible tener más de una configuración según como se llame al servicio de actualizar la configuración, pero he decido devolver solo la configuración más reciente tal como hace el ADT.

Nota: Este servicio solo esta disponible en versiones ABAP más recientes, con lo cual si el método te devuelve que no ha ido bien y el codigo de error 404 entonces estás en una versión de ABAP antigua y no podrás usar determina funcionalidad.

Ejemplo de llamada:

adt.searchConfigurations().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as SearchConfigurations;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				if (valuesError.err==404)
					console.log("Tienen una versión ABAP antigua")
				else
					console.log(valuesError.message);
			}
		});
Obtener los valores de la configuración

Clase: AdtTransport

Método: getConfiguration

Al método hay que pasarle el ID de configuración obtenido con el método searchConfigurations y devuelve una estructura con los valores.

Ejemplo de llamada:

adt.searchConfigurations().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as SearchConfigurations;
				adt.getConfiguration(values.idConfiguration).then((response) => {
					if (response.isSuccess) {
						let valuesConf = response.getValue() as TransportConfiguration;
					} else {
						let valuesError = response.getErrorValue() as AdtException;
						console.log(valuesError.message);
					}
				});
		} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});
Modificar los valores de la configuración

Clase: AdtTransport

Método: setConfiguration

Al método hay que pasarle el ID de configuración obtenido con el método searchConfigurations, la estructura de datos obtenida en el método getConfiguration pero con los ajustes necesarios y como opcional esta el valor ETAG que se recupera el método searchConfigurations. El campo ETAG si no se informa generará una configuración nueva y si se pasa se actualiza la existente. Vía ADT siempre se pasa por lo cual siempre se actualiza la misma.

Ejemplo de llamada:

adt.searchConfigurations().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as SearchConfigurations;
				adt.getConfiguration(values.idConfiguration).then((response) => {
					if (response.isSuccess) {
						let valuesConf = response.getValue() as TransportConfiguration;
						valuesConf.transportOfCopies = true;
						valuesConf.dateFilter = TransportDateFilter.DateRange;
						valuesConf.fromDate = new Date("2024-06-01");
						valuesConf.toDate = new Date("2024-06-20");
						adt
							.setConfiguration(values.idConfiguration, valuesConf, values.etag)
							.then((response2) => {
								if (response2.isSuccess) {
									let valuesConf2 =
										response2.getValue() as TransportConfiguration;
									console.log(valuesConf2);
								} else {
									let valuesError = response2.getErrorValue() as AdtException;
									console.log(valuesError.message);
								}
							});
					} else {
						let valuesError = response.getErrorValue() as AdtException;
						console.log(valuesError.message);
					}
				});
		} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Obtener ordenes del usuario

Hay dos métodos para obtener las ordenes del usuarios según la versión de ABAP que se tenga. Lo he separado en dos métodos porque los parámetros de entrada son distintos.

En ambos métodos la estructura de datos que se devuelve es siempre la misma (como se ha comentado anteriormente habrá campos informados si la versión ABAP es más reciente) y es la siguiente:

|- workbench -> Array de ordenes de tipo Workbench |-- Task -> Array con las tareas |---- Objects --> Array con los objetos |---- Links --> Links con las acciones posibles |---- Campos informativos |-- Campos informativos |- customizing -> Array de ordenes de tipo customizing con los mismo subniveles que las ordenes de workbench.

Obtener usuario en versiones <= 7.51

Clase: AdtTransport

Método: getUsersOrdersWOConf

Se le pasa el usuario el cual queremos leer sus ordenes.

Ejemplo de llamada:

adt.getUsersOrdersWOConf("DEVELOPER").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as UserOrders;
		console.log(values);
	} else {
		let valuesError = response.getErrorValue() as AdtException;
		console.log(valuesError.message);
	}

})
Obtener usuario en versiones <= 7.51

Clase: AdtTransport

Método: getUsersOrders

Tiene dos parámetros opcionales:

  • El primer es el target que será true y devuelve la información del sistema al cual se va a transportar. En el ADT esto es un nivel más yo he decidido devolveré como un campo más de información en la orden.
  • El segundo es el ID de configuración, si no se pasa se recuperará el más reciente y se usa para buscar las ordenes.

Ejemplo de llamada:

adt.getUsersOrders("DEVELOPER").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as UserOrders;
		console.log(values);
	} else {
		let valuesError = response.getErrorValue() as AdtException;
		console.log(valuesError.message);
	}

});

Detalle de una orden/tarea

Clase: AdtTransport

Método: detailOrderTask

Devuelve el detalle de una orden o tarea. La información devuelta es la misma que la que se recupera al obtener las ordenes del usuario, pero en este caso solo habrá una orden.

adt.detailOrderTask("A4HK900101").then((response) => {
			if (response.isSuccess) {
				//let values = response.getValue() as TransportAddObject;
				//console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Añadir usuario a una orden

Clase: AdtTransport

Método: addUserOrder

Versión ABAP: Todas

Método que se le pasa la orden y el usuario ha añadir. Este método es valido en todas las versiones ABAP.

Ejemplo de llamada:

adt.addUserOrder("A4HK900101", "BWDEVELOPER").then((response) => {
	if (response.isSuccess) {
		let values = response.getValue() as TransportTask;
			console.log(values);
	} else {
		let valuesError = response.getErrorValue() as AdtException;
		console.log(valuesError.message);
	}

})

Crear una orden

Clase: AdtTransport

Método: createOrder

Versión ABAP: > 7.51

Método que se le pasa la descripción de la orden, el tipo de la orden y el usuario de la misma.

Ejemplo de llamada:

adt.createOrder("prueba", TransportOrderTaskType.Workbench, "DEVELOPER")
			.then((response) => {
				if (response.isSuccess) {
					let values = response.getValue() as TransportCreateOrder;
					console.log(values);
				} else {
					let valuesError = response.getErrorValue() as AdtException;
					console.log(valuesError.message);
				}
			});

Borrar una orden/tarea

Clase: AdtTransport

Método: deleteOrder

Versión ABAP: Todas

Método que se le pasa la orden o tarea a eliminar. Este método es valido en todas las versiones ABAP.

Ejemplo de llamada:

adt.deleteOrder("A4HK900044").then((response) => {
	if (response.isSuccess) {
		console.log("borrada");
	} else {
		let valuesError = response.getErrorValue() as AdtException;
		console.log(valuesError.message);
	}

})

Liberar una orden/tarea

Clase: AdtTransport

Método: releaseOrder

Versión ABAP: Todas

Método que se le pasa la orden o tarea a liberar. Si la liberación no es posible, ejemplo se intenta liberar una orden sin haber liberado sus tareas o no pasar los controles del ATC, el mensaje de error se tiene que recuperar mediante el método getErrorValue de la clase devuelta en la API.

A modo informativo el ADT en el eclipse busca la el ID del ATC por defecto para pasarselo en el proceso de liberación. Este método esa búsqueda se hace por internamente, pero hay que tener en cuenta que siempre se ejecuta el ATC al liberar una orden. Igual que se lanza cuando se libera una orden desde la SE09/SE10.

Ejemplo de llamada:

adt.releaseOrder("A4HK900101").then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportReleaseOrder;
				console.log(values);
			} else {
				// Mensajes de error técnico y funcionales(validaciones ATC,
				// otros validaciones propias de la liberación).
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Cambiar el usuario de una orden/tarea

Clase: AdtTransport

Método: changeUserOrder

Versión ABAP: Todas

Método que se le pasa la orden o tarea y el nuevo usuario.

Ejemplo de llamada:

Ejemplo de llamada:

adt.changeUserOrder("NPLK900263", "BWDEVELOPER").then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as ChangeUserOrder;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Cambiar el tipo de tarea

Clase: AdtTransport

Método: changeTaskType

Versión ABAP: > 7.51

Cambia el tipo de tarea. Los tipos permitidos están en la enumeración TransportTaskType

Ejemplo de llamada:

adt
			.changeTaskType("A4HK900100", TransportTaskType.DevelopmentCorrection)
			.then((response) => {
				if (response.isSuccess) {
					console.log("tipo cambiado");
				} else {
					let valuesError = response.getErrorValue() as AdtException;
					console.log(valuesError.message);
				}
			});

Reasignar una tarea

Clase: AdtTransport

Método: reassignTask

Versión ABAP: > 7.51

Método que se le pasa la tarea y la nueva orden.

Ejemplo de llamada:

adt.reassignTask("A4HK900100", "A4HK900098").then((response) => {
			if (response.isSuccess) {
				console.log("tarea reasignado");
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Ordenar y comprimir una orden/tarea

Clase: AdtTransport

Método: sortAndCompress

Versión ABAP: > 7.51

Método que ordena y compacta los objetos de una orden/tarea

Ejemplo de llamada:

adt.sortAndCompress("A4HK900100").then((response) => {
			if (response.isSuccess) {
				console.log("realizado");
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Bloqueo de una orden/tarea

Clase: AdtTransport

Método: lockOrder

Versión ABAP: > 7.51

Bloquea una orden/tarea para poderla modificar.

Ejemplo de llamada:

adt.lockOrder("A4HK900101").then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportLockObject;
				console.log(values.lockHandle);

			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Desbloqueo de una orden/tarea

Clase: AdtTransport

Método: unlockOrder

Versión ABAP: > 7.51

Desbloquea una orden/tarea pasandole el código de bloqueo obtenido en el método lockOrder

Ejemplo de llamada:

adt.lockOrder("A4HK900101").then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportLockObject;
				console.log(values.lockHandle);

			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

Mover objeto entre ordenes

Clase: AdtTransport

Método: moveObject

Versión ABAP: > 7.51

Metodo que permite mover el objeto de una orden/tarea a otra orden/tarea. Los datos del objeto se obtienen al recuperar las ordenes del usuario, por comodidad la estructura de entrada del método y la de los objetos en la orden/tarea es la misma.

Ejemplo de llamada:

		adt
			.moveObject(
				{
					name: "Z_PRUEBAS",
					type: "PROG",
					objInfo: "Program",
					dummyUri:
						"/sap/bc/adt/cts/transportrequests/reference?obj_name=Z_PRUEBAS&amp;obj_wbtype=PROG&amp;pgmid=R3TR",
					wbtype: "PROG/P",
					pgmid: "R3TR",
					imgActivity: "",
					lockStatus: "X",
					objDesc: "pruebas de orden",
					position: 1,
				},
				"A4HK900100", // Orden donde esta el objeto
				"A4HK900102" // Orden donde se quiere mover
			)
			.then((response) => {
				if (response.isSuccess) {
					let values = response.getValue() as TransportMoveObject;
					console.log(values);
				} else {
					let valuesError = response.getErrorValue() as AdtException;
					console.log(valuesError.message);
				}
			});

Borrar objeto de una orden/tarea

Clase: AdtTransport

Método: removeObject

Versión ABAP: > 7.51

Metodo que borra un objeto de una orden/tarea. Los datos del objeto se obtienen al recuperar las ordenes del usuario, por comodidad la estructura de entrada del método y la de los objetos en la orden/tarea es la misma.

Ejemplo de llamada:

		adt
			.removeObject(
				{
					name: "Z_PRUEBAS",
					type: "PROG",
					objInfo: "Program",
					dummyUri:
						"/sap/bc/adt/cts/transportrequests/reference?obj_name=Z_PRUEBAS&amp;obj_wbtype=PROG&amp;pgmid=R3TR",
					wbtype: "PROG/P",
					pgmid: "R3TR",
					imgActivity: "",
					lockStatus: "X",
					objDesc: "pruebas de orden",
					position: 1,
				},
				"A4HK900102"
			)
			.then((response) => {
				if (response.isSuccess) {
					let values = response.getValue() as TransportRemoveObject;
					console.log(values);
				} else {
					let valuesError = response.getErrorValue() as AdtException;
					console.log(valuesError.message);
				}
			});

Añadir un objeto a una orden

Clase: AdtTransport

Método: AddObject

Versión ABAP: > 7.51

Metodo que añade un objeto a una orden/tarea. El objeto que se añade se bloquea, en el caso que el tipo de objeto permita, de manera automática. Pero en la respuesta de ADT, y por consiguiente en la respuesta del método, no sale informado. Desconozo el motivo de esta incongruencia pero es recomemdable una vez añadido volver a leer los datos de la orden/tarea

Ejemplo de llamada:

		adt
			.AddObject("A4HK900102", "Z_PRUEBAS", "R3TR", "PROG")
			.then((response) => {
				if (response.isSuccess) {
					let values = response.getValue() as TransportAddObject;
					console.log(values);
				} else {
					let valuesError = response.getErrorValue() as AdtException;
					console.log(valuesError.message);
				}
			});

Ayudas para búsqueda

Hay una serie de ayudas para búsqueda que se usan en distintos procesos de transportes, como la creación de ordenes, para poder montar las ayudas para búsqueda. Todos los métodos devuelven la misma estructura de datos.

Sistemas destino

Clase: AdtTransport

Método: getTargetVH

Versión ABAP: > 7.51

Devuelve los sistemas a los cuales se puede transportar una orden, como el sistema que se indica en transporte de copias. Se le puede pasar por parámetro un filtro de valores.

Ejemplo de llamada:

adt.getTargetVH().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportValueHelpItems;
				console.log(values);console.log("tarea reasignado");
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});
Proyectos CTS

Clase: AdtTransport

Método: getCTSProjectVH

Versión ABAP: > 7.51

Devuelve los proyectos CTS. Se le puede pasar por parámetro un filtro de valores.

Ejemplo de llamada:

adt.getCTSProjectVH().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportValueHelpItems;
				console.log(values);console.log("tarea reasignado");
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});
Tipos de objeto

Clase: AdtTransport

Método: getTypeVH

Versión ABAP: > 7.51

Devuelve los tipos de objeto. Se le puede pasar por parámetro un filtro de valores. Este método se usa para obtener el valor del campo "Program ID" a partir del tipo de objeto. Por ejemplo, si se buscr el tipo de objeto "PROG" en el campo data de la respuesta obtendremos el valor "PGMID = R3TR".

Ejemplo de llamada:

adt.getCTSProjectVH().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as TransportValueHelpItems;
				console.log(values);console.log("tarea reasignado");
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError.message);
			}
		});

ATC

El ATC es el ABAP Test Cockpit.

Obtener el ID del ATC para llamadas donde se necesita

Clase: AdtAtc

Método: getWorklist

El ID del ATC es un identificador que se pasa en algunos métodos, como al liberar una orden, para que ejecute las validaciones del ATC antes de realizar un proceso, como liberar una orden.

Ejemplo de llamada:

		atc.getWorklist().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as AtcWorklist;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError);
			}
		});

Obtener la variante por defecto

Clase: AdtAtc

Método: getDefaultVariant

Devuelve el nombre de la variante por defecto del ATC

Ejemplo de llamada:

		atc.getDefaultVariant().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as AtcDefaultVariant;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError);
			}
		});

Obtener la parametrización del ATC

Clase: AdtAtc

Método: getCustomizing

Devuelve la configuración del ATC.

Ejemplo de llamada:

		atc.getCustomizing().then((response) => {
			if (response.isSuccess) {
				let values = response.getValue() as AtcCustomizing;
				console.log(values);
			} else {
				let valuesError = response.getErrorValue() as AdtException;
				console.log(valuesError);
			}
		});

Keywords

FAQs

Package last updated on 13 Nov 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc