{"_id":"@babamba2/mcp-abap-adt-clients","_rev":"2-1663e8fccd2b80f935f3e47d0d9af938","name":"@babamba2/mcp-abap-adt-clients","dist-tags":{"latest":"3.13.1"},"versions":{"3.13.0":{"name":"@babamba2/mcp-abap-adt-clients","version":"3.13.0","keywords":["abap","sap","adt","clients","runtime","mcp"],"author":{"name":"babamba2","email":"psspss1122@gmail.com"},"license":"MIT","_id":"@babamba2/mcp-abap-adt-clients@3.13.0","maintainers":[{"name":"psspss1122","email":"psspss1122@gmail.com"},{"name":"s2hoon326","email":"s2hoon326@gmail.com"}],"contributors":[{"url":"original author","name":"Oleksii Kyslytsia","email":"oleksij.kyslytsja@gmail.com"}],"homepage":"https://github.com/babamba2/mcp-abap-adt-clients#readme","bugs":{"url":"https://github.com/babamba2/mcp-abap-adt-clients/issues"},"dist":{"shasum":"cd4a4bae3b96907e604aa06fdee311c221136902","tarball":"https://registry.npmjs.org/@babamba2/mcp-abap-adt-clients/-/mcp-abap-adt-clients-3.13.0.tgz","fileCount":987,"integrity":"sha512-2Mdmx7ErTlaApJ93NIjcovowozfJ+nAPF/ab6I2XnJo4qitRtrKJ9mEM7K0IyCWNk+VQvNFHf5qKYpLKeQ1Adw==","signatures":[{"sig":"MEQCIAiIMl2EW9LxxHv9w3c1DvsfLnSYwVvGmOd2+oHhJ8cMAiBQzcyGRmVmNxAnclUe9tQBUvrCoKQfnHui1dG7IihyTA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2063320},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"03dd21358c5231cc7cc5c367027d7d763a2f8266","scripts":{"lint":"npx biome check --write src","test":"npx jest --runInBand","build":"npm run --silent clean && npx biome check src --diagnostic-level=error && npx tsc -p tsconfig.json","clean":"node -e \"const fs=require('fs');['dist','tsconfig.tsbuildinfo'].forEach(p=>{try{fs.rmSync(p,{recursive:true,force:true})}catch{}})\"","chrono":"./tools/version-stats.sh","format":"npx biome format --write src","pretest":"npm run test:check:integration","test:init":"node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';if(fs.existsSync(s)){console.log(s+' already exists, skipping (use test:reinit to overwrite)')}else{fs.copyFileSync(t,s);console.log('Created '+s+' — edit lines marked CHANGE')}\"","build:fast":"npx tsc -p tsconfig.json","lint:check":"npx biome check src","test:check":"npx tsc --noEmit --project tsconfig.test.json","test:module":"node scripts/test-module.js","test:reinit":"node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';fs.copyFileSync(t,s);console.log('Recreated '+s+' from template')\"","adt:entities":"node tools/adt-object-entities.js","shared:check":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/check","shared:setup":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/setup","prepublishOnly":"npm run build:fast","shared:teardown":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/teardown","test:sequential":"node scripts/run-tests-sequential.js","test:type-check":"npm run test:check","package:contents":"npx ts-node scripts/show-package-contents.ts","discovery:markdown":"npx ts-node tools/discovery-to-markdown.ts","test:check:integration":"npx tsc --noEmit --project tsconfig.test.integration.json","test:long-polling-read":"npx ts-node scripts/test-long-polling-read.ts"},"_npmUser":{"name":"psspss1122","email":"psspss1122@gmail.com"},"repository":{"url":"git+https://github.com/babamba2/mcp-abap-adt-clients.git","type":"git"},"_npmVersion":"11.8.0","description":"ADT clients for SAP ABAP systems - AdtClient and AdtRuntimeClient (fork of @mcp-abap-adt/adt-clients by fr0ster, with fixValues silent-drop fix)","directories":{},"_nodeVersion":"24.13.1","dependencies":{"yaml":"^2.3.4","axios":"^1.13.6","fast-xml-parser":"^5.4.1","@babamba2/mcp-abap-adt-logger":"^0.1.4","@babamba2/mcp-abap-adt-interfaces":"^5.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.0.5","yaml":"^2.8.1","dotenv":"^17.3.1","ts-jest":"^29.4.1","jest-util":"^30.2.0","typescript":"^5.9.2","@types/jest":"^30.0.0","@types/node":"^25.3.3","@biomejs/biome":"^2.4.4","@babamba2/mcp-abap-connection":"^1.5.3"},"optionalDependencies":{"node-rfc":"^3.3.1"},"_npmOperationalInternal":{"tmp":"tmp/mcp-abap-adt-clients_3.13.0_1776501214610_0.6123432564268592","host":"s3://npm-registry-packages-npm-production"}},"3.13.1":{"name":"@babamba2/mcp-abap-adt-clients","version":"3.13.1","description":"ADT clients for SAP ABAP systems - AdtClient and AdtRuntimeClient (fork of @mcp-abap-adt/adt-clients by fr0ster, with fixValues silent-drop fix)","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"keywords":["abap","sap","adt","clients","runtime","mcp"],"author":{"name":"babamba2","email":"psspss1122@gmail.com"},"contributors":[{"name":"Oleksii Kyslytsia","email":"oleksij.kyslytsja@gmail.com","url":"original author"}],"license":"MIT","homepage":"https://github.com/babamba2/mcp-abap-adt-clients#readme","bugs":{"url":"https://github.com/babamba2/mcp-abap-adt-clients/issues"},"repository":{"type":"git","url":"git+https://github.com/babamba2/mcp-abap-adt-clients.git"},"publishConfig":{"access":"public"},"scripts":{"chrono":"./tools/version-stats.sh","clean":"node -e \"const fs=require('fs');['dist','tsconfig.tsbuildinfo'].forEach(p=>{try{fs.rmSync(p,{recursive:true,force:true})}catch{}})\"","lint":"npx biome check --write src","lint:check":"npx biome check src","format":"npx biome format --write src","build":"npm run --silent clean && npx biome check src --diagnostic-level=error && npx tsc -p tsconfig.json","build:fast":"npx tsc -p tsconfig.json","test:init":"node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';if(fs.existsSync(s)){console.log(s+' already exists, skipping (use test:reinit to overwrite)')}else{fs.copyFileSync(t,s);console.log('Created '+s+' — edit lines marked CHANGE')}\"","test:reinit":"node -e \"const fs=require('fs'),s='src/__tests__/helpers/test-config.yaml',t=s+'.template';fs.copyFileSync(t,s);console.log('Recreated '+s+' from template')\"","test":"npx jest --runInBand","test:check":"npx tsc --noEmit --project tsconfig.test.json","test:type-check":"npm run test:check","test:check:integration":"npx tsc --noEmit --project tsconfig.test.integration.json","test:sequential":"node scripts/run-tests-sequential.js","test:module":"node scripts/test-module.js","test:long-polling-read":"npx ts-node scripts/test-long-polling-read.ts","package:contents":"npx ts-node scripts/show-package-contents.ts","discovery:markdown":"npx ts-node tools/discovery-to-markdown.ts","adt:entities":"node tools/adt-object-entities.js","shared:setup":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/setup","shared:teardown":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/teardown","shared:check":"npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/check","pretest":"npm run test:check:integration","prepublishOnly":"npm run build:fast"},"engines":{"node":">=18.0.0"},"dependencies":{"@babamba2/mcp-abap-adt-interfaces":"^5.0.0","@babamba2/mcp-abap-adt-logger":"^0.1.4","axios":"^1.13.6","fast-xml-parser":"^5.4.1","yaml":"^2.3.4"},"optionalDependencies":{"node-rfc":"^3.3.1"},"devDependencies":{"@biomejs/biome":"^2.4.4","@babamba2/mcp-abap-connection":"^1.5.3","@types/jest":"^30.0.0","@types/node":"^25.3.3","dotenv":"^17.3.1","jest":"^30.0.5","jest-util":"^30.2.0","ts-jest":"^29.4.1","typescript":"^5.9.2","yaml":"^2.8.1"},"gitHead":"c39b637bc29558211d9e85dac97dee4027b6560e","_id":"@babamba2/mcp-abap-adt-clients@3.13.1","_nodeVersion":"24.13.1","_npmVersion":"11.8.0","dist":{"integrity":"sha512-Z0PaCMC8fSzeu1oq6llMfq9NPrX2JIYIovUyeIE/4tc3NCpRtzXMv46mLhNsIV4vwGQCib+KYJAVXsYEWMOOpQ==","shasum":"480c70f9b9aa6ffb4f15dbc61f96e6c2433abb7f","tarball":"https://registry.npmjs.org/@babamba2/mcp-abap-adt-clients/-/mcp-abap-adt-clients-3.13.1.tgz","fileCount":987,"unpackedSize":2064072,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHfIbs2XG5atsrXgNKMRtPhi3HjQrsDSlum+YGgxTglUAiBGkCnUF+s6vc+68JVy+YB09CDsDQYKpsthxo+PuBeqgg=="}]},"_npmUser":{"name":"psspss1122","email":"psspss1122@gmail.com"},"directories":{},"maintainers":[{"name":"psspss1122","email":"psspss1122@gmail.com"},{"name":"s2hoon326","email":"s2hoon326@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-abap-adt-clients_3.13.1_1776523297212_0.6917375923054208"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-18T08:33:34.522Z","modified":"2026-04-18T14:41:37.548Z","3.13.0":"2026-04-18T08:33:34.783Z","3.13.1":"2026-04-18T14:41:37.374Z"},"bugs":{"url":"https://github.com/babamba2/mcp-abap-adt-clients/issues"},"author":{"name":"babamba2","email":"psspss1122@gmail.com"},"license":"MIT","homepage":"https://github.com/babamba2/mcp-abap-adt-clients#readme","keywords":["abap","sap","adt","clients","runtime","mcp"],"repository":{"type":"git","url":"git+https://github.com/babamba2/mcp-abap-adt-clients.git"},"description":"ADT clients for SAP ABAP systems - AdtClient and AdtRuntimeClient (fork of @mcp-abap-adt/adt-clients by fr0ster, with fixValues silent-drop fix)","contributors":[{"name":"Oleksii Kyslytsia","email":"oleksij.kyslytsja@gmail.com","url":"original author"}],"maintainers":[{"name":"psspss1122","email":"psspss1122@gmail.com"},{"name":"s2hoon326","email":"s2hoon326@gmail.com"}],"readme":"# @mcp-abap-adt/adt-clients\r\n\r\n[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)\r\n\r\nTypeScript clients for SAP ABAP Development Tools (ADT).\r\n\r\n## Features\r\n\r\n- ✅ **Client API** – simplified interface for common operations:\r\n  - `AdtClient` – high-level CRUD API with automatic operation chains\r\n  - `AdtClientBatch` – batch mode: multiple read operations in a single HTTP round-trip\r\n  - `AdtExecutor` – execution API via `IExecutor` contracts (class/program, with profiling)\r\n  - `AdtRuntimeClient` – stable runtime operations (ABAP debugger, traces, logs, dumps)\r\n  - `AdtRuntimeClientBatch` – batch mode for runtime operations\r\n  - `AdtRuntimeClientExperimental` – runtime APIs in progress (for example AMDP debugger)\r\n  - `AdtClientsWS` – realtime WebSocket facade for event-driven workflows\r\n- ✅ **ABAP Unit test support** – run and manage ABAP Unit tests (class and CDS view tests)\r\n- ✅ **Stateful session management** – maintains `sap-adt-connection-id` across operations\r\n- ✅ **Lock registry** – persistent `.locks/active-locks.json` with CLI tools for recovery\r\n- ✅ **TypeScript-first** – full type safety with comprehensive interfaces\r\n- ✅ **Response headers are normalized** – ADT response headers can be non-string; normalize before parsing in contributors’ code\r\n- ✅ **Public API is clients + supporting types** – internal builders and low-level utilities are not exported from the package root\r\n\r\n## Responsibilities and Design Principles\r\n\r\n### Core Development Principle\r\n\r\n**Interface-Only Communication**: This package follows a fundamental development principle: **all interactions with external dependencies happen ONLY through interfaces**. The code knows **NOTHING beyond what is defined in the interfaces**.\r\n\r\nThis means:\r\n- Does not know about concrete implementation classes from other packages\r\n- Does not know about internal data structures or methods not defined in interfaces\r\n- Does not make assumptions about implementation behavior beyond interface contracts\r\n- Does not access properties or methods not explicitly defined in interfaces\r\n\r\nThis principle ensures:\r\n- **Loose coupling**: Clients are decoupled from concrete implementations in other packages\r\n- **Flexibility**: New implementations can be added without modifying clients\r\n- **Testability**: Easy to mock dependencies for testing\r\n- **Maintainability**: Changes to implementations don't affect clients\r\n\r\n### Package Responsibilities\r\n\r\nThis package is responsible for:\r\n\r\n1. **ADT operations**: Provides high-level and low-level client APIs for interacting with SAP ABAP Development Tools (ADT)\r\n2. **Object management**: CRUD operations for ABAP objects (classes, interfaces, programs, etc.)\r\n3. **Session management**: Maintains session state across operations using `sap-adt-connection-id`\r\n4. **Lock management**: Handles object locking with persistent registry\r\n\r\n#### What This Package Does\r\n\r\n- **Provides ADT clients**: `AdtClient` and specialized clients for ADT operations\r\n- **Manages locks**: Lock registry with persistent storage and CLI tools\r\n- **Handles requests**: Makes HTTP requests to SAP ADT endpoints through connection interface\r\n- **Manages state**: Maintains object state across chained operations\r\n\r\n#### What This Package Does NOT Do\r\n\r\n- **Does NOT handle authentication**: Authentication is handled by `@mcp-abap-adt/connection`\r\n- **Does NOT manage connections**: Connection management is handled by `@mcp-abap-adt/connection`\r\n- **Does NOT validate headers**: Header validation is handled by `@mcp-abap-adt/header-validator`\r\n- **Does NOT store tokens**: Token storage is handled by `@mcp-abap-adt/auth-stores`\r\n- **Does NOT orchestrate authentication**: Token lifecycle is handled by `@mcp-abap-adt/auth-broker`\r\n\r\n### External Dependencies\r\n\r\nThis package interacts with external packages **ONLY through interfaces**:\r\n\r\n- **`@mcp-abap-adt/connection`**: Uses `AbapConnection` interface for HTTP requests - does not know about concrete connection implementation\r\n- **No direct dependencies on other packages**: All interactions happen through well-defined interfaces\r\n\r\n## Installation\r\n\r\n### As npm Package\r\n\r\n```bash\r\n# Install globally for CLI tools\r\nnpm install -g @mcp-abap-adt/adt-clients\r\n\r\n# Or install in project\r\nnpm install @mcp-abap-adt/adt-clients\r\n```\r\n\r\n## Architecture\r\n\r\n### Public API\r\n\r\n1. **AdtClient** (High-level, recommended)\r\n   - Simplified CRUD operations with automatic operation chains\r\n   - Factory pattern: `client.getClass()`, `client.getProgram()`, etc.\r\n   - Automatic error handling and resource cleanup\r\n   - Utility functions via `client.getUtils()`\r\n   - Example: `await client.getClass().create({...}, { activateOnCreate: true })`\r\n\r\n2. **AdtRuntimeClient**\r\n   - Stable runtime operations for ABAP debugging, traces, dumps, and logs\r\n   - Example: `await runtimeClient.getDebugger(...)`\r\n\r\n3. **AdtExecutor**\r\n   - Typed execution API based on `IExecutor`\r\n   - Executors:\r\n     - `getClassExecutor()` for `classrun`\r\n     - `getProgramExecutor()` for `programrun` (on-premise systems)\r\n   - Methods: `run`, `runWithProfiler`, `runWithProfiling`\r\n\r\n4. **AdtRuntimeClientExperimental**\r\n   - Runtime APIs in progress that may change without backward-compatibility guarantees\r\n   - Current scope: AMDP debugger + AMDP data preview\r\n   - Example: `await experimentalRuntime.startAmdpDebugger(...)`\r\n\r\n5. **AdtClientsWS**\r\n   - Realtime request/event facade over `IWebSocketTransport`\r\n   - Includes debugger-session facade: listen, attach, step, stack, variables\r\n   - Example: `await wsClient.request('debugger.listen', { timeoutSeconds: 30 })`\r\n\r\n6. **AdtClientBatch** / **AdtRuntimeClientBatch**\r\n   - Execute multiple independent read operations in a single HTTP round-trip\r\n   - Uses SAP ADT batch endpoint (`POST /sap/bc/adt/debugger/batch`) with `multipart/mixed` payloads\r\n   - Same factory API as `AdtClient` / `AdtRuntimeClient` — record calls, then `batchExecute()`\r\n   - Example: `const batch = new AdtClientBatch(connection); batch.getClass().readMetadata({...}); await batch.batchExecute();`\r\n\r\n## Supported Object Types\r\n\r\n| Object Type | AdtClient |\r\n|------------|-----------|\r\n| Classes (CLAS) | ✅ |\r\n| Behavior Implementations (CLAS) | ✅ |\r\n| Behavior Definitions (BDEF) | ✅ |\r\n| Interfaces (INTF) | ✅ |\r\n| Programs (PROG) | ✅ |\r\n| Function Groups (FUGR) | ✅ |\r\n| Function Modules (FUGR/FF) | ✅ |\r\n| Domains (DOMA) | ✅ |\r\n| Data Elements (DTEL) | ✅ |\r\n| Structures (TABL/DS) | ✅ |\r\n| Tables (TABL/DT) | ✅ |\r\n| Views (DDLS) | ✅ |\r\n| Metadata Extensions (DDLX) | ✅ |\r\n| Packages (DEVC) | ✅ |\r\n| Transports (TRNS) | ✅ |\r\n\r\n## Quick Start\r\n\r\n### Using AdtClient (Recommended - High-Level CRUD API)\r\n\r\n```typescript\r\nimport { createAbapConnection } from '@mcp-abap-adt/connection';\r\nimport { AdtClient } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst connection = createAbapConnection({\r\n  url: 'https://your-sap-system.example.com',\r\n  client: '100',\r\n  authType: 'basic',\r\n  username: process.env.SAP_USERNAME!,\r\n  password: process.env.SAP_PASSWORD!\r\n}, console);\r\n\r\nconst client = new AdtClient(connection, console);\r\n\r\n// Simple CRUD operations with automatic operation chains\r\nawait client.getClass().create({\r\n  className: 'ZCL_TEST',\r\n  packageName: 'ZPACKAGE',\r\n  description: 'Test class'\r\n}, { activateOnCreate: true });\r\n\r\n// Utility functions\r\nconst utils = client.getUtils();\r\nawait utils.searchObjects({ query: 'Z*', objectType: 'CLAS' });\r\n\r\n// Where-used with parsed results (recommended)\r\nconst result = await utils.getWhereUsedList({\r\n  object_name: 'ZCL_TEST',\r\n  object_type: 'class',\r\n  enableAllTypes: true  // Eclipse \"select all\" behavior\r\n});\r\nconsole.log(`Found ${result.totalReferences} references`);\r\nfor (const ref of result.references) {\r\n  console.log(`${ref.name} (${ref.type}) in ${ref.packageName}`);\r\n}\r\n\r\n// Where-used with raw XML (legacy)\r\nawait utils.getWhereUsed({ object_name: 'ZCL_TEST', object_type: 'class' });\r\n```\r\n\r\n### Using AdtClientsWS (Realtime)\r\n\r\n```typescript\r\nimport { AdtClientsWS } from '@mcp-abap-adt/adt-clients';\r\nimport type { IWebSocketTransport } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst transport: IWebSocketTransport = createYourTransport();\r\nconst wsClient = new AdtClientsWS(transport, console, {\r\n  requestTimeoutMs: 30000,\r\n});\r\n\r\nawait wsClient.connect('wss://your-realtime-endpoint');\r\n\r\nconst debuggerSession = wsClient.getDebuggerSessionClient();\r\nawait debuggerSession.listen({ timeoutSeconds: 60 });\r\nawait debuggerSession.step({ action: 'step_over' });\r\n```\r\n\r\n### Using AdtClientBatch (Batch Read Operations)\r\n\r\n`AdtClientBatch` sends multiple independent read operations in a single HTTP round-trip via `multipart/mixed` batch requests.\r\n\r\n```typescript\r\nimport { AdtClientBatch } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst batch = new AdtClientBatch(connection, console);\r\n\r\n// Record operations (not yet executed)\r\nconst classPromise = batch.getClass().readMetadata({ className: 'CL_ABAP_TYPEDESCR' });\r\nconst domainPromise = batch.getDomain().readMetadata({ domainName: 'MANDT' });\r\nconst dePromise = batch.getDataElement().readMetadata({ dataElementName: 'MANDT' });\r\n\r\n// Execute all in one HTTP request\r\nawait batch.batchExecute();\r\n\r\n// Resolve individual results\r\nconst classState = await classPromise;\r\nconst domainState = await domainPromise;\r\nconst deState = await dePromise;\r\n```\r\n\r\n**Batch-safe operations** (single-step, no chained awaits):\r\n- `read()`, `readMetadata()`, `readTransport()` — single GET\r\n- `check()`, `validate()`, `activate()` — single POST\r\n\r\n**NOT batch-safe** (multi-step chains): `create()`, `update()`, `delete()`.\r\n\r\n### ABAP Debugger Step Operations via Batch Endpoint\r\n\r\n`AdtRuntimeClient` executes step operations through debugger batch requests (`POST /sap/bc/adt/debugger/batch`) using `multipart/mixed` payloads.\r\n\r\n```typescript\r\nimport { AdtRuntimeClient } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst runtime = new AdtRuntimeClient(connection);\r\n\r\n// Executes stepInto + getStack in one batch request\r\nconst batchResponse = await runtime.stepIntoDebuggerBatch();\r\n\r\n// Also available:\r\nawait runtime.stepOutDebuggerBatch();\r\nawait runtime.stepContinueDebuggerBatch();\r\n```\r\n\r\nFor non-step actions keep using `executeDebuggerAction(action, value?)`.  \r\nStep actions (`stepInto`, `stepOut`, `stepContinue`) are reserved for batch-only execution.\r\n\r\n### Using AdtExecutor (Execution API)\r\n\r\n```typescript\r\nimport { AdtExecutor } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst executor = new AdtExecutor(connection, console);\r\n\r\n// Class execution\r\nawait executor.getClassExecutor().run({ className: 'ZCL_MY_CLASSRUN' });\r\n\r\n// Program execution (on-premise)\r\nawait executor.getProgramExecutor().run({ programName: 'ZMY_EXEC_REPORT' });\r\n\r\n// Program execution with profiling\r\nconst runWithProfilingResult = await executor.getProgramExecutor().runWithProfiling(\r\n  { programName: 'ZMY_EXEC_REPORT' },\r\n  {\r\n    profilerParameters: {\r\n      allProceduralUnits: true,\r\n      sqlTrace: true,\r\n      allDbEvents: true,\r\n    },\r\n  },\r\n);\r\n\r\nconsole.log(runWithProfilingResult.traceId);\r\n```\r\n\r\n**AdtUtils read type safety:**\r\n`readObjectMetadata` and `readObjectSource` accept strict object type unions to prevent invalid inputs like `view:ZOBJ`.\r\n\r\n```typescript\r\nimport type { AdtObjectType, AdtSourceObjectType } from '@mcp-abap-adt/adt-clients';\r\n\r\nawait utils.readObjectMetadata('DDLS/DF' satisfies AdtObjectType, 'ZOK_I_CDS_TEST');\r\nawait utils.readObjectSource('view' satisfies AdtSourceObjectType, 'ZOK_I_CDS_TEST');\r\n```\r\n\r\n**Benefits:**\r\n- ✅ Simplified API - no manual lock/unlock management\r\n- ✅ Automatic operation chains (validate → create → check → lock → update → unlock → activate)\r\n- ✅ Consistent error handling and resource cleanup\r\n- ✅ Separation of CRUD operations and utility functions\r\n- ✅ Long polling support for object readiness\r\n\r\n### Using Long Polling for Object Readiness\r\n\r\nThe `withLongPolling` parameter allows you to wait for objects to become available after create/update/activate operations, replacing fixed timeouts with server-driven waiting:\r\n\r\n```typescript\r\nimport { AdtClient } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst client = new AdtClient(connection);\r\n\r\n// Create a class\r\nawait client.getClass().create({\r\n  className: 'ZCL_TEST',\r\n  packageName: 'ZPACKAGE',\r\n  description: 'Test class'\r\n});\r\n\r\n// Wait for object to be ready using long polling\r\n// The server will hold the connection until the object is available\r\nawait client.getClass().read(\r\n  { className: 'ZCL_TEST' },\r\n  'active',\r\n  { withLongPolling: true }\r\n);\r\n\r\n// Now the object is guaranteed to be ready for subsequent operations\r\nawait client.getClass().update({\r\n  className: 'ZCL_TEST'\r\n}, { sourceCode: updatedCode });\r\n```\r\n\r\n**Benefits of Long Polling:**\r\n- ✅ **No arbitrary timeouts** - waits for actual object readiness\r\n- ✅ **Faster tests** - no unnecessary delays when object is ready quickly\r\n- ✅ **More reliable** - server-driven waiting ensures object is actually available\r\n- ✅ **Automatic in create/update** - `AdtObject` implementations use long polling internally\r\n\r\n**Note:** Long polling is automatically used in `create()` and `update()` methods of all `AdtObject` implementations to ensure objects are ready before proceeding with subsequent operations.\r\n\r\n### Creating Behavior Implementation Classes\r\n\r\n```typescript\r\nimport { AdtClient } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst client = new AdtClient(connection);\r\n\r\nawait client.getBehaviorImplementation().create(\r\n  {\r\n    className: 'ZBP_OK_I_CDS_TEST',\r\n    packageName: 'ZOK_TEST_PKG_01',\r\n    behaviorDefinition: 'ZOK_I_CDS_TEST',\r\n    description: 'Behavior Implementation for ZOK_I_CDS_TEST',\r\n    transportRequest: 'E19K900001'\r\n  },\r\n  { activateOnCreate: true }\r\n);\r\n```\r\n\r\n## Developer Tools\r\n\r\n### ADT Discovery Script\r\n\r\nThe package includes a tool for generating documentation from the ADT discovery endpoint, which lists all available ADT API endpoints.\r\n\r\n**Purpose:** Explore available ADT API endpoints and generate markdown documentation.\r\n\r\n**Usage:**\r\n```bash\r\n# Generate discovery documentation (default output: docs/architecture/discovery.md)\r\nnpm run discovery:markdown\r\n\r\n# Custom output file\r\nnpm run discovery:markdown -- --output custom-discovery.md\r\n\r\n# Custom SAP system URL\r\nnpm run discovery:markdown -- --url https://your-system.com\r\n\r\n# Custom .env file\r\nnpm run discovery:markdown -- --env /path/to/.env\r\n```\r\n\r\n**What it does:**\r\n1. Connects to the SAP system using credentials from `.env` file\r\n2. Fetches the discovery endpoint: `GET /sap/bc/adt/discovery` (via `AdtUtils.discovery()`)\r\n3. Parses the XML response\r\n4. Converts it to readable markdown with endpoint categories, HTTP methods, URLs, content types, and descriptions\r\n5. Saves the pretty-printed discovery XML next to the markdown output\r\n\r\n**Output:** \r\n- Default: `docs/architecture/discovery.md` and `docs/architecture/discovery.xml`\r\n- Custom: Path specified via `--output` option, plus `discovery.xml` in the same directory\r\n\r\n**Environment Variables:**\r\nThe script uses the same environment variables as the main package:\r\n- `SAP_URL` - SAP system URL (required)\r\n- `SAP_AUTH_TYPE` - Authentication type: `'basic'` or `'jwt'` (default: `'basic'`)\r\n- `SAP_USERNAME` - Username for basic auth\r\n- `SAP_PASSWORD` - Password for basic auth\r\n- `SAP_JWT_TOKEN` - JWT token for JWT auth\r\n- `SAP_CLIENT` - Client number (optional)\r\n\r\n**When to use:**\r\n- To explore available ADT API endpoints on your SAP system\r\n- To generate up-to-date documentation for ADT API\r\n- To understand the structure of ADT discovery responses\r\n- To verify endpoint availability on a specific SAP system\r\n\r\nSee [Tools Documentation](tools/README.md) for complete details and options.\r\n\r\n## API Reference\r\n\r\n### AdtClient Overview\r\n\r\n- Factory accessors for ADT objects: `client.getClass()`, `client.getProgram()`, `client.getView()`, `client.getTable()`, `client.getRequest()`, `client.getUtils()`, etc.\r\n- Each accessor returns an `Adt*` object implementing `IAdtObject` operations.\r\n- See `src/index.ts` for the full type exports and object configs.\r\n\r\n### AdtObject Methods (with Long Polling Support)\r\n\r\nAll `AdtObject` implementations support the `withLongPolling` parameter for read operations:\r\n\r\n```typescript\r\n// Read with long polling - waits for object to be ready\r\nawait adtObject.read(config, 'active', { withLongPolling: true });\r\n\r\n// Read metadata with long polling\r\nawait adtObject.readMetadata(config, { withLongPolling: true });\r\n\r\n// Read metadata with explicit version\r\nawait adtObject.readMetadata(config, { version: 'active' });\r\n\r\n// Read transport info with long polling\r\nawait adtObject.readTransport(config, { withLongPolling: true });\r\n```\r\n\r\n**When to use long polling:**\r\n- After `create()` operations - wait for object to be available\r\n- After `update()` operations - wait for changes to be persisted\r\n- After `activate()` operations - wait for object to be available in active version\r\n- In tests - replace fixed `setTimeout` delays with long polling for better reliability\r\n\r\nOperation results are stored on the returned state (`createResult`, `updateResult`, `checkResult`, etc.):\r\n\r\n```typescript\r\nconst createState = await client.getFunctionModule().create({\r\n  functionGroupName: 'ZFGROUP',\r\n  functionModuleName: 'ZFM_TEST',\r\n  description: 'Test FM',\r\n});\r\n\r\nconsole.log(createState.createResult?.status);\r\n```\r\n\r\n### Accept Negotiation (Optional)\r\n\r\nSome ADT endpoints return `406` when the `Accept` header does not match the system’s supported media types. The client can\r\noptionally auto-correct `Accept` by retrying with supported values returned in the 406 response.\r\n\r\n**Enable globally:**\r\n```typescript\r\nimport { AdtClient } from '@mcp-abap-adt/adt-clients';\r\n\r\nconst client = new AdtClient(connection, console, {\r\n  enableAcceptCorrection: true,\r\n});\r\n```\r\n\r\n**Enable via environment:**\r\n```bash\r\nADT_ACCEPT_CORRECTION=true npm test\r\n```\r\n\r\n**Override per read call:**\r\n```typescript\r\nawait client.getClass().read(\r\n  { className: 'ZCL_TEST' },\r\n  'active',\r\n  { accept: 'text/plain' }\r\n);\r\n\r\nawait client.getClass().readMetadata(\r\n  { className: 'ZCL_TEST' },\r\n  { accept: 'application/vnd.sap.adt.oo.classes.v4+xml', version: 'active' }\r\n);\r\n\r\n// Read source without version (initial post-create state)\r\nawait client.getClass().read({ className: 'ZCL_TEST' }, undefined);\r\n```\r\n\r\nNotes:\r\n- Disabled by default.\r\n- Correction retries once and caches the supported `Accept` per endpoint.\r\n\r\n### Specialized Clients\r\n\r\n- **ManagementClient**: batch activation + check operations\r\n- **LockClient**: explicit lock/unlock with `.locks` registry integration\r\n- **ValidationClient**: name validation mirroring ADT validation endpoint\r\n\r\nRefer to the TypeScript typings (`src/index.ts`) for the full API surface.\r\n\r\n## Type System\r\n\r\n### Centralized Type Definitions\r\n\r\nAll type definitions are centralized in module-specific `types.ts` files:\r\n\r\n```typescript\r\n// Import types from module exports\r\nimport type {\r\n  IClassConfig,\r\n  IClassState,\r\n  IProgramConfig\r\n} from '@mcp-abap-adt/adt-clients';\r\n```\r\n\r\n### Naming Conventions\r\n\r\nThe package uses **dual naming conventions** to distinguish API layers:\r\n\r\n#### Low-Level Parameters (snake_case)\r\n\r\nUsed by internal ADT API functions.\r\n\r\n#### AdtObject Configuration (camelCase)\r\n\r\nUsed by `AdtClient` and `Adt*` object configs:\r\n\r\n```typescript\r\ninterface IClassConfig {\r\n  className: string;\r\n  packageName?: string;\r\n  transportRequest?: string;\r\n  description: string;\r\n  sourceCode?: string;\r\n}\r\n```\r\n\r\nThis dual convention:\r\n- Makes low-level/high-level distinction clear\r\n- Matches SAP ADT XML parameter naming (`class_name` in ADT requests)\r\n- Provides familiar camelCase for JavaScript/TypeScript consumers\r\n- Enables proper type checking at each layer\r\n\r\nSee [Architecture Documentation](docs/architecture/ARCHITECTURE.md#type-system-organization) for details.\r\n\r\n## Migration Guide\r\n\r\n### From Timeouts to Long Polling\r\n\r\n**Migration from fixed timeouts to long polling:**\r\n\r\nThe package now uses long polling (`?withLongPolling=true`) instead of fixed timeouts for waiting object readiness. This provides better reliability and faster execution.\r\n\r\n```typescript\r\n// ❌ Before - Using fixed timeouts\r\nawait client.getClass().create({ className: 'ZCL_TEST', ... });\r\nawait new Promise(resolve => setTimeout(resolve, 2000)); // Fixed delay\r\nawait client.getClass().update({ className: 'ZCL_TEST' }, { sourceCode });\r\n\r\n// ✅ After - Using long polling\r\nawait client.getClass().create({ className: 'ZCL_TEST', ... });\r\n// Long polling is automatically used in create/update methods\r\nawait client.getClass().update({ className: 'ZCL_TEST' }, { sourceCode });\r\n\r\n// Or explicitly use long polling in read operations\r\nawait client.getClass().read(\r\n  { className: 'ZCL_TEST' },\r\n  'active',\r\n  { withLongPolling: true }\r\n);\r\n```\r\n\r\n**Benefits:**\r\n- No arbitrary delays - waits for actual object readiness\r\n- Faster execution when objects are ready quickly\r\n- More reliable - server-driven waiting ensures object is available\r\n- Automatic in `create()` and `update()` methods\r\n\r\n### Builderless API\r\n\r\n- `CrudClient`, `ReadOnlyClient`, and Builder classes are removed in the builderless API.\r\n- Use `AdtClient` and the `Adt*` objects (`client.getClass()`, `client.getView()`, etc.).\r\n\r\n## Documentation\r\n\r\n- **[Operation Delays](docs/OPERATION_DELAYS.md)** – configurable delays for SAP operations in tests (sequential execution, timing issues)\r\n- **[Architecture](docs/architecture/ARCHITECTURE.md)** – package structure and design decisions\r\n- **[Test Configuration Schema](docs/TEST_CONFIG_SCHEMA.md)** – YAML test configuration reference\r\n\r\n## Logging and Debugging\r\n\r\nThe library uses a **5-tier granular debug flag system** for different code layers:\r\n\r\n### Debug Environment Variables\r\n\r\n```bash\r\n# Connection package logs (HTTP, sessions, CSRF tokens)\r\nDEBUG_CONNECTORS=true npm test\r\n\r\n# Core library logs\r\nDEBUG_ADT_LIBS=true npm test\r\n\r\n# Integration test execution logs\r\nDEBUG_ADT_TESTS=true npm test\r\n\r\n# E2E integration test logs\r\nDEBUG_ADT_E2E_TESTS=true npm test\r\n\r\n# Test helper function logs\r\nDEBUG_ADT_HELPER_TESTS=true npm test\r\n\r\n# Enable ALL ADT scopes at once\r\nDEBUG_ADT_TESTS=true npm test\r\n```\r\n\r\n### Logger Interface\r\n\r\nAll clients accept a unified `ILogger` interface:\r\n\r\n```typescript\r\nimport type { ILogger } from '@mcp-abap-adt/adt-clients';\r\nimport { AdtClient } from '@mcp-abap-adt/adt-clients';\r\n\r\n// Custom logger example\r\nconst logger: ILogger = {\r\n  debug: (msg, ...args) => console.debug(msg, ...args),\r\n  info: (msg, ...args) => console.info(msg, ...args),\r\n  warn: (msg, ...args) => console.warn(msg, ...args),\r\n  error: (msg, ...args) => console.error(msg, ...args),\r\n};\r\n\r\nconst client = new AdtClient(connection, logger);\r\n```\r\n\r\n**Note:** All logger methods are optional. Lock handles are always logged in full (not truncated).\r\n\r\nSee [docs/DEBUG.md](docs/DEBUG.md) for detailed debugging guide.\r\n\r\n## Changelog\r\n\r\nSee [CHANGELOG.md](CHANGELOG.md) for package-specific release notes.\r\nLatest (0.3.14): added `getWhereUsedList()` for parsed where-used results.\r\n\r\n## Tests\r\n\r\nIntegration tests use YAML configuration (`src/__tests__/helpers/test-config.yaml`) and the `BaseTester` pattern.  \r\nSome ADT endpoints are system-specific; 406 is treated as an Accept/header support issue and can be explicitly allowed via `test_settings.allow_406` or per-test `params.allow_406` (e.g., objectstructure/nodestructure).\r\n\r\n## License\r\n\r\nMIT\r\n\r\n## Author\r\n\r\nOleksii Kyslytsia <oleksij.kyslytsja@gmail.com>\r\n","readmeFilename":"README.md"}