@mcp-abap-adt/connection 0.1.6 → 0.1.8

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.
@@ -13,6 +13,8 @@ export interface AbapConnection {
13
13
  getConfig(): SapConfig;
14
14
  getBaseUrl(): Promise<string>;
15
15
  getAuthHeaders(): Promise<Record<string, string>>;
16
+ getSessionId(): string | null;
17
+ setSessionType(type: "stateful" | "stateless"): void;
16
18
  makeAdtRequest(options: AbapRequestOptions): Promise<AxiosResponse>;
17
19
  connect(): Promise<void>;
18
20
  reset(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"AbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbapConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,IAAI,SAAS,CAAC;IACvB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,eAAe,IAAI,YAAY,GAAG,IAAI,CAAC;IACvC,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5C"}
1
+ {"version":3,"file":"AbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbapConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,IAAI,SAAS,CAAC;IACvB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,YAAY,IAAI,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC;IACrD,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,eAAe,IAAI,YAAY,GAAG,IAAI,CAAC;IACvC,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5C"}
@@ -9,20 +9,29 @@ declare abstract class AbstractAbapConnection implements AbapConnection {
9
9
  private csrfToken;
10
10
  private cookies;
11
11
  private cookieStore;
12
- private cachedBaseUrl;
12
+ private baseUrl;
13
13
  private sessionId;
14
14
  private sessionStorage;
15
15
  private sessionMode;
16
16
  protected constructor(config: SapConfig, logger: ILogger, sessionStorage?: ISessionStorage, sessionId?: string);
17
+ /**
18
+ * Set session type (stateful or stateless)
19
+ * Controls whether x-sap-adt-sessiontype: stateful header is added to requests
20
+ * - stateful: SAP maintains session state between requests (locks, transactions)
21
+ * - stateless: Each request is independent
22
+ */
23
+ setSessionType(type: "stateful" | "stateless"): void;
17
24
  /**
18
25
  * Enable stateful session mode (tells SAP to maintain stateful session)
19
26
  * This controls whether x-sap-adt-sessiontype: stateful header is used
20
27
  * Storage is controlled separately via setSessionStorage()
28
+ * @deprecated Use setSessionType("stateful") instead
21
29
  */
22
30
  enableStatefulSession(): void;
23
31
  /**
24
32
  * Disable stateful session mode (switch to stateless)
25
33
  * Optionally saves current state before switching
34
+ * @deprecated Use setSessionType("stateless") instead
26
35
  */
27
36
  disableStatefulSession(saveBeforeDisable?: boolean): Promise<void>;
28
37
  /**
@@ -108,7 +117,6 @@ declare abstract class AbstractAbapConnection implements AbapConnection {
108
117
  protected getCookies(): string | null;
109
118
  private updateCookiesFromResponse;
110
119
  private getAxiosInstance;
111
- private normalizeRequestUrl;
112
120
  private ensureFreshCsrfToken;
113
121
  private shouldRetryCsrf;
114
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,aAAa,CAAuB;IAC5C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,cAAc,CAAgC;IACtD,OAAO,CAAC,WAAW,CAAyC;IAE5D,SAAS,aACU,MAAM,EAAE,SAAS,EACf,MAAM,EAAE,OAAO,EAClC,cAAc,CAAC,EAAE,eAAe,EAChC,SAAS,CAAC,EAAE,MAAM;IAWpB;;;;OAIG;IACH,qBAAqB,IAAI,IAAI;IAQ7B;;;OAGG;IACG,sBAAsB,CAAC,iBAAiB,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/E;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,UAAU;IAI1C;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IASrC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAcvE;;OAEG;IACH,iBAAiB,IAAI,eAAe,GAAG,IAAI;IAI3C;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBvC;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBvC;;;;OAIG;IACH,eAAe,IAAI,YAAY,GAAG,IAAI;IAYtC;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAY1C;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBxC,SAAS,IAAI,SAAS;IAItB,KAAK,IAAI,IAAI;IAYP,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB7B,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAevD;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3B,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAwMzE,SAAS,CAAC,QAAQ,CAAC,wBAAwB,IAAI,MAAM;IAErD;;;OAGG;cACa,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAI,EAAE,UAAU,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAgL/F;;OAEG;IACH,SAAS,CAAC,YAAY,IAAI,MAAM,GAAG,IAAI;IAIvC;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIlD;;OAEG;IACH,SAAS,CAAC,UAAU,IAAI,MAAM,GAAG,IAAI;IAIrC,OAAO,CAAC,yBAAyB;IAuDjC,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,mBAAmB;YAOb,oBAAoB;IAwBlC,OAAO,CAAC,eAAe;CAyBxB;AAGD,OAAO,EAAE,sBAAsB,EAAE,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
- cachedBaseUrl = null;
48
+ baseUrl;
49
49
  sessionId = null;
50
50
  sessionStorage = null;
51
51
  sessionMode = "stateless";
@@ -57,23 +57,42 @@ 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
  }
70
+ /**
71
+ * Set session type (stateful or stateless)
72
+ * Controls whether x-sap-adt-sessiontype: stateful header is added to requests
73
+ * - stateful: SAP maintains session state between requests (locks, transactions)
74
+ * - stateless: Each request is independent
75
+ */
76
+ setSessionType(type) {
77
+ this.sessionMode = type;
78
+ this.logger.debug(`Session type set to: ${type}`, {
79
+ sessionId: this.sessionId?.substring(0, 8),
80
+ hasStorage: !!this.sessionStorage
81
+ });
82
+ }
62
83
  /**
63
84
  * Enable stateful session mode (tells SAP to maintain stateful session)
64
85
  * This controls whether x-sap-adt-sessiontype: stateful header is used
65
86
  * Storage is controlled separately via setSessionStorage()
87
+ * @deprecated Use setSessionType("stateful") instead
66
88
  */
67
89
  enableStatefulSession() {
68
- this.sessionMode = "stateful";
69
- this.logger.debug("Stateful session mode enabled", {
70
- sessionId: this.sessionId?.substring(0, 8),
71
- hasStorage: !!this.sessionStorage
72
- });
90
+ this.setSessionType("stateful");
73
91
  }
74
92
  /**
75
93
  * Disable stateful session mode (switch to stateless)
76
94
  * Optionally saves current state before switching
95
+ * @deprecated Use setSessionType("stateless") instead
77
96
  */
78
97
  async disableStatefulSession(saveBeforeDisable = false) {
79
98
  if (this.sessionMode === "stateless") {
@@ -251,22 +270,10 @@ class AbstractAbapConnection {
251
270
  this.csrfToken = null;
252
271
  this.cookies = null;
253
272
  this.cookieStore.clear();
254
- this.cachedBaseUrl = null;
273
+ // Note: baseUrl is not reset as it's derived from immutable config
255
274
  }
256
275
  async getBaseUrl() {
257
- if (this.cachedBaseUrl) {
258
- return this.cachedBaseUrl;
259
- }
260
- const { url } = this.config;
261
- try {
262
- const urlObj = new URL(url);
263
- this.cachedBaseUrl = urlObj.origin;
264
- return this.cachedBaseUrl;
265
- }
266
- catch (error) {
267
- const errorMessage = `Invalid URL in configuration: ${error instanceof Error ? error.message : error}`;
268
- throw new Error(errorMessage);
269
- }
276
+ return this.baseUrl;
270
277
  }
271
278
  async getAuthHeaders() {
272
279
  const headers = {};
@@ -280,9 +287,10 @@ class AbstractAbapConnection {
280
287
  return headers;
281
288
  }
282
289
  async makeAdtRequest(options) {
283
- const { url, method, timeout, data, params, headers: customHeaders } = options;
290
+ const { url: endpoint, method, timeout, data, params, headers: customHeaders } = options;
284
291
  const normalizedMethod = method.toUpperCase();
285
- const requestUrl = this.normalizeRequestUrl(url);
292
+ // Build full URL: baseUrl + endpoint
293
+ const requestUrl = `${this.baseUrl}${endpoint}`;
286
294
  // Try to ensure CSRF token is available for POST/PUT/DELETE, but don't fail if it can't be fetched
287
295
  // The retry logic will handle CSRF token errors automatically
288
296
  if (normalizedMethod === "POST" || normalizedMethod === "PUT" || normalizedMethod === "DELETE") {
@@ -306,6 +314,16 @@ class AbstractAbapConnection {
306
314
  if (customHeaders) {
307
315
  Object.assign(requestHeaders, customHeaders);
308
316
  }
317
+ // ALWAYS add sap-adt-connection-id header (connectionId is sent for ALL session types)
318
+ if (this.sessionId) {
319
+ requestHeaders["sap-adt-connection-id"] = this.sessionId;
320
+ }
321
+ // Add stateful session headers if stateful mode enabled via enableStatefulSession()
322
+ if (this.sessionMode === "stateful") {
323
+ requestHeaders["x-sap-adt-sessiontype"] = "stateful";
324
+ requestHeaders["sap-adt-request-id"] = (0, crypto_1.randomUUID)().replace(/-/g, '');
325
+ requestHeaders["X-sap-adt-profiling"] = "server-time";
326
+ }
309
327
  // Add auth headers (these MUST NOT be overridden)
310
328
  Object.assign(requestHeaders, await this.getAuthHeaders());
311
329
  if ((normalizedMethod === "POST" || normalizedMethod === "PUT" || normalizedMethod === "DELETE") && this.csrfToken) {
@@ -667,12 +685,6 @@ class AbstractAbapConnection {
667
685
  }
668
686
  return this.axiosInstance;
669
687
  }
670
- normalizeRequestUrl(url) {
671
- if (!url.includes("/sap/bc/adt/") && !url.endsWith("/sap/bc/adt")) {
672
- return url.endsWith("/") ? `${url}sap/bc/adt` : `${url}/sap/bc/adt`;
673
- }
674
- return url;
675
- }
676
688
  async ensureFreshCsrfToken(requestUrl) {
677
689
  // If we already have a CSRF token, reuse it to keep the same SAP session
678
690
  // SAP ties the lock handle to the HTTP session (SAP_SESSIONID cookie)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/connection",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "ABAP connection layer for MCP ABAP ADT server",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",