@mcp-abap-adt/connection 1.10.1 → 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.
- package/CHANGELOG.md +758 -0
- package/README.md +42 -11
- package/dist/__tests__/helpers/session.d.ts +15 -0
- package/dist/__tests__/helpers/session.d.ts.map +1 -0
- package/dist/__tests__/helpers/session.js +19 -0
- package/dist/auth/ntlm.d.ts +15 -0
- package/dist/auth/ntlm.d.ts.map +1 -1
- package/dist/auth/ntlm.js +38 -0
- package/dist/connection/AbstractAbapConnection.d.ts +163 -11
- package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.js +351 -14
- package/dist/connection/BaseAbapConnection.d.ts +5 -1
- package/dist/connection/BaseAbapConnection.d.ts.map +1 -1
- package/dist/connection/BaseAbapConnection.js +11 -1
- package/dist/connection/CertificateAbapConnection.d.ts +5 -1
- package/dist/connection/CertificateAbapConnection.d.ts.map +1 -1
- package/dist/connection/CertificateAbapConnection.js +11 -1
- package/dist/connection/JwtAbapConnection.d.ts +3 -2
- package/dist/connection/JwtAbapConnection.d.ts.map +1 -1
- package/dist/connection/JwtAbapConnection.js +19 -8
- package/dist/connection/KerberosAbapConnection.d.ts +5 -1
- package/dist/connection/KerberosAbapConnection.d.ts.map +1 -1
- package/dist/connection/KerberosAbapConnection.js +54 -3
- package/dist/connection/SamlAbapConnection.d.ts +5 -1
- package/dist/connection/SamlAbapConnection.d.ts.map +1 -1
- package/dist/connection/SamlAbapConnection.js +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/session/SessionLifecycle.d.ts +131 -0
- package/dist/session/SessionLifecycle.d.ts.map +1 -0
- package/dist/session/SessionLifecycle.js +301 -0
- package/docs/INDEX.md +106 -0
- package/docs/INSTALLATION.md +304 -0
- package/docs/JWT_AUTH_TOOLS.md +142 -0
- package/docs/MIGRATION-2.0.md +125 -0
- package/docs/SCOPE.md +44 -0
- package/docs/STATEFUL_SESSION_GUIDE.md +121 -0
- package/docs/USAGE.md +749 -0
- package/examples/README.md +112 -0
- package/examples/basic-connection.js +55 -0
- package/examples/jwt-with-token-refresh.js +87 -0
- package/examples/saml-connection.js +52 -0
- package/examples/websocket-transport.js +87 -0
- package/package.json +11 -4
package/docs/INDEX.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Documentation Index
|
|
2
|
+
|
|
3
|
+
**Package:** `@mcp-abap-adt/connection`
|
|
4
|
+
**Version:** see [CHANGELOG.md](../CHANGELOG.md) — kept there rather than
|
|
5
|
+
duplicated here, where it went stale by eight minor versions.
|
|
6
|
+
|
|
7
|
+
## Package Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
mcp-abap-connection/
|
|
11
|
+
├── README.md # Main package documentation
|
|
12
|
+
├── CHANGELOG.md # Version history and changes
|
|
13
|
+
├── docs/ # Detailed documentation
|
|
14
|
+
│ ├── INDEX.md # This file - documentation overview
|
|
15
|
+
│ ├── INSTALLATION.md # Setup and installation guide
|
|
16
|
+
│ ├── USAGE.md # API documentation and examples
|
|
17
|
+
│ ├── MIGRATION-2.0.md # Moving to the explicit session lifecycle
|
|
18
|
+
│ ├── SCOPE.md # What this package does and does not own
|
|
19
|
+
│ ├── STATEFUL_SESSION_GUIDE.md # Stateful requests and lock windows
|
|
20
|
+
│ └── JWT_AUTH_TOOLS.md # CLI tool for authentication
|
|
21
|
+
├── examples/ # Working code examples
|
|
22
|
+
│ ├── README.md # Examples overview
|
|
23
|
+
│ └── basic-connection.js # Simple connection example
|
|
24
|
+
├── bin/ # CLI tools
|
|
25
|
+
│ └── sap-abap-auth.js # JWT authentication CLI
|
|
26
|
+
└── src/ # Source code
|
|
27
|
+
├── connection/ # Connection classes
|
|
28
|
+
├── config/ # Configuration utilities
|
|
29
|
+
├── utils/ # Helper functions
|
|
30
|
+
└── __tests__/ # Unit tests
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Links
|
|
34
|
+
|
|
35
|
+
### Getting Started
|
|
36
|
+
- 📦 [Installation Guide](./INSTALLATION.md) - How to install and set up the package
|
|
37
|
+
- 📚 [Usage Guide](./USAGE.md) - Basic usage and comprehensive API documentation
|
|
38
|
+
- 📖 [Main README](../README.md) - Package overview and quick start
|
|
39
|
+
- 🧭 [Scope and Boundaries](./SCOPE.md) - What this package does (and does not), sibling packages, and why there is no RFC to cloud
|
|
40
|
+
|
|
41
|
+
### Core Features
|
|
42
|
+
- 🔑 [JWT Auth Tools](./JWT_AUTH_TOOLS.md) - CLI tool for browser-based authentication
|
|
43
|
+
|
|
44
|
+
### Version Information
|
|
45
|
+
- 📋 [CHANGELOG](../CHANGELOG.md) - Complete version history, including what the latest release changed
|
|
46
|
+
|
|
47
|
+
### Examples
|
|
48
|
+
- 📁 [Examples Overview](../examples/README.md) - All available examples
|
|
49
|
+
- 🔌 [Basic Connection](../examples/basic-connection.js) - Simple connection setup
|
|
50
|
+
|
|
51
|
+
## Documentation by Topic
|
|
52
|
+
|
|
53
|
+
### Authentication
|
|
54
|
+
- **Basic Auth**: [USAGE.md - Basic Authentication](./USAGE.md#basic-authentication-on-premise)
|
|
55
|
+
- **JWT/OAuth2**: [USAGE.md - JWT Authentication](./USAGE.md#jwt-authentication-cloudbtp)
|
|
56
|
+
- **Token Refresh**: Handled by `@mcp-abap-adt/auth-broker` package (removed in 0.2.0)
|
|
57
|
+
- **CLI Tool**: [JWT_AUTH_TOOLS.md](./JWT_AUTH_TOOLS.md)
|
|
58
|
+
|
|
59
|
+
### Session Management
|
|
60
|
+
- **Overview**: [USAGE.md - Session Management](./USAGE.md#session-management)
|
|
61
|
+
- **Stateful Mode**: Use `setSessionType('stateful')` for session headers
|
|
62
|
+
- **Session State Persistence**: Handled by `@mcp-abap-adt/auth-broker` package
|
|
63
|
+
- **API Methods**:
|
|
64
|
+
- `getSessionId()` - Get current session ID (auto-generated UUID)
|
|
65
|
+
- `setSessionType()` - Switch between stateful/stateless modes
|
|
66
|
+
|
|
67
|
+
### API Reference
|
|
68
|
+
- **Connection Interface**: [USAGE.md - API Reference](./USAGE.md#api-reference)
|
|
69
|
+
- **Configuration Types**: [USAGE.md - Configuration Types](./USAGE.md#configuration-types)
|
|
70
|
+
- **Factory Function**: `createAbapConnection()`
|
|
71
|
+
- **Connection Classes**: `BaseAbapConnection`, `JwtAbapConnection`
|
|
72
|
+
|
|
73
|
+
## Version Highlights
|
|
74
|
+
|
|
75
|
+
See [CHANGELOG.md](../CHANGELOG.md). This section used to restate it and drifted
|
|
76
|
+
eight minor versions behind — a second copy of a changelog is a changelog that
|
|
77
|
+
is wrong.
|
|
78
|
+
|
|
79
|
+
## Documentation Standards
|
|
80
|
+
|
|
81
|
+
### File Organization
|
|
82
|
+
- **README.md** - Package overview, quick start, basic API
|
|
83
|
+
- **CHANGELOG.md** - All changes, following [Keep a Changelog](https://keepachangelog.com/)
|
|
84
|
+
- **docs/** - Detailed documentation, tutorials, guides
|
|
85
|
+
- **examples/** - Working code examples with README
|
|
86
|
+
|
|
87
|
+
### Naming Conventions
|
|
88
|
+
- `UPPERCASE.md` - Main documentation files (README, CHANGELOG)
|
|
89
|
+
- `PascalCase.md` - Detailed guides in docs/ folder
|
|
90
|
+
- `kebab-case.js` - Example files
|
|
91
|
+
|
|
92
|
+
### Content Guidelines
|
|
93
|
+
- Keep README concise, link to detailed docs
|
|
94
|
+
- Include working code examples
|
|
95
|
+
- Document environment variables and configuration
|
|
96
|
+
- Provide troubleshooting sections
|
|
97
|
+
- Show both success and error handling
|
|
98
|
+
|
|
99
|
+
## Contributing Documentation
|
|
100
|
+
|
|
101
|
+
When adding new features:
|
|
102
|
+
1. Update CHANGELOG.md with changes
|
|
103
|
+
2. Add usage examples to USAGE.md
|
|
104
|
+
3. Create working examples in examples/
|
|
105
|
+
4. Update README.md if API changes
|
|
106
|
+
5. Add troubleshooting to relevant guide
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Installation Guide
|
|
2
|
+
|
|
3
|
+
**Version:** see [CHANGELOG.md](../CHANGELOG.md)
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js >= 18.0.0
|
|
8
|
+
- npm or yarn package manager
|
|
9
|
+
- Access to SAP ABAP system (on-premise or BTP)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
### As NPM Package (Recommended)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @mcp-abap-adt/connection
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### With Yarn
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add @mcp-abap-adt/connection
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### From Source
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/fr0ster/mcp-abap-connection.git
|
|
29
|
+
cd mcp-abap-connection
|
|
30
|
+
npm install
|
|
31
|
+
npm run build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Environment Setup
|
|
35
|
+
|
|
36
|
+
### Basic Authentication (On-Premise)
|
|
37
|
+
|
|
38
|
+
Create a `.env` file in your project root:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
SAP_URL=https://your-sap-server.com:8000
|
|
42
|
+
SAP_CLIENT=100
|
|
43
|
+
SAP_AUTH_TYPE=basic
|
|
44
|
+
SAP_USERNAME=your-username
|
|
45
|
+
SAP_PASSWORD=your-password
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### JWT Authentication (SAP BTP Cloud)
|
|
49
|
+
|
|
50
|
+
When using the `sap-abap-auth` CLI tool, the generated `.env` file will include token expiry information:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Token Expiry Information (auto-generated)
|
|
54
|
+
# JWT Token expires: Monday, December 25, 2025 at 10:30:45 AM UTC
|
|
55
|
+
# JWT Token expires at: 2025-12-25T10:30:45.000Z
|
|
56
|
+
# Refresh Token expires: Tuesday, January 25, 2026 at 10:30:45 AM UTC
|
|
57
|
+
# Refresh Token expires at: 2026-01-25T10:30:45.000Z
|
|
58
|
+
|
|
59
|
+
SAP_URL=https://your-instance.abap.cloud.sap
|
|
60
|
+
SAP_CLIENT=100
|
|
61
|
+
SAP_AUTH_TYPE=jwt
|
|
62
|
+
SAP_JWT_TOKEN=your-jwt-token
|
|
63
|
+
|
|
64
|
+
# Note: Token refresh is handled by @mcp-abap-adt/auth-broker package
|
|
65
|
+
# Connection package does not use refresh token credentials
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Manual Setup:** If creating `.env` manually (without CLI), you can omit the expiry comments:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
SAP_URL=https://your-instance.abap.cloud.sap
|
|
72
|
+
SAP_CLIENT=100
|
|
73
|
+
SAP_AUTH_TYPE=jwt
|
|
74
|
+
SAP_JWT_TOKEN=your-jwt-token
|
|
75
|
+
|
|
76
|
+
# Note: Token refresh is handled by @mcp-abap-adt/auth-broker package
|
|
77
|
+
# Connection package does not use refresh token credentials
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Loading Environment Variables
|
|
81
|
+
|
|
82
|
+
In your code:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import 'dotenv/config'; // or require('dotenv').config();
|
|
86
|
+
import { createAbapConnection } from '@mcp-abap-adt/connection';
|
|
87
|
+
|
|
88
|
+
const config = {
|
|
89
|
+
url: process.env.SAP_URL!,
|
|
90
|
+
client: process.env.SAP_CLIENT,
|
|
91
|
+
authType: process.env.SAP_AUTH_TYPE as 'basic' | 'jwt',
|
|
92
|
+
username: process.env.SAP_USERNAME,
|
|
93
|
+
password: process.env.SAP_PASSWORD,
|
|
94
|
+
jwtToken: process.env.SAP_JWT_TOKEN,
|
|
95
|
+
// Note: Token refresh credentials are not used by connection package
|
|
96
|
+
// Token refresh is handled by @mcp-abap-adt/auth-broker
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## CLI Tool Installation
|
|
101
|
+
|
|
102
|
+
The package includes `sap-abap-auth` CLI tool for browser-based JWT authentication.
|
|
103
|
+
|
|
104
|
+
### Global Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm install -g @mcp-abap-adt/connection
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then use directly:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
sap-abap-auth auth -k service-key.json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Local Project Installation
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm install --save-dev @mcp-abap-adt/connection
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use via npx:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx sap-abap-auth auth -k service-key.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### On-Demand (No Installation)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npx @mcp-abap-adt/connection sap-abap-auth auth -k service-key.json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
See [JWT_AUTH_TOOLS.md](./JWT_AUTH_TOOLS.md) for detailed CLI documentation.
|
|
135
|
+
|
|
136
|
+
## Verification
|
|
137
|
+
|
|
138
|
+
### Test Installation
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
node -e "const { createAbapConnection } = require('@mcp-abap-adt/connection'); console.log('✓ Package loaded successfully');"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Test Connection (Basic Auth)
|
|
145
|
+
|
|
146
|
+
Create `test-connection.js`:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const { createAbapConnection } = require('@mcp-abap-adt/connection');
|
|
150
|
+
|
|
151
|
+
const config = {
|
|
152
|
+
url: 'https://your-sap-server.com',
|
|
153
|
+
authType: 'basic',
|
|
154
|
+
username: 'your-username',
|
|
155
|
+
password: 'your-password',
|
|
156
|
+
client: '100'
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const logger = {
|
|
160
|
+
info: (msg) => console.log('[INFO]', msg),
|
|
161
|
+
error: (msg) => console.error('[ERROR]', msg),
|
|
162
|
+
warn: (msg) => console.warn('[WARN]', msg),
|
|
163
|
+
debug: (msg) => console.log('[DEBUG]', msg),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const connection = createAbapConnection(config, logger);
|
|
167
|
+
|
|
168
|
+
connection.connect()
|
|
169
|
+
.then(() =>
|
|
170
|
+
connection.makeAdtRequest({
|
|
171
|
+
method: 'GET',
|
|
172
|
+
url: '/sap/bc/adt/discovery',
|
|
173
|
+
}),
|
|
174
|
+
)
|
|
175
|
+
.then(() => console.log('✓ Connection successful'))
|
|
176
|
+
.catch((err) => console.error('✗ Connection failed:', err.message));
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Run:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
node test-connection.js
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## TypeScript Setup
|
|
186
|
+
|
|
187
|
+
### Install TypeScript
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
npm install --save-dev typescript @types/node
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Create `tsconfig.json`
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"compilerOptions": {
|
|
198
|
+
"target": "ES2020",
|
|
199
|
+
"module": "commonjs",
|
|
200
|
+
"lib": ["ES2020"],
|
|
201
|
+
"outDir": "./dist",
|
|
202
|
+
"rootDir": "./src",
|
|
203
|
+
"strict": true,
|
|
204
|
+
"esModuleInterop": true,
|
|
205
|
+
"skipLibCheck": true,
|
|
206
|
+
"forceConsistentCasingInFileNames": true,
|
|
207
|
+
"resolveJsonModule": true
|
|
208
|
+
},
|
|
209
|
+
"include": ["src/**/*"],
|
|
210
|
+
"exclude": ["node_modules", "dist"]
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### TypeScript Example
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { createAbapConnection, SapConfig, ILogger } from '@mcp-abap-adt/connection';
|
|
218
|
+
|
|
219
|
+
const config: SapConfig = {
|
|
220
|
+
url: 'https://your-sap-server.com',
|
|
221
|
+
authType: 'basic',
|
|
222
|
+
username: 'user',
|
|
223
|
+
password: 'pass',
|
|
224
|
+
client: '100'
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const logger: ILogger = {
|
|
228
|
+
info: (msg: string) => console.log(msg),
|
|
229
|
+
error: (msg: string) => console.error(msg),
|
|
230
|
+
warn: (msg: string) => console.warn(msg),
|
|
231
|
+
debug: (msg: string) => console.log(msg),
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const connection = createAbapConnection(config, logger);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Troubleshooting
|
|
238
|
+
|
|
239
|
+
### Module not found
|
|
240
|
+
|
|
241
|
+
If you get "Cannot find module" error after installation:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
# Clear cache
|
|
245
|
+
npm cache clean --force
|
|
246
|
+
|
|
247
|
+
# Reinstall
|
|
248
|
+
rm -rf node_modules package-lock.json
|
|
249
|
+
npm install
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### TypeScript errors
|
|
253
|
+
|
|
254
|
+
Ensure TypeScript version compatibility:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm install --save-dev typescript@^5.9.2
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Build errors
|
|
261
|
+
|
|
262
|
+
If building from source fails:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Check Node version
|
|
266
|
+
node --version # Should be >= 18.0.0
|
|
267
|
+
|
|
268
|
+
# Rebuild
|
|
269
|
+
npm run build
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Connection errors
|
|
273
|
+
|
|
274
|
+
**401 Unauthorized**: Check username/password or JWT token
|
|
275
|
+
**403 Forbidden**: Check user permissions in SAP
|
|
276
|
+
**ENOTFOUND**: Check SAP URL is correct and reachable
|
|
277
|
+
**ETIMEDOUT**: Check network/firewall, try increasing timeout
|
|
278
|
+
|
|
279
|
+
### SSL/TLS errors
|
|
280
|
+
|
|
281
|
+
For development with self-signed certificates:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**⚠️ Warning**: Never use this in production!
|
|
288
|
+
|
|
289
|
+
## Version Compatibility
|
|
290
|
+
|
|
291
|
+
| Package Version | Node.js | TypeScript |
|
|
292
|
+
|----------------|---------|------------|
|
|
293
|
+
| 0.1.10 | >= 18.0 | >= 5.0 |
|
|
294
|
+
| 0.1.9 | >= 18.0 | >= 5.0 |
|
|
295
|
+
| 0.1.8 | >= 18.0 | >= 5.0 |
|
|
296
|
+
| 0.1.0 - 0.1.7 | >= 18.0 | >= 4.5 |
|
|
297
|
+
|
|
298
|
+
## Next Steps
|
|
299
|
+
|
|
300
|
+
- 📚 Read [USAGE.md](./USAGE.md) for detailed usage examples
|
|
301
|
+
- 🔄 Token refresh is handled by `@mcp-abap-adt/auth-broker` package
|
|
302
|
+
- 💾 Session state persistence is handled by `@mcp-abap-adt/auth-broker` package
|
|
303
|
+
- 🔑 Use [JWT auth CLI tool](./JWT_AUTH_TOOLS.md)
|
|
304
|
+
- 📖 Review [CHANGELOG.md](../CHANGELOG.md) for version history
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# JWT Auth Tools
|
|
2
|
+
|
|
3
|
+
This package ships with a helper CLI (`sap-abap-auth`) to obtain JWT and refresh tokens for SAP BTP ABAP systems.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
|
|
8
|
+
- Node.js >= 18
|
|
9
|
+
- Service key JSON for your SAP BTP ABAP instance (from SAP BTP Cockpit)
|
|
10
|
+
- Browser access (for OAuth flow)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx sap-abap-auth auth -k path/to/service-key.json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This launches the OAuth browser flow and prints a `.env` file containing `SAP_JWT_TOKEN`, `SAP_REFRESH_TOKEN`, `SAP_UAA_URL`, etc.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Installation Options
|
|
23
|
+
|
|
24
|
+
### Local (Project) Install
|
|
25
|
+
|
|
26
|
+
If `@mcp-abap-adt/connection` is part of your `dependencies` or `devDependencies`, you already have the CLI available:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @mcp-abap-adt/connection --save-dev
|
|
30
|
+
npx sap-abap-auth auth -k service-key.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Pros:
|
|
34
|
+
- CLI travels with your project.
|
|
35
|
+
- No need for global npm installs.
|
|
36
|
+
|
|
37
|
+
### Global Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install -g @mcp-abap-adt/connection
|
|
41
|
+
sap-abap-auth auth -k service-key.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Pros:
|
|
45
|
+
- Available system-wide.
|
|
46
|
+
- Useful if you run the tool frequently from the terminal.
|
|
47
|
+
|
|
48
|
+
### On-Demand (One-off) Usage
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx @mcp-abap-adt/connection sap-abap-auth auth -k service-key.json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Pros:
|
|
55
|
+
- No install needed.
|
|
56
|
+
- Perfect for quick usage on CI or temporary machines.
|
|
57
|
+
|
|
58
|
+
## CLI Usage
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Show help
|
|
62
|
+
sap-abap-auth --help
|
|
63
|
+
|
|
64
|
+
# Authenticate using service key JSON
|
|
65
|
+
sap-abap-auth auth -k service-key.json
|
|
66
|
+
|
|
67
|
+
# Use specific browser (chrome, firefox, edge, system, none)
|
|
68
|
+
sap-abap-auth auth -k service-key.json --browser chrome
|
|
69
|
+
|
|
70
|
+
# Output to custom file (default: .env)
|
|
71
|
+
sap-abap-auth auth -k service-key.json --output .env.production
|
|
72
|
+
|
|
73
|
+
# Print tokens to stdout (no file)
|
|
74
|
+
sap-abap-auth auth -k service-key.json --browser none --output -
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Full Command Reference
|
|
78
|
+
|
|
79
|
+
| Option | Description |
|
|
80
|
+
|-------------------------|------------------------------------------------------|
|
|
81
|
+
| `-k, --key <path>` | Path to service key JSON (required) |
|
|
82
|
+
| `-b, --browser <name>` | Browser to open (chrome, edge, firefox, system, none)|
|
|
83
|
+
| `-o, --output <path>` | Output `.env` path (`-` for stdout, defaults to `.env`) |
|
|
84
|
+
| `--config <path>` | Use config file with saved credentials |
|
|
85
|
+
| `--no-open` | Same as `--browser none` |
|
|
86
|
+
| `--help` | Show help |
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
## Using Generated Tokens
|
|
90
|
+
|
|
91
|
+
After running the CLI, you get `.env` similar to:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
# Token Expiry Information (auto-generated)
|
|
95
|
+
# JWT Token expires: Monday, December 25, 2025 at 10:30:45 AM UTC
|
|
96
|
+
# JWT Token expires at: 2025-12-25T10:30:45.000Z
|
|
97
|
+
# Refresh Token expires: Tuesday, January 25, 2026 at 10:30:45 AM UTC
|
|
98
|
+
# Refresh Token expires at: 2026-01-25T10:30:45.000Z
|
|
99
|
+
|
|
100
|
+
SAP_URL=https://<your-abap-instance>.abap.whatever.sap
|
|
101
|
+
SAP_AUTH_TYPE=jwt
|
|
102
|
+
SAP_JWT_TOKEN=eyJhbGciOi...
|
|
103
|
+
SAP_REFRESH_TOKEN=eyJraWQiOi...
|
|
104
|
+
SAP_UAA_URL=https://<your>-authentication.<region>.hana.ondemand.com/oauth/token
|
|
105
|
+
SAP_UAA_CLIENT_ID=sb-<id>
|
|
106
|
+
SAP_UAA_CLIENT_SECRET=<secret>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Note:** The token expiry information at the top of the `.env` file is automatically generated by decoding the JWT tokens. This helps you:
|
|
110
|
+
- Know when tokens will expire
|
|
111
|
+
- Plan token refresh in advance
|
|
112
|
+
- Troubleshoot authentication issues related to expired tokens
|
|
113
|
+
|
|
114
|
+
If a token's expiry cannot be determined (e.g., non-standard JWT format), a comment will indicate this.
|
|
115
|
+
|
|
116
|
+
Load it in your project:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
source .env
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Or configure `SapConfig` directly:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { createAbapConnection } from "@mcp-abap-adt/connection";
|
|
127
|
+
|
|
128
|
+
const connection = createAbapConnection({
|
|
129
|
+
url: process.env.SAP_URL!,
|
|
130
|
+
authType: "jwt",
|
|
131
|
+
jwtToken: process.env.SAP_JWT_TOKEN!,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Note: Token refresh is handled by @mcp-abap-adt/auth-broker package
|
|
135
|
+
// The refresh token credentials in .env are used by auth-broker, not connection
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
## Automating in CI
|
|
140
|
+
|
|
141
|
+
You can run the CLI once locally, store `.env` in secure storage, then load those variables in CI/CD to feed `@mcp-abap-adt/connection`. بهدف
|
|
142
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Migrating to the explicit session lifecycle
|
|
2
|
+
|
|
3
|
+
The connection now owns its session, and says so. If your code never called
|
|
4
|
+
`connect()`, it will fail at startup rather than at the first request — the
|
|
5
|
+
better failure, but a new one.
|
|
6
|
+
|
|
7
|
+
## What breaks, and what to do
|
|
8
|
+
|
|
9
|
+
### 1. `connect()` is required
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
const connection = createAbapConnection(config, logger);
|
|
13
|
+
await connection.connect(); // ← add this
|
|
14
|
+
await connection.makeAdtRequest(...);
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Without it every request is refused with `ADT_NOT_CONNECTED` and nothing
|
|
18
|
+
reaches the server.
|
|
19
|
+
|
|
20
|
+
**Why it changed.** Requests used to establish the session on the fly, which
|
|
21
|
+
meant a caller could never tell whether it had a session, whose it was, or
|
|
22
|
+
whether the one it locked in was still there. That is what let the connector
|
|
23
|
+
replace the session under a caller holding a lock without saying anything.
|
|
24
|
+
|
|
25
|
+
### 2. `connect()` rejects on failure
|
|
26
|
+
|
|
27
|
+
It used to log a warning and resolve anyway, deferring the work to the first
|
|
28
|
+
request. Now a resolved promise means a usable session exists.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
try {
|
|
32
|
+
await connection.connect();
|
|
33
|
+
} catch (error) {
|
|
34
|
+
// Handle it here, at startup, where it is cheap.
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you never checked the result of `connect()`, you were relying on that
|
|
39
|
+
deferral. The failure has not appeared — it has moved to where you can see it.
|
|
40
|
+
|
|
41
|
+
**Kerberos**: `connect()` now surfaces a limitation that used to be hidden. If
|
|
42
|
+
the server continues the SPNEGO exchange (a 401 carrying a `Negotiate` token),
|
|
43
|
+
this client cannot continue it — the GSS context is not retained — and
|
|
44
|
+
`connect()` fails saying so. Previously the same situation resolved and failed
|
|
45
|
+
later, on the first request, as an unrelated-looking 401.
|
|
46
|
+
|
|
47
|
+
### 3. Requests are refused after a teardown
|
|
48
|
+
|
|
49
|
+
`disconnect()` and `reset()` stop the connection from serving requests until
|
|
50
|
+
the next `connect()`. An in-flight request is not cut off: a teardown drains
|
|
51
|
+
before it clears anything.
|
|
52
|
+
|
|
53
|
+
### 4. If you hold locks, tell the connection
|
|
54
|
+
|
|
55
|
+
Available on the HTTP connection classes; see the availability note in
|
|
56
|
+
[USAGE.md — Session Lifecycle](./USAGE.md#session-lifecycle).
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const token = connection.beginWindow('Class/ZCL_MY_CLASS');
|
|
60
|
+
|
|
61
|
+
let lockHandle: string | undefined;
|
|
62
|
+
try {
|
|
63
|
+
lockHandle = await lock(connection, 'ZCL_MY_CLASS');
|
|
64
|
+
} catch (error) {
|
|
65
|
+
connection.endWindow(token); // confirmed NOT locked: nothing is held
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await update(connection, 'ZCL_MY_CLASS', lockHandle);
|
|
71
|
+
await unlock(connection, 'ZCL_MY_CLASS', lockHandle);
|
|
72
|
+
connection.endWindow(token); // confirmed unlocked: the lock is released
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// Left open on purpose: the unlock may have failed, never gone out, or come
|
|
75
|
+
// back with an unknown outcome. Do NOT use a finally here.
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
You are not required to use windows at all. Without them a teardown cannot know
|
|
81
|
+
a lock is open, so it will not wait for your unlock and will not report the lock
|
|
82
|
+
if it gives up — it simply tears down, and the object stays locked on the server.
|
|
83
|
+
|
|
84
|
+
But do not open a window and forget to close it on success: every later teardown
|
|
85
|
+
then waits out `SAP_TIMEOUT_CRITICAL` before reporting it as abandoned.
|
|
86
|
+
|
|
87
|
+
### 5. A new error you should handle
|
|
88
|
+
|
|
89
|
+
`ADT_SESSION_REPLACED` means the SAP session is gone. It is raised when a
|
|
90
|
+
replacement happens **while you hold a lock window**, and whenever the server
|
|
91
|
+
itself says the session no longer exists — that second case regardless of any
|
|
92
|
+
window. **Your lock handle is dead**: unlocking with it will not work, and the
|
|
93
|
+
object may still be locked on the server. The connector does not retry such
|
|
94
|
+
a request — retrying blindly is what produced further orphaned locks in the
|
|
95
|
+
field.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// (connection already established)
|
|
99
|
+
try {
|
|
100
|
+
await connection.makeAdtRequest(...);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error.code === 'ADT_SESSION_REPLACED') {
|
|
103
|
+
// Reconnect, then deal with the lock you can no longer release.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## What did NOT change
|
|
109
|
+
|
|
110
|
+
- `makeAdtRequest()` keeps its signature and its behaviour on a healthy session.
|
|
111
|
+
- `IAbapConnection` is unchanged: `connect()` was already on it. The rest of the
|
|
112
|
+
lifecycle API lives on the HTTP connection classes for now, so code holding
|
|
113
|
+
the interface type sees no new members and needs no change.
|
|
114
|
+
- Automatic recovery still happens: a CSRF token refresh, a 401 retry, a JWT
|
|
115
|
+
refresh. What changed is that a recovery which **replaces the session** while
|
|
116
|
+
you hold a lock now fails loudly instead of continuing on the new one.
|
|
117
|
+
- RFC connections already required an open client, so nothing there changes for
|
|
118
|
+
callers.
|
|
119
|
+
|
|
120
|
+
## What to check on your side
|
|
121
|
+
|
|
122
|
+
- every place a connection is created — does `connect()` follow it?
|
|
123
|
+
- every place `connect()` is called — is its rejection handled?
|
|
124
|
+
- error handling around lock/unlock flows — is `ADT_SESSION_REPLACED` handled,
|
|
125
|
+
or does it fall into a generic catch that retries?
|