Skip to main content
Glama
activationUtils.tsâ€ĸ6.81 kB
/** * Activation Utilities - Centralized ABAP Object Activation Functions * * Two types of activation endpoints: * 1. Individual activation: /sap/bc/adt/activation (for single object in session) * 2. Group activation: /sap/bc/adt/activation/runs (for multiple objects) */ import { AxiosResponse } from './utils'; import { makeAdtRequestWithSession } from './sessionUtils'; import { makeAdtRequestWithTimeout, getBaseUrl, encodeSapObjectName } from './utils'; /** * Build object URI from name and type * Used by both individual and group activation * * @param name - Object name (e.g., 'ZCL_MY_CLASS', 'Z_MY_PROGRAM') * @param type - Object type code (e.g., 'CLAS/OC', 'PROG/P', 'DDLS/DF') * @returns ADT URI for the object */ export function buildObjectUri(name: string, type?: string): string { const lowerName = encodeSapObjectName(name).toLowerCase(); if (!type) { // Try to guess type from name prefix if (name.startsWith('ZCL_') || name.startsWith('CL_')) { return `/sap/bc/adt/oo/classes/${lowerName}`; } else if (name.startsWith('Z') && name.includes('_PROGRAM')) { return `/sap/bc/adt/programs/programs/${lowerName}`; } // Default: assume program return `/sap/bc/adt/programs/programs/${lowerName}`; } // Map type to URI path switch (type.toUpperCase()) { case 'CLAS/OC': case 'CLAS': return `/sap/bc/adt/oo/classes/${lowerName}`; case 'PROG/P': case 'PROG': return `/sap/bc/adt/programs/programs/${lowerName}`; case 'FUGR': case 'FUNC': return `/sap/bc/adt/functions/groups/${lowerName}`; case 'TABL/DT': case 'TABL': return `/sap/bc/adt/ddic/tables/${lowerName}`; case 'TABL/DS': case 'STRU/DS': case 'STRU': return `/sap/bc/adt/ddic/structures/${lowerName}`; case 'DDLS/DF': case 'DDLS': return `/sap/bc/adt/ddic/ddl/sources/${lowerName}`; case 'VIEW/DV': case 'VIEW': return `/sap/bc/adt/ddic/views/${lowerName}`; case 'DTEL/DE': case 'DTEL': return `/sap/bc/adt/ddic/dataelements/${lowerName}`; case 'DOMA/DD': case 'DOMA': return `/sap/bc/adt/ddic/domains/${lowerName}`; case 'INTF/OI': case 'INTF': return `/sap/bc/adt/oo/interfaces/${lowerName}`; default: // Fallback: try to construct URI from type return `/sap/bc/adt/${type.toLowerCase()}/${lowerName}`; } } /** * Individual object activation (within a session) * Used by Update/Create handlers after lock/unlock operations * * @param objectUri - ADT URI of the object (e.g., '/sap/bc/adt/oo/classes/zcl_test') * @param objectName - Object name in uppercase (e.g., 'ZCL_TEST') * @param sessionId - Session ID for stateful operations * @param preaudit - Request pre-audit before activation (default: true) * @returns Axios response with activation result */ export async function activateObjectInSession( objectUri: string, objectName: string, sessionId: string, preaudit: boolean = true ): Promise<AxiosResponse> { const url = `/sap/bc/adt/activation?method=activate&preauditRequested=${preaudit}`; const activationXml = `<?xml version="1.0" encoding="UTF-8"?> <adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core"> <adtcore:objectReference adtcore:uri="${objectUri}" adtcore:name="${objectName}"/> </adtcore:objectReferences>`; const headers = { 'Content-Type': 'application/vnd.sap.adt.activation+xml', 'Accept': 'application/xml' }; return await makeAdtRequestWithSession(url, 'POST', sessionId, activationXml, headers); } /** * Group activation (multiple objects, stateless) * Used by ActivateObject tool for batch activation * * @param objects - Array of objects to activate with uri and name * @param preaudit - Request pre-audit before activation (default: true) * @returns Axios response with activation result */ export async function activateObjectsGroup( objects: Array<{ uri: string; name: string }>, preaudit: boolean = true ): Promise<AxiosResponse> { const baseUrl = await getBaseUrl(); const url = `${baseUrl}/sap/bc/adt/activation/runs?method=activate&preauditRequested=${preaudit}`; const objectReferences = objects.map(obj => ` <adtcore:objectReference adtcore:uri="${obj.uri}" adtcore:name="${obj.name}"/>` ).join('\n'); const activationXml = `<?xml version="1.0" encoding="UTF-8"?><adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core"> ${objectReferences} </adtcore:objectReferences>`; const headers = { 'Accept': 'application/xml', 'Content-Type': 'application/xml' }; return await makeAdtRequestWithTimeout(url, 'POST', 'default', activationXml, undefined, headers); } /** * Parse activation response to extract status and messages * Common parsing logic for both individual and group activation * * @param responseData - XML response data from activation endpoint * @returns Parsed activation result with status and messages */ export function parseActivationResponse(responseData: string): { activated: boolean; checked: boolean; generated: boolean; messages: Array<{ type: string; text: string; line?: number; column?: number }>; } { const { XMLParser } = require('fast-xml-parser'); const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_', parseAttributeValue: true }); try { const result = parser.parse(responseData); // Check for properties element const properties = result['chkl:messages']?.['chkl:properties']; const activated = properties?.['@_activationExecuted'] === 'true' || properties?.['@_activationExecuted'] === true; const checked = properties?.['@_checkExecuted'] === 'true' || properties?.['@_checkExecuted'] === true; const generated = properties?.['@_generationExecuted'] === 'true' || properties?.['@_generationExecuted'] === true; // Parse messages (warnings/errors) const messages: Array<{ type: string; text: string; line?: number; column?: number }> = []; const msgData = result['chkl:messages']?.['msg']; if (msgData) { const msgArray = Array.isArray(msgData) ? msgData : [msgData]; msgArray.forEach((msg: any) => { messages.push({ type: msg['@_type'] || 'info', text: msg['shortText']?.['txt'] || msg['shortText'] || 'Unknown message', line: msg['@_line'], column: msg['@_column'] }); }); } return { activated, checked, generated, messages }; } catch (error) { return { activated: false, checked: false, generated: false, messages: [{ type: 'error', text: 'Failed to parse activation response' }] }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fr0ster/mcp-abap-adt'

If you have feedback or need assistance with the MCP directory API, please join our Discord server