@mcp-abap-adt/connection 0.1.12 → 0.1.14

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
@@ -46,6 +46,58 @@ The package uses a clean separation of concerns:
46
46
  - Permission vs auth error detection
47
47
  - Suitable for SAP BTP ABAP Environment
48
48
 
49
+ ## Responsibilities and Design Principles
50
+
51
+ ### Core Development Principle
52
+
53
+ **Interface-Only Communication**: This package follows a fundamental development principle: **all interactions with external dependencies happen ONLY through interfaces**. The code knows **NOTHING beyond what is defined in the interfaces**.
54
+
55
+ This means:
56
+ - Does not know about concrete implementation classes from other packages
57
+ - Does not know about internal data structures or methods not defined in interfaces
58
+ - Does not make assumptions about implementation behavior beyond interface contracts
59
+ - Does not access properties or methods not explicitly defined in interfaces
60
+
61
+ This principle ensures:
62
+ - **Loose coupling**: Connection classes are decoupled from concrete implementations in other packages
63
+ - **Flexibility**: New implementations can be added without modifying connection classes
64
+ - **Testability**: Easy to mock dependencies for testing
65
+ - **Maintainability**: Changes to implementations don't affect connection classes
66
+
67
+ ### Package Responsibilities
68
+
69
+ This package is responsible for:
70
+
71
+ 1. **HTTP communication with SAP systems**: Makes HTTP requests to SAP ABAP systems via ADT protocol
72
+ 2. **Authentication handling**: Supports Basic Auth and JWT/OAuth2 authentication methods
73
+ 3. **Session management**: Manages cookies, CSRF tokens, and session state
74
+ 4. **Token refresh**: Automatically refreshes expired JWT tokens (for `JwtAbapConnection`)
75
+ 5. **Error handling**: Distinguishes between authentication errors and permission errors
76
+
77
+ #### What This Package Does
78
+
79
+ - **Provides connection abstraction**: `AbapConnection` interface for interacting with SAP systems
80
+ - **Handles HTTP requests**: Makes requests to SAP ADT endpoints with proper headers and authentication
81
+ - **Manages sessions**: Handles cookies, CSRF tokens, and session state persistence
82
+ - **Refreshes tokens**: Automatically refreshes expired JWT tokens when detected
83
+ - **Validates tokens**: Detects expired tokens by analyzing HTTP response codes (401/403)
84
+
85
+ #### What This Package Does NOT Do
86
+
87
+ - **Does NOT obtain tokens**: Token acquisition is handled by `@mcp-abap-adt/auth-providers` and `@mcp-abap-adt/auth-broker`
88
+ - **Does NOT store tokens**: Token storage is handled by `@mcp-abap-adt/auth-stores`
89
+ - **Does NOT orchestrate authentication**: Token lifecycle management is handled by `@mcp-abap-adt/auth-broker`
90
+ - **Does NOT know about destinations**: Destination-based authentication is handled by consumers
91
+ - **Does NOT handle OAuth2 flows**: OAuth2 flows are handled by token providers
92
+
93
+ ### External Dependencies
94
+
95
+ This package interacts with external packages **ONLY through interfaces**:
96
+
97
+ - **Logger interface**: Uses `ILogger` interface for logging - does not know about concrete logger implementation
98
+ - **Session storage interface**: Uses `ISessionStorage` interface for session persistence - does not know about concrete storage implementation
99
+ - **No direct dependencies on auth packages**: All token-related operations are handled through configuration (`SapConfig`) passed by consumers
100
+
49
101
  ## Documentation
50
102
 
51
103
  - 📦 **[Installation Guide](./docs/INSTALLATION.md)** - Setup and installation instructions
@@ -371,6 +423,66 @@ function createAbapConnection(
371
423
  ): AbapConnection;
372
424
  ```
373
425
 
426
+ #### `CSRF_CONFIG` and `CSRF_ERROR_MESSAGES`
427
+
428
+ **New in 0.1.13+:** Exported constants for consistent CSRF token handling across different connection implementations.
429
+
430
+ ```typescript
431
+ import { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from '@mcp-abap-adt/connection';
432
+
433
+ // CSRF_CONFIG contains:
434
+ // - RETRY_COUNT: number (default: 3)
435
+ // - RETRY_DELAY: number (default: 1000ms)
436
+ // - ENDPOINT: string (default: '/sap/bc/adt/core/discovery')
437
+ // - REQUIRED_HEADERS: { 'x-csrf-token': 'fetch', 'Accept': 'application/atomsvc+xml' }
438
+
439
+ // CSRF_ERROR_MESSAGES contains:
440
+ // - FETCH_FAILED(attempts: number, cause: string): string
441
+ // - NOT_IN_HEADERS: string
442
+ // - REQUIRED_FOR_MUTATION: string
443
+ ```
444
+
445
+ **Use case:** When implementing custom connection classes (e.g., Cloud SDK-based), you can use these constants to ensure consistent CSRF token handling:
446
+
447
+ ```typescript
448
+ import { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from '@mcp-abap-adt/connection';
449
+
450
+ async function fetchCsrfToken(baseUrl: string): Promise<string> {
451
+ const csrfUrl = `${baseUrl}${CSRF_CONFIG.ENDPOINT}`;
452
+
453
+ for (let attempt = 0; attempt <= CSRF_CONFIG.RETRY_COUNT; attempt++) {
454
+ try {
455
+ const response = await yourHttpClient.get(csrfUrl, {
456
+ headers: CSRF_CONFIG.REQUIRED_HEADERS
457
+ });
458
+
459
+ const token = response.headers['x-csrf-token'];
460
+ if (!token) {
461
+ if (attempt < CSRF_CONFIG.RETRY_COUNT) {
462
+ await new Promise(resolve => setTimeout(resolve, CSRF_CONFIG.RETRY_DELAY));
463
+ continue;
464
+ }
465
+ throw new Error(CSRF_ERROR_MESSAGES.NOT_IN_HEADERS);
466
+ }
467
+
468
+ return token;
469
+ } catch (error) {
470
+ if (attempt >= CSRF_CONFIG.RETRY_COUNT) {
471
+ throw new Error(
472
+ CSRF_ERROR_MESSAGES.FETCH_FAILED(
473
+ CSRF_CONFIG.RETRY_COUNT + 1,
474
+ error instanceof Error ? error.message : String(error)
475
+ )
476
+ );
477
+ }
478
+ await new Promise(resolve => setTimeout(resolve, CSRF_CONFIG.RETRY_DELAY));
479
+ }
480
+ }
481
+ }
482
+ ```
483
+
484
+ See [PR Proposal](./PR_PROPOSAL_CSRF_CONFIG.md) for more details.
485
+
374
486
  ## Requirements
375
487
 
376
488
  - Node.js >= 18.0.0
@@ -380,11 +492,10 @@ function createAbapConnection(
380
492
 
381
493
  See [CHANGELOG.md](./CHANGELOG.md) for detailed version history and breaking changes.
382
494
 
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
495
+ **Latest version: 0.1.13**
496
+ - Added `CSRF_CONFIG` and `CSRF_ERROR_MESSAGES` exports for consistent CSRF token handling
497
+ - Updated CSRF token endpoint to `/sap/bc/adt/core/discovery` (lighter response, available on all systems)
498
+ - See [CHANGELOG.md](./CHANGELOG.md) for full details
388
499
 
389
500
  ## Documentation
390
501
 
@@ -1,15 +1,5 @@
1
- export type SapAuthType = "basic" | "jwt";
2
- export interface SapConfig {
3
- url: string;
4
- client?: string;
5
- authType: SapAuthType;
6
- username?: string;
7
- password?: string;
8
- jwtToken?: string;
9
- refreshToken?: string;
10
- uaaUrl?: string;
11
- uaaClientId?: string;
12
- uaaClientSecret?: string;
13
- }
14
- export declare function sapConfigSignature(config: SapConfig): string;
1
+ import type { ISapConfig, SapAuthType } from '@mcp-abap-adt/interfaces';
2
+ export type { SapAuthType };
3
+ export type SapConfig = ISapConfig;
4
+ export declare function sapConfigSignature(config: ISapConfig): string;
15
5
  //# sourceMappingURL=sapConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sapConfig.d.ts","sourceRoot":"","sources":["../../src/config/sapConfig.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1C,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAmB5D"}
1
+ {"version":3,"file":"sapConfig.d.ts","sourceRoot":"","sources":["../../src/config/sapConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGxE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC5B,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AAEnC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAmB7D"}
@@ -1,24 +1,4 @@
1
- import { AxiosResponse } from "axios";
2
- import { SapConfig } from "../config/sapConfig.js";
3
- import { SessionState } from "../logger.js";
4
- export interface AbapRequestOptions {
5
- url: string;
6
- method: string;
7
- timeout: number;
8
- data?: any;
9
- params?: any;
10
- headers?: Record<string, string>;
11
- }
12
- export interface AbapConnection {
13
- getConfig(): SapConfig;
14
- getBaseUrl(): Promise<string>;
15
- getAuthHeaders(): Promise<Record<string, string>>;
16
- getSessionId(): string | null;
17
- setSessionType(type: "stateful" | "stateless"): void;
18
- makeAdtRequest(options: AbapRequestOptions): Promise<AxiosResponse>;
19
- connect(): Promise<void>;
20
- reset(): void;
21
- getSessionState(): SessionState | null;
22
- setSessionState(state: SessionState): void;
23
- }
1
+ import type { IAbapRequestOptions, IAbapConnection } from '@mcp-abap-adt/interfaces';
2
+ export type AbapRequestOptions = IAbapRequestOptions;
3
+ export type AbapConnection = IAbapConnection;
24
4
  //# sourceMappingURL=AbapConnection.d.ts.map
@@ -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,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"}
1
+ {"version":3,"file":"AbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbapConnection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGrF,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,7 @@ const axios_1 = __importStar(require("axios"));
38
38
  const https_1 = require("https");
39
39
  const crypto_1 = require("crypto");
40
40
  const timeouts_js_1 = require("../utils/timeouts.js");
41
+ const csrfConfig_js_1 = require("./csrfConfig.js");
41
42
  class AbstractAbapConnection {
42
43
  config;
43
44
  logger;
@@ -464,15 +465,19 @@ class AbstractAbapConnection {
464
465
  * Fetch CSRF token from SAP system
465
466
  * Protected method for use by concrete implementations in their connect() method
466
467
  */
467
- async fetchCsrfToken(url, retryCount = 3, retryDelay = 1000) {
468
+ async fetchCsrfToken(url, retryCount = csrfConfig_js_1.CSRF_CONFIG.RETRY_COUNT, retryDelay = csrfConfig_js_1.CSRF_CONFIG.RETRY_DELAY) {
468
469
  let csrfUrl = url;
470
+ // Build CSRF endpoint URL from base URL
469
471
  if (!url.includes("/sap/bc/adt/")) {
470
- csrfUrl = url.endsWith("/") ? `${url}sap/bc/adt/discovery` : `${url}/sap/bc/adt/discovery`;
472
+ // If URL doesn't contain ADT path, append endpoint
473
+ csrfUrl = url.endsWith("/") ? `${url}${csrfConfig_js_1.CSRF_CONFIG.ENDPOINT.slice(1)}` : `${url}${csrfConfig_js_1.CSRF_CONFIG.ENDPOINT}`;
471
474
  }
472
- else if (!url.includes("/sap/bc/adt/discovery")) {
475
+ else if (!url.includes(csrfConfig_js_1.CSRF_CONFIG.ENDPOINT)) {
476
+ // If URL contains ADT path but not our endpoint, extract base and append endpoint
473
477
  const base = url.split("/sap/bc/adt")[0];
474
- csrfUrl = `${base}/sap/bc/adt/discovery`;
478
+ csrfUrl = `${base}${csrfConfig_js_1.CSRF_CONFIG.ENDPOINT}`;
475
479
  }
480
+ // If URL already contains the endpoint, use it as is
476
481
  if (this.logger.csrfToken) {
477
482
  this.logger.csrfToken("fetch", `Fetching CSRF token from: ${csrfUrl}`);
478
483
  }
@@ -484,8 +489,7 @@ class AbstractAbapConnection {
484
489
  const authHeaders = await this.getAuthHeaders();
485
490
  const headers = {
486
491
  ...authHeaders,
487
- "x-csrf-token": "fetch",
488
- Accept: "application/atomsvc+xml"
492
+ ...csrfConfig_js_1.CSRF_CONFIG.REQUIRED_HEADERS
489
493
  };
490
494
  // Always add cookies if available - they are needed for session continuity
491
495
  // Even on first attempt, if we have cookies from previous session or error response, use them
@@ -517,7 +521,7 @@ class AbstractAbapConnection {
517
521
  await new Promise((resolve) => setTimeout(resolve, retryDelay));
518
522
  continue;
519
523
  }
520
- throw new Error("No CSRF token in response headers");
524
+ throw new Error(csrfConfig_js_1.CSRF_ERROR_MESSAGES.NOT_IN_HEADERS);
521
525
  }
522
526
  if (response.headers["set-cookie"]) {
523
527
  this.updateCookiesFromResponse(response.headers);
@@ -606,7 +610,7 @@ class AbstractAbapConnection {
606
610
  // Re-throw the original AxiosError to preserve response information
607
611
  throw error;
608
612
  }
609
- throw new Error(`Failed to fetch CSRF token after ${retryCount + 1} attempts: ${error instanceof Error ? error.message : String(error)}`);
613
+ throw new Error(csrfConfig_js_1.CSRF_ERROR_MESSAGES.FETCH_FAILED(retryCount + 1, error instanceof Error ? error.message : String(error)));
610
614
  }
611
615
  }
612
616
  throw new Error("CSRF token fetch failed unexpectedly");
@@ -699,7 +703,7 @@ class AbstractAbapConnection {
699
703
  catch (error) {
700
704
  // fetchCsrfToken already handles auth errors and auto-refresh
701
705
  // Just re-throw the error with minimal logging to avoid duplicate error messages
702
- const errorMsg = error instanceof Error ? error.message : "CSRF token is required for POST/PUT requests but could not be fetched";
706
+ const errorMsg = error instanceof Error ? error.message : csrfConfig_js_1.CSRF_ERROR_MESSAGES.REQUIRED_FOR_MUTATION;
703
707
  // Only log at DEBUG level to avoid duplicate error messages
704
708
  // (fetchCsrfToken already logged the error at ERROR level if auth failed)
705
709
  this.logger.debug(`[DEBUG] BaseAbapConnection - ensureFreshCsrfToken failed: ${errorMsg}`);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * CSRF Token Configuration
3
+ *
4
+ * Centralized constants for CSRF token fetching to ensure consistency
5
+ * across different connection implementations.
6
+ */
7
+ export declare const CSRF_CONFIG: {
8
+ /**
9
+ * Number of retry attempts for CSRF token fetch
10
+ * Default: 3 attempts (total of 4 requests: initial + 3 retries)
11
+ */
12
+ readonly RETRY_COUNT: 3;
13
+ /**
14
+ * Delay between retry attempts (milliseconds)
15
+ * Default: 1000ms (1 second)
16
+ */
17
+ readonly RETRY_DELAY: 1000;
18
+ /**
19
+ * CSRF token endpoint path
20
+ * Standard SAP ADT core discovery endpoint (available on all systems, returns smaller response)
21
+ */
22
+ readonly ENDPOINT: "/sap/bc/adt/core/discovery";
23
+ /**
24
+ * Required headers for CSRF token fetch
25
+ */
26
+ readonly REQUIRED_HEADERS: {
27
+ readonly 'x-csrf-token': "fetch";
28
+ readonly Accept: "application/atomsvc+xml";
29
+ };
30
+ };
31
+ /**
32
+ * CSRF token error messages
33
+ * Standardized error messages for consistent error reporting
34
+ */
35
+ export declare const CSRF_ERROR_MESSAGES: {
36
+ readonly FETCH_FAILED: (attempts: number, cause: string) => string;
37
+ readonly NOT_IN_HEADERS: "No CSRF token in response headers";
38
+ readonly REQUIRED_FOR_MUTATION: "CSRF token is required for POST/PUT requests but could not be fetched";
39
+ };
40
+ //# sourceMappingURL=csrfConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csrfConfig.d.ts","sourceRoot":"","sources":["../../src/connection/csrfConfig.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,WAAW;IACtB;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;OAEG;;;;;CAKK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB;sCACL,MAAM,SAAS,MAAM;;;CAMtC,CAAC"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = void 0;
4
+ /**
5
+ * CSRF Token Configuration
6
+ *
7
+ * Centralized constants for CSRF token fetching to ensure consistency
8
+ * across different connection implementations.
9
+ */
10
+ exports.CSRF_CONFIG = {
11
+ /**
12
+ * Number of retry attempts for CSRF token fetch
13
+ * Default: 3 attempts (total of 4 requests: initial + 3 retries)
14
+ */
15
+ RETRY_COUNT: 3,
16
+ /**
17
+ * Delay between retry attempts (milliseconds)
18
+ * Default: 1000ms (1 second)
19
+ */
20
+ RETRY_DELAY: 1000,
21
+ /**
22
+ * CSRF token endpoint path
23
+ * Standard SAP ADT core discovery endpoint (available on all systems, returns smaller response)
24
+ */
25
+ ENDPOINT: '/sap/bc/adt/core/discovery',
26
+ /**
27
+ * Required headers for CSRF token fetch
28
+ */
29
+ REQUIRED_HEADERS: {
30
+ 'x-csrf-token': 'fetch',
31
+ 'Accept': 'application/atomsvc+xml'
32
+ }
33
+ };
34
+ /**
35
+ * CSRF token error messages
36
+ * Standardized error messages for consistent error reporting
37
+ */
38
+ exports.CSRF_ERROR_MESSAGES = {
39
+ FETCH_FAILED: (attempts, cause) => `Failed to fetch CSRF token after ${attempts} attempts: ${cause}`,
40
+ NOT_IN_HEADERS: 'No CSRF token in response headers',
41
+ REQUIRED_FOR_MUTATION: 'CSRF token is required for POST/PUT requests but could not be fetched'
42
+ };
package/dist/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export { JwtAbapConnection as CloudAbapConnection } from "./connection/JwtAbapCo
10
10
  export { createAbapConnection } from "./connection/connectionFactory.js";
11
11
  export { sapConfigSignature } from "./config/sapConfig.js";
12
12
  export { getTimeout, getTimeoutConfig, type TimeoutConfig } from "./utils/timeouts.js";
13
+ export { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from "./connection/csrfConfig.js";
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAGnG,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAGtE,OAAO,EAAE,kBAAkB,IAAI,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,iBAAiB,IAAI,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1E,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAGnG,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAGtE,OAAO,EAAE,kBAAkB,IAAI,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAChG,OAAO,EAAE,iBAAiB,IAAI,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTimeoutConfig = exports.getTimeout = exports.sapConfigSignature = exports.createAbapConnection = exports.CloudAbapConnection = exports.OnPremAbapConnection = exports.JwtAbapConnection = exports.BaseAbapConnection = exports.FileSessionStorage = void 0;
3
+ exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.getTimeoutConfig = exports.getTimeout = exports.sapConfigSignature = exports.createAbapConnection = exports.CloudAbapConnection = exports.OnPremAbapConnection = exports.JwtAbapConnection = exports.BaseAbapConnection = exports.FileSessionStorage = void 0;
4
4
  // Session storage implementations
5
5
  var FileSessionStorage_js_1 = require("./utils/FileSessionStorage.js");
6
6
  Object.defineProperty(exports, "FileSessionStorage", { enumerable: true, get: function () { return FileSessionStorage_js_1.FileSessionStorage; } });
@@ -24,3 +24,7 @@ Object.defineProperty(exports, "sapConfigSignature", { enumerable: true, get: fu
24
24
  var timeouts_js_1 = require("./utils/timeouts.js");
25
25
  Object.defineProperty(exports, "getTimeout", { enumerable: true, get: function () { return timeouts_js_1.getTimeout; } });
26
26
  Object.defineProperty(exports, "getTimeoutConfig", { enumerable: true, get: function () { return timeouts_js_1.getTimeoutConfig; } });
27
+ // CSRF configuration
28
+ var csrfConfig_js_1 = require("./connection/csrfConfig.js");
29
+ Object.defineProperty(exports, "CSRF_CONFIG", { enumerable: true, get: function () { return csrfConfig_js_1.CSRF_CONFIG; } });
30
+ Object.defineProperty(exports, "CSRF_ERROR_MESSAGES", { enumerable: true, get: function () { return csrfConfig_js_1.CSRF_ERROR_MESSAGES; } });
package/dist/logger.d.ts CHANGED
@@ -1,67 +1,4 @@
1
- /**
2
- * Logger interface for connection layer
3
- * Allows connection layer to be independent of specific logger implementation
4
- */
5
- export interface ILogger {
6
- /**
7
- * Log informational message
8
- */
9
- info(message: string, meta?: any): void;
10
- /**
11
- * Log error message
12
- */
13
- error(message: string, meta?: any): void;
14
- /**
15
- * Log warning message
16
- */
17
- warn(message: string, meta?: any): void;
18
- /**
19
- * Log debug message
20
- */
21
- debug(message: string, meta?: any): void;
22
- /**
23
- * Log CSRF token operations
24
- * @param action - Type of CSRF operation: "fetch", "retry", "success", or "error"
25
- * @param message - Log message
26
- * @param meta - Additional metadata
27
- */
28
- csrfToken?(action: "fetch" | "retry" | "success" | "error", message: string, meta?: any): void;
29
- /**
30
- * Log TLS configuration
31
- * @param rejectUnauthorized - Whether TLS certificate validation is enabled
32
- */
33
- tlsConfig?(rejectUnauthorized: boolean): void;
34
- }
35
- /**
36
- * Session state interface for stateful connections
37
- * Contains cookies and CSRF token that need to be preserved across requests
38
- */
39
- export interface SessionState {
40
- cookies: string | null;
41
- csrfToken: string | null;
42
- cookieStore: Record<string, string>;
43
- }
44
- /**
45
- * Interface for storing and retrieving session state
46
- * Allows connection layer to persist session state (cookies, CSRF token) externally
47
- */
48
- export interface ISessionStorage {
49
- /**
50
- * Save session state for a given session ID
51
- * @param sessionId - Unique session identifier
52
- * @param state - Session state to save
53
- */
54
- save(sessionId: string, state: SessionState): Promise<void>;
55
- /**
56
- * Load session state for a given session ID
57
- * @param sessionId - Unique session identifier
58
- * @returns Session state or null if not found
59
- */
60
- load(sessionId: string): Promise<SessionState | null>;
61
- /**
62
- * Delete session state for a given session ID
63
- * @param sessionId - Unique session identifier
64
- */
65
- delete(sessionId: string): Promise<void>;
66
- }
1
+ import type { ILogger, ISessionStorage, ISessionState } from '@mcp-abap-adt/interfaces';
2
+ export type { ILogger, ISessionStorage };
3
+ export type SessionState = ISessionState;
67
4
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAExC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAEzC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAExC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAEzC;;;;;OAKG;IACH,SAAS,CAAC,CACR,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,EAC/C,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,GAAG,GACT,IAAI,CAAC;IAER;;;OAGG;IACH,SAAS,CAAC,CAAC,kBAAkB,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAEtD;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGxF,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;AACzC,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC"}
@@ -1,8 +1,5 @@
1
- export interface TimeoutConfig {
2
- default: number;
3
- csrf: number;
4
- long: number;
5
- }
6
- export declare function getTimeoutConfig(): TimeoutConfig;
1
+ import type { ITimeoutConfig } from '@mcp-abap-adt/interfaces';
2
+ export type TimeoutConfig = ITimeoutConfig;
3
+ export declare function getTimeoutConfig(): ITimeoutConfig;
7
4
  export declare function getTimeout(type?: "default" | "csrf" | "long" | number): number;
8
5
  //# sourceMappingURL=timeouts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeouts.d.ts","sourceRoot":"","sources":["../../src/utils/timeouts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAUhD;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAkB,GAAG,MAAM,CAOzF"}
1
+ {"version":3,"file":"timeouts.d.ts","sourceRoot":"","sources":["../../src/utils/timeouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC;AAE3C,wBAAgB,gBAAgB,IAAI,cAAc,CAUjD;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAkB,GAAG,MAAM,CAOzF"}
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Token refresh utilities for JWT authentication
3
3
  */
4
- export interface TokenRefreshResult {
5
- accessToken: string;
6
- refreshToken?: string;
7
- }
4
+ import type { ITokenRefreshResult } from '@mcp-abap-adt/interfaces';
5
+ export type TokenRefreshResult = ITokenRefreshResult;
8
6
  /**
9
7
  * Refreshes the access token using refresh token
10
8
  * @param refreshToken Refresh token
@@ -13,5 +11,5 @@ export interface TokenRefreshResult {
13
11
  * @param clientSecret UAA client secret
14
12
  * @returns Promise that resolves to new tokens
15
13
  */
16
- export declare function refreshJwtToken(refreshToken: string, uaaUrl: string, clientId: string, clientSecret: string): Promise<TokenRefreshResult>;
14
+ export declare function refreshJwtToken(refreshToken: string, uaaUrl: string, clientId: string, clientSecret: string): Promise<ITokenRefreshResult>;
17
15
  //# sourceMappingURL=tokenRefresh.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../../src/utils/tokenRefresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAqC7B"}
1
+ {"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../../src/utils/tokenRefresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGpE,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,mBAAmB,CAAC,CAqC9B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/connection",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "ABAP connection layer for MCP ABAP ADT server",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -43,6 +43,7 @@
43
43
  "node": ">=18.0.0"
44
44
  },
45
45
  "dependencies": {
46
+ "@mcp-abap-adt/interfaces": "^0.1.0",
46
47
  "axios": "^1.11.0",
47
48
  "commander": "^14.0.2",
48
49
  "express": "^5.1.0",