@mcp-abap-adt/connection 0.1.7 → 0.1.9
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
CHANGED
|
@@ -320,9 +320,15 @@ interface AbapConnection {
|
|
|
320
320
|
enableStatefulSession(sessionId: string, storage: ISessionStorage): Promise<void>;
|
|
321
321
|
disableStatefulSession(): void;
|
|
322
322
|
getSessionMode(): "stateless" | "stateful";
|
|
323
|
+
getSessionId(): string | undefined; // Get current session ID
|
|
324
|
+
setSessionType(type: "stateless" | "stateful"): void; // Switch session type
|
|
323
325
|
}
|
|
324
326
|
```
|
|
325
327
|
|
|
328
|
+
**New in 0.1.6+:**
|
|
329
|
+
- `getSessionId()`: Returns the current session ID if stateful session is enabled, otherwise `undefined`
|
|
330
|
+
- `setSessionType(type)`: Programmatically switch between stateful and stateless modes without recreating connection
|
|
331
|
+
|
|
326
332
|
#### `ILogger`
|
|
327
333
|
|
|
328
334
|
Logger interface for custom logging implementations.
|
|
@@ -370,10 +376,21 @@ function createAbapConnection(
|
|
|
370
376
|
- Node.js >= 18.0.0
|
|
371
377
|
- Access to SAP ABAP system (on-premise or BTP)
|
|
372
378
|
|
|
379
|
+
## Changelog
|
|
380
|
+
|
|
381
|
+
See [CHANGELOG.md](./CHANGELOG.md) for detailed version history and breaking changes.
|
|
382
|
+
|
|
383
|
+
**Latest version: 0.1.9**
|
|
384
|
+
- Comprehensive documentation updates
|
|
385
|
+
- Enhanced README with new API methods documentation
|
|
386
|
+
- Complete version history in CHANGELOG
|
|
387
|
+
- Fixed documentation structure and links
|
|
388
|
+
|
|
373
389
|
## Documentation
|
|
374
390
|
|
|
375
|
-
- [Custom Session Storage](./CUSTOM_SESSION_STORAGE.md) - How to implement custom session persistence (database, Redis, etc.)
|
|
391
|
+
- [Custom Session Storage](./docs/CUSTOM_SESSION_STORAGE.md) - How to implement custom session persistence (database, Redis, etc.)
|
|
376
392
|
- [Examples](./examples/README.md) - Working code examples
|
|
393
|
+
- [Changelog](./CHANGELOG.md) - Version history and release notes
|
|
377
394
|
|
|
378
395
|
## License
|
|
379
396
|
|
|
@@ -9,7 +9,7 @@ declare abstract class AbstractAbapConnection implements AbapConnection {
|
|
|
9
9
|
private csrfToken;
|
|
10
10
|
private cookies;
|
|
11
11
|
private cookieStore;
|
|
12
|
-
private
|
|
12
|
+
private baseUrl;
|
|
13
13
|
private sessionId;
|
|
14
14
|
private sessionStorage;
|
|
15
15
|
private sessionMode;
|
|
@@ -117,7 +117,6 @@ declare abstract class AbstractAbapConnection implements AbapConnection {
|
|
|
117
117
|
protected getCookies(): string | null;
|
|
118
118
|
private updateCookiesFromResponse;
|
|
119
119
|
private getAxiosInstance;
|
|
120
|
-
private normalizeRequestUrl;
|
|
121
120
|
private ensureFreshCsrfToken;
|
|
122
121
|
private shouldRetryCsrf;
|
|
123
122
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"AAAA,OAAc,EAAiD,aAAa,EAAE,MAAM,OAAO,CAAC;AAG5F,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,uBAAe,sBAAuB,YAAW,cAAc;IAW3D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO;IAXpC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,7 +45,7 @@ class AbstractAbapConnection {
|
|
|
45
45
|
csrfToken = null;
|
|
46
46
|
cookies = null;
|
|
47
47
|
cookieStore = new Map();
|
|
48
|
-
|
|
48
|
+
baseUrl;
|
|
49
49
|
sessionId = null;
|
|
50
50
|
sessionStorage = null;
|
|
51
51
|
sessionMode = "stateless";
|
|
@@ -57,6 +57,14 @@ class AbstractAbapConnection {
|
|
|
57
57
|
this.sessionId = sessionId || (0, crypto_1.randomUUID)();
|
|
58
58
|
// Session mode depends only on storage availability (sessionId exists for both modes)
|
|
59
59
|
this.sessionMode = sessionStorage ? "stateful" : "stateless";
|
|
60
|
+
// Initialize baseUrl from config (required, will throw if invalid)
|
|
61
|
+
try {
|
|
62
|
+
const urlObj = new URL(config.url);
|
|
63
|
+
this.baseUrl = urlObj.origin;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new Error(`Invalid URL in configuration: ${error instanceof Error ? error.message : error}`);
|
|
67
|
+
}
|
|
60
68
|
this.logger.debug(`AbstractAbapConnection - Session ID: ${this.sessionId.substring(0, 8)}..., mode: ${this.sessionMode}`);
|
|
61
69
|
}
|
|
62
70
|
/**
|
|
@@ -262,22 +270,10 @@ class AbstractAbapConnection {
|
|
|
262
270
|
this.csrfToken = null;
|
|
263
271
|
this.cookies = null;
|
|
264
272
|
this.cookieStore.clear();
|
|
265
|
-
|
|
273
|
+
// Note: baseUrl is not reset as it's derived from immutable config
|
|
266
274
|
}
|
|
267
275
|
async getBaseUrl() {
|
|
268
|
-
|
|
269
|
-
return this.cachedBaseUrl;
|
|
270
|
-
}
|
|
271
|
-
const { url } = this.config;
|
|
272
|
-
try {
|
|
273
|
-
const urlObj = new URL(url);
|
|
274
|
-
this.cachedBaseUrl = urlObj.origin;
|
|
275
|
-
return this.cachedBaseUrl;
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
const errorMessage = `Invalid URL in configuration: ${error instanceof Error ? error.message : error}`;
|
|
279
|
-
throw new Error(errorMessage);
|
|
280
|
-
}
|
|
276
|
+
return this.baseUrl;
|
|
281
277
|
}
|
|
282
278
|
async getAuthHeaders() {
|
|
283
279
|
const headers = {};
|
|
@@ -291,9 +287,10 @@ class AbstractAbapConnection {
|
|
|
291
287
|
return headers;
|
|
292
288
|
}
|
|
293
289
|
async makeAdtRequest(options) {
|
|
294
|
-
const { url, method, timeout, data, params, headers: customHeaders } = options;
|
|
290
|
+
const { url: endpoint, method, timeout, data, params, headers: customHeaders } = options;
|
|
295
291
|
const normalizedMethod = method.toUpperCase();
|
|
296
|
-
|
|
292
|
+
// Build full URL: baseUrl + endpoint
|
|
293
|
+
const requestUrl = `${this.baseUrl}${endpoint}`;
|
|
297
294
|
// Try to ensure CSRF token is available for POST/PUT/DELETE, but don't fail if it can't be fetched
|
|
298
295
|
// The retry logic will handle CSRF token errors automatically
|
|
299
296
|
if (normalizedMethod === "POST" || normalizedMethod === "PUT" || normalizedMethod === "DELETE") {
|
|
@@ -688,12 +685,6 @@ class AbstractAbapConnection {
|
|
|
688
685
|
}
|
|
689
686
|
return this.axiosInstance;
|
|
690
687
|
}
|
|
691
|
-
normalizeRequestUrl(url) {
|
|
692
|
-
if (!url.includes("/sap/bc/adt/") && !url.endsWith("/sap/bc/adt")) {
|
|
693
|
-
return url.endsWith("/") ? `${url}sap/bc/adt` : `${url}/sap/bc/adt`;
|
|
694
|
-
}
|
|
695
|
-
return url;
|
|
696
|
-
}
|
|
697
688
|
async ensureFreshCsrfToken(requestUrl) {
|
|
698
689
|
// If we already have a CSRF token, reuse it to keep the same SAP session
|
|
699
690
|
// SAP ties the lock handle to the HTTP session (SAP_SESSIONID cookie)
|