@numends/abap-client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/dist/abap-object-utils.d.ts +31 -0
- package/dist/abap-object-utils.js +113 -0
- package/dist/abap-object-utils.js.map +1 -0
- package/dist/config.d.ts +62 -0
- package/dist/config.js +117 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/lock-manager.d.ts +25 -0
- package/dist/lock-manager.js +92 -0
- package/dist/lock-manager.js.map +1 -0
- package/dist/sap-client.d.ts +39 -0
- package/dist/sap-client.js +241 -0
- package/dist/sap-client.js.map +1 -0
- package/dist/websocket-client.d.ts +26 -0
- package/dist/websocket-client.js +461 -0
- package/dist/websocket-client.js.map +1 -0
- package/dist/xml-utils.d.ts +11 -0
- package/dist/xml-utils.js +109 -0
- package/dist/xml-utils.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# @numends/abap-client
|
|
2
|
+
|
|
3
|
+
WebSocket client that connects your local machine to ABAP MCP Cloud, enabling SAP ADT operations from within your VPN.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────┐ ┌──────────────┐
|
|
9
|
+
│ Cursor/ │ │ abap-client │
|
|
10
|
+
│ Claude IDE │ │ (this tool) │
|
|
11
|
+
└──────┬──────┘ └──────┬───────┘
|
|
12
|
+
│ │
|
|
13
|
+
↓ │
|
|
14
|
+
┌─────────────┐ WebSocket │
|
|
15
|
+
│ MCP Cloud │◄──────────────────────────┤
|
|
16
|
+
│ (Server) │ │
|
|
17
|
+
└──────┬──────┘ │
|
|
18
|
+
│ │
|
|
19
|
+
└──────Command──────────────────────►
|
|
20
|
+
↓
|
|
21
|
+
┌──────────────┐
|
|
22
|
+
│ SAP S/4 │
|
|
23
|
+
│ (VPN) │
|
|
24
|
+
└──────────────┘
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
1. Connects to MCP Cloud via WebSocket (outbound connection)
|
|
28
|
+
2. Receives commands from MCP Cloud
|
|
29
|
+
3. Executes HTTP requests to SAP S/4HANA (within VPN)
|
|
30
|
+
4. Returns results back to MCP Cloud
|
|
31
|
+
5. Manages SAP session automatically (CSRF tokens, cookies, keep-alive)
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Prerequisites
|
|
36
|
+
|
|
37
|
+
- Node.js 20 or higher
|
|
38
|
+
- VPN access to the SAP system
|
|
39
|
+
- An `arc_*` API key from the [Arcanum admin portal](https://arcanum.mcps.b2rise.com)
|
|
40
|
+
- SAP environments registered in the admin portal
|
|
41
|
+
|
|
42
|
+
### Run with npx (no install needed)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx @numends/abap-client
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
On first run, you'll be prompted to enter your API key interactively. It will be saved to a `.env` file automatically so you won't need to enter it again.
|
|
49
|
+
|
|
50
|
+
You can also pass it directly:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
API_KEY=arc_your_key_here npx @numends/abap-client
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Global install
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g @numends/abap-client
|
|
60
|
+
abap-client
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
The only required configuration is your API key. All other settings (WebSocket URL, admin URL, keep-alive) are handled automatically.
|
|
66
|
+
|
|
67
|
+
| Variable | Required | Description |
|
|
68
|
+
|----------|----------|-------------|
|
|
69
|
+
| `API_KEY` | Yes | Your `arc_*` API key from the admin portal |
|
|
70
|
+
| `ENV` | No | Set to `DEVELOPMENT` to use QAS endpoints |
|
|
71
|
+
|
|
72
|
+
SAP system credentials are managed in the [Arcanum admin portal](https://arcanum.mcps.b2rise.com) and fetched automatically on startup.
|
|
73
|
+
|
|
74
|
+
## Troubleshooting
|
|
75
|
+
|
|
76
|
+
### "401 Unauthorized" from SAP
|
|
77
|
+
- Verify SAP username and password in the admin portal
|
|
78
|
+
- Check that the SAP user has the required ADT permissions
|
|
79
|
+
|
|
80
|
+
### Connection keeps reconnecting
|
|
81
|
+
- Check if API_KEY is valid and has an active subscription
|
|
82
|
+
- Verify the MCP Cloud server is accessible
|
|
83
|
+
|
|
84
|
+
### "No SAP environments configured"
|
|
85
|
+
- Register your SAP systems in the admin portal first
|
|
86
|
+
|
|
87
|
+
## Security
|
|
88
|
+
|
|
89
|
+
- Never commit `.env` files with real credentials
|
|
90
|
+
- API keys should be treated as secrets
|
|
91
|
+
- SAP passwords are encrypted at rest in the admin portal
|
|
92
|
+
- Connections to MCP Cloud use WSS (TLS)
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ABAP Object Utilities
|
|
3
|
+
* Functions for working with ABAP object types and URLs
|
|
4
|
+
*/
|
|
5
|
+
export interface ObjectInfo {
|
|
6
|
+
objectName: string | null;
|
|
7
|
+
objectType: string | null;
|
|
8
|
+
}
|
|
9
|
+
interface UrlPattern {
|
|
10
|
+
regex: RegExp;
|
|
11
|
+
type: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Callspec {
|
|
14
|
+
name?: string;
|
|
15
|
+
step?: string;
|
|
16
|
+
method: string;
|
|
17
|
+
url: string;
|
|
18
|
+
headers: Record<string, string>;
|
|
19
|
+
body?: string;
|
|
20
|
+
extract_from_response?: Record<string, boolean>;
|
|
21
|
+
package?: string;
|
|
22
|
+
}
|
|
23
|
+
declare const URL_PATTERNS: UrlPattern[];
|
|
24
|
+
export declare function extractObjectInfoFromUrl(url: string): ObjectInfo;
|
|
25
|
+
export declare function getObjectUriPath(objectType: string): string | null;
|
|
26
|
+
export declare function isLockOperation(callspec: Callspec): boolean;
|
|
27
|
+
export declare function isUnlockOperation(callspec: Callspec): boolean;
|
|
28
|
+
export declare function isActivateOperation(action: string): boolean;
|
|
29
|
+
export declare function getObjectTypeName(objectType: string): string;
|
|
30
|
+
export declare function getLockSuffix(url: string): string;
|
|
31
|
+
export { URL_PATTERNS };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ABAP Object Utilities
|
|
3
|
+
* Functions for working with ABAP object types and URLs
|
|
4
|
+
*/
|
|
5
|
+
const URL_PATTERNS = [
|
|
6
|
+
{ regex: /\/adt\/bo\/behaviordefinitions\/([^/?]+)/, type: 'BDEF' },
|
|
7
|
+
{ regex: /\/adt\/ddic\/ddl\/sources\/([^/?]+)/, type: 'DDLS' },
|
|
8
|
+
{ regex: /\/adt\/oo\/classes\/([^/?]+)/, type: 'CLAS' },
|
|
9
|
+
{ regex: /\/adt\/oo\/interfaces\/([^/?]+)/, type: 'INTF' },
|
|
10
|
+
{ regex: /\/adt\/programs\/programs\/([^/?]+)/, type: 'PROG' },
|
|
11
|
+
{ regex: /\/adt\/programs\/includes\/([^/?]+)/, type: 'INCL' },
|
|
12
|
+
{ regex: /\/adt\/ddic\/ddlx\/sources\/([^/?]+)/, type: 'DDLX' },
|
|
13
|
+
{ regex: /\/adt\/ddic\/srvd\/sources\/([^/?]+)/, type: 'SRVD' },
|
|
14
|
+
{ regex: /\/adt\/srvd\/src\/([^/?]+)/, type: 'SRVD' },
|
|
15
|
+
{ regex: /\/adt\/srvb\/src\/([^/?]+)/, type: 'SRVB' },
|
|
16
|
+
{ regex: /\/adt\/ddic\/tables\/([^/?]+)/, type: 'TABL' },
|
|
17
|
+
{ regex: /\/adt\/ddic\/structures\/([^/?]+)/, type: 'STRU' },
|
|
18
|
+
{ regex: /\/adt\/ddic\/dataelements\/([^/?]+)/, type: 'DTEL' },
|
|
19
|
+
{ regex: /\/adt\/ddic\/domains\/([^/?]+)/, type: 'DOMA' },
|
|
20
|
+
{ regex: /\/adt\/ddic\/tabletypes\/([^/?]+)/, type: 'TTYP' },
|
|
21
|
+
{ regex: /\/adt\/functions\/groups\/([^/?]+)\/fmodules\/([^/?]+)/, type: 'FUNC' },
|
|
22
|
+
{ regex: /\/adt\/functions\/groups\/([^/?]+)/, type: 'FUGR' },
|
|
23
|
+
];
|
|
24
|
+
export function extractObjectInfoFromUrl(url) {
|
|
25
|
+
if (!url) {
|
|
26
|
+
return { objectName: null, objectType: null };
|
|
27
|
+
}
|
|
28
|
+
for (const pattern of URL_PATTERNS) {
|
|
29
|
+
const match = url.match(pattern.regex);
|
|
30
|
+
if (match) {
|
|
31
|
+
const objectName = match[2] || match[1];
|
|
32
|
+
return {
|
|
33
|
+
objectName: objectName.toUpperCase(),
|
|
34
|
+
objectType: pattern.type
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { objectName: null, objectType: null };
|
|
39
|
+
}
|
|
40
|
+
export function getObjectUriPath(objectType) {
|
|
41
|
+
const uriMap = {
|
|
42
|
+
'BDEF': '/sap/bc/adt/bo/behaviordefinitions/',
|
|
43
|
+
'DDLS': '/sap/bc/adt/ddic/ddl/sources/',
|
|
44
|
+
'CLAS': '/sap/bc/adt/oo/classes/',
|
|
45
|
+
'INTF': '/sap/bc/adt/oo/interfaces/',
|
|
46
|
+
'PROG': '/sap/bc/adt/programs/programs/',
|
|
47
|
+
'INCL': '/sap/bc/adt/programs/includes/',
|
|
48
|
+
'DDLX': '/sap/bc/adt/ddic/ddlx/sources/',
|
|
49
|
+
'SRVD': '/sap/bc/adt/ddic/srvd/sources/',
|
|
50
|
+
'SRVB': '/sap/bc/adt/srvb/src/',
|
|
51
|
+
'TABL': '/sap/bc/adt/ddic/tables/',
|
|
52
|
+
'STRU': '/sap/bc/adt/ddic/structures/',
|
|
53
|
+
'DTEL': '/sap/bc/adt/ddic/dataelements/',
|
|
54
|
+
'DOMA': '/sap/bc/adt/ddic/domains/',
|
|
55
|
+
'TTYP': '/sap/bc/adt/ddic/tabletypes/',
|
|
56
|
+
'FUGR': '/sap/bc/adt/functions/groups/'
|
|
57
|
+
};
|
|
58
|
+
return uriMap[objectType.toUpperCase()] || null;
|
|
59
|
+
}
|
|
60
|
+
export function isLockOperation(callspec) {
|
|
61
|
+
if (callspec.name === 'UNLOCK' ||
|
|
62
|
+
callspec.name?.startsWith('UNLOCK') ||
|
|
63
|
+
callspec.url?.includes('_action=UNLOCK')) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return callspec.name === 'LOCK' ||
|
|
67
|
+
(callspec.name?.startsWith('LOCK') ?? false) ||
|
|
68
|
+
(callspec.url?.includes('_action=LOCK') ?? false);
|
|
69
|
+
}
|
|
70
|
+
export function isUnlockOperation(callspec) {
|
|
71
|
+
return callspec.name === 'UNLOCK' ||
|
|
72
|
+
(callspec.name?.includes('UNLOCK') ?? false) ||
|
|
73
|
+
(callspec.url?.includes('_action=UNLOCK') ?? false);
|
|
74
|
+
}
|
|
75
|
+
export function isActivateOperation(action) {
|
|
76
|
+
return action === 'activate' ||
|
|
77
|
+
action?.includes('activate') ||
|
|
78
|
+
action === 'adt_activate';
|
|
79
|
+
}
|
|
80
|
+
export function getObjectTypeName(objectType) {
|
|
81
|
+
const names = {
|
|
82
|
+
'BDEF': 'Behavior Definition',
|
|
83
|
+
'DDLS': 'CDS View',
|
|
84
|
+
'CLAS': 'Class',
|
|
85
|
+
'INTF': 'Interface',
|
|
86
|
+
'PROG': 'Program',
|
|
87
|
+
'INCL': 'Include',
|
|
88
|
+
'DDLX': 'Metadata Extension',
|
|
89
|
+
'SRVD': 'Service Definition',
|
|
90
|
+
'SRVB': 'Service Binding',
|
|
91
|
+
'TABL': 'Database Table',
|
|
92
|
+
'STRU': 'Structure',
|
|
93
|
+
'DTEL': 'Data Element',
|
|
94
|
+
'DOMA': 'Domain',
|
|
95
|
+
'TTYP': 'Table Type',
|
|
96
|
+
'FUGR': 'Function Group',
|
|
97
|
+
'FUNC': 'Function Module'
|
|
98
|
+
};
|
|
99
|
+
return names[objectType.toUpperCase()] || objectType;
|
|
100
|
+
}
|
|
101
|
+
export function getLockSuffix(url) {
|
|
102
|
+
if (!url)
|
|
103
|
+
return '';
|
|
104
|
+
if (url.includes('/testclasses') || url.includes('/includes/testclasses')) {
|
|
105
|
+
return 'TESTCLASSES';
|
|
106
|
+
}
|
|
107
|
+
if (url.includes('/implementations') || url.includes('/includes/implementations')) {
|
|
108
|
+
return 'IMPLEMENTATIONS';
|
|
109
|
+
}
|
|
110
|
+
return '';
|
|
111
|
+
}
|
|
112
|
+
export { URL_PATTERNS };
|
|
113
|
+
//# sourceMappingURL=abap-object-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abap-object-utils.js","sourceRoot":"","sources":["../src/abap-object-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Module
|
|
3
|
+
* Centralizes all configuration for the WebSocket client.
|
|
4
|
+
*
|
|
5
|
+
* All URLs are derived in code based on ENV variable:
|
|
6
|
+
* - ENV=DEVELOPMENT -> QAS endpoints
|
|
7
|
+
* - Otherwise -> Production endpoints
|
|
8
|
+
*
|
|
9
|
+
* Only API_KEY needs to be configured by the user.
|
|
10
|
+
*/
|
|
11
|
+
export interface SapSystemConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
client: string;
|
|
15
|
+
username: string;
|
|
16
|
+
password: string;
|
|
17
|
+
language: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SapActiveConfig extends SapSystemConfig {
|
|
20
|
+
systemKey: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface AppConfig {
|
|
23
|
+
WS_URL: string;
|
|
24
|
+
API_KEY: string;
|
|
25
|
+
MCP_ADMIN_URL: string;
|
|
26
|
+
SAP: SapActiveConfig;
|
|
27
|
+
RETRY: {
|
|
28
|
+
maxAttempts: number;
|
|
29
|
+
delayMs: number;
|
|
30
|
+
backoffMultiplier: number;
|
|
31
|
+
};
|
|
32
|
+
KEEPALIVE: {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
intervalMs: number;
|
|
35
|
+
};
|
|
36
|
+
LOCK: {
|
|
37
|
+
ttlMs: number;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
interface SwitchResult {
|
|
41
|
+
success: boolean;
|
|
42
|
+
system: string;
|
|
43
|
+
config: {
|
|
44
|
+
name: string;
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
client: string;
|
|
47
|
+
language: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
interface SystemSummary {
|
|
51
|
+
key: string;
|
|
52
|
+
name: string;
|
|
53
|
+
baseUrl: string;
|
|
54
|
+
client: string;
|
|
55
|
+
}
|
|
56
|
+
export declare function fetchSapSystems(): Promise<Record<string, SapSystemConfig>>;
|
|
57
|
+
export declare function getSapConfig(systemKey?: string | null): SapActiveConfig;
|
|
58
|
+
export declare function switchSystem(systemKey: string): SwitchResult;
|
|
59
|
+
export declare function getAvailableSystems(): SystemSummary[];
|
|
60
|
+
export declare function getActiveSystem(): string | null;
|
|
61
|
+
export declare const CONFIG: AppConfig;
|
|
62
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Module
|
|
3
|
+
* Centralizes all configuration for the WebSocket client.
|
|
4
|
+
*
|
|
5
|
+
* All URLs are derived in code based on ENV variable:
|
|
6
|
+
* - ENV=DEVELOPMENT -> QAS endpoints
|
|
7
|
+
* - Otherwise -> Production endpoints
|
|
8
|
+
*
|
|
9
|
+
* Only API_KEY needs to be configured by the user.
|
|
10
|
+
*/
|
|
11
|
+
import axios from 'axios';
|
|
12
|
+
const PRODUCTION_ADMIN_URL = 'https://arcanum.mcps.b2rise.com';
|
|
13
|
+
const DEVELOPMENT_ADMIN_URL = 'https://qas-arcanum.mcps.b2rise.com';
|
|
14
|
+
const PRODUCTION_WS_URL = 'wss://abap-mcp.mcps.b2rise.com/ws';
|
|
15
|
+
const DEVELOPMENT_WS_URL = 'wss://qas-abap-mcp.mcps.b2rise.com/ws';
|
|
16
|
+
const KEEPALIVE_INTERVAL_MS = 5 * 60 * 1000;
|
|
17
|
+
function isDevelopment() {
|
|
18
|
+
return (process.env.ENV || '').toUpperCase() === 'DEVELOPMENT';
|
|
19
|
+
}
|
|
20
|
+
let sapSystems = {};
|
|
21
|
+
let activeSystemKey = null;
|
|
22
|
+
export async function fetchSapSystems() {
|
|
23
|
+
const adminUrl = CONFIG.MCP_ADMIN_URL;
|
|
24
|
+
const apiKey = CONFIG.API_KEY;
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
throw new Error('API_KEY is required to fetch SAP environments');
|
|
27
|
+
}
|
|
28
|
+
const response = await axios.post(`${adminUrl}/api/sap-environments/by-api-key`, { key: apiKey }, { timeout: 15_000 });
|
|
29
|
+
if (!response.data.valid) {
|
|
30
|
+
throw new Error(`API key validation failed: ${response.data.reason}`);
|
|
31
|
+
}
|
|
32
|
+
sapSystems = response.data.systems || {};
|
|
33
|
+
const systemKeys = Object.keys(sapSystems);
|
|
34
|
+
if (systemKeys.length === 0) {
|
|
35
|
+
throw new Error('No SAP environments configured. Register your systems at the admin portal.');
|
|
36
|
+
}
|
|
37
|
+
if (!activeSystemKey || !sapSystems[activeSystemKey]) {
|
|
38
|
+
activeSystemKey = systemKeys[0];
|
|
39
|
+
}
|
|
40
|
+
CONFIG.SAP = {
|
|
41
|
+
...sapSystems[activeSystemKey],
|
|
42
|
+
systemKey: activeSystemKey,
|
|
43
|
+
};
|
|
44
|
+
console.log(` ✅ Loaded ${systemKeys.length} SAP system(s): ${systemKeys.join(', ')}`);
|
|
45
|
+
console.log(` 📌 Active system: ${activeSystemKey}`);
|
|
46
|
+
return sapSystems;
|
|
47
|
+
}
|
|
48
|
+
export function getSapConfig(systemKey = null) {
|
|
49
|
+
const key = systemKey || activeSystemKey;
|
|
50
|
+
if (!key || !sapSystems[key]) {
|
|
51
|
+
const available = Object.keys(sapSystems).join(', ') || 'none';
|
|
52
|
+
throw new Error(`System "${key}" not found. Available: ${available}`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
...sapSystems[key],
|
|
56
|
+
systemKey: key,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function switchSystem(systemKey) {
|
|
60
|
+
if (!sapSystems[systemKey]) {
|
|
61
|
+
const available = Object.keys(sapSystems).join(', ') || 'none';
|
|
62
|
+
throw new Error(`System "${systemKey}" not found. Available: ${available}`);
|
|
63
|
+
}
|
|
64
|
+
activeSystemKey = systemKey;
|
|
65
|
+
CONFIG.SAP = {
|
|
66
|
+
...sapSystems[systemKey],
|
|
67
|
+
systemKey,
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
system: systemKey,
|
|
72
|
+
config: {
|
|
73
|
+
name: sapSystems[systemKey].name,
|
|
74
|
+
baseUrl: sapSystems[systemKey].baseUrl,
|
|
75
|
+
client: sapSystems[systemKey].client,
|
|
76
|
+
language: sapSystems[systemKey].language,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function getAvailableSystems() {
|
|
81
|
+
return Object.keys(sapSystems).map(key => ({
|
|
82
|
+
key,
|
|
83
|
+
name: sapSystems[key].name,
|
|
84
|
+
baseUrl: sapSystems[key].baseUrl,
|
|
85
|
+
client: sapSystems[key].client,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
export function getActiveSystem() {
|
|
89
|
+
return activeSystemKey;
|
|
90
|
+
}
|
|
91
|
+
export const CONFIG = {
|
|
92
|
+
WS_URL: isDevelopment() ? DEVELOPMENT_WS_URL : PRODUCTION_WS_URL,
|
|
93
|
+
API_KEY: process.env.API_KEY || '',
|
|
94
|
+
MCP_ADMIN_URL: isDevelopment() ? DEVELOPMENT_ADMIN_URL : PRODUCTION_ADMIN_URL,
|
|
95
|
+
SAP: {
|
|
96
|
+
systemKey: null,
|
|
97
|
+
name: '',
|
|
98
|
+
baseUrl: '',
|
|
99
|
+
username: '',
|
|
100
|
+
password: '',
|
|
101
|
+
client: '',
|
|
102
|
+
language: '',
|
|
103
|
+
},
|
|
104
|
+
RETRY: {
|
|
105
|
+
maxAttempts: 3,
|
|
106
|
+
delayMs: 1000,
|
|
107
|
+
backoffMultiplier: 2,
|
|
108
|
+
},
|
|
109
|
+
KEEPALIVE: {
|
|
110
|
+
enabled: true,
|
|
111
|
+
intervalMs: KEEPALIVE_INTERVAL_MS,
|
|
112
|
+
},
|
|
113
|
+
LOCK: {
|
|
114
|
+
ttlMs: 30 * 60 * 1000,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @numends/abap-client
|
|
4
|
+
* WebSocket client that connects to MCP Cloud and executes SAP ADT operations locally.
|
|
5
|
+
* SAP environments are fetched from the Arcanum admin portal on startup.
|
|
6
|
+
*/
|
|
7
|
+
import 'dotenv/config';
|
|
8
|
+
import { createInterface } from 'readline';
|
|
9
|
+
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { CONFIG, fetchSapSystems } from './config.js';
|
|
12
|
+
import { WebSocketClient } from './websocket-client.js';
|
|
13
|
+
const ENV_PATH = join(process.cwd(), '.env');
|
|
14
|
+
function prompt(question) {
|
|
15
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
rl.question(question, (answer) => {
|
|
18
|
+
rl.close();
|
|
19
|
+
resolve(answer.trim());
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function saveApiKey(apiKey) {
|
|
24
|
+
if (existsSync(ENV_PATH)) {
|
|
25
|
+
const content = readFileSync(ENV_PATH, 'utf-8');
|
|
26
|
+
if (content.includes('API_KEY=')) {
|
|
27
|
+
const updated = content.replace(/^API_KEY=.*$/m, `API_KEY=${apiKey}`);
|
|
28
|
+
writeFileSync(ENV_PATH, updated);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
writeFileSync(ENV_PATH, content.trimEnd() + `\nAPI_KEY=${apiKey}\n`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
writeFileSync(ENV_PATH, `API_KEY=${apiKey}\n`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function interactiveSetup() {
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log('🔧 First-time setup');
|
|
41
|
+
console.log('─────────────────────────────────────────────');
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log('You need an API key to connect to Arcanum MCP Cloud.');
|
|
44
|
+
console.log('Get yours at: https://arcanum.mcps.b2rise.com');
|
|
45
|
+
console.log('');
|
|
46
|
+
const apiKey = await prompt(' Paste your API key (arc_...): ');
|
|
47
|
+
if (!apiKey || !apiKey.startsWith('arc_')) {
|
|
48
|
+
console.error('\n❌ Invalid API key. It must start with "arc_".');
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
saveApiKey(apiKey);
|
|
52
|
+
console.log(`\n✅ API key saved to ${ENV_PATH}`);
|
|
53
|
+
console.log(' You won\'t need to enter it again.\n');
|
|
54
|
+
return apiKey;
|
|
55
|
+
}
|
|
56
|
+
async function main() {
|
|
57
|
+
console.log('╔════════════════════════════════════════════════════════════╗');
|
|
58
|
+
console.log('║ ABAP Client - SAP WebSocket Bridge ║');
|
|
59
|
+
console.log('║ Connects to MCP Cloud and executes SAP operations ║');
|
|
60
|
+
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
|
61
|
+
if (!CONFIG.API_KEY) {
|
|
62
|
+
const apiKey = await interactiveSetup();
|
|
63
|
+
CONFIG.API_KEY = apiKey;
|
|
64
|
+
}
|
|
65
|
+
console.log('📋 Configuration:');
|
|
66
|
+
console.log(` WebSocket: ${CONFIG.WS_URL}`);
|
|
67
|
+
console.log(` Admin: ${CONFIG.MCP_ADMIN_URL}`);
|
|
68
|
+
console.log(` API Key: ${CONFIG.API_KEY.substring(0, 12)}...`);
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log('🔄 Fetching SAP environments from admin...');
|
|
71
|
+
try {
|
|
72
|
+
await fetchSapSystems();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(`\n❌ Failed to fetch SAP environments: ${error.message}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
console.log('');
|
|
79
|
+
console.log(` SAP System: ${CONFIG.SAP.baseUrl}`);
|
|
80
|
+
console.log(` SAP Client: ${CONFIG.SAP.client}`);
|
|
81
|
+
console.log(` SAP User: ${CONFIG.SAP.username}`);
|
|
82
|
+
console.log('');
|
|
83
|
+
const client = new WebSocketClient(CONFIG);
|
|
84
|
+
client.connect();
|
|
85
|
+
process.on('SIGINT', () => {
|
|
86
|
+
console.log('\n\n⚠️ Shutting down gracefully...');
|
|
87
|
+
client.disconnect();
|
|
88
|
+
process.exit(0);
|
|
89
|
+
});
|
|
90
|
+
process.on('SIGTERM', () => {
|
|
91
|
+
console.log('\n\n⚠️ Shutting down gracefully...');
|
|
92
|
+
client.disconnect();
|
|
93
|
+
process.exit(0);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
main().catch((error) => {
|
|
97
|
+
console.error(`❌ Fatal error: ${error.message}`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock Manager
|
|
3
|
+
* Manages ABAP object locks to avoid re-locking during multi-step operations
|
|
4
|
+
*/
|
|
5
|
+
export interface LockEntry {
|
|
6
|
+
lockHandle: string;
|
|
7
|
+
transportRequest: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
export interface LockStats {
|
|
11
|
+
activeLocks: number;
|
|
12
|
+
locks: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare class LockManager {
|
|
15
|
+
private locks;
|
|
16
|
+
private lockTTL;
|
|
17
|
+
constructor();
|
|
18
|
+
buildKey(objectName: string, objectType: string, suffix?: string): string;
|
|
19
|
+
getLock(objectName: string, objectType: string, suffix?: string): LockEntry | null;
|
|
20
|
+
saveLock(objectName: string, objectType: string, lockHandle: string, transportRequest: string, suffix?: string): void;
|
|
21
|
+
clearLock(objectName: string, objectType: string, suffix?: string): boolean;
|
|
22
|
+
clearAll(): number;
|
|
23
|
+
getStats(): LockStats;
|
|
24
|
+
printLockTable(operation?: string): void;
|
|
25
|
+
}
|