@mcp-abap-adt/connection 1.8.0 → 1.9.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/dist/auth/FileCertificateMaterialLoader.d.ts +5 -0
- package/dist/auth/FileCertificateMaterialLoader.d.ts.map +1 -0
- package/dist/auth/FileCertificateMaterialLoader.js +28 -0
- package/dist/auth/kerberosSpnego.d.ts +3 -0
- package/dist/auth/kerberosSpnego.d.ts.map +1 -0
- package/dist/auth/kerberosSpnego.js +56 -0
- package/dist/config/sapConfig.d.ts.map +1 -1
- package/dist/config/sapConfig.js +5 -0
- package/dist/connection/AbstractAbapConnection.d.ts +13 -0
- package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.js +60 -11
- package/dist/connection/CertificateAbapConnection.d.ts +21 -0
- package/dist/connection/CertificateAbapConnection.d.ts.map +1 -0
- package/dist/connection/CertificateAbapConnection.js +69 -0
- package/dist/connection/KerberosAbapConnection.d.ts +20 -0
- package/dist/connection/KerberosAbapConnection.d.ts.map +1 -0
- package/dist/connection/KerberosAbapConnection.js +63 -0
- package/dist/connection/connectionFactory.d.ts +2 -1
- package/dist/connection/connectionFactory.d.ts.map +1 -1
- package/dist/connection/connectionFactory.js +9 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/package.json +4 -3
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ICertificateMaterial, ICertificateMaterialLoader, ISapConfig } from '@mcp-abap-adt/interfaces';
|
|
2
|
+
export declare class FileCertificateMaterialLoader implements ICertificateMaterialLoader {
|
|
3
|
+
load(config: ISapConfig): Promise<ICertificateMaterial>;
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=FileCertificateMaterialLoader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileCertificateMaterialLoader.d.ts","sourceRoot":"","sources":["../../src/auth/FileCertificateMaterialLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,UAAU,EACX,MAAM,0BAA0B,CAAC;AAElC,qBAAa,6BACX,YAAW,0BAA0B;IAE/B,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAyB9D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileCertificateMaterialLoader = void 0;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
class FileCertificateMaterialLoader {
|
|
6
|
+
async load(config) {
|
|
7
|
+
const hasPem = !!(config.certPath || config.certKeyPath); // any PEM-style field present
|
|
8
|
+
const hasPfx = !!config.certPfxPath;
|
|
9
|
+
if (hasPem && hasPfx) {
|
|
10
|
+
throw new Error('Certificate auth: provide either PEM (certPath+certKeyPath) OR certPfxPath, not both.');
|
|
11
|
+
}
|
|
12
|
+
if (hasPfx) {
|
|
13
|
+
return {
|
|
14
|
+
pfx: await (0, promises_1.readFile)(config.certPfxPath),
|
|
15
|
+
passphrase: config.certPassphrase,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (config.certPath && config.certKeyPath) {
|
|
19
|
+
return {
|
|
20
|
+
cert: await (0, promises_1.readFile)(config.certPath),
|
|
21
|
+
key: await (0, promises_1.readFile)(config.certKeyPath),
|
|
22
|
+
passphrase: config.certPassphrase,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
throw new Error('Certificate auth requires certPfxPath OR (certPath AND certKeyPath).');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.FileCertificateMaterialLoader = FileCertificateMaterialLoader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kerberosSpnego.d.ts","sourceRoot":"","sources":["../../src/auth/kerberosSpnego.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBtE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateSpnegoToken = generateSpnegoToken;
|
|
37
|
+
/** Thin, lazily-loaded wrapper over the optional `kerberos` native package. */
|
|
38
|
+
async function generateSpnegoToken(spn) {
|
|
39
|
+
// optional peer dep; typed as any because the module/types may be absent
|
|
40
|
+
let kerberos;
|
|
41
|
+
try {
|
|
42
|
+
// @ts-expect-error optional peer dependency — module may be absent at build time (TS2307)
|
|
43
|
+
kerberos = await Promise.resolve().then(() => __importStar(require('kerberos')));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error('Kerberos authentication requires the optional "kerberos" package. ' +
|
|
47
|
+
'Install it (needs GSSAPI dev libs on Linux / build tools on Windows): npm i kerberos');
|
|
48
|
+
}
|
|
49
|
+
const client = await kerberos.initializeClient(spn, {});
|
|
50
|
+
await client.step('');
|
|
51
|
+
const token = client.response;
|
|
52
|
+
if (!token) {
|
|
53
|
+
throw new Error('Kerberos: no SPNEGO token produced (no TGT? run kinit, or check SPN).');
|
|
54
|
+
}
|
|
55
|
+
return token;
|
|
56
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sapConfig.d.ts","sourceRoot":"","sources":["../../src/config/sapConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;AAC/C,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AAEnC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"sapConfig.d.ts","sourceRoot":"","sources":["../../src/config/sapConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;AAC/C,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC;AAEnC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA4B7D"}
|
package/dist/config/sapConfig.js
CHANGED
|
@@ -22,5 +22,10 @@ function sapConfigSignature(config) {
|
|
|
22
22
|
jwtToken: jwtTokenPreview,
|
|
23
23
|
refreshToken: refreshTokenPreview,
|
|
24
24
|
sessionCookies: sessionCookiesPreview,
|
|
25
|
+
certPath: config.certPath ?? null,
|
|
26
|
+
certKeyPath: config.certKeyPath ?? null,
|
|
27
|
+
certPfxPath: config.certPfxPath ?? null,
|
|
28
|
+
certPassphrase: config.certPassphrase ? 'set' : null,
|
|
29
|
+
kerberosSpn: config.kerberosSpn ?? null,
|
|
25
30
|
});
|
|
26
31
|
}
|
|
@@ -81,8 +81,21 @@ declare abstract class AbstractAbapConnection implements AbapConnection {
|
|
|
81
81
|
protected getCookies(): string | null;
|
|
82
82
|
protected setInitialCookies(cookies: string): void;
|
|
83
83
|
private updateCookiesFromResponse;
|
|
84
|
+
/**
|
|
85
|
+
* Subclasses override to inject extra https.Agent options (e.g. mTLS cert/key/pfx).
|
|
86
|
+
* The returned options are merged with the base options (rejectUnauthorized).
|
|
87
|
+
*/
|
|
88
|
+
protected getHttpsAgentOptions(): import('node:https').AgentOptions;
|
|
84
89
|
private getAxiosInstance;
|
|
85
90
|
private ensureFreshCsrfToken;
|
|
91
|
+
/**
|
|
92
|
+
* Clear SAP-side session state when SAP rejects the cached CSRF token + session
|
|
93
|
+
* cookies (HTTP 401 on a mutation while a cached token exists). This forces the
|
|
94
|
+
* next request path to fetch a fresh token and a fresh SAP_SESSIONID cookie.
|
|
95
|
+
*
|
|
96
|
+
* Distinct from reset(): this leaves the axios instance and interceptors in place.
|
|
97
|
+
*/
|
|
98
|
+
private invalidateSession;
|
|
86
99
|
private shouldRetryCsrf;
|
|
87
100
|
}
|
|
88
101
|
export { AbstractAbapConnection };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,0BAA0B,CAAC;AAM7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,uBAAe,sBAAuB,YAAW,cAAc;IAW3D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAX3C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,eAAe,CAAU;IAEjC,SAAS,aACU,MAAM,EAAE,SAAS,EACf,MAAM,EAAE,OAAO,GAAG,IAAI,EACzC,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE;IAqBzC;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAUpD;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,UAAU;IAI1C;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,SAAS,IAAI,SAAS;IAItB,KAAK,IAAI,IAAI;IAYP,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,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,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,EACnC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,0BAA0B,CAAC;AAM7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9E,uBAAe,sBAAuB,YAAW,cAAc;IAW3D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAX3C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,eAAe,CAAU;IAEjC,SAAS,aACU,MAAM,EAAE,SAAS,EACf,MAAM,EAAE,OAAO,GAAG,IAAI,EACzC,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE;IAqBzC;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAUpD;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,UAAU;IAI1C;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKrC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B,SAAS,IAAI,SAAS;IAItB,KAAK,IAAI,IAAI;IAYP,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,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,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,EACnC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IA+R9B,SAAS,CAAC,QAAQ,CAAC,wBAAwB,IAAI,MAAM;IAErD;;;OAGG;cACa,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAAgC,EAC5C,UAAU,GAAE,MAAgC,GAC3C,OAAO,CAAC,MAAM,CAAC;IA2ClB;;OAEG;YACW,0BAA0B;IAsKxC;;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,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlD,OAAO,CAAC,yBAAyB;IAkEjC;;;OAGG;IACH,SAAS,CAAC,oBAAoB,IAAI,OAAO,YAAY,EAAE,YAAY;IAInE,OAAO,CAAC,gBAAgB;YAsBV,oBAAoB;IAiClC;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;CA+BxB;AAGD,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -263,22 +263,51 @@ class AbstractAbapConnection {
|
|
|
263
263
|
else {
|
|
264
264
|
this.logger?.error(errorDetails.message, errorDetails);
|
|
265
265
|
}
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
266
|
+
// Detect the "login-form 401" pattern: SAP returned 401 for a mutation while
|
|
267
|
+
// we have a cached CSRF token. The token and its bound SAP session must be
|
|
268
|
+
// discarded before the retry. Basic auth only — JWT/SAML lifecycles are
|
|
269
|
+
// managed elsewhere.
|
|
270
|
+
const isCachedTokenStale = error instanceof axios_1.AxiosError &&
|
|
271
|
+
this.config.authType === 'basic' &&
|
|
272
|
+
(normalizedMethod === 'POST' ||
|
|
273
|
+
normalizedMethod === 'PUT' ||
|
|
274
|
+
normalizedMethod === 'DELETE') &&
|
|
275
|
+
error.response?.status === 401 &&
|
|
276
|
+
this.getCsrfToken() !== null;
|
|
277
|
+
// Retry logic for CSRF token errors (403 with CSRF message) and the
|
|
278
|
+
// login-form 401 pattern.
|
|
279
|
+
if (this.shouldRetryCsrf(error) || isCachedTokenStale) {
|
|
280
|
+
this.logger?.debug(isCachedTokenStale
|
|
281
|
+
? 'Stale CSRF token / SAP session — invalidating and retrying'
|
|
282
|
+
: 'CSRF token validation failed, fetching new token and retrying request', {
|
|
269
283
|
url: requestUrl,
|
|
270
284
|
method: normalizedMethod,
|
|
271
285
|
});
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
requestHeaders
|
|
286
|
+
if (isCachedTokenStale) {
|
|
287
|
+
this.invalidateSession();
|
|
288
|
+
delete requestHeaders.Cookie;
|
|
289
|
+
delete requestHeaders.cookie;
|
|
275
290
|
}
|
|
276
|
-
|
|
277
|
-
|
|
291
|
+
try {
|
|
292
|
+
this.setCsrfToken(await this.fetchCsrfToken(requestUrl, 5, 2000));
|
|
293
|
+
const refreshedToken = this.getCsrfToken();
|
|
294
|
+
if (refreshedToken) {
|
|
295
|
+
requestHeaders['x-csrf-token'] = refreshedToken;
|
|
296
|
+
}
|
|
297
|
+
const refreshedCookies = this.getCookies();
|
|
298
|
+
if (refreshedCookies) {
|
|
299
|
+
requestHeaders.Cookie = refreshedCookies;
|
|
300
|
+
}
|
|
301
|
+
const retryResponse = await this.getAxiosInstance()(requestConfig);
|
|
302
|
+
this.updateCookiesFromResponse(retryResponse.headers);
|
|
303
|
+
return retryResponse;
|
|
304
|
+
}
|
|
305
|
+
catch (retryError) {
|
|
306
|
+
this.logger?.debug(`CSRF retry failed; rethrowing original error: ${retryError instanceof Error
|
|
307
|
+
? retryError.message
|
|
308
|
+
: String(retryError)}`);
|
|
309
|
+
throw error;
|
|
278
310
|
}
|
|
279
|
-
const retryResponse = await this.getAxiosInstance()(requestConfig);
|
|
280
|
-
this.updateCookiesFromResponse(retryResponse.headers);
|
|
281
|
-
return retryResponse;
|
|
282
311
|
}
|
|
283
312
|
// Retry logic for 401 errors on GET requests (authentication issue - need cookies)
|
|
284
313
|
// Only for basic auth - JWT auth will be handled by refresh logic below
|
|
@@ -548,6 +577,13 @@ class AbstractAbapConnection {
|
|
|
548
577
|
this.cookies = combined;
|
|
549
578
|
this.logger?.debug(`[DEBUG] BaseAbapConnection - Updated cookies from response (first 100 chars): ${this.cookies.substring(0, 100)}...`);
|
|
550
579
|
}
|
|
580
|
+
/**
|
|
581
|
+
* Subclasses override to inject extra https.Agent options (e.g. mTLS cert/key/pfx).
|
|
582
|
+
* The returned options are merged with the base options (rejectUnauthorized).
|
|
583
|
+
*/
|
|
584
|
+
getHttpsAgentOptions() {
|
|
585
|
+
return {};
|
|
586
|
+
}
|
|
551
587
|
getAxiosInstance() {
|
|
552
588
|
if (!this.axiosInstance) {
|
|
553
589
|
const rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '1' ||
|
|
@@ -557,6 +593,7 @@ class AbstractAbapConnection {
|
|
|
557
593
|
this.axiosInstance = axios_1.default.create({
|
|
558
594
|
httpsAgent: new node_https_1.Agent({
|
|
559
595
|
rejectUnauthorized,
|
|
596
|
+
...this.getHttpsAgentOptions(),
|
|
560
597
|
}),
|
|
561
598
|
});
|
|
562
599
|
}
|
|
@@ -585,6 +622,18 @@ class AbstractAbapConnection {
|
|
|
585
622
|
throw error;
|
|
586
623
|
}
|
|
587
624
|
}
|
|
625
|
+
/**
|
|
626
|
+
* Clear SAP-side session state when SAP rejects the cached CSRF token + session
|
|
627
|
+
* cookies (HTTP 401 on a mutation while a cached token exists). This forces the
|
|
628
|
+
* next request path to fetch a fresh token and a fresh SAP_SESSIONID cookie.
|
|
629
|
+
*
|
|
630
|
+
* Distinct from reset(): this leaves the axios instance and interceptors in place.
|
|
631
|
+
*/
|
|
632
|
+
invalidateSession() {
|
|
633
|
+
this.setCsrfToken(null);
|
|
634
|
+
this.cookies = null;
|
|
635
|
+
this.cookieStore.clear();
|
|
636
|
+
}
|
|
588
637
|
shouldRetryCsrf(error) {
|
|
589
638
|
if (!(error instanceof axios_1.AxiosError)) {
|
|
590
639
|
return false;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentOptions } from 'node:https';
|
|
2
|
+
import type { ICertificateMaterialLoader } from '@mcp-abap-adt/interfaces';
|
|
3
|
+
import type { SapConfig } from '../config/sapConfig.js';
|
|
4
|
+
import type { ILogger } from '../logger.js';
|
|
5
|
+
import { AbstractAbapConnection } from './AbstractAbapConnection.js';
|
|
6
|
+
/** Client-certificate (mTLS) authentication. Credential lives on the TLS agent. */
|
|
7
|
+
export declare class CertificateAbapConnection extends AbstractAbapConnection {
|
|
8
|
+
private loader;
|
|
9
|
+
private material;
|
|
10
|
+
constructor(config: SapConfig, logger?: ILogger | null, sessionId?: string, loader?: ICertificateMaterialLoader);
|
|
11
|
+
private static validateConfig;
|
|
12
|
+
protected ensureMaterial(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Loads certificate material and primes the session. MUST be called before the first
|
|
15
|
+
* request — the TLS agent is built lazily and needs the client cert present.
|
|
16
|
+
*/
|
|
17
|
+
connect(): Promise<void>;
|
|
18
|
+
protected getHttpsAgentOptions(): AgentOptions;
|
|
19
|
+
protected buildAuthorizationHeader(): string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=CertificateAbapConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CertificateAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/CertificateAbapConnection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAEV,0BAA0B,EAC3B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,mFAAmF;AACnF,qBAAa,yBAA0B,SAAQ,sBAAsB;IACnE,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAqC;gBAGnD,MAAM,EAAE,SAAS,EACjB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,0BAA0B;IAOrC,OAAO,CAAC,MAAM,CAAC,cAAc;cAyBb,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/C;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB9B,SAAS,CAAC,oBAAoB,IAAI,YAAY;IAU9C,SAAS,CAAC,wBAAwB,IAAI,MAAM;CAG7C"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CertificateAbapConnection = void 0;
|
|
4
|
+
const axios_1 = require("axios");
|
|
5
|
+
const FileCertificateMaterialLoader_js_1 = require("../auth/FileCertificateMaterialLoader.js");
|
|
6
|
+
const AbstractAbapConnection_js_1 = require("./AbstractAbapConnection.js");
|
|
7
|
+
/** Client-certificate (mTLS) authentication. Credential lives on the TLS agent. */
|
|
8
|
+
class CertificateAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnection {
|
|
9
|
+
loader;
|
|
10
|
+
material = null;
|
|
11
|
+
constructor(config, logger, sessionId, loader) {
|
|
12
|
+
CertificateAbapConnection.validateConfig(config);
|
|
13
|
+
super(config, logger || null, sessionId);
|
|
14
|
+
this.loader = loader ?? new FileCertificateMaterialLoader_js_1.FileCertificateMaterialLoader();
|
|
15
|
+
}
|
|
16
|
+
static validateConfig(config) {
|
|
17
|
+
if (config.authType !== 'certificate') {
|
|
18
|
+
throw new Error(`Certificate connection expects authType "certificate", got "${config.authType}"`);
|
|
19
|
+
}
|
|
20
|
+
if (config.connectionType === 'rfc') {
|
|
21
|
+
throw new Error('Certificate auth is not supported with connectionType "rfc".');
|
|
22
|
+
}
|
|
23
|
+
const hasPem = !!(config.certPath && config.certKeyPath); // complete PEM pair present
|
|
24
|
+
const hasPfx = !!config.certPfxPath;
|
|
25
|
+
if (!hasPem && !hasPfx) {
|
|
26
|
+
throw new Error('Certificate auth requires certPfxPath OR (certPath AND certKeyPath).');
|
|
27
|
+
}
|
|
28
|
+
if ((config.certPath || config.certKeyPath) && config.certPfxPath) {
|
|
29
|
+
throw new Error('Certificate auth: provide either PEM pair OR PFX, not both.');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async ensureMaterial() {
|
|
33
|
+
if (!this.material) {
|
|
34
|
+
this.material = await this.loader.load(this.getConfig());
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Loads certificate material and primes the session. MUST be called before the first
|
|
39
|
+
* request — the TLS agent is built lazily and needs the client cert present.
|
|
40
|
+
*/
|
|
41
|
+
async connect() {
|
|
42
|
+
await this.ensureMaterial();
|
|
43
|
+
const baseUrl = await this.getBaseUrl();
|
|
44
|
+
const discoveryUrl = `${baseUrl}/sap/bc/adt/discovery`;
|
|
45
|
+
try {
|
|
46
|
+
const token = await this.fetchCsrfToken(discoveryUrl, 3, 1000);
|
|
47
|
+
this.setCsrfToken(token);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.logger?.warn(`[WARN] CertificateAbapConnection - connect deferred: ${error instanceof Error ? error.message : String(error)}`);
|
|
51
|
+
if (error instanceof axios_1.AxiosError && error.response?.headers) {
|
|
52
|
+
if (this.getCookies()) {
|
|
53
|
+
this.logger?.debug(`[DEBUG] CertificateAbapConnection - Cookies extracted from error response during connect (first 100 chars): ${this.getCookies()?.substring(0, 100)}...`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
getHttpsAgentOptions() {
|
|
59
|
+
if (!this.material) {
|
|
60
|
+
throw new Error('CertificateAbapConnection: certificate material not loaded. Call connect() before making requests.');
|
|
61
|
+
}
|
|
62
|
+
const { cert, key, pfx, passphrase } = this.material;
|
|
63
|
+
return { cert, key, pfx, passphrase };
|
|
64
|
+
}
|
|
65
|
+
buildAuthorizationHeader() {
|
|
66
|
+
return '';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.CertificateAbapConnection = CertificateAbapConnection;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SapConfig } from '../config/sapConfig.js';
|
|
2
|
+
import type { ILogger } from '../logger.js';
|
|
3
|
+
import { AbstractAbapConnection } from './AbstractAbapConnection.js';
|
|
4
|
+
/** Kerberos / SPNEGO single-leg auth: send Negotiate token, reuse the resulting SAP session cookie. */
|
|
5
|
+
export declare class KerberosAbapConnection extends AbstractAbapConnection {
|
|
6
|
+
private spn;
|
|
7
|
+
private currentToken;
|
|
8
|
+
constructor(config: SapConfig, logger?: ILogger | null, sessionId?: string);
|
|
9
|
+
private static validateConfig;
|
|
10
|
+
/** Generate the SPNEGO token once (single-leg). */
|
|
11
|
+
protected ensureToken(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Generates the SPNEGO token and primes the session. MUST be called before the first
|
|
14
|
+
* request — the first request carries the Negotiate header; SAP then issues a session
|
|
15
|
+
* cookie which is reused for subsequent requests.
|
|
16
|
+
*/
|
|
17
|
+
connect(): Promise<void>;
|
|
18
|
+
protected buildAuthorizationHeader(): string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=KerberosAbapConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KerberosAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/KerberosAbapConnection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,uGAAuG;AACvG,qBAAa,sBAAuB,SAAQ,sBAAsB;IAChE,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAAM;gBAEd,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM;IAQ1E,OAAO,CAAC,MAAM,CAAC,cAAc;IAa7B,mDAAmD;cACnC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5C;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B9B,SAAS,CAAC,wBAAwB,IAAI,MAAM;CAS7C"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KerberosAbapConnection = void 0;
|
|
4
|
+
const axios_1 = require("axios");
|
|
5
|
+
const kerberosSpnego_js_1 = require("../auth/kerberosSpnego.js");
|
|
6
|
+
const AbstractAbapConnection_js_1 = require("./AbstractAbapConnection.js");
|
|
7
|
+
/** Kerberos / SPNEGO single-leg auth: send Negotiate token, reuse the resulting SAP session cookie. */
|
|
8
|
+
class KerberosAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnection {
|
|
9
|
+
spn;
|
|
10
|
+
currentToken = '';
|
|
11
|
+
constructor(config, logger, sessionId) {
|
|
12
|
+
KerberosAbapConnection.validateConfig(config);
|
|
13
|
+
super(config, logger || null, sessionId);
|
|
14
|
+
this.spn =
|
|
15
|
+
config.kerberosSpn ??
|
|
16
|
+
`${config.kerberosService ?? 'HTTP'}@${new URL(config.url).hostname}`;
|
|
17
|
+
}
|
|
18
|
+
static validateConfig(config) {
|
|
19
|
+
if (config.authType !== 'kerberos') {
|
|
20
|
+
throw new Error(`Kerberos connection expects authType "kerberos", got "${config.authType}"`);
|
|
21
|
+
}
|
|
22
|
+
if (config.connectionType === 'rfc') {
|
|
23
|
+
throw new Error('Kerberos auth is not supported with connectionType "rfc".');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Generate the SPNEGO token once (single-leg). */
|
|
27
|
+
async ensureToken() {
|
|
28
|
+
if (!this.currentToken)
|
|
29
|
+
this.currentToken = await (0, kerberosSpnego_js_1.generateSpnegoToken)(this.spn);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generates the SPNEGO token and primes the session. MUST be called before the first
|
|
33
|
+
* request — the first request carries the Negotiate header; SAP then issues a session
|
|
34
|
+
* cookie which is reused for subsequent requests.
|
|
35
|
+
*/
|
|
36
|
+
async connect() {
|
|
37
|
+
await this.ensureToken();
|
|
38
|
+
const baseUrl = await this.getBaseUrl();
|
|
39
|
+
const discoveryUrl = `${baseUrl}/sap/bc/adt/discovery`;
|
|
40
|
+
this.logger?.debug(`[DEBUG] KerberosAbapConnection - Connecting to SAP system: ${discoveryUrl}`);
|
|
41
|
+
try {
|
|
42
|
+
const token = await this.fetchCsrfToken(discoveryUrl, 3, 1000);
|
|
43
|
+
this.setCsrfToken(token);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
this.logger?.warn(`[WARN] KerberosAbapConnection - connect deferred: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
+
if (error instanceof axios_1.AxiosError &&
|
|
48
|
+
error.response?.headers &&
|
|
49
|
+
this.getCookies()) {
|
|
50
|
+
this.logger?.debug('[DEBUG] KerberosAbapConnection - cookies captured from error response during connect');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
buildAuthorizationHeader() {
|
|
55
|
+
if (this.getCookies())
|
|
56
|
+
return ''; // cookie carries auth after first round-trip
|
|
57
|
+
if (!this.currentToken) {
|
|
58
|
+
throw new Error('KerberosAbapConnection: SPNEGO token not yet available. Call connect() before making requests.');
|
|
59
|
+
}
|
|
60
|
+
return `Negotiate ${this.currentToken}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.KerberosAbapConnection = KerberosAbapConnection;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ITokenRefresher } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import type { ICertificateMaterialLoader, ITokenRefresher } from '@mcp-abap-adt/interfaces';
|
|
2
2
|
import type { SapConfig } from '../config/sapConfig.js';
|
|
3
3
|
import type { ILogger } from '../logger.js';
|
|
4
4
|
import type { AbapConnection } from './AbapConnection.js';
|
|
5
5
|
export declare function createAbapConnection(config: SapConfig, logger?: ILogger | null, sessionId?: string, tokenRefresher?: ITokenRefresher, options?: {
|
|
6
6
|
skipSessionType?: boolean;
|
|
7
|
+
certLoader?: ICertificateMaterialLoader;
|
|
7
8
|
}): AbapConnection;
|
|
8
9
|
//# sourceMappingURL=connectionFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"connectionFactory.d.ts","sourceRoot":"","sources":["../../src/connection/connectionFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,eAAe,EAChB,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;AAQ1D,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;IACR,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,0BAA0B,CAAC;CACzC,GACA,cAAc,CAgChB"}
|
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAbapConnection = createAbapConnection;
|
|
4
4
|
const BaseAbapConnection_js_1 = require("./BaseAbapConnection.js");
|
|
5
|
+
const CertificateAbapConnection_js_1 = require("./CertificateAbapConnection.js");
|
|
5
6
|
const JwtAbapConnection_js_1 = require("./JwtAbapConnection.js");
|
|
7
|
+
const KerberosAbapConnection_js_1 = require("./KerberosAbapConnection.js");
|
|
6
8
|
const RfcAbapConnection_js_1 = require("./RfcAbapConnection.js");
|
|
7
9
|
const SamlAbapConnection_js_1 = require("./SamlAbapConnection.js");
|
|
8
10
|
function createAbapConnection(config, logger, sessionId, tokenRefresher, options) {
|
|
9
11
|
// RFC connection type takes priority over auth type
|
|
10
12
|
if (config.connectionType === 'rfc') {
|
|
13
|
+
if (config.authType === 'certificate' || config.authType === 'kerberos') {
|
|
14
|
+
throw new Error(`authType "${config.authType}" is not supported with connectionType "rfc".`);
|
|
15
|
+
}
|
|
11
16
|
return new RfcAbapConnection_js_1.RfcAbapConnection(config, logger);
|
|
12
17
|
}
|
|
13
18
|
switch (config.authType) {
|
|
@@ -17,6 +22,10 @@ function createAbapConnection(config, logger, sessionId, tokenRefresher, options
|
|
|
17
22
|
return new JwtAbapConnection_js_1.JwtAbapConnection(config, logger, sessionId, tokenRefresher);
|
|
18
23
|
case 'saml':
|
|
19
24
|
return new SamlAbapConnection_js_1.SamlAbapConnection(config, logger, sessionId, options);
|
|
25
|
+
case 'certificate':
|
|
26
|
+
return new CertificateAbapConnection_js_1.CertificateAbapConnection(config, logger, sessionId, options?.certLoader);
|
|
27
|
+
case 'kerberos':
|
|
28
|
+
return new KerberosAbapConnection_js_1.KerberosAbapConnection(config, logger, sessionId);
|
|
20
29
|
default:
|
|
21
30
|
throw new Error(`Unsupported SAP authentication type: ${config.authType}`);
|
|
22
31
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
export type { IWebSocketCloseInfo, IWebSocketConnectOptions, IWebSocketMessageEnvelope, IWebSocketMessageHandler, IWebSocketTransport, } from '@mcp-abap-adt/interfaces';
|
|
2
|
+
export { FileCertificateMaterialLoader } from './auth/FileCertificateMaterialLoader.js';
|
|
2
3
|
export type { SapAuthType, SapConfig, SapConnectionType, } from './config/sapConfig.js';
|
|
3
4
|
export { sapConfigSignature } from './config/sapConfig.js';
|
|
4
5
|
export type { AbapConnection, AbapRequestOptions, } from './connection/AbapConnection.js';
|
|
5
6
|
export { BaseAbapConnection, BaseAbapConnection as OnPremAbapConnection, } from './connection/BaseAbapConnection.js';
|
|
7
|
+
export { CertificateAbapConnection } from './connection/CertificateAbapConnection.js';
|
|
6
8
|
export { createAbapConnection } from './connection/connectionFactory.js';
|
|
7
9
|
export { CSRF_CONFIG, CSRF_ERROR_MESSAGES } from './connection/csrfConfig.js';
|
|
8
10
|
export { GenericWebSocketTransport, type IWebSocketFactory, type IWebSocketLike, } from './connection/GenericWebSocketTransport.js';
|
|
9
11
|
export { JwtAbapConnection, JwtAbapConnection as CloudAbapConnection, } from './connection/JwtAbapConnection.js';
|
|
12
|
+
export { KerberosAbapConnection } from './connection/KerberosAbapConnection.js';
|
|
10
13
|
export { RfcAbapConnection } from './connection/RfcAbapConnection.js';
|
|
11
14
|
export { SamlAbapConnection } from './connection/SamlAbapConnection.js';
|
|
12
15
|
export type { ILogger } from './logger.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,EACT,iBAAiB,GAClB,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;
|
|
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,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AACxF,YAAY,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,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;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,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,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,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,9 @@
|
|
|
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.RfcAbapConnection = 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.KerberosAbapConnection = exports.CloudAbapConnection = exports.JwtAbapConnection = exports.GenericWebSocketTransport = exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.createAbapConnection = exports.CertificateAbapConnection = exports.OnPremAbapConnection = exports.BaseAbapConnection = exports.sapConfigSignature = exports.FileCertificateMaterialLoader = void 0;
|
|
5
|
+
var FileCertificateMaterialLoader_js_1 = require("./auth/FileCertificateMaterialLoader.js");
|
|
6
|
+
Object.defineProperty(exports, "FileCertificateMaterialLoader", { enumerable: true, get: function () { return FileCertificateMaterialLoader_js_1.FileCertificateMaterialLoader; } });
|
|
5
7
|
// Config utilities
|
|
6
8
|
var sapConfig_js_1 = require("./config/sapConfig.js");
|
|
7
9
|
Object.defineProperty(exports, "sapConfigSignature", { enumerable: true, get: function () { return sapConfig_js_1.sapConfigSignature; } });
|
|
@@ -10,6 +12,8 @@ Object.defineProperty(exports, "sapConfigSignature", { enumerable: true, get: fu
|
|
|
10
12
|
var BaseAbapConnection_js_1 = require("./connection/BaseAbapConnection.js");
|
|
11
13
|
Object.defineProperty(exports, "BaseAbapConnection", { enumerable: true, get: function () { return BaseAbapConnection_js_1.BaseAbapConnection; } });
|
|
12
14
|
Object.defineProperty(exports, "OnPremAbapConnection", { enumerable: true, get: function () { return BaseAbapConnection_js_1.BaseAbapConnection; } });
|
|
15
|
+
var CertificateAbapConnection_js_1 = require("./connection/CertificateAbapConnection.js");
|
|
16
|
+
Object.defineProperty(exports, "CertificateAbapConnection", { enumerable: true, get: function () { return CertificateAbapConnection_js_1.CertificateAbapConnection; } });
|
|
13
17
|
// Factory
|
|
14
18
|
var connectionFactory_js_1 = require("./connection/connectionFactory.js");
|
|
15
19
|
Object.defineProperty(exports, "createAbapConnection", { enumerable: true, get: function () { return connectionFactory_js_1.createAbapConnection; } });
|
|
@@ -22,6 +26,8 @@ Object.defineProperty(exports, "GenericWebSocketTransport", { enumerable: true,
|
|
|
22
26
|
var JwtAbapConnection_js_1 = require("./connection/JwtAbapConnection.js");
|
|
23
27
|
Object.defineProperty(exports, "JwtAbapConnection", { enumerable: true, get: function () { return JwtAbapConnection_js_1.JwtAbapConnection; } });
|
|
24
28
|
Object.defineProperty(exports, "CloudAbapConnection", { enumerable: true, get: function () { return JwtAbapConnection_js_1.JwtAbapConnection; } });
|
|
29
|
+
var KerberosAbapConnection_js_1 = require("./connection/KerberosAbapConnection.js");
|
|
30
|
+
Object.defineProperty(exports, "KerberosAbapConnection", { enumerable: true, get: function () { return KerberosAbapConnection_js_1.KerberosAbapConnection; } });
|
|
25
31
|
var RfcAbapConnection_js_1 = require("./connection/RfcAbapConnection.js");
|
|
26
32
|
Object.defineProperty(exports, "RfcAbapConnection", { enumerable: true, get: function () { return RfcAbapConnection_js_1.RfcAbapConnection; } });
|
|
27
33
|
var SamlAbapConnection_js_1 = require("./connection/SamlAbapConnection.js");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/connection",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.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",
|
|
@@ -46,14 +46,15 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@mcp-abap-adt/interfaces": "^7.
|
|
49
|
+
"@mcp-abap-adt/interfaces": "^7.2.0",
|
|
50
50
|
"axios": "^1.13.5",
|
|
51
51
|
"commander": "^14.0.3",
|
|
52
52
|
"express": "^5.1.0",
|
|
53
53
|
"open": "^11.0.0"
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
-
"@mcp-abap-adt/sap-rfc-lite": "^0.1.0"
|
|
56
|
+
"@mcp-abap-adt/sap-rfc-lite": "^0.1.0",
|
|
57
|
+
"kerberos": "^2.1.0"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@biomejs/biome": "^2.3.14",
|