@mcp-abap-adt/connection 1.3.2 → 1.4.1
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/dist/connection/RfcAbapConnection.d.ts +42 -0
- package/dist/connection/RfcAbapConnection.d.ts.map +1 -0
- package/dist/connection/RfcAbapConnection.js +265 -0
- package/dist/connection/connectionFactory.d.ts.map +1 -1
- package/dist/connection/connectionFactory.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/package.json +2 -2
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IAbapRequestOptions, IAdtResponse } from '@mcp-abap-adt/interfaces';
|
|
2
|
+
import type { SapConfig } from '../config/sapConfig.js';
|
|
3
|
+
import type { ILogger } from '../logger.js';
|
|
4
|
+
import type { AbapConnection } from './AbapConnection.js';
|
|
5
|
+
/**
|
|
6
|
+
* RFC-based connection for on-premise SAP systems.
|
|
7
|
+
*
|
|
8
|
+
* Uses node-rfc to call SADT_REST_RFC_ENDPOINT — the same standard SAP FM
|
|
9
|
+
* that Eclipse ADT uses for all on-premise ADT operations via JCo.
|
|
10
|
+
*
|
|
11
|
+
* RFC connections are inherently stateful: one ABAP session persists for the
|
|
12
|
+
* entire connection lifetime. This solves the HTTP 423 "invalid lock handle"
|
|
13
|
+
* problem on legacy systems (BASIS < 7.50) where HTTP stateful sessions
|
|
14
|
+
* are not supported.
|
|
15
|
+
*
|
|
16
|
+
* Connection parameters are derived from the standard ISapConfig.url field:
|
|
17
|
+
* http://saphost:8000 → ashost=saphost, sysnr=00
|
|
18
|
+
*
|
|
19
|
+
* Prerequisites:
|
|
20
|
+
* - SAP NW RFC SDK installed on the machine
|
|
21
|
+
* - node-rfc package installed: npm install node-rfc
|
|
22
|
+
*/
|
|
23
|
+
export declare class RfcAbapConnection implements AbapConnection {
|
|
24
|
+
private readonly config;
|
|
25
|
+
private readonly logger;
|
|
26
|
+
private rfcClient;
|
|
27
|
+
private readonly sessionId;
|
|
28
|
+
private readonly baseUrl;
|
|
29
|
+
private readonly rfcParams;
|
|
30
|
+
constructor(config: SapConfig, logger?: ILogger | null);
|
|
31
|
+
connect(): Promise<void>;
|
|
32
|
+
getBaseUrl(): Promise<string>;
|
|
33
|
+
getSessionId(): string | null;
|
|
34
|
+
setSessionType(_type: 'stateful' | 'stateless'): void;
|
|
35
|
+
makeAdtRequest<T = any, D = any>(options: IAbapRequestOptions): Promise<IAdtResponse<T, D>>;
|
|
36
|
+
/**
|
|
37
|
+
* Close the RFC connection and release the ABAP session.
|
|
38
|
+
*/
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
private static validateConfig;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=RfcAbapConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RfcAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/RfcAbapConnection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA0F1D;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IAOpD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;gBAG7B,MAAM,EAAE,SAAS,EACjB,MAAM,GAAE,OAAO,GAAG,IAAW;IAa1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAInC,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAI/C,cAAc,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,EACnC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IA6I9B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B,OAAO,CAAC,MAAM,CAAC,cAAc;CAqB9B"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RfcAbapConnection = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
/**
|
|
6
|
+
* Derive RFC connection parameters from ISapConfig.
|
|
7
|
+
* Parses hostname from config.url, system number from port (80XX → XX).
|
|
8
|
+
*
|
|
9
|
+
* Examples:
|
|
10
|
+
* http://saphost:8000 → ashost=saphost, sysnr=00
|
|
11
|
+
* http://saphost:8001 → ashost=saphost, sysnr=01
|
|
12
|
+
* http://saphost:8042 → ashost=saphost, sysnr=42
|
|
13
|
+
*/
|
|
14
|
+
function buildRfcParams(config) {
|
|
15
|
+
const parsed = new URL(config.url);
|
|
16
|
+
const port = Number.parseInt(parsed.port || '8000', 10);
|
|
17
|
+
// SAP HTTP port convention: 80XX where XX = system number
|
|
18
|
+
const sysnr = String(port - 8000).padStart(2, '0');
|
|
19
|
+
return {
|
|
20
|
+
ashost: parsed.hostname,
|
|
21
|
+
sysnr,
|
|
22
|
+
client: config.client || '000',
|
|
23
|
+
user: config.username || '',
|
|
24
|
+
passwd: config.password || '',
|
|
25
|
+
lang: 'EN',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Map ADT exception type names to HTTP status codes.
|
|
30
|
+
* These are standard ADT exception types returned in `<exc:exception>` XML.
|
|
31
|
+
*/
|
|
32
|
+
const EXCEPTION_STATUS_MAP = {
|
|
33
|
+
ExceptionResourceNotFound: { code: 404, text: 'Not Found' },
|
|
34
|
+
ExceptionResourceNoAuthorization: { code: 403, text: 'Forbidden' },
|
|
35
|
+
ExceptionResourceAlreadyExists: { code: 409, text: 'Conflict' },
|
|
36
|
+
ExceptionResourceLocked: { code: 423, text: 'Locked' },
|
|
37
|
+
ExceptionBadRequest: { code: 400, text: 'Bad Request' },
|
|
38
|
+
ExceptionNotSupported: { code: 501, text: 'Not Implemented' },
|
|
39
|
+
ExceptionConflict: { code: 409, text: 'Conflict' },
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Detect HTTP status from ADT exception XML in response body.
|
|
43
|
+
* On some legacy systems, SADT_REST_RFC_ENDPOINT returns errors as XML
|
|
44
|
+
* exceptions without setting proper HTTP status codes in STATUS_LINE.
|
|
45
|
+
*/
|
|
46
|
+
function detectExceptionStatus(body) {
|
|
47
|
+
// Extract exception type: <exc:exception ... xmlns:exc="..."><exc:type>ExceptionName</exc:type>
|
|
48
|
+
const typeMatch = body.match(/<exc:type[^>]*>([^<]+)<\/exc:type>/);
|
|
49
|
+
if (typeMatch) {
|
|
50
|
+
const exType = typeMatch[1].trim();
|
|
51
|
+
const mapped = EXCEPTION_STATUS_MAP[exType];
|
|
52
|
+
if (mapped) {
|
|
53
|
+
return { statusCode: mapped.code, statusText: mapped.text };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Unknown exception type — return 500 as generic server error
|
|
57
|
+
return { statusCode: 500, statusText: 'Internal Server Error' };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* RFC-based connection for on-premise SAP systems.
|
|
61
|
+
*
|
|
62
|
+
* Uses node-rfc to call SADT_REST_RFC_ENDPOINT — the same standard SAP FM
|
|
63
|
+
* that Eclipse ADT uses for all on-premise ADT operations via JCo.
|
|
64
|
+
*
|
|
65
|
+
* RFC connections are inherently stateful: one ABAP session persists for the
|
|
66
|
+
* entire connection lifetime. This solves the HTTP 423 "invalid lock handle"
|
|
67
|
+
* problem on legacy systems (BASIS < 7.50) where HTTP stateful sessions
|
|
68
|
+
* are not supported.
|
|
69
|
+
*
|
|
70
|
+
* Connection parameters are derived from the standard ISapConfig.url field:
|
|
71
|
+
* http://saphost:8000 → ashost=saphost, sysnr=00
|
|
72
|
+
*
|
|
73
|
+
* Prerequisites:
|
|
74
|
+
* - SAP NW RFC SDK installed on the machine
|
|
75
|
+
* - node-rfc package installed: npm install node-rfc
|
|
76
|
+
*/
|
|
77
|
+
class RfcAbapConnection {
|
|
78
|
+
config;
|
|
79
|
+
logger;
|
|
80
|
+
rfcClient = null;
|
|
81
|
+
sessionId;
|
|
82
|
+
baseUrl;
|
|
83
|
+
rfcParams;
|
|
84
|
+
constructor(config, logger = null) {
|
|
85
|
+
this.config = config;
|
|
86
|
+
this.logger = logger;
|
|
87
|
+
RfcAbapConnection.validateConfig(config);
|
|
88
|
+
this.sessionId = (0, node_crypto_1.randomUUID)();
|
|
89
|
+
this.baseUrl = config.url;
|
|
90
|
+
this.rfcParams = buildRfcParams(config);
|
|
91
|
+
this.logger?.debug(`RfcAbapConnection created for ${this.rfcParams.ashost}:${this.rfcParams.sysnr}, client ${this.rfcParams.client}`);
|
|
92
|
+
}
|
|
93
|
+
async connect() {
|
|
94
|
+
let Client;
|
|
95
|
+
try {
|
|
96
|
+
// Dynamic require — node-rfc is NOT a declared dependency.
|
|
97
|
+
// Users who need RFC connections must install it manually:
|
|
98
|
+
// npm install node-rfc (+ SAP NW RFC SDK on the machine)
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
100
|
+
const noderfc = require('node-rfc');
|
|
101
|
+
Client = noderfc.Client;
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
throw new Error('node-rfc is not available. To use RFC connections, install SAP NW RFC SDK ' +
|
|
105
|
+
'and run: npm install node-rfc. ' +
|
|
106
|
+
`Details: ${e instanceof Error ? e.message : String(e)}`);
|
|
107
|
+
}
|
|
108
|
+
this.rfcClient = new Client(this.rfcParams);
|
|
109
|
+
try {
|
|
110
|
+
await this.rfcClient.open();
|
|
111
|
+
this.logger?.debug('RFC connection opened (stateful session)');
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
this.rfcClient = null;
|
|
115
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
116
|
+
this.logger?.error(`RFC connection failed: ${msg}`);
|
|
117
|
+
throw new Error(`Failed to open RFC connection: ${msg}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async getBaseUrl() {
|
|
121
|
+
return this.baseUrl;
|
|
122
|
+
}
|
|
123
|
+
getSessionId() {
|
|
124
|
+
return this.sessionId;
|
|
125
|
+
}
|
|
126
|
+
setSessionType(_type) {
|
|
127
|
+
// No-op — RFC connections are always stateful
|
|
128
|
+
}
|
|
129
|
+
async makeAdtRequest(options) {
|
|
130
|
+
if (!this.rfcClient?.alive) {
|
|
131
|
+
throw new Error('RFC connection is not open. Call connect() first.');
|
|
132
|
+
}
|
|
133
|
+
const method = options.method.toUpperCase();
|
|
134
|
+
const uri = options.url;
|
|
135
|
+
// Note: sap-client is NOT added to URI for RFC connections.
|
|
136
|
+
// The RFC session is already logged into the correct client
|
|
137
|
+
// (via the 'client' param in RFC connection). Adding sap-client
|
|
138
|
+
// to the URI can cause "object not found" on some systems.
|
|
139
|
+
// Build header fields
|
|
140
|
+
const headerFields = [];
|
|
141
|
+
if (options.headers) {
|
|
142
|
+
for (const [name, value] of Object.entries(options.headers)) {
|
|
143
|
+
headerFields.push({ NAME: name, VALUE: value });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Ensure Content-Type for body
|
|
147
|
+
const body = options.data !== undefined && options.data !== null
|
|
148
|
+
? String(options.data)
|
|
149
|
+
: '';
|
|
150
|
+
if (body &&
|
|
151
|
+
!headerFields.some((h) => h.NAME.toLowerCase() === 'content-type')) {
|
|
152
|
+
headerFields.push({
|
|
153
|
+
NAME: 'Content-Type',
|
|
154
|
+
VALUE: 'text/plain; charset=utf-8',
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
this.logger?.debug(`RFC → ${method} ${uri}`);
|
|
158
|
+
try {
|
|
159
|
+
const result = await this.rfcClient.call('SADT_REST_RFC_ENDPOINT', {
|
|
160
|
+
REQUEST: {
|
|
161
|
+
REQUEST_LINE: {
|
|
162
|
+
METHOD: method,
|
|
163
|
+
URI: uri,
|
|
164
|
+
VERSION: 'HTTP/1.1',
|
|
165
|
+
},
|
|
166
|
+
HEADER_FIELDS: headerFields,
|
|
167
|
+
MESSAGE_BODY: body ? Buffer.from(body, 'utf-8') : Buffer.alloc(0),
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
const resp = result.RESPONSE || result;
|
|
171
|
+
// Log raw RFC response structure for debugging
|
|
172
|
+
this.logger?.debug(`RFC raw response keys: ${Object.keys(resp).join(', ')}`);
|
|
173
|
+
if (resp.STATUS_LINE) {
|
|
174
|
+
this.logger?.debug(`RFC STATUS_LINE: ${JSON.stringify(resp.STATUS_LINE)}`);
|
|
175
|
+
}
|
|
176
|
+
// Parse status — RFC returns status in STATUS_LINE structure
|
|
177
|
+
// Field names: STATUS_CODE (not CODE), REASON_PHRASE (not REASON)
|
|
178
|
+
const rawCode = resp.STATUS_LINE?.STATUS_CODE || resp.STATUS_LINE?.CODE || 0;
|
|
179
|
+
let statusCode = typeof rawCode === 'string' ? Number.parseInt(rawCode, 10) : rawCode;
|
|
180
|
+
let statusText = resp.STATUS_LINE?.REASON_PHRASE || resp.STATUS_LINE?.REASON || '';
|
|
181
|
+
// Parse response body
|
|
182
|
+
const respBody = resp.MESSAGE_BODY
|
|
183
|
+
? Buffer.isBuffer(resp.MESSAGE_BODY)
|
|
184
|
+
? resp.MESSAGE_BODY.toString('utf-8')
|
|
185
|
+
: String(resp.MESSAGE_BODY)
|
|
186
|
+
: '';
|
|
187
|
+
// Parse response headers
|
|
188
|
+
const respHeaders = {};
|
|
189
|
+
const respHeaderFields = resp.HEADER_FIELDS || [];
|
|
190
|
+
for (const field of respHeaderFields) {
|
|
191
|
+
if (field.NAME && field.VALUE !== undefined) {
|
|
192
|
+
respHeaders[field.NAME.toLowerCase()] = field.VALUE;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// On some systems (e.g. BASIS < 7.50), SADT_REST_RFC_ENDPOINT does not
|
|
196
|
+
// populate STATUS_LINE, returning status 0. Detect errors from the
|
|
197
|
+
// response body: ADT exception XML indicates a failed request.
|
|
198
|
+
if (!statusCode && respBody.includes('<exc:exception')) {
|
|
199
|
+
const detected = detectExceptionStatus(respBody);
|
|
200
|
+
statusCode = detected.statusCode;
|
|
201
|
+
statusText = detected.statusText;
|
|
202
|
+
this.logger?.debug(`RFC: STATUS_LINE empty, detected ${statusCode} from exception XML`);
|
|
203
|
+
}
|
|
204
|
+
// Default to 200 OK only when no error was detected
|
|
205
|
+
if (!statusCode) {
|
|
206
|
+
statusCode = 200;
|
|
207
|
+
statusText = statusText || 'OK';
|
|
208
|
+
}
|
|
209
|
+
this.logger?.debug(`RFC ← ${statusCode} ${statusText} (${respBody.length} bytes)`);
|
|
210
|
+
const response = {
|
|
211
|
+
data: respBody,
|
|
212
|
+
status: statusCode,
|
|
213
|
+
statusText,
|
|
214
|
+
headers: respHeaders,
|
|
215
|
+
};
|
|
216
|
+
// Throw for error status codes (matching HTTP/axios behavior)
|
|
217
|
+
if (statusCode >= 400) {
|
|
218
|
+
const error = new Error(`Request failed with status ${statusCode}: ${method} ${uri}`);
|
|
219
|
+
error.response = response;
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
return response;
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
// Re-throw our own errors (status >= 400)
|
|
226
|
+
if (e?.response) {
|
|
227
|
+
throw e;
|
|
228
|
+
}
|
|
229
|
+
// RFC-level error
|
|
230
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
231
|
+
this.logger?.error(`RFC call failed: ${msg}`);
|
|
232
|
+
throw new Error(`RFC call to SADT_REST_RFC_ENDPOINT failed: ${msg}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Close the RFC connection and release the ABAP session.
|
|
237
|
+
*/
|
|
238
|
+
async close() {
|
|
239
|
+
if (this.rfcClient) {
|
|
240
|
+
try {
|
|
241
|
+
await this.rfcClient.close();
|
|
242
|
+
this.logger?.debug('RFC connection closed');
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
this.logger?.debug(`RFC close error: ${e instanceof Error ? e.message : String(e)}`);
|
|
246
|
+
}
|
|
247
|
+
this.rfcClient = null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
static validateConfig(config) {
|
|
251
|
+
if (config.authType !== 'rfc') {
|
|
252
|
+
throw new Error(`RFC connection expects authType "rfc", got "${config.authType}"`);
|
|
253
|
+
}
|
|
254
|
+
if (!config.url) {
|
|
255
|
+
throw new Error('RFC connection requires url (hostname is parsed from it)');
|
|
256
|
+
}
|
|
257
|
+
if (!config.username || !config.password) {
|
|
258
|
+
throw new Error('RFC connection requires both username and password');
|
|
259
|
+
}
|
|
260
|
+
if (!config.client) {
|
|
261
|
+
throw new Error('RFC connection requires SAP client');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
exports.RfcAbapConnection = RfcAbapConnection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAM1D,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,eAAe,EAChC,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACtC,cAAc,CAehB"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createAbapConnection = createAbapConnection;
|
|
4
4
|
const BaseAbapConnection_js_1 = require("./BaseAbapConnection.js");
|
|
5
5
|
const JwtAbapConnection_js_1 = require("./JwtAbapConnection.js");
|
|
6
|
+
const RfcAbapConnection_js_1 = require("./RfcAbapConnection.js");
|
|
6
7
|
const SamlAbapConnection_js_1 = require("./SamlAbapConnection.js");
|
|
7
8
|
function createAbapConnection(config, logger, sessionId, tokenRefresher, options) {
|
|
8
9
|
switch (config.authType) {
|
|
@@ -12,6 +13,8 @@ function createAbapConnection(config, logger, sessionId, tokenRefresher, options
|
|
|
12
13
|
return new JwtAbapConnection_js_1.JwtAbapConnection(config, logger, sessionId, tokenRefresher);
|
|
13
14
|
case 'saml':
|
|
14
15
|
return new SamlAbapConnection_js_1.SamlAbapConnection(config, logger, sessionId, options);
|
|
16
|
+
case 'rfc':
|
|
17
|
+
return new RfcAbapConnection_js_1.RfcAbapConnection(config, logger);
|
|
15
18
|
default:
|
|
16
19
|
throw new Error(`Unsupported SAP authentication type: ${config.authType}`);
|
|
17
20
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { createAbapConnection } from './connection/connectionFactory.js';
|
|
|
7
7
|
export { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from './connection/csrfConfig.js';
|
|
8
8
|
export { GenericWebSocketTransport, type IWebSocketFactory, type IWebSocketLike, } from './connection/GenericWebSocketTransport.js';
|
|
9
9
|
export { JwtAbapConnection, JwtAbapConnection as CloudAbapConnection, } from './connection/JwtAbapConnection.js';
|
|
10
|
+
export { RfcAbapConnection } from './connection/RfcAbapConnection.js';
|
|
10
11
|
export { SamlAbapConnection } from './connection/SamlAbapConnection.js';
|
|
11
12
|
export type { ILogger } from './logger.js';
|
|
12
13
|
export { getTimeout, getTimeoutConfig, type TimeoutConfig, } from './utils/timeouts.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,WAAW,EACX,SAAS,GACV,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,YAAY,EACV,cAAc,EACd,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,IAAI,oBAAoB,GAC3C,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,mBAAmB,GACzC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,WAAW,EACX,SAAS,GACV,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,YAAY,EACV,cAAc,EACd,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,IAAI,oBAAoB,GAC3C,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,mBAAmB,GACzC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Types - re-exported from interfaces package with backward compatibility aliases
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.getTimeoutConfig = exports.getTimeout = exports.SamlAbapConnection = exports.CloudAbapConnection = exports.JwtAbapConnection = exports.GenericWebSocketTransport = exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.createAbapConnection = exports.OnPremAbapConnection = exports.BaseAbapConnection = exports.sapConfigSignature = void 0;
|
|
4
|
+
exports.getTimeoutConfig = exports.getTimeout = exports.SamlAbapConnection = exports.RfcAbapConnection = exports.CloudAbapConnection = exports.JwtAbapConnection = exports.GenericWebSocketTransport = exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.createAbapConnection = exports.OnPremAbapConnection = exports.BaseAbapConnection = exports.sapConfigSignature = void 0;
|
|
5
5
|
// Config utilities
|
|
6
6
|
var sapConfig_js_1 = require("./config/sapConfig.js");
|
|
7
7
|
Object.defineProperty(exports, "sapConfigSignature", { enumerable: true, get: function () { return sapConfig_js_1.sapConfigSignature; } });
|
|
@@ -22,6 +22,8 @@ Object.defineProperty(exports, "GenericWebSocketTransport", { enumerable: true,
|
|
|
22
22
|
var JwtAbapConnection_js_1 = require("./connection/JwtAbapConnection.js");
|
|
23
23
|
Object.defineProperty(exports, "JwtAbapConnection", { enumerable: true, get: function () { return JwtAbapConnection_js_1.JwtAbapConnection; } });
|
|
24
24
|
Object.defineProperty(exports, "CloudAbapConnection", { enumerable: true, get: function () { return JwtAbapConnection_js_1.JwtAbapConnection; } });
|
|
25
|
+
var RfcAbapConnection_js_1 = require("./connection/RfcAbapConnection.js");
|
|
26
|
+
Object.defineProperty(exports, "RfcAbapConnection", { enumerable: true, get: function () { return RfcAbapConnection_js_1.RfcAbapConnection; } });
|
|
25
27
|
var SamlAbapConnection_js_1 = require("./connection/SamlAbapConnection.js");
|
|
26
28
|
Object.defineProperty(exports, "SamlAbapConnection", { enumerable: true, get: function () { return SamlAbapConnection_js_1.SamlAbapConnection; } });
|
|
27
29
|
// Timeouts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/connection",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "ABAP connection layer for MCP ABAP ADT server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@mcp-abap-adt/interfaces": "^2.
|
|
49
|
+
"@mcp-abap-adt/interfaces": "^2.7.0",
|
|
50
50
|
"axios": "^1.13.5",
|
|
51
51
|
"commander": "^14.0.3",
|
|
52
52
|
"express": "^5.1.0",
|