@mcp-abap-adt/adt-clients 3.11.3 → 3.12.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.
|
@@ -51,9 +51,9 @@ function buildBatchPayload(parts, boundary = createBatchBoundary()) {
|
|
|
51
51
|
innerRequest,
|
|
52
52
|
].join('\r\n');
|
|
53
53
|
})
|
|
54
|
-
.join('');
|
|
54
|
+
.join('\r\n');
|
|
55
55
|
return {
|
|
56
56
|
boundary,
|
|
57
|
-
body: `${multipartParts}--${boundary}--\r\n`,
|
|
57
|
+
body: `${multipartParts}\r\n--${boundary}--\r\n`,
|
|
58
58
|
};
|
|
59
59
|
}
|
|
@@ -7,6 +7,7 @@ export declare function clearAcceptCache(): void;
|
|
|
7
7
|
export declare function setAcceptCorrectionEnabled(enabled?: boolean): void;
|
|
8
8
|
export declare function getAcceptCorrectionEnabled(): boolean;
|
|
9
9
|
export declare function extractSupportedAccept(error: unknown): string[];
|
|
10
|
+
export declare function extractSupportedContentType(error: unknown): string[];
|
|
10
11
|
export declare function wrapConnectionAcceptNegotiation(connection: IAbapConnection, logger?: ILogger): void;
|
|
11
12
|
export declare function makeAdtRequestWithAcceptNegotiation<T = unknown, D = unknown>(connection: IAbapConnection, request: IAbapRequestOptions, options?: IAcceptNegotiationOptions): Promise<IAdtResponse<T, D>>;
|
|
12
13
|
//# sourceMappingURL=acceptNegotiation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acceptNegotiation.d.ts","sourceRoot":"","sources":["../../src/utils/acceptNegotiation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,OAAO,EACR,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"acceptNegotiation.d.ts","sourceRoot":"","sources":["../../src/utils/acceptNegotiation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,OAAO,EACR,MAAM,0BAA0B,CAAC;AAUlC,MAAM,WAAW,yBAAyB;IACxC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAElE;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAKpD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAoC/D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAsCpE;AAcD,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,eAAe,EAC3B,MAAM,CAAC,EAAE,OAAO,GACf,IAAI,CAkBN;AAED,wBAAsB,mCAAmC,CACvD,CAAC,GAAG,OAAO,EACX,CAAC,GAAG,OAAO,EAEX,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CA6E7B"}
|
|
@@ -4,13 +4,16 @@ exports.clearAcceptCache = clearAcceptCache;
|
|
|
4
4
|
exports.setAcceptCorrectionEnabled = setAcceptCorrectionEnabled;
|
|
5
5
|
exports.getAcceptCorrectionEnabled = getAcceptCorrectionEnabled;
|
|
6
6
|
exports.extractSupportedAccept = extractSupportedAccept;
|
|
7
|
+
exports.extractSupportedContentType = extractSupportedContentType;
|
|
7
8
|
exports.wrapConnectionAcceptNegotiation = wrapConnectionAcceptNegotiation;
|
|
8
9
|
exports.makeAdtRequestWithAcceptNegotiation = makeAdtRequestWithAcceptNegotiation;
|
|
9
10
|
const acceptCache = new Map();
|
|
11
|
+
const contentTypeCache = new Map();
|
|
10
12
|
const baseRequestMap = new WeakMap();
|
|
11
13
|
let acceptCorrectionOverride;
|
|
12
14
|
function clearAcceptCache() {
|
|
13
15
|
acceptCache.clear();
|
|
16
|
+
contentTypeCache.clear();
|
|
14
17
|
}
|
|
15
18
|
function setAcceptCorrectionEnabled(enabled) {
|
|
16
19
|
acceptCorrectionOverride = enabled;
|
|
@@ -19,7 +22,7 @@ function getAcceptCorrectionEnabled() {
|
|
|
19
22
|
if (acceptCorrectionOverride !== undefined) {
|
|
20
23
|
return acceptCorrectionOverride;
|
|
21
24
|
}
|
|
22
|
-
return process.env.ADT_ACCEPT_CORRECTION
|
|
25
|
+
return process.env.ADT_ACCEPT_CORRECTION !== 'false';
|
|
23
26
|
}
|
|
24
27
|
function extractSupportedAccept(error) {
|
|
25
28
|
const types = new Set();
|
|
@@ -53,6 +56,39 @@ function extractSupportedAccept(error) {
|
|
|
53
56
|
}
|
|
54
57
|
return Array.from(types).filter(Boolean);
|
|
55
58
|
}
|
|
59
|
+
function extractSupportedContentType(error) {
|
|
60
|
+
const e = error;
|
|
61
|
+
if (e?.response?.status !== 415) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const types = new Set();
|
|
65
|
+
const headers = (e?.response?.headers || {});
|
|
66
|
+
const headerCandidates = [
|
|
67
|
+
headers['content-type'],
|
|
68
|
+
headers['x-sap-adt-supported-content-type'],
|
|
69
|
+
headers['supported-content-type'],
|
|
70
|
+
];
|
|
71
|
+
for (const value of headerCandidates) {
|
|
72
|
+
if (typeof value === 'string') {
|
|
73
|
+
value
|
|
74
|
+
.split(',')
|
|
75
|
+
.map((entry) => entry.trim())
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.forEach((entry) => {
|
|
78
|
+
types.add(entry);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const data = e?.response?.data;
|
|
83
|
+
const text = typeof data === 'string' ? data : data ? JSON.stringify(data) : '';
|
|
84
|
+
if (text) {
|
|
85
|
+
const matches = text.match(/[a-zA-Z0-9.+-]+\/[a-zA-Z0-9.+-]+(?:;[^,\s]+)?/g) || [];
|
|
86
|
+
for (const match of matches) {
|
|
87
|
+
types.add(match);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Array.from(types).filter(Boolean);
|
|
91
|
+
}
|
|
56
92
|
function buildCacheKey(request) {
|
|
57
93
|
return `${request.method.toUpperCase()} ${request.url}`;
|
|
58
94
|
}
|
|
@@ -78,6 +114,12 @@ async function makeAdtRequestWithAcceptNegotiation(connection, request, options)
|
|
|
78
114
|
if (cachedAccept) {
|
|
79
115
|
headers.Accept = cachedAccept;
|
|
80
116
|
}
|
|
117
|
+
const cachedContentType = enableCorrection
|
|
118
|
+
? contentTypeCache.get(cacheKey)
|
|
119
|
+
: undefined;
|
|
120
|
+
if (cachedContentType) {
|
|
121
|
+
headers['Content-Type'] = cachedContentType;
|
|
122
|
+
}
|
|
81
123
|
const baseRequest = getBaseRequest(connection);
|
|
82
124
|
try {
|
|
83
125
|
return await baseRequest({
|
|
@@ -104,6 +146,23 @@ async function makeAdtRequestWithAcceptNegotiation(connection, request, options)
|
|
|
104
146
|
}
|
|
105
147
|
}
|
|
106
148
|
}
|
|
149
|
+
if (e.response?.status === 415) {
|
|
150
|
+
const supported = extractSupportedContentType(error);
|
|
151
|
+
if (supported.length > 0) {
|
|
152
|
+
logger?.warn?.(`Content-Type not supported for ${request.url}. Supported Content-Type: ${supported.join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
if (enableCorrection && supported.length > 0) {
|
|
155
|
+
const nextContentType = supported[0];
|
|
156
|
+
if (headers['Content-Type'] !== nextContentType) {
|
|
157
|
+
contentTypeCache.set(cacheKey, nextContentType);
|
|
158
|
+
logger?.warn?.(`Retrying ${request.url} with corrected Content-Type: ${nextContentType}`);
|
|
159
|
+
return await baseRequest({
|
|
160
|
+
...request,
|
|
161
|
+
headers: { ...headers, 'Content-Type': nextContentType },
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
107
166
|
throw error;
|
|
108
167
|
}
|
|
109
168
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/adt-clients",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.0",
|
|
4
4
|
"description": "ADT clients for SAP ABAP systems - AdtClient and AdtRuntimeClient",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
"shared:teardown": "npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/teardown",
|
|
61
61
|
"shared:check": "npx jest --testPathIgnorePatterns node_modules --testPathPatterns admin/shared-deps/check",
|
|
62
62
|
"pretest": "npm run test:check:integration",
|
|
63
|
-
"prepublishOnly": "npm run build"
|
|
63
|
+
"prepublishOnly": "npm run build",
|
|
64
|
+
"prepare": "husky"
|
|
64
65
|
},
|
|
65
66
|
"engines": {
|
|
66
67
|
"node": ">=18.0.0"
|
|
@@ -81,6 +82,7 @@
|
|
|
81
82
|
"@types/jest": "^30.0.0",
|
|
82
83
|
"@types/node": "^25.3.3",
|
|
83
84
|
"dotenv": "^17.3.1",
|
|
85
|
+
"husky": "^9.1.7",
|
|
84
86
|
"jest": "^30.0.5",
|
|
85
87
|
"jest-util": "^30.2.0",
|
|
86
88
|
"ts-jest": "^29.4.1",
|