@mcp-abap-adt/connection 1.10.2 → 2.0.0

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +758 -0
  2. package/README.md +42 -11
  3. package/dist/__tests__/helpers/session.d.ts +15 -0
  4. package/dist/__tests__/helpers/session.d.ts.map +1 -0
  5. package/dist/__tests__/helpers/session.js +19 -0
  6. package/dist/auth/ntlm.d.ts +15 -0
  7. package/dist/auth/ntlm.d.ts.map +1 -1
  8. package/dist/auth/ntlm.js +38 -0
  9. package/dist/connection/AbstractAbapConnection.d.ts +163 -11
  10. package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
  11. package/dist/connection/AbstractAbapConnection.js +351 -14
  12. package/dist/connection/BaseAbapConnection.d.ts +5 -1
  13. package/dist/connection/BaseAbapConnection.d.ts.map +1 -1
  14. package/dist/connection/BaseAbapConnection.js +11 -1
  15. package/dist/connection/CertificateAbapConnection.d.ts +5 -1
  16. package/dist/connection/CertificateAbapConnection.d.ts.map +1 -1
  17. package/dist/connection/CertificateAbapConnection.js +11 -1
  18. package/dist/connection/JwtAbapConnection.d.ts +3 -2
  19. package/dist/connection/JwtAbapConnection.d.ts.map +1 -1
  20. package/dist/connection/JwtAbapConnection.js +19 -8
  21. package/dist/connection/KerberosAbapConnection.d.ts +5 -1
  22. package/dist/connection/KerberosAbapConnection.d.ts.map +1 -1
  23. package/dist/connection/KerberosAbapConnection.js +54 -3
  24. package/dist/connection/SamlAbapConnection.d.ts +5 -1
  25. package/dist/connection/SamlAbapConnection.d.ts.map +1 -1
  26. package/dist/connection/SamlAbapConnection.js +11 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/session/SessionLifecycle.d.ts +2 -9
  30. package/dist/session/SessionLifecycle.d.ts.map +1 -1
  31. package/dist/session/SessionLifecycle.js +8 -8
  32. package/docs/INDEX.md +106 -0
  33. package/docs/INSTALLATION.md +304 -0
  34. package/docs/JWT_AUTH_TOOLS.md +142 -0
  35. package/docs/MIGRATION-2.0.md +125 -0
  36. package/docs/SCOPE.md +44 -0
  37. package/docs/STATEFUL_SESSION_GUIDE.md +121 -0
  38. package/docs/USAGE.md +749 -0
  39. package/examples/README.md +112 -0
  40. package/examples/basic-connection.js +55 -0
  41. package/examples/jwt-with-token-refresh.js +87 -0
  42. package/examples/saml-connection.js +52 -0
  43. package/examples/websocket-transport.js +87 -0
  44. package/package.json +11 -4
@@ -0,0 +1,112 @@
1
+ # Connection Examples
2
+
3
+ This directory contains example code demonstrating how to use the `@mcp-abap-adt/connection` package.
4
+
5
+ ## Prerequisites
6
+
7
+ ```bash
8
+ # Install dependencies
9
+ cd packages/connection
10
+ npm install
11
+
12
+ # Build the package
13
+ npm run build
14
+
15
+ # Set up environment variables
16
+ cp .env.example .env
17
+ # Edit .env with your SAP credentials
18
+ ```
19
+
20
+ ## Available Examples
21
+
22
+ ### basic-connection.js
23
+
24
+ Simple example showing how to connect to SAP and make an ADT request.
25
+
26
+ ```bash
27
+ node examples/basic-connection.js
28
+ ```
29
+
30
+ **What it demonstrates:**
31
+ - Creating connection with factory function
32
+ - Connecting to SAP system
33
+ - Making GET request to ADT endpoint
34
+ - Basic error handling
35
+
36
+ ### jwt-with-token-refresh.js
37
+
38
+ Shows how to use `ITokenRefresher` for automatic token refresh.
39
+
40
+ ```bash
41
+ node examples/jwt-with-token-refresh.js
42
+ ```
43
+
44
+ **What it demonstrates:**
45
+ - Creating connection with token refresher injection
46
+ - Automatic token refresh on 401/403 errors
47
+ - Retry logic with refreshed token
48
+
49
+ ### saml-connection.js
50
+
51
+ Shows how to use cookie-based SAML connection.
52
+
53
+ ```bash
54
+ node examples/saml-connection.js
55
+ ```
56
+
57
+ **What it demonstrates:**
58
+ - Creating SAML connection via factory (`authType: "saml"`)
59
+ - Using `sessionCookies` from environment
60
+ - Fetching CSRF token and making ADT request with cookie auth
61
+
62
+ ### websocket-transport.js
63
+
64
+ Shows how to use `GenericWebSocketTransport` with injected WS factory.
65
+
66
+ ```bash
67
+ node examples/websocket-transport.js
68
+ ```
69
+
70
+ **What it demonstrates:**
71
+ - Creating `GenericWebSocketTransport`
72
+ - Registering `onOpen`, `onMessage`, `onError`, `onClose` handlers
73
+ - Sending `IWebSocketMessageEnvelope` payload
74
+ - Connecting/disconnecting transport lifecycle
75
+
76
+ ## Configuration
77
+
78
+ ### Using .env file
79
+
80
+ Create `.env` in project root:
81
+
82
+ ```bash
83
+ # Basic Auth
84
+ SAP_URL=https://your-sap-system.com
85
+ SAP_AUTH_TYPE=basic
86
+ SAP_USERNAME=your_username
87
+ SAP_PASSWORD=your_password
88
+ SAP_CLIENT=100
89
+
90
+ # JWT Auth (Cloud/BTP)
91
+ SAP_AUTH_TYPE=jwt
92
+ SAP_JWT_TOKEN=eyJhbGciOiJSUzI1NiIs...
93
+ # Note: Token refresh is handled by @mcp-abap-adt/auth-broker package
94
+
95
+ # SAML Auth (Cookie-based)
96
+ SAP_AUTH_TYPE=saml
97
+ SAP_SESSION_COOKIES=sap-usercontext=sap-client=100; sap-contextid=...
98
+ ```
99
+
100
+ ### Using Environment Variables
101
+
102
+ ```bash
103
+ export SAP_URL=https://your-sap-system.com
104
+ export SAP_USERNAME=your_username
105
+ export SAP_PASSWORD=your_password
106
+ node examples/basic-connection.js
107
+ ```
108
+
109
+ ## See Also
110
+
111
+ - [Connection README](../README.md) - Main package documentation
112
+ - [Session Lifecycle](../docs/USAGE.md#session-lifecycle) - connect/disconnect, lock windows, a lost session
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Basic Connection Example
3
+ *
4
+ * Demonstrates simple connection to SAP system and making ADT request
5
+ */
6
+
7
+ const { createAbapConnection } = require('@mcp-abap-adt/connection');
8
+
9
+ async function main() {
10
+ // Configuration from environment or hardcoded
11
+ const config = {
12
+ url: process.env.SAP_URL || 'https://your-sap-server.com',
13
+ authType: process.env.SAP_AUTH_TYPE || 'basic',
14
+ username: process.env.SAP_USERNAME,
15
+ password: process.env.SAP_PASSWORD,
16
+ client: process.env.SAP_CLIENT || '100',
17
+ };
18
+
19
+ console.log('Creating connection to', config.url);
20
+
21
+ // Create connection (factory auto-detects cloud vs on-premise)
22
+ const connection = createAbapConnection(config, console);
23
+
24
+ try {
25
+ // Connect and get CSRF token
26
+ console.log('Connecting to SAP system...');
27
+ await connection.connect();
28
+ console.log('✓ Connected successfully');
29
+
30
+ // Make a simple ADT request
31
+ console.log('\nFetching repository structure...');
32
+ const response = await connection.makeAdtRequest({
33
+ method: 'GET',
34
+ url: '/sap/bc/adt/repository/nodestructure',
35
+ params: {
36
+ parent_name: 'DEVC/K',
37
+ parent_type: 'DEVC/K',
38
+ withShortDescriptions: 'true',
39
+ },
40
+ });
41
+
42
+ console.log('✓ Request successful');
43
+ console.log('Response status:', response.status);
44
+ console.log('Data length:', response.data.length);
45
+ } catch (error) {
46
+ console.error('✗ Error:', error.message);
47
+ if (error.response) {
48
+ console.error(' Status:', error.response.status);
49
+ console.error(' Data:', error.response.data);
50
+ }
51
+ process.exit(1);
52
+ }
53
+ }
54
+
55
+ main();
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Example: JWT Connection with Automatic Token Refresh
3
+ *
4
+ * This example demonstrates how to create a JwtAbapConnection with
5
+ * automatic token refresh using ITokenRefresher from auth-broker.
6
+ *
7
+ * When 401/403 errors occur, the connection automatically:
8
+ * 1. Calls tokenRefresher.refreshToken() to get a new token
9
+ * 2. Updates internal token state
10
+ * 3. Retries the failed request with the new token
11
+ */
12
+
13
+ const { JwtAbapConnection } = require('@mcp-abap-adt/connection');
14
+ // const { AuthBroker } = require('@mcp-abap-adt/auth-broker');
15
+
16
+ // Simple logger
17
+ const logger = {
18
+ info: (msg, meta) => console.log('[INFO]', msg, meta || ''),
19
+ error: (msg, meta) => console.error('[ERROR]', msg, meta || ''),
20
+ warn: (msg, meta) => console.warn('[WARN]', msg, meta || ''),
21
+ debug: (msg, meta) => console.debug('[DEBUG]', msg, meta || ''),
22
+ };
23
+
24
+ async function main() {
25
+ // Option 1: Using AuthBroker (recommended for production)
26
+ // const broker = new AuthBroker({
27
+ // sessionStore: mySessionStore,
28
+ // serviceKeyStore: myServiceKeyStore,
29
+ // tokenProvider: myTokenProvider,
30
+ // });
31
+ // const tokenRefresher = broker.createTokenRefresher('TRIAL');
32
+ // const initialToken = await tokenRefresher.getToken();
33
+
34
+ // Option 2: Manual ITokenRefresher implementation (for testing/custom scenarios)
35
+ const tokenRefresher = {
36
+ getToken: async () => {
37
+ console.log('getToken called - returning cached or refreshed token');
38
+ return process.env.SAP_JWT_TOKEN || 'your-jwt-token';
39
+ },
40
+ refreshToken: async () => {
41
+ console.log('refreshToken called - forcing token refresh');
42
+ // In real implementation: call OAuth2 token endpoint
43
+ // Save new token to session store
44
+ // Return new token
45
+ return 'newly-refreshed-jwt-token';
46
+ },
47
+ };
48
+
49
+ // Get initial token
50
+ const initialToken = await tokenRefresher.getToken();
51
+
52
+ // JWT configuration
53
+ const config = {
54
+ url: process.env.SAP_URL || 'https://your-instance.abap.cloud.sap',
55
+ authType: 'jwt',
56
+ jwtToken: initialToken,
57
+ };
58
+
59
+ // Create connection with token refresher
60
+ // 4th parameter is the ITokenRefresher
61
+ const connection = new JwtAbapConnection(
62
+ config,
63
+ logger,
64
+ undefined,
65
+ tokenRefresher,
66
+ );
67
+
68
+ try {
69
+ await connection.connect();
70
+
71
+ // This request will automatically refresh token if 401/403 occurs. Note
72
+ // that a refresh replaces the SAP session: with a lock window open the
73
+ // request would fail with ADT_SESSION_REPLACED rather than continue on a
74
+ // session your lock is not in.
75
+ const response = await connection.makeAdtRequest({
76
+ method: 'GET',
77
+ url: '/sap/bc/adt/discovery',
78
+ });
79
+
80
+ console.log('Request succeeded:', response.status);
81
+ console.log('Discovery data available');
82
+ } catch (error) {
83
+ console.error('Request failed:', error.message);
84
+ }
85
+ }
86
+
87
+ main().catch(console.error);
@@ -0,0 +1,52 @@
1
+ /**
2
+ * SAML Connection Example
3
+ *
4
+ * Demonstrates using cookie-based SAML authentication.
5
+ * Session cookies are expected from prior login flow.
6
+ */
7
+
8
+ const { createAbapConnection } = require('@mcp-abap-adt/connection');
9
+
10
+ async function main() {
11
+ const config = {
12
+ url: process.env.SAP_URL || 'https://your-sap-server.com',
13
+ authType: 'saml',
14
+ sessionCookies: process.env.SAP_SESSION_COOKIES,
15
+ client: process.env.SAP_CLIENT || '100',
16
+ };
17
+
18
+ if (!config.sessionCookies) {
19
+ throw new Error(
20
+ 'SAP_SESSION_COOKIES is required for SAML example (full Cookie header value)',
21
+ );
22
+ }
23
+
24
+ console.log('Creating SAML connection to', config.url);
25
+ const connection = createAbapConnection(config, console);
26
+
27
+ try {
28
+ console.log('Connecting using session cookies...');
29
+ await connection.connect();
30
+ console.log('✓ Connected successfully');
31
+
32
+ const response = await connection.makeAdtRequest({
33
+ method: 'GET',
34
+ url: '/sap/bc/adt/discovery',
35
+ });
36
+
37
+ console.log('✓ Request successful');
38
+ console.log('Response status:', response.status);
39
+ } catch (error) {
40
+ console.error('✗ Error:', error.message || String(error));
41
+ if (error.response) {
42
+ console.error(' Status:', error.response.status);
43
+ console.error(' Data:', error.response.data);
44
+ }
45
+ process.exit(1);
46
+ }
47
+ }
48
+
49
+ main().catch((error) => {
50
+ console.error('Fatal:', error.message || String(error));
51
+ process.exit(1);
52
+ });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Generic WebSocket Transport Example
3
+ *
4
+ * Demonstrates how to plug a concrete WebSocket implementation
5
+ * into GenericWebSocketTransport through the factory interface.
6
+ */
7
+
8
+ const { GenericWebSocketTransport } = require('@mcp-abap-adt/connection');
9
+
10
+ class MockWebSocket {
11
+ constructor() {
12
+ this.readyState = 0;
13
+ this.onopen = null;
14
+ this.onmessage = null;
15
+ this.onerror = null;
16
+ this.onclose = null;
17
+
18
+ setTimeout(() => {
19
+ this.readyState = 1;
20
+ if (this.onopen) this.onopen({});
21
+ }, 10);
22
+ }
23
+
24
+ send(payload) {
25
+ // Echo payload back as "event" for demo purposes.
26
+ if (this.onmessage) {
27
+ this.onmessage({ data: payload });
28
+ }
29
+ }
30
+
31
+ close(code, reason) {
32
+ this.readyState = 3;
33
+ if (this.onclose) {
34
+ this.onclose({
35
+ code: code || 1000,
36
+ reason: reason || 'normal',
37
+ wasClean: true,
38
+ });
39
+ }
40
+ }
41
+ }
42
+
43
+ const mockFactory = {
44
+ create(_url, _protocols, _options) {
45
+ return new MockWebSocket();
46
+ },
47
+ };
48
+
49
+ async function main() {
50
+ const transport = new GenericWebSocketTransport(mockFactory);
51
+
52
+ transport.onOpen(() => {
53
+ console.log('✓ WS open');
54
+ });
55
+
56
+ transport.onMessage((message) => {
57
+ console.log('message:', message);
58
+ });
59
+
60
+ transport.onError((error) => {
61
+ console.error('error:', error.message);
62
+ });
63
+
64
+ transport.onClose((info) => {
65
+ console.log('closed:', info);
66
+ });
67
+
68
+ await transport.connect('wss://example.invalid/realtime', {
69
+ connectTimeoutMs: 5000,
70
+ heartbeatIntervalMs: 30000,
71
+ });
72
+
73
+ await transport.send({
74
+ kind: 'request',
75
+ correlationId: 'demo-1',
76
+ operation: 'debugger.listen',
77
+ payload: { timeoutSeconds: 30 },
78
+ timestamp: Date.now(),
79
+ });
80
+
81
+ await transport.disconnect(1000, 'demo finished');
82
+ }
83
+
84
+ main().catch((error) => {
85
+ console.error('Fatal:', error.message || String(error));
86
+ process.exit(1);
87
+ });
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/connection",
3
- "version": "1.10.2",
3
+ "version": "2.0.0",
4
4
  "description": "ABAP connection layer for MCP ABAP ADT server",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
8
  "dist",
9
9
  "bin",
10
+ "docs",
11
+ "examples",
10
12
  "README.md",
13
+ "CHANGELOG.md",
11
14
  "LICENSE"
12
15
  ],
13
16
  "bin": {
@@ -39,14 +42,15 @@
39
42
  "format": "npx biome format --write src",
40
43
  "build": "npm run --silent clean && npx biome check src --diagnostic-level=error && npx tsc -p tsconfig.json",
41
44
  "build:fast": "npx tsc -p tsconfig.json",
42
- "test": "jest",
43
- "prepublishOnly": "npm run build"
45
+ "test": "npm run --silent check:docs && jest",
46
+ "prepublishOnly": "npm run build && npm run check:docs",
47
+ "check:docs": "node scripts/check-docs.mjs"
44
48
  },
45
49
  "engines": {
46
50
  "node": ">=18.0.0"
47
51
  },
48
52
  "dependencies": {
49
- "@mcp-abap-adt/interfaces": "^7.2.0",
53
+ "@mcp-abap-adt/interfaces": "^11.5.0",
50
54
  "axios": "^1.16.0",
51
55
  "commander": "^14.0.3",
52
56
  "express": "^5.1.0",
@@ -65,5 +69,8 @@
65
69
  "jest-util": "^30.2.0",
66
70
  "ts-jest": "^29.2.5",
67
71
  "typescript": "^5.9.2"
72
+ },
73
+ "overrides": {
74
+ "brace-expansion": "^5.0.8"
68
75
  }
69
76
  }