@mcp-abap-adt/connection 0.1.15 → 0.2.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/README.md +34 -95
- package/dist/connection/AbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.d.ts +6 -44
- package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.js +45 -199
- package/dist/connection/BaseAbapConnection.d.ts +2 -2
- package/dist/connection/BaseAbapConnection.d.ts.map +1 -1
- package/dist/connection/BaseAbapConnection.js +6 -9
- package/dist/connection/JwtAbapConnection.d.ts +8 -16
- package/dist/connection/JwtAbapConnection.d.ts.map +1 -1
- package/dist/connection/JwtAbapConnection.js +24 -248
- package/dist/connection/connectionFactory.d.ts +2 -2
- package/dist/connection/connectionFactory.d.ts.map +1 -1
- package/dist/connection/connectionFactory.js +3 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/logger.d.ts +2 -3
- package/dist/logger.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/utils/FileSessionStorage.d.ts +0 -73
- package/dist/utils/FileSessionStorage.d.ts.map +0 -1
- package/dist/utils/FileSessionStorage.js +0 -191
|
@@ -2,156 +2,37 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.JwtAbapConnection = void 0;
|
|
4
4
|
const AbstractAbapConnection_js_1 = require("./AbstractAbapConnection.js");
|
|
5
|
-
const tokenRefresh_js_1 = require("../utils/tokenRefresh.js");
|
|
6
5
|
const axios_1 = require("axios");
|
|
7
6
|
/**
|
|
8
7
|
* JWT Authentication connection for SAP BTP Cloud systems
|
|
9
|
-
*
|
|
8
|
+
* Note: Token refresh functionality is not supported in this package.
|
|
9
|
+
* Use @mcp-abap-adt/auth-broker for token refresh functionality.
|
|
10
10
|
*/
|
|
11
11
|
class JwtAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnection {
|
|
12
|
-
|
|
13
|
-
constructor(config, logger, sessionStorage, sessionId) {
|
|
12
|
+
constructor(config, logger, sessionId) {
|
|
14
13
|
JwtAbapConnection.validateConfig(config);
|
|
15
|
-
super(config, logger
|
|
14
|
+
super(config, logger || null, sessionId);
|
|
16
15
|
}
|
|
17
16
|
buildAuthorizationHeader() {
|
|
18
17
|
const config = this.getConfig();
|
|
19
18
|
const { jwtToken } = config;
|
|
20
19
|
// Log token preview for debugging (first 10 and last 4 chars)
|
|
21
20
|
const tokenPreview = jwtToken ? `${jwtToken.substring(0, 10)}...${jwtToken.substring(Math.max(0, jwtToken.length - 4))}` : 'null';
|
|
22
|
-
this.logger
|
|
21
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection.buildAuthorizationHeader - Using token: ${tokenPreview}`);
|
|
23
22
|
return `Bearer ${jwtToken}`;
|
|
24
23
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Refresh JWT token using refresh token
|
|
27
|
-
* @returns Promise that resolves when token is refreshed
|
|
28
|
-
*/
|
|
29
|
-
async refreshToken() {
|
|
30
|
-
const config = this.getConfig();
|
|
31
|
-
if (!config.refreshToken) {
|
|
32
|
-
throw new Error("Refresh token is not available. Please re-authenticate.");
|
|
33
|
-
}
|
|
34
|
-
if (!config.uaaUrl || !config.uaaClientId || !config.uaaClientSecret) {
|
|
35
|
-
throw new Error("UAA credentials are not available for token refresh. " +
|
|
36
|
-
"Please provide UAA_URL, UAA_CLIENT_ID, and UAA_CLIENT_SECRET in configuration or re-authenticate.");
|
|
37
|
-
}
|
|
38
|
-
// Prevent concurrent refresh attempts
|
|
39
|
-
if (this.tokenRefreshInProgress) {
|
|
40
|
-
this.logger.debug("Token refresh already in progress, waiting...");
|
|
41
|
-
// Wait for ongoing refresh to complete
|
|
42
|
-
while (this.tokenRefreshInProgress) {
|
|
43
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
this.tokenRefreshInProgress = true;
|
|
48
|
-
try {
|
|
49
|
-
this.logger.debug("Refreshing JWT token...");
|
|
50
|
-
const tokens = await (0, tokenRefresh_js_1.refreshJwtToken)(config.refreshToken, config.uaaUrl, config.uaaClientId, config.uaaClientSecret);
|
|
51
|
-
// Update config with new tokens
|
|
52
|
-
// NOTE: This updates the config object directly, which is shared with the connection cache
|
|
53
|
-
// The connection cache will be invalidated on next getManagedConnection() call because
|
|
54
|
-
// sapConfigSignature includes token preview, so signature will change
|
|
55
|
-
const oldTokenPreview = config.jwtToken ? `${config.jwtToken.substring(0, 10)}...${config.jwtToken.substring(Math.max(0, config.jwtToken.length - 4))}` : 'null';
|
|
56
|
-
config.jwtToken = tokens.accessToken;
|
|
57
|
-
if (tokens.refreshToken) {
|
|
58
|
-
config.refreshToken = tokens.refreshToken;
|
|
59
|
-
}
|
|
60
|
-
const newTokenPreview = config.jwtToken ? `${config.jwtToken.substring(0, 10)}...${config.jwtToken.substring(Math.max(0, config.jwtToken.length - 4))}` : 'null';
|
|
61
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.refreshToken - Token updated in config: ${oldTokenPreview} -> ${newTokenPreview}`);
|
|
62
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.refreshToken - Config object reference check: ${config === this.getConfig() ? 'same object ✓' : 'different object ✗'}`);
|
|
63
|
-
// Clear CSRF token and cookies to force new session with new token
|
|
64
|
-
// IMPORTANT: After token refresh, we must clear saved session state because
|
|
65
|
-
// old cookies/CSRF token are tied to the old JWT token and won't work with new token
|
|
66
|
-
this.reset();
|
|
67
|
-
// Also clear saved session state from storage if using stateful session
|
|
68
|
-
// This prevents reloading old cookies/CSRF token that are tied to old JWT token
|
|
69
|
-
const sessionStorage = this.getSessionStorage();
|
|
70
|
-
const sessionId = this.getSessionId();
|
|
71
|
-
if (sessionStorage && sessionId) {
|
|
72
|
-
try {
|
|
73
|
-
await this.clearSessionState();
|
|
74
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.refreshToken - Cleared saved session state from storage`);
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
this.logger.warn(`[DEBUG] JwtAbapConnection.refreshToken - Failed to clear session state: ${error instanceof Error ? error.message : String(error)}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
this.logger.debug("JWT token refreshed successfully");
|
|
81
|
-
this.logger.debug("NOTE: Connection cache will be invalidated on next getManagedConnection() call due to changed token signature");
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
this.logger.error(`Failed to refresh JWT token: ${error.message}`);
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
finally {
|
|
88
|
-
this.tokenRefreshInProgress = false;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Check if token refresh is possible
|
|
93
|
-
*/
|
|
94
|
-
canRefreshToken() {
|
|
95
|
-
const config = this.getConfig();
|
|
96
|
-
return !!(config.refreshToken &&
|
|
97
|
-
config.uaaUrl &&
|
|
98
|
-
config.uaaClientId &&
|
|
99
|
-
config.uaaClientSecret);
|
|
100
|
-
}
|
|
101
24
|
/**
|
|
102
25
|
* Override connect to handle JWT token refresh on errors
|
|
103
26
|
*/
|
|
104
27
|
async connect() {
|
|
105
28
|
const baseUrl = await this.getBaseUrl();
|
|
106
29
|
const discoveryUrl = `${baseUrl}/sap/bc/adt/discovery`;
|
|
107
|
-
this.logger
|
|
108
|
-
// If we have saved session state, load it first to compare later
|
|
109
|
-
const sessionStorage = this.getSessionStorage();
|
|
110
|
-
const sessionId = this.getSessionId();
|
|
111
|
-
let savedState = null;
|
|
112
|
-
if (sessionStorage && sessionId) {
|
|
113
|
-
try {
|
|
114
|
-
savedState = await sessionStorage.load(sessionId);
|
|
115
|
-
if (savedState) {
|
|
116
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.connect - Loaded saved session state for comparison`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.connect - No saved session state found or failed to load`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
30
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection - Connecting to SAP system: ${discoveryUrl}`);
|
|
123
31
|
try {
|
|
124
32
|
// Try to get CSRF token (this will also get cookies)
|
|
125
33
|
const token = await this.fetchCsrfToken(discoveryUrl, 3, 1000);
|
|
126
34
|
this.setCsrfToken(token);
|
|
127
|
-
|
|
128
|
-
const newState = {
|
|
129
|
-
cookies: this.getCookies(),
|
|
130
|
-
csrfToken: this.getCsrfToken(),
|
|
131
|
-
cookieStore: Object.fromEntries(this.cookieStore || new Map())
|
|
132
|
-
};
|
|
133
|
-
// Only save if session state changed
|
|
134
|
-
if (savedState) {
|
|
135
|
-
const cookiesChanged = savedState.cookies !== newState.cookies;
|
|
136
|
-
const csrfTokenChanged = savedState.csrfToken !== newState.csrfToken;
|
|
137
|
-
const cookieStoreChanged = JSON.stringify(savedState.cookieStore) !== JSON.stringify(newState.cookieStore);
|
|
138
|
-
if (cookiesChanged || csrfTokenChanged || cookieStoreChanged) {
|
|
139
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.connect - Session state changed, saving new state`, {
|
|
140
|
-
cookiesChanged,
|
|
141
|
-
csrfTokenChanged,
|
|
142
|
-
cookieStoreChanged
|
|
143
|
-
});
|
|
144
|
-
await this.saveSessionState();
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.connect - Session state unchanged, not saving`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// No saved state, save new one
|
|
152
|
-
await this.saveSessionState();
|
|
153
|
-
}
|
|
154
|
-
this.logger.debug("Successfully connected to SAP system", {
|
|
35
|
+
this.logger?.debug("Successfully connected to SAP system", {
|
|
155
36
|
hasCsrfToken: !!this.getCsrfToken(),
|
|
156
37
|
hasCookies: !!this.getCookies(),
|
|
157
38
|
cookieLength: this.getCookies()?.length || 0
|
|
@@ -170,52 +51,31 @@ class JwtAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnecti
|
|
|
170
51
|
responseText.includes("Missing authorization")) {
|
|
171
52
|
throw error;
|
|
172
53
|
}
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
this.logger.debug(`Received ${error.response.status} during connect, attempting JWT token refresh...`);
|
|
177
|
-
await this.refreshToken();
|
|
178
|
-
this.logger.debug(`✓ Token refreshed successfully, retrying connect...`);
|
|
179
|
-
// Retry CSRF token fetch with new JWT token
|
|
180
|
-
const token = await this.fetchCsrfToken(discoveryUrl, 3, 1000);
|
|
181
|
-
this.setCsrfToken(token);
|
|
182
|
-
await this.saveSessionState();
|
|
183
|
-
this.logger.debug("Successfully connected after JWT refresh", {
|
|
184
|
-
hasCsrfToken: !!this.getCsrfToken(),
|
|
185
|
-
hasCookies: !!this.getCookies()
|
|
186
|
-
});
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
catch (refreshError) {
|
|
190
|
-
this.logger.error(`❌ Token refresh failed during connect: ${refreshError.message}`);
|
|
191
|
-
throw new Error("Refresh token has expired. Please re-authenticate.");
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
// No refresh token available - JWT token expired, need to re-authenticate
|
|
196
|
-
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
197
|
-
}
|
|
54
|
+
// Token refresh is not supported in connection package
|
|
55
|
+
// Use auth-broker for token refresh functionality
|
|
56
|
+
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
198
57
|
}
|
|
199
58
|
// Re-throw other errors
|
|
200
59
|
throw error;
|
|
201
60
|
}
|
|
202
61
|
}
|
|
203
62
|
/**
|
|
204
|
-
* Override makeAdtRequest to handle JWT
|
|
63
|
+
* Override makeAdtRequest to handle JWT auth errors
|
|
64
|
+
* Note: Token refresh is not supported in connection package - use auth-broker instead
|
|
205
65
|
*/
|
|
206
66
|
async makeAdtRequest(options) {
|
|
207
|
-
this.logger
|
|
67
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection.makeAdtRequest - Starting request: ${options.method} ${options.url}`);
|
|
208
68
|
try {
|
|
209
69
|
const response = await super.makeAdtRequest(options);
|
|
210
|
-
this.logger
|
|
70
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection.makeAdtRequest - Request succeeded: ${response.status}`);
|
|
211
71
|
return response;
|
|
212
72
|
}
|
|
213
73
|
catch (error) {
|
|
214
|
-
this.logger
|
|
74
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection.makeAdtRequest - Request failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
215
75
|
// Handle JWT auth errors (401/403)
|
|
216
76
|
if (error instanceof axios_1.AxiosError &&
|
|
217
77
|
(error.response?.status === 401 || error.response?.status === 403)) {
|
|
218
|
-
this.logger
|
|
78
|
+
this.logger?.debug(`[DEBUG] JwtAbapConnection.makeAdtRequest - Got ${error.response.status}, checking if refresh is possible...`);
|
|
219
79
|
// Check if this is really an auth error, not a permissions error
|
|
220
80
|
const responseData = error.response?.data;
|
|
221
81
|
const responseText = typeof responseData === "string" ? responseData : JSON.stringify(responseData || "");
|
|
@@ -225,85 +85,16 @@ class JwtAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnecti
|
|
|
225
85
|
responseText.includes("Missing authorization")) {
|
|
226
86
|
throw error;
|
|
227
87
|
}
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection.makeAdtRequest - canRefreshToken: ${canRefresh}`, {
|
|
232
|
-
hasRefreshToken: !!config.refreshToken,
|
|
233
|
-
hasUaaUrl: !!config.uaaUrl,
|
|
234
|
-
hasUaaClientId: !!config.uaaClientId,
|
|
235
|
-
hasUaaClientSecret: !!config.uaaClientSecret
|
|
236
|
-
});
|
|
237
|
-
if (canRefresh) {
|
|
238
|
-
// Step 1: Refresh token
|
|
239
|
-
try {
|
|
240
|
-
this.logger.debug(`Received ${error.response.status}, attempting JWT token refresh...`);
|
|
241
|
-
await this.refreshToken();
|
|
242
|
-
this.logger.debug(`✓ Token refreshed successfully, reconnecting to get new CSRF token...`);
|
|
243
|
-
}
|
|
244
|
-
catch (refreshError) {
|
|
245
|
-
// Only catch errors from refreshToken()
|
|
246
|
-
this.logger.error(`❌ Token refresh failed: ${refreshError.message}`);
|
|
247
|
-
throw new Error("Refresh token has expired. Please re-authenticate.");
|
|
248
|
-
}
|
|
249
|
-
// Step 2: Reconnect to get new CSRF token and cookies
|
|
250
|
-
try {
|
|
251
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection - Calling connect() after token refresh to get CSRF token...`);
|
|
252
|
-
await this.connect();
|
|
253
|
-
const hasCsrf = !!this.getCsrfToken();
|
|
254
|
-
const hasCookies = !!this.getCookies();
|
|
255
|
-
this.logger.debug(`✓ Reconnected successfully after token refresh`, {
|
|
256
|
-
hasCsrfToken: hasCsrf,
|
|
257
|
-
hasCookies: hasCookies,
|
|
258
|
-
csrfTokenLength: this.getCsrfToken()?.length || 0,
|
|
259
|
-
cookiesLength: this.getCookies()?.length || 0
|
|
260
|
-
});
|
|
261
|
-
if (!hasCsrf) {
|
|
262
|
-
this.logger.error(`❌ CRITICAL: CSRF token not obtained after reconnect! Request may fail.`);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
catch (connectError) {
|
|
266
|
-
// If connect() fails after token refresh, it means the refresh token was invalid
|
|
267
|
-
// Check if it's an auth error (401/403)
|
|
268
|
-
if (connectError instanceof axios_1.AxiosError &&
|
|
269
|
-
(connectError.response?.status === 401 || connectError.response?.status === 403)) {
|
|
270
|
-
this.logger.error(`❌ Failed to reconnect after token refresh: ${connectError.message}`);
|
|
271
|
-
throw new Error("Refresh token has expired. Please re-authenticate.");
|
|
272
|
-
}
|
|
273
|
-
// For other errors, log but continue - ensureFreshCsrfToken will try to get CSRF token during request retry
|
|
274
|
-
this.logger.error(`❌ Failed to reconnect after token refresh: ${connectError.message}`);
|
|
275
|
-
this.logger.error(`❌ This means CSRF token will not be available for POST/PUT/DELETE requests`);
|
|
276
|
-
}
|
|
277
|
-
// Step 3: Retry the request with new token
|
|
278
|
-
// ensureFreshCsrfToken will be called automatically if CSRF token is missing
|
|
279
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection - Retrying ADT request after token refresh...`);
|
|
280
|
-
try {
|
|
281
|
-
return await super.makeAdtRequest(options);
|
|
282
|
-
}
|
|
283
|
-
catch (retryError) {
|
|
284
|
-
// If retry fails with 401/403, it means token refresh didn't help - re-throw as auth error
|
|
285
|
-
if (retryError instanceof axios_1.AxiosError &&
|
|
286
|
-
(retryError.response?.status === 401 || retryError.response?.status === 403)) {
|
|
287
|
-
this.logger.error(`❌ Token refresh didn't help - still getting ${retryError.response.status}`);
|
|
288
|
-
throw new Error("Refresh token has expired. Please re-authenticate.");
|
|
289
|
-
}
|
|
290
|
-
// For other errors (400, 500, etc.), re-throw the original error
|
|
291
|
-
// These are not auth errors, so they should be handled by the caller
|
|
292
|
-
this.logger.debug(`[DEBUG] JwtAbapConnection - Retry request failed with non-auth error: ${retryError.response?.status || 'unknown'}`);
|
|
293
|
-
throw retryError;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
// No refresh token available - JWT token expired, need to re-authenticate
|
|
298
|
-
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
299
|
-
}
|
|
88
|
+
// Token refresh is not supported in connection package
|
|
89
|
+
// Use auth-broker for token refresh functionality
|
|
90
|
+
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
300
91
|
}
|
|
301
92
|
throw error;
|
|
302
93
|
}
|
|
303
94
|
}
|
|
304
95
|
/**
|
|
305
|
-
* Override fetchCsrfToken to handle JWT
|
|
306
|
-
*
|
|
96
|
+
* Override fetchCsrfToken to handle JWT auth errors
|
|
97
|
+
* Note: Token refresh is not supported in connection package - use auth-broker instead
|
|
307
98
|
*/
|
|
308
99
|
async fetchCsrfToken(url, retryCount = 3, retryDelay = 1000) {
|
|
309
100
|
try {
|
|
@@ -323,24 +114,9 @@ class JwtAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnecti
|
|
|
323
114
|
responseText.includes("Missing authorization")) {
|
|
324
115
|
throw error;
|
|
325
116
|
}
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
this.logger.debug(`Received ${error.response.status} during CSRF token fetch, attempting JWT token refresh...`);
|
|
330
|
-
await this.refreshToken();
|
|
331
|
-
this.logger.debug(`✓ Token refreshed successfully, retrying CSRF token fetch...`);
|
|
332
|
-
// Retry CSRF token fetch with new JWT token
|
|
333
|
-
return await super.fetchCsrfToken(url, retryCount, retryDelay);
|
|
334
|
-
}
|
|
335
|
-
catch (refreshError) {
|
|
336
|
-
this.logger.error(`❌ Token refresh failed during CSRF token fetch: ${refreshError.message}`);
|
|
337
|
-
throw new Error("Refresh token has expired. Please re-authenticate.");
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
// No refresh token available - JWT token expired, need to re-authenticate
|
|
342
|
-
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
343
|
-
}
|
|
117
|
+
// Token refresh is not supported in connection package
|
|
118
|
+
// Use auth-broker for token refresh functionality
|
|
119
|
+
throw new Error("JWT token has expired. Please re-authenticate.");
|
|
344
120
|
}
|
|
345
121
|
// Re-throw other errors
|
|
346
122
|
throw error;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SapConfig } from "../config/sapConfig.js";
|
|
2
2
|
import { AbapConnection } from "./AbapConnection.js";
|
|
3
|
-
import { ILogger
|
|
4
|
-
export declare function createAbapConnection(config: SapConfig, logger
|
|
3
|
+
import { ILogger } from "../logger.js";
|
|
4
|
+
export declare function createAbapConnection(config: SapConfig, logger?: ILogger | null, sessionId?: string): AbapConnection;
|
|
5
5
|
//# sourceMappingURL=connectionFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAShB"}
|
|
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createAbapConnection = createAbapConnection;
|
|
4
4
|
const JwtAbapConnection_js_1 = require("./JwtAbapConnection.js");
|
|
5
5
|
const BaseAbapConnection_js_1 = require("./BaseAbapConnection.js");
|
|
6
|
-
function createAbapConnection(config, logger,
|
|
6
|
+
function createAbapConnection(config, logger, sessionId) {
|
|
7
7
|
switch (config.authType) {
|
|
8
8
|
case "basic":
|
|
9
|
-
return new BaseAbapConnection_js_1.BaseAbapConnection(config, logger,
|
|
9
|
+
return new BaseAbapConnection_js_1.BaseAbapConnection(config, logger, sessionId);
|
|
10
10
|
case "jwt":
|
|
11
|
-
return new JwtAbapConnection_js_1.JwtAbapConnection(config, logger,
|
|
11
|
+
return new JwtAbapConnection_js_1.JwtAbapConnection(config, logger, sessionId);
|
|
12
12
|
default:
|
|
13
13
|
throw new Error(`Unsupported SAP authentication type: ${config.authType}`);
|
|
14
14
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export type { SapConfig, SapAuthType, } from "./config/sapConfig.js";
|
|
2
2
|
export type { AbapRequestOptions } from "./connection/AbapConnection.js";
|
|
3
3
|
export { type AbapConnection } from "./connection/AbapConnection.js";
|
|
4
|
-
export type { ILogger
|
|
5
|
-
export { FileSessionStorage, type FileSessionStorageOptions } from "./utils/FileSessionStorage.js";
|
|
4
|
+
export type { ILogger } from "./logger.js";
|
|
6
5
|
export { BaseAbapConnection } from "./connection/BaseAbapConnection.js";
|
|
7
6
|
export { JwtAbapConnection } from "./connection/JwtAbapConnection.js";
|
|
8
7
|
export { BaseAbapConnection as OnPremAbapConnection } from "./connection/BaseAbapConnection.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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,MAAM,aAAa,CAAC;AAG3C,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,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.getTimeoutConfig = exports.getTimeout = exports.sapConfigSignature = exports.createAbapConnection = exports.CloudAbapConnection = exports.OnPremAbapConnection = exports.JwtAbapConnection = exports.BaseAbapConnection =
|
|
4
|
-
// Session storage implementations
|
|
5
|
-
var FileSessionStorage_js_1 = require("./utils/FileSessionStorage.js");
|
|
6
|
-
Object.defineProperty(exports, "FileSessionStorage", { enumerable: true, get: function () { return FileSessionStorage_js_1.FileSessionStorage; } });
|
|
3
|
+
exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.getTimeoutConfig = exports.getTimeout = exports.sapConfigSignature = exports.createAbapConnection = exports.CloudAbapConnection = exports.OnPremAbapConnection = exports.JwtAbapConnection = exports.BaseAbapConnection = void 0;
|
|
7
4
|
// Connection classes - only final implementations
|
|
8
5
|
var BaseAbapConnection_js_1 = require("./connection/BaseAbapConnection.js");
|
|
9
6
|
Object.defineProperty(exports, "BaseAbapConnection", { enumerable: true, get: function () { return BaseAbapConnection_js_1.BaseAbapConnection; } });
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ILogger
|
|
2
|
-
export type { ILogger
|
|
3
|
-
export type SessionState = ISessionState;
|
|
1
|
+
import type { ILogger } from '@mcp-abap-adt/interfaces';
|
|
2
|
+
export type { ILogger };
|
|
4
3
|
//# sourceMappingURL=logger.d.ts.map
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGxD,YAAY,EAAE,OAAO,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/connection",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"node": ">=18.0.0"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@mcp-abap-adt/interfaces": "^0.1.
|
|
46
|
+
"@mcp-abap-adt/interfaces": "^0.1.4",
|
|
47
47
|
"axios": "^1.11.0",
|
|
48
48
|
"commander": "^14.0.2",
|
|
49
49
|
"express": "^5.1.0",
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File-based session storage implementation
|
|
3
|
-
* Stores session state (cookies, CSRF tokens) in JSON files on disk
|
|
4
|
-
*/
|
|
5
|
-
import { ISessionStorage, SessionState } from '../logger.js';
|
|
6
|
-
export interface FileSessionStorageOptions {
|
|
7
|
-
/**
|
|
8
|
-
* Directory to store session files
|
|
9
|
-
* @default '.sessions'
|
|
10
|
-
*/
|
|
11
|
-
sessionDir?: string;
|
|
12
|
-
/**
|
|
13
|
-
* Whether to create session directory if it doesn't exist
|
|
14
|
-
* @default true
|
|
15
|
-
*/
|
|
16
|
-
createDir?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Pretty-print JSON files (for debugging)
|
|
19
|
-
* @default false
|
|
20
|
-
*/
|
|
21
|
-
prettyPrint?: boolean;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* File-based session storage
|
|
25
|
-
* Stores each session in a separate JSON file: .sessions/<sessionId>.json
|
|
26
|
-
*/
|
|
27
|
-
export declare class FileSessionStorage implements ISessionStorage {
|
|
28
|
-
private readonly sessionDir;
|
|
29
|
-
private readonly prettyPrint;
|
|
30
|
-
constructor(options?: FileSessionStorageOptions);
|
|
31
|
-
/**
|
|
32
|
-
* Get file path for session
|
|
33
|
-
*/
|
|
34
|
-
private getSessionFilePath;
|
|
35
|
-
/**
|
|
36
|
-
* Save session state to file
|
|
37
|
-
*/
|
|
38
|
-
save(sessionId: string, state: SessionState): Promise<void>;
|
|
39
|
-
/**
|
|
40
|
-
* Load session state from file
|
|
41
|
-
*/
|
|
42
|
-
load(sessionId: string): Promise<SessionState | null>;
|
|
43
|
-
/**
|
|
44
|
-
* Delete session state file
|
|
45
|
-
*/
|
|
46
|
-
delete(sessionId: string): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
-
* List all session IDs
|
|
49
|
-
*/
|
|
50
|
-
listSessions(): Promise<string[]>;
|
|
51
|
-
/**
|
|
52
|
-
* Get session metadata (without loading full state)
|
|
53
|
-
*/
|
|
54
|
-
getSessionMetadata(sessionId: string): Promise<{
|
|
55
|
-
sessionId: string;
|
|
56
|
-
timestamp: number;
|
|
57
|
-
pid: number;
|
|
58
|
-
age: number;
|
|
59
|
-
} | null>;
|
|
60
|
-
/**
|
|
61
|
-
* Clean up stale sessions (older than maxAge)
|
|
62
|
-
*/
|
|
63
|
-
cleanupStaleSessions(maxAgeMs?: number): Promise<string[]>;
|
|
64
|
-
/**
|
|
65
|
-
* Clean up sessions from dead processes
|
|
66
|
-
*/
|
|
67
|
-
cleanupDeadProcessSessions(): Promise<string[]>;
|
|
68
|
-
/**
|
|
69
|
-
* Clear all sessions
|
|
70
|
-
*/
|
|
71
|
-
clearAll(): Promise<void>;
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=FileSessionStorage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FileSessionStorage.d.ts","sourceRoot":"","sources":["../../src/utils/FileSessionStorage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7D,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;gBAE1B,OAAO,GAAE,yBAA8B;IAenD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjE;;OAEG;IACG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAiB3D;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAWvC;;OAEG;IACG,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QACnD,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,IAAI,CAAC;IAqBT;;OAEG;IACG,oBAAoB,CAAC,QAAQ,GAAE,MAAuB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBhF;;OAEG;IACG,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAqBrD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAMhC"}
|