arc-1 1.0.2 → 1.1.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.
Files changed (166) hide show
  1. package/bin/arc1-cli.js +3 -7
  2. package/bin/arc1.js +4 -9
  3. package/dist/adt/abapgit.d.ts +10 -5
  4. package/dist/adt/abapgit.d.ts.map +1 -1
  5. package/dist/adt/abapgit.js +357 -76
  6. package/dist/adt/abapgit.js.map +1 -1
  7. package/dist/adt/atc.d.ts +49 -0
  8. package/dist/adt/atc.d.ts.map +1 -0
  9. package/dist/adt/atc.js +294 -0
  10. package/dist/adt/atc.js.map +1 -0
  11. package/dist/adt/aunit-package.d.ts +22 -0
  12. package/dist/adt/aunit-package.d.ts.map +1 -0
  13. package/dist/adt/aunit-package.js +78 -0
  14. package/dist/adt/aunit-package.js.map +1 -0
  15. package/dist/adt/aunit.d.ts +143 -0
  16. package/dist/adt/aunit.d.ts.map +1 -0
  17. package/dist/adt/aunit.js +987 -0
  18. package/dist/adt/aunit.js.map +1 -0
  19. package/dist/adt/client.d.ts +9 -7
  20. package/dist/adt/client.d.ts.map +1 -1
  21. package/dist/adt/client.js +55 -64
  22. package/dist/adt/client.js.map +1 -1
  23. package/dist/adt/config.d.ts +2 -0
  24. package/dist/adt/config.d.ts.map +1 -1
  25. package/dist/adt/config.js +1 -0
  26. package/dist/adt/config.js.map +1 -1
  27. package/dist/adt/devtools.d.ts +8 -30
  28. package/dist/adt/devtools.d.ts.map +1 -1
  29. package/dist/adt/devtools.js +41 -218
  30. package/dist/adt/devtools.js.map +1 -1
  31. package/dist/adt/diagnostics.d.ts +1 -1
  32. package/dist/adt/diagnostics.d.ts.map +1 -1
  33. package/dist/adt/diagnostics.js +12 -12
  34. package/dist/adt/diagnostics.js.map +1 -1
  35. package/dist/adt/errors.d.ts +7 -0
  36. package/dist/adt/errors.d.ts.map +1 -1
  37. package/dist/adt/errors.js +7 -0
  38. package/dist/adt/errors.js.map +1 -1
  39. package/dist/adt/features.d.ts +9 -3
  40. package/dist/adt/features.d.ts.map +1 -1
  41. package/dist/adt/features.js +40 -8
  42. package/dist/adt/features.js.map +1 -1
  43. package/dist/adt/gcts.d.ts +12 -45
  44. package/dist/adt/gcts.d.ts.map +1 -1
  45. package/dist/adt/gcts.js +299 -171
  46. package/dist/adt/gcts.js.map +1 -1
  47. package/dist/adt/http-deadline.d.ts +23 -0
  48. package/dist/adt/http-deadline.d.ts.map +1 -0
  49. package/dist/adt/http-deadline.js +106 -0
  50. package/dist/adt/http-deadline.js.map +1 -0
  51. package/dist/adt/http-wire-body.d.ts +2 -0
  52. package/dist/adt/http-wire-body.d.ts.map +1 -0
  53. package/dist/adt/http-wire-body.js +14 -0
  54. package/dist/adt/http-wire-body.js.map +1 -0
  55. package/dist/adt/http.d.ts +10 -24
  56. package/dist/adt/http.d.ts.map +1 -1
  57. package/dist/adt/http.js +89 -53
  58. package/dist/adt/http.js.map +1 -1
  59. package/dist/adt/path-safety.d.ts +16 -0
  60. package/dist/adt/path-safety.d.ts.map +1 -0
  61. package/dist/adt/path-safety.js +101 -0
  62. package/dist/adt/path-safety.js.map +1 -0
  63. package/dist/adt/semaphore.d.ts +2 -2
  64. package/dist/adt/semaphore.d.ts.map +1 -1
  65. package/dist/adt/semaphore.js +26 -9
  66. package/dist/adt/semaphore.js.map +1 -1
  67. package/dist/adt/source-diff.d.ts +10 -1
  68. package/dist/adt/source-diff.d.ts.map +1 -1
  69. package/dist/adt/source-diff.js +33 -7
  70. package/dist/adt/source-diff.js.map +1 -1
  71. package/dist/adt/text-search.d.ts +25 -0
  72. package/dist/adt/text-search.d.ts.map +1 -0
  73. package/dist/adt/text-search.js +152 -0
  74. package/dist/adt/text-search.js.map +1 -0
  75. package/dist/adt/transport-diff.d.ts +128 -0
  76. package/dist/adt/transport-diff.d.ts.map +1 -0
  77. package/dist/adt/transport-diff.js +524 -0
  78. package/dist/adt/transport-diff.js.map +1 -0
  79. package/dist/adt/transport.d.ts +78 -13
  80. package/dist/adt/transport.d.ts.map +1 -1
  81. package/dist/adt/transport.js +443 -41
  82. package/dist/adt/transport.js.map +1 -1
  83. package/dist/adt/types.d.ts +23 -12
  84. package/dist/adt/types.d.ts.map +1 -1
  85. package/dist/adt/xml-parser.d.ts +1 -8
  86. package/dist/adt/xml-parser.d.ts.map +1 -1
  87. package/dist/adt/xml-parser.js +54 -60
  88. package/dist/adt/xml-parser.js.map +1 -1
  89. package/dist/authz/policy.d.ts.map +1 -1
  90. package/dist/authz/policy.js +5 -2
  91. package/dist/authz/policy.js.map +1 -1
  92. package/dist/cli-args.d.ts +2 -2
  93. package/dist/cli-args.js +2 -2
  94. package/dist/cli-checks.d.ts +56 -0
  95. package/dist/cli-checks.d.ts.map +1 -0
  96. package/dist/cli-checks.js +368 -0
  97. package/dist/cli-checks.js.map +1 -0
  98. package/dist/cli.d.ts +68 -15
  99. package/dist/cli.d.ts.map +1 -1
  100. package/dist/cli.js +677 -297
  101. package/dist/cli.js.map +1 -1
  102. package/dist/handlers/cds-hints.d.ts.map +1 -1
  103. package/dist/handlers/cds-hints.js +1 -10
  104. package/dist/handlers/cds-hints.js.map +1 -1
  105. package/dist/handlers/diagnose.d.ts +4 -0
  106. package/dist/handlers/diagnose.d.ts.map +1 -1
  107. package/dist/handlers/diagnose.js +616 -9
  108. package/dist/handlers/diagnose.js.map +1 -1
  109. package/dist/handlers/dispatch.d.ts.map +1 -1
  110. package/dist/handlers/dispatch.js +40 -1
  111. package/dist/handlers/dispatch.js.map +1 -1
  112. package/dist/handlers/git.d.ts.map +1 -1
  113. package/dist/handlers/git.js +165 -84
  114. package/dist/handlers/git.js.map +1 -1
  115. package/dist/handlers/read.d.ts.map +1 -1
  116. package/dist/handlers/read.js +15 -0
  117. package/dist/handlers/read.js.map +1 -1
  118. package/dist/handlers/schemas.d.ts +15 -2
  119. package/dist/handlers/schemas.d.ts.map +1 -1
  120. package/dist/handlers/schemas.js +75 -6
  121. package/dist/handlers/schemas.js.map +1 -1
  122. package/dist/handlers/search.js +1 -1
  123. package/dist/handlers/search.js.map +1 -1
  124. package/dist/handlers/tools.d.ts.map +1 -1
  125. package/dist/handlers/tools.js +51 -42
  126. package/dist/handlers/tools.js.map +1 -1
  127. package/dist/handlers/transport.d.ts +2 -1
  128. package/dist/handlers/transport.d.ts.map +1 -1
  129. package/dist/handlers/transport.js +128 -27
  130. package/dist/handlers/transport.js.map +1 -1
  131. package/dist/handlers/write/create.d.ts.map +1 -1
  132. package/dist/handlers/write/create.js +11 -0
  133. package/dist/handlers/write/create.js.map +1 -1
  134. package/dist/handlers/write/update-delete.d.ts.map +1 -1
  135. package/dist/handlers/write/update-delete.js +33 -10
  136. package/dist/handlers/write/update-delete.js.map +1 -1
  137. package/dist/handlers/write-helpers.d.ts.map +1 -1
  138. package/dist/handlers/write-helpers.js +3 -2
  139. package/dist/handlers/write-helpers.js.map +1 -1
  140. package/dist/server/audit.d.ts +1 -1
  141. package/dist/server/audit.d.ts.map +1 -1
  142. package/dist/server/audit.js +228 -21
  143. package/dist/server/audit.js.map +1 -1
  144. package/dist/server/config.d.ts +16 -0
  145. package/dist/server/config.d.ts.map +1 -1
  146. package/dist/server/config.js +145 -17
  147. package/dist/server/config.js.map +1 -1
  148. package/dist/server/effective-policy-log.d.ts +2 -1
  149. package/dist/server/effective-policy-log.d.ts.map +1 -1
  150. package/dist/server/effective-policy-log.js +8 -2
  151. package/dist/server/effective-policy-log.js.map +1 -1
  152. package/dist/server/multi-target-runtime.d.ts.map +1 -1
  153. package/dist/server/multi-target-runtime.js +3 -0
  154. package/dist/server/multi-target-runtime.js.map +1 -1
  155. package/dist/server/multi-target-tools.d.ts.map +1 -1
  156. package/dist/server/multi-target-tools.js +5 -0
  157. package/dist/server/multi-target-tools.js.map +1 -1
  158. package/dist/server/server.d.ts +15 -13
  159. package/dist/server/server.d.ts.map +1 -1
  160. package/dist/server/server.js +36 -26
  161. package/dist/server/server.js.map +1 -1
  162. package/dist/server/types.d.ts +2 -0
  163. package/dist/server/types.d.ts.map +1 -1
  164. package/dist/server/types.js +1 -0
  165. package/dist/server/types.js.map +1 -1
  166. package/package.json +13 -13
@@ -0,0 +1,106 @@
1
+ import { setTimeout as sleep } from 'node:timers/promises';
2
+ import { AdtNetworkError } from './errors.js';
3
+ const DEFAULT_FETCH_TIMEOUT_MS = 120_000;
4
+ function callerDeadlineRemaining(options) {
5
+ if (options?.deadline === undefined)
6
+ return undefined;
7
+ if (!Number.isFinite(options.deadline)) {
8
+ throw new RangeError('ADT request deadline must be a finite epoch-millisecond value.');
9
+ }
10
+ return Math.ceil(options.deadline - Date.now());
11
+ }
12
+ function requestDeadlineRemaining(options) {
13
+ const callerRemaining = callerDeadlineRemaining(options);
14
+ const configuredTimeout = options?.fetchTimeoutMs;
15
+ if (configuredTimeout !== undefined && (!Number.isFinite(configuredTimeout) || configuredTimeout <= 0)) {
16
+ throw new RangeError('ADT fetch timeout must be a positive finite millisecond value.');
17
+ }
18
+ const fetchTimeout = configuredTimeout === undefined ? DEFAULT_FETCH_TIMEOUT_MS : Math.ceil(configuredTimeout);
19
+ return callerRemaining === undefined ? fetchTimeout : Math.min(fetchTimeout, callerRemaining);
20
+ }
21
+ function requestTimeoutError() {
22
+ return new DOMException('The ADT request deadline was exceeded.', 'TimeoutError');
23
+ }
24
+ function requestAbortError(signal) {
25
+ const cause = signal.reason instanceof Error ? signal.reason : new Error('The ADT request was aborted.');
26
+ return new AdtNetworkError(cause.message, cause);
27
+ }
28
+ export function throwIfRequestCancelled(options) {
29
+ if (options?.signal?.aborted) {
30
+ throw requestAbortError(options.signal);
31
+ }
32
+ const callerRemaining = callerDeadlineRemaining(options);
33
+ if (callerRemaining !== undefined && callerRemaining <= 0) {
34
+ const cause = requestTimeoutError();
35
+ throw new AdtNetworkError(cause.message, cause);
36
+ }
37
+ }
38
+ /** Caller-owned cancellation only (no built-in fetch timeout). */
39
+ export function requestBudgetSignal(options) {
40
+ throwIfRequestCancelled(options);
41
+ const signals = [];
42
+ if (options?.signal)
43
+ signals.push(options.signal);
44
+ const callerRemaining = callerDeadlineRemaining(options);
45
+ if (callerRemaining !== undefined)
46
+ signals.push(AbortSignal.timeout(Math.max(1, callerRemaining)));
47
+ if (signals.length === 0)
48
+ return undefined;
49
+ return signals.length === 1 ? signals[0] : AbortSignal.any(signals);
50
+ }
51
+ /** Await a non-fetch dependency without leaving an unhandled rejection after cancellation. */
52
+ export async function awaitWithRequestSignal(operation, signal) {
53
+ if (!signal)
54
+ return operation;
55
+ return new Promise((resolve, reject) => {
56
+ let settled = false;
57
+ const finish = (fn) => {
58
+ if (settled)
59
+ return;
60
+ settled = true;
61
+ signal.removeEventListener('abort', onAbort);
62
+ fn();
63
+ };
64
+ const onAbort = () => finish(() => reject(requestAbortError(signal)));
65
+ signal.addEventListener('abort', onAbort, { once: true });
66
+ operation.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
67
+ if (signal.aborted)
68
+ onAbort();
69
+ });
70
+ }
71
+ export function awaitWithinRequestBudget(operation, options) {
72
+ try {
73
+ return awaitWithRequestSignal(operation, requestBudgetSignal(options));
74
+ }
75
+ catch (error) {
76
+ // `operation` was already created by the caller. Observe any later rejection
77
+ // even when the deadline expires while a provider is returning its promise.
78
+ void operation.catch(() => undefined);
79
+ return Promise.reject(error);
80
+ }
81
+ }
82
+ /** Compose the built-in per-fetch timeout with the caller's signal/deadline. */
83
+ export function requestSignal(options) {
84
+ throwIfRequestCancelled(options);
85
+ const signals = [AbortSignal.timeout(requestDeadlineRemaining(options))];
86
+ if (options?.signal)
87
+ signals.unshift(options.signal);
88
+ return signals.length === 1 ? signals[0] : AbortSignal.any(signals);
89
+ }
90
+ /** Retry delays consume the same caller budget as their surrounding HTTP request. */
91
+ export async function sleepWithinRequestBudget(delayMs, options) {
92
+ if (delayMs <= 0) {
93
+ throwIfRequestCancelled(options);
94
+ return;
95
+ }
96
+ const signal = requestSignal(options);
97
+ try {
98
+ await sleep(delayMs, undefined, { signal });
99
+ }
100
+ catch (error) {
101
+ if (signal.aborted)
102
+ throw signal.reason ?? requestTimeoutError();
103
+ throw error;
104
+ }
105
+ }
106
+ //# sourceMappingURL=http-deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-deadline.js","sourceRoot":"","sources":["../../src/adt/http-deadline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function prepareDataPreviewWireBody(enabled: boolean, method: string, path: string, body: string | undefined, headers: Record<string, string>): string | Buffer | undefined;
2
+ //# sourceMappingURL=http-wire-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-wire-body.d.ts","sourceRoot":"","sources":["../../src/adt/http-wire-body.ts"],"names":[],"mappings":"AAIA,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,GAAG,MAAM,GAAG,SAAS,CAS7B"}
@@ -0,0 +1,14 @@
1
+ import { gzipSync } from 'node:zlib';
2
+ const GZIP_DATA_PREVIEW_PATHS = new Set(['/sap/bc/adt/datapreview/freestyle', '/sap/bc/adt/datapreview/ddic']);
3
+ export function prepareDataPreviewWireBody(enabled, method, path, body, headers) {
4
+ const collectionPath = path.split(/[?#]/, 1)[0] ?? '';
5
+ if (!enabled || method !== 'POST' || !body || !GZIP_DATA_PREVIEW_PATHS.has(collectionPath))
6
+ return body;
7
+ for (const key of Object.keys(headers)) {
8
+ if (key.toLowerCase() === 'content-encoding')
9
+ delete headers[key];
10
+ }
11
+ headers['Content-Encoding'] = 'gzip';
12
+ return gzipSync(body);
13
+ }
14
+ //# sourceMappingURL=http-wire-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-wire-body.js","sourceRoot":"","sources":["../../src/adt/http-wire-body.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,mCAAmC,EAAE,8BAA8B,CAAC,CAAC,CAAC;AAE/G,MAAM,UAAU,0BAA0B,CACxC,OAAgB,EAChB,MAAc,EACd,IAAY,EACZ,IAAwB,EACxB,OAA+B;IAE/B,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,OAAO,IAAI,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAC;IAExG,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,kBAAkB;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC;IACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
@@ -27,25 +27,9 @@
27
27
  * No external HTTP dependencies — undici ships with Node.js 22+.
28
28
  */
29
29
  import type { BTPProxyConfig } from '@arc-mcp/xsuaa-auth/btp';
30
+ import { type AdtRequestOptions } from './http-deadline.js';
30
31
  import type { Semaphore } from './semaphore.js';
31
- export interface AdtRequestOptions {
32
- /**
33
- * Some ADT subresources are optional and legitimately return 404, for example
34
- * class local includes such as testclasses on classes without ABAP Unit code.
35
- * Callers that handle those 404s can opt into debug-level audit logging.
36
- */
37
- suppressNotFoundLog?: boolean;
38
- /**
39
- * Startup capability/discovery probe. ANY non-2xx is expected here (the feature
40
- * is simply absent/not activated, or the endpoint intentionally 400s without
41
- * query params, e.g. the RAP probe on `/ddic/ddl/sources`). The outcome is
42
- * captured as structured data and re-reported at a higher layer (feature map,
43
- * the `Authorization probe: …` lines, the contextual discovery warn), so the
44
- * raw `http_request` failure is logged at debug instead of warn to keep a
45
- * healthy startup quiet. Unlike `suppressNotFoundLog` this is not limited to 404.
46
- */
47
- probe?: boolean;
48
- }
32
+ export type { AdtRequestOptions } from './http-deadline.js';
49
33
  /** Session type for ADT requests */
50
34
  export type SessionType = 'stateful' | 'stateless' | undefined;
51
35
  /** Configuration for the ADT HTTP client */
@@ -56,6 +40,8 @@ export interface AdtHttpConfig {
56
40
  client?: string;
57
41
  language?: string;
58
42
  insecure?: boolean;
43
+ /** Gzip non-empty data-preview POST bodies for approved WAF compatibility. */
44
+ gzipDataPreviewBody?: boolean;
59
45
  cookies?: Record<string, string>;
60
46
  /** Path to cookie file — enables hot-reload on stale auth */
61
47
  cookieFile?: string;
@@ -119,6 +105,7 @@ export declare class AdtHttpClient {
119
105
  private negotiatedHeaders;
120
106
  private csrfToken;
121
107
  private dispatcher;
108
+ private longOperationDispatcher;
122
109
  private config;
123
110
  /**
124
111
  * Cookie jar — stores Set-Cookie headers from responses and sends them back.
@@ -152,13 +139,13 @@ export declare class AdtHttpClient {
152
139
  /** GET request */
153
140
  get(path: string, headers?: Record<string, string>, options?: AdtRequestOptions): Promise<AdtResponse>;
154
141
  /** HEAD request — lightweight probe, no response body */
155
- head(path: string, headers?: Record<string, string>): Promise<AdtResponse>;
142
+ head(path: string, headers?: Record<string, string>, options?: AdtRequestOptions): Promise<AdtResponse>;
156
143
  /** POST request (includes CSRF token) */
157
- post(path: string, body?: string, contentType?: string, headers?: Record<string, string>): Promise<AdtResponse>;
144
+ post(path: string, body?: string, contentType?: string, headers?: Record<string, string>, options?: AdtRequestOptions): Promise<AdtResponse>;
158
145
  /** PUT request (includes CSRF token) */
159
- put(path: string, body: string, contentType?: string, headers?: Record<string, string>): Promise<AdtResponse>;
146
+ put(path: string, body: string, contentType?: string, headers?: Record<string, string>, options?: AdtRequestOptions): Promise<AdtResponse>;
160
147
  /** DELETE request (includes CSRF token) */
161
- delete(path: string, headers?: Record<string, string>): Promise<AdtResponse>;
148
+ delete(path: string, headers?: Record<string, string>, options?: AdtRequestOptions): Promise<AdtResponse>;
162
149
  /**
163
150
  * Execute a function within an isolated stateful session.
164
151
  * Ensures lock/modify/unlock share the same SAP session cookies.
@@ -181,7 +168,7 @@ export declare class AdtHttpClient {
181
168
  * Fetch CSRF token from SAP.
182
169
  * Uses HEAD /sap/bc/adt/core/discovery for speed.
183
170
  */
184
- fetchCsrfToken(): Promise<void>;
171
+ fetchCsrfToken(options?: AdtRequestOptions): Promise<void>;
185
172
  /**
186
173
  * Detect "database connection is not open" error from SAP.
187
174
  * This happens when a work process loses its HANA DB connection.
@@ -304,5 +291,4 @@ export declare function parseRetryAfter(header: string | null | undefined, fallb
304
291
  delayMs: number;
305
292
  source: 'header' | 'fallback';
306
293
  };
307
- export {};
308
294
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/adt/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAQ9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAkED,oCAAoC;AACpC,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;AAE/D,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAC;IACtE,0DAA0D;IAC1D,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,0BAA0B;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,iBAAiB,CAAqE;IAC9F,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,MAAM,CAAgB;IAC9B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS,CAAkC;IACnD,qEAAqE;IACrE,OAAO,CAAC,iBAAiB,CAAS;IAClC,sFAAsF;IACtF,OAAO,CAAC,cAAc,CAAS;IAC/B,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA6B;IACxE,YAAY,MAAM,EAAE,aAAa,EAAE,0BAA0B,CAAC,EAAE,0BAA0B,EAWzF;IAED,yEAAyE;IACzE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAEhD;IAED,6GAA6G;IAC7G,gBAAgB,IAAI,OAAO,CAE1B;IAED,sHAAsH;IACtH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnD;IAED;;mGAE+F;IAC/F,IAAI,SAAS,IAAI,SAAS,GAAG,SAAS,CAErC;IAED,kBAAkB;IACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAE3G;IAED,yDAAyD;IACnD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAE/E;IAED,yCAAyC;IACnC,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,WAAW,CAAC,CAEtB;IAED,wCAAwC;IAClC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAElH;IAED,2CAA2C;IACrC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAEjF;IAED;;;;;;OAMG;IACG,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAYlF;IAED,iFAAiF;YACnE,OAAO;YA2BP,kCAAkC;IAiBhD,gEAAgE;YAClD,YAAY;IAigB1B,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,kBAAkB;IAW1B,yEAAyE;IACzE,OAAO,CAAC,cAAc;IAyCtB;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAmIpC;IAED;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,gBAAgB;IAIxB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;;;OAOG;IACH,gBAAgB,IAAI,IAAI,CAGvB;IAED;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAqB/B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAKpB;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,YAAY;IAgBpB,mEAAmE;IACnE,OAAO,CAAC,QAAQ;IAkBhB,2FAA2F;IAC3F,OAAO,CAAC,eAAe;IAsBvB;;;;;;;;;;;OAWG;YACW,OAAO;IA0BrB;;;;;;;;;;;;;;;;OAgBG;YACW,cAAc;CA2E7B;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,UAAU,EAAE,MAAM,GACjB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;CAAE,CAoBpD"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/adt/http.ts"],"names":[],"mappings":"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"}
package/dist/adt/http.js CHANGED
@@ -33,6 +33,8 @@ import { traceHeaders } from '../server/trace-context.js';
33
33
  import { resolveCookies } from './cookies.js';
34
34
  import { resolveAcceptType, resolveContentType } from './discovery.js';
35
35
  import { AdtApiError, AdtNetworkError } from './errors.js';
36
+ import { awaitWithinRequestBudget, requestBudgetSignal, requestSignal, sleepWithinRequestBudget, throwIfRequestCancelled, } from './http-deadline.js';
37
+ import { prepareDataPreviewWireBody } from './http-wire-body.js';
36
38
  /**
37
39
  * Opt-in wire-level debug logging.
38
40
  *
@@ -95,6 +97,7 @@ export class AdtHttpClient {
95
97
  negotiatedHeaders = new Map();
96
98
  csrfToken = '';
97
99
  dispatcher;
100
+ longOperationDispatcher;
98
101
  config;
99
102
  /**
100
103
  * Cookie jar — stores Set-Cookie headers from responses and sends them back.
@@ -122,7 +125,7 @@ export class AdtHttpClient {
122
125
  // (see doProxyRequest()) — undici 8.x ProxyAgent always uses CONNECT tunneling,
123
126
  // which BTP's connectivity proxy doesn't support (HTTP 405).
124
127
  if (!config.btpProxy && config.insecure) {
125
- this.dispatcher = new Agent({ connect: { rejectUnauthorized: false } });
128
+ this.dispatcher = new Agent({ connect: { rejectUnauthorized: false }, headersTimeout: 0, bodyTimeout: 0 });
126
129
  }
127
130
  }
128
131
  /** Inject startup discovery data used for proactive MIME negotiation. */
@@ -148,20 +151,20 @@ export class AdtHttpClient {
148
151
  return this.request('GET', path, undefined, undefined, headers, options);
149
152
  }
150
153
  /** HEAD request — lightweight probe, no response body */
151
- async head(path, headers) {
152
- return this.request('HEAD', path, undefined, undefined, headers);
154
+ async head(path, headers, options) {
155
+ return this.request('HEAD', path, undefined, undefined, headers, options);
153
156
  }
154
157
  /** POST request (includes CSRF token) */
155
- async post(path, body, contentType, headers) {
156
- return this.request('POST', path, body, contentType, headers);
158
+ async post(path, body, contentType, headers, options) {
159
+ return this.request('POST', path, body, contentType, headers, options);
157
160
  }
158
161
  /** PUT request (includes CSRF token) */
159
- async put(path, body, contentType, headers) {
160
- return this.request('PUT', path, body, contentType, headers);
162
+ async put(path, body, contentType, headers, options) {
163
+ return this.request('PUT', path, body, contentType, headers, options);
161
164
  }
162
165
  /** DELETE request (includes CSRF token) */
163
- async delete(path, headers) {
164
- return this.request('DELETE', path, undefined, undefined, headers);
166
+ async delete(path, headers, options) {
167
+ return this.request('DELETE', path, undefined, undefined, headers, options);
165
168
  }
166
169
  /**
167
170
  * Execute a function within an isolated stateful session.
@@ -185,43 +188,60 @@ export class AdtHttpClient {
185
188
  }
186
189
  /** Core request method — wraps requestInner with optional concurrency limiter */
187
190
  async request(method, path, body, contentType, extraHeaders, options) {
188
- const execute = () => {
189
- if (this.config.semaphore) {
190
- return this.config.semaphore.run(() => this.requestInner(method, path, body, contentType, extraHeaders, options));
191
+ throwIfRequestCancelled(options);
192
+ const execute = async () => {
193
+ try {
194
+ if (this.config.semaphore) {
195
+ return await this.config.semaphore.run(() => this.requestInner(method, path, body, contentType, extraHeaders, options), requestBudgetSignal(options));
196
+ }
197
+ return await this.requestInner(method, path, body, contentType, extraHeaders, options);
198
+ }
199
+ catch (error) {
200
+ if (error instanceof AdtApiError || error instanceof AdtNetworkError)
201
+ throw error;
202
+ if (!options?.signal && options?.deadline === undefined)
203
+ throw error;
204
+ const cause = error instanceof Error ? error : new Error(String(error));
205
+ throw new AdtNetworkError(cause.message, cause);
191
206
  }
192
- return this.requestInner(method, path, body, contentType, extraHeaders, options);
193
207
  };
194
208
  // Shared Basic clients disable 401 retries. Serialize their internal HTTP fan-out as well:
195
209
  // feature probes and compound handlers can otherwise start several requests with the same
196
210
  // expired password before the first 401 is observed. Once rejected, later requests on this
197
211
  // per-call client fail locally and never contact SAP.
198
212
  if (this.config.retryUnauthorized === false) {
199
- return this.runSerializedAuthenticationAttempt(path, execute);
213
+ return this.runSerializedAuthenticationAttempt(path, execute, options);
200
214
  }
201
215
  return execute();
202
216
  }
203
- async runSerializedAuthenticationAttempt(path, execute) {
217
+ async runSerializedAuthenticationAttempt(path, execute, options) {
204
218
  const previous = this.authenticationAttemptState.tail;
205
219
  let release;
206
220
  this.authenticationAttemptState.tail = new Promise((resolve) => {
207
221
  release = resolve;
208
222
  });
209
- await previous;
223
+ let turnStarted = false;
210
224
  try {
225
+ await awaitWithinRequestBudget(previous, options);
226
+ turnStarted = true;
211
227
  if (this.authenticationAttemptState.rejected) {
212
228
  throw new AdtApiError('Shared Basic authentication was already rejected for this request.', 401, path);
213
229
  }
214
230
  return await execute();
215
231
  }
216
232
  finally {
217
- release();
233
+ if (turnStarted)
234
+ release();
235
+ else
236
+ void previous.then(release, release);
218
237
  }
219
238
  }
220
239
  /** Inner request method — CSRF, retries, content negotiation */
221
240
  async requestInner(method, path, body, contentType, extraHeaders, options) {
241
+ throwIfRequestCancelled(options);
222
242
  // Auto-fetch CSRF token for modifying requests
223
243
  if (isModifyingMethod(method) && !this.csrfToken) {
224
- await this.fetchCsrfToken();
244
+ await this.fetchCsrfToken(options);
225
245
  }
226
246
  const headers = { Accept: '*/*' };
227
247
  const negotiationKey = this.normalizeHeaderCacheKey(path);
@@ -253,19 +273,19 @@ export class AdtHttpClient {
253
273
  if (this.config.disableSaml) {
254
274
  headers['X-SAP-SAML2'] = 'disabled';
255
275
  }
256
- if (isModifyingMethod(method)) {
257
- headers['X-CSRF-Token'] = this.csrfToken;
258
- }
259
276
  if (this.config.sessionType === 'stateful') {
260
277
  headers['X-sap-adt-sessiontype'] = 'stateful';
261
278
  }
262
279
  if (contentType) {
263
280
  headers['Content-Type'] = contentType;
264
281
  }
282
+ // Keep `body` as the logical plaintext for debug audit fields; only `wireBody` is sent.
283
+ const wireBody = prepareDataPreviewWireBody(this.config.gzipDataPreviewBody === true, method, path, body, headers);
265
284
  // Auth: Bearer token (BTP ABAP) or Basic Auth (on-premise)
266
285
  this.applyAuthHeader(headers);
267
286
  if (this.config.bearerTokenProvider) {
268
- const token = await this.config.bearerTokenProvider();
287
+ throwIfRequestCancelled(options);
288
+ const token = await awaitWithinRequestBudget(this.config.bearerTokenProvider(), options);
269
289
  headers.Authorization = `Bearer ${token}`;
270
290
  }
271
291
  // Lazy cookie reload: if cookies were cleared on a previous 401,
@@ -273,6 +293,12 @@ export class AdtHttpClient {
273
293
  if (this.cookiesCleared && this.isCookieAuthMode()) {
274
294
  this.reloadCookiesFromSource();
275
295
  }
296
+ // Read the CSRF token together with the cookie header below — SAP binds the token to the
297
+ // session cookie, and a concurrent fetchCsrfToken() can replace both across the bearer
298
+ // await above; a torn pair 403s. The retry paths below already read them adjacently.
299
+ if (isModifyingMethod(method)) {
300
+ headers['X-CSRF-Token'] = this.csrfToken;
301
+ }
276
302
  // Build cookie header from config cookies + cookie jar, with the jar winning
277
303
  // on a name collision (see composeCookieHeader — issue #293).
278
304
  const cookieHeader = this.composeCookieHeader();
@@ -297,7 +323,7 @@ export class AdtHttpClient {
297
323
  let authRetried = false;
298
324
  let retried429 = false;
299
325
  try {
300
- let response = await this.doFetch(url, method, headers, body);
326
+ let response = await this.doFetch(url, method, headers, wireBody, options);
301
327
  let responseBody = await response.text();
302
328
  // Persist any Set-Cookie headers from the response
303
329
  this.storeCookies(response);
@@ -323,7 +349,7 @@ export class AdtHttpClient {
323
349
  this.resetSession();
324
350
  // Re-fetch CSRF token (needed for modifying requests, harmless for reads)
325
351
  if (isModifyingMethod(method)) {
326
- await this.fetchCsrfToken();
352
+ await this.fetchCsrfToken(options);
327
353
  headers['X-CSRF-Token'] = this.csrfToken;
328
354
  }
329
355
  // Rebuild cookie header from fresh jar
@@ -337,7 +363,7 @@ export class AdtHttpClient {
337
363
  else {
338
364
  delete headers.Cookie;
339
365
  }
340
- const retryResp = await this.doFetch(url, method, headers, body);
366
+ const retryResp = await this.doFetch(url, method, headers, wireBody, options);
341
367
  const retryBody = await retryResp.text();
342
368
  this.storeCookies(retryResp);
343
369
  const retryResult = this.handleResponse(retryResp.status, retryResp.headers, retryBody, path);
@@ -374,8 +400,8 @@ export class AdtHttpClient {
374
400
  durationMs: Date.now() - httpStart,
375
401
  errorBody: `503 Service Unavailable — retrying in ${Math.round(jitterMs)}ms (${source})`,
376
402
  });
377
- await new Promise((resolve) => setTimeout(resolve, jitterMs));
378
- const retryResp = await this.doFetch(url, method, headers, body);
403
+ await sleepWithinRequestBudget(jitterMs, options);
404
+ const retryResp = await this.doFetch(url, method, headers, wireBody, options);
379
405
  const retryBody = await retryResp.text();
380
406
  this.storeCookies(retryResp);
381
407
  logger.emitAudit({
@@ -410,8 +436,8 @@ export class AdtHttpClient {
410
436
  durationMs: Date.now() - httpStart,
411
437
  errorBody: `429 Too Many Requests — retrying in ${Math.round(jitterMs)}ms (${source})`,
412
438
  });
413
- await new Promise((resolve) => setTimeout(resolve, jitterMs));
414
- const retryResp = await this.doFetch(url, method, headers, body);
439
+ await sleepWithinRequestBudget(jitterMs, options);
440
+ const retryResp = await this.doFetch(url, method, headers, wireBody, options);
415
441
  const retryBody = await retryResp.text();
416
442
  this.storeCookies(retryResp);
417
443
  logger.emitAudit({
@@ -454,12 +480,13 @@ export class AdtHttpClient {
454
480
  // Re-apply auth credentials
455
481
  this.applyAuthHeader(headers);
456
482
  if (this.config.bearerTokenProvider) {
457
- const token = await this.config.bearerTokenProvider();
483
+ throwIfRequestCancelled(options);
484
+ const token = await awaitWithinRequestBudget(this.config.bearerTokenProvider(), options);
458
485
  headers.Authorization = `Bearer ${token}`;
459
486
  }
460
487
  // Re-fetch CSRF token for modifying requests
461
488
  if (isModifyingMethod(method)) {
462
- await this.fetchCsrfToken();
489
+ await this.fetchCsrfToken(options);
463
490
  headers['X-CSRF-Token'] = this.csrfToken;
464
491
  }
465
492
  // Rebuild cookie header from config cookies + fresh jar (jar wins).
@@ -470,7 +497,7 @@ export class AdtHttpClient {
470
497
  else {
471
498
  delete headers.Cookie;
472
499
  }
473
- response = await this.doFetch(url, method, headers, body);
500
+ response = await this.doFetch(url, method, headers, wireBody, options);
474
501
  responseBody = await response.text();
475
502
  this.storeCookies(response);
476
503
  logger.emitAudit({
@@ -492,7 +519,7 @@ export class AdtHttpClient {
492
519
  }
493
520
  // Handle CSRF token refresh on 403 (modifying requests only)
494
521
  if (response.status === 403 && isModifyingMethod(method)) {
495
- await this.fetchCsrfToken();
522
+ await this.fetchCsrfToken(options);
496
523
  headers['X-CSRF-Token'] = this.csrfToken;
497
524
  // Update cookie header after CSRF fetch may have set new cookies. Use the
498
525
  // merged builder (jar wins) so auth cookies in config.cookies (e.g.
@@ -501,7 +528,7 @@ export class AdtHttpClient {
501
528
  if (csrfRefreshedCookieHeader) {
502
529
  headers.Cookie = csrfRefreshedCookieHeader;
503
530
  }
504
- const retryResponse = await this.doFetch(url, method, headers, body);
531
+ const retryResponse = await this.doFetch(url, method, headers, wireBody, options);
505
532
  const retryBody = await retryResponse.text();
506
533
  this.storeCookies(retryResponse);
507
534
  const result = this.handleResponse(retryResponse.status, retryResponse.headers, retryBody, path);
@@ -570,7 +597,7 @@ export class AdtHttpClient {
570
597
  durationMs: Date.now() - httpStart,
571
598
  errorBody: `Content negotiation ${response.status} — retrying with fallback headers`,
572
599
  });
573
- const retryResp = await this.doFetch(url, method, fallbackHeaders, body);
600
+ const retryResp = await this.doFetch(url, method, fallbackHeaders, wireBody, options);
574
601
  const retryBody = await retryResp.text();
575
602
  this.storeCookies(retryResp);
576
603
  // Store CSRF token from retry response
@@ -657,6 +684,8 @@ export class AdtHttpClient {
657
684
  });
658
685
  throw err;
659
686
  }
687
+ if (err instanceof AdtNetworkError)
688
+ throw err;
660
689
  const message = err instanceof Error ? err.message : String(err);
661
690
  throw new AdtNetworkError(message, err instanceof Error ? err : undefined);
662
691
  }
@@ -729,7 +758,8 @@ export class AdtHttpClient {
729
758
  * Fetch CSRF token from SAP.
730
759
  * Uses HEAD /sap/bc/adt/core/discovery for speed.
731
760
  */
732
- async fetchCsrfToken() {
761
+ async fetchCsrfToken(options) {
762
+ throwIfRequestCancelled(options);
733
763
  const url = this.buildUrl('/sap/bc/adt/core/discovery');
734
764
  const headers = {
735
765
  'X-CSRF-Token': 'fetch',
@@ -744,7 +774,8 @@ export class AdtHttpClient {
744
774
  // Auth: Bearer token (BTP ABAP) or Basic Auth (on-premise)
745
775
  this.applyAuthHeader(headers);
746
776
  if (this.config.bearerTokenProvider) {
747
- const token = await this.config.bearerTokenProvider();
777
+ throwIfRequestCancelled(options);
778
+ const token = await awaitWithinRequestBudget(this.config.bearerTokenProvider(), options);
748
779
  headers.Authorization = `Bearer ${token}`;
749
780
  }
750
781
  // Principal Propagation via SAP-Connectivity-Authentication header (Option 2).
@@ -765,7 +796,7 @@ export class AdtHttpClient {
765
796
  headers.Cookie = cookieHeader;
766
797
  }
767
798
  try {
768
- let response = await this.doFetch(url, 'HEAD', headers);
799
+ let response = await this.doFetch(url, 'HEAD', headers, undefined, options);
769
800
  // Retry once on 503 — ICM may be temporarily overloaded (thread/MPI exhaustion)
770
801
  if (response.status === 503) {
771
802
  const jitterMs = 1000 + Math.random() * 1000;
@@ -779,8 +810,8 @@ export class AdtHttpClient {
779
810
  durationMs: 0,
780
811
  errorBody: `CSRF fetch got 503 — retrying in ${Math.round(jitterMs)}ms`,
781
812
  });
782
- await new Promise((resolve) => setTimeout(resolve, jitterMs));
783
- response = await this.doFetch(url, 'HEAD', headers);
813
+ await sleepWithinRequestBudget(jitterMs, options);
814
+ response = await this.doFetch(url, 'HEAD', headers, undefined, options);
784
815
  }
785
816
  // Preserve any session established by HEAD before deciding whether GET is needed.
786
817
  // The fallback request must use the same SAP session as the eventual write.
@@ -810,7 +841,7 @@ export class AdtHttpClient {
810
841
  ? 'CSRF HEAD returned 403 — retrying with GET (S/4HANA Public Cloud compat)'
811
842
  : 'CSRF HEAD returned no usable token — retrying with GET',
812
843
  });
813
- response = await this.doFetch(url, 'GET', headers);
844
+ response = await this.doFetch(url, 'GET', headers, undefined, options);
814
845
  }
815
846
  // Store cookies from the final CSRF response — critical for session correlation.
816
847
  this.storeCookies(response);
@@ -831,7 +862,7 @@ export class AdtHttpClient {
831
862
  this.csrfToken = token;
832
863
  }
833
864
  catch (err) {
834
- if (err instanceof AdtApiError)
865
+ if (err instanceof AdtApiError || err instanceof AdtNetworkError)
835
866
  throw err;
836
867
  const message = err instanceof Error ? err.message : String(err);
837
868
  throw new AdtNetworkError(`CSRF token fetch failed: ${message}`, err instanceof Error ? err : undefined);
@@ -1018,22 +1049,27 @@ export class AdtHttpClient {
1018
1049
  * Node 22's built-in fetch embeds an older undici version whose dispatcher
1019
1050
  * interface is incompatible with npm undici@8 Agent/ProxyAgent instances.
1020
1051
  */
1021
- async doFetch(url, method, headers, body) {
1052
+ async doFetch(url, method, headers, body, options) {
1053
+ throwIfRequestCancelled(options);
1022
1054
  // Forward the caller's W3C trace context to SAP so one trace spans agent → ARC-1 → SAP.
1023
1055
  // Empty unless the MCP client sent a valid `traceparent`; ARC-1 never originates a trace.
1024
1056
  // Injected here because doFetch is the single outbound choke point (the proxy branch below
1025
1057
  // spreads these headers too).
1026
1058
  const outbound = { ...headers, ...traceHeaders(getCurrentContext()) };
1027
- // BTP Connectivity proxy: use standard HTTP proxy protocol (not CONNECT)
1028
1059
  if (this.config.btpProxy) {
1029
- return this.doProxyRequest(url, method, outbound, body);
1060
+ return this.doProxyRequest(url, method, outbound, body, options);
1030
1061
  }
1062
+ // Let the explicit operation budget override undici's 300-second header timeout.
1063
+ const dispatcher = this.dispatcher ??
1064
+ (options?.fetchTimeoutMs === undefined
1065
+ ? undefined
1066
+ : (this.longOperationDispatcher ??= new Agent({ headersTimeout: 0, bodyTimeout: 0 })));
1031
1067
  return undiciFetch(url, {
1032
1068
  method,
1033
1069
  headers: outbound,
1034
1070
  body,
1035
- signal: AbortSignal.timeout(120_000),
1036
- ...(this.dispatcher ? { dispatcher: this.dispatcher } : {}),
1071
+ signal: requestSignal(options),
1072
+ ...(dispatcher ? { dispatcher } : {}),
1037
1073
  });
1038
1074
  }
1039
1075
  /**
@@ -1053,19 +1089,18 @@ export class AdtHttpClient {
1053
1089
  * to the proxy, and by setting the `path` to the full target URL, the proxy
1054
1090
  * forwards it to the Cloud Connector → on-premise SAP system.
1055
1091
  */
1056
- async doProxyRequest(url, method, headers, body) {
1092
+ async doProxyRequest(url, method, headers, body, options) {
1057
1093
  const proxy = this.config.btpProxy;
1058
1094
  const proxyOrigin = `${proxy.protocol}://${proxy.host}:${proxy.port}`;
1059
- // Get proxy auth token
1060
1095
  let proxyAuth;
1096
+ throwIfRequestCancelled(options);
1061
1097
  if (this.config.ppProxyAuth) {
1062
1098
  proxyAuth = this.config.ppProxyAuth;
1063
1099
  }
1064
1100
  else {
1065
- const proxyToken = await proxy.getProxyToken();
1101
+ const proxyToken = await awaitWithinRequestBudget(proxy.getProxyToken(), options);
1066
1102
  proxyAuth = `Bearer ${proxyToken}`;
1067
1103
  }
1068
- // Extract host from target URL for the Host header
1069
1104
  const targetUrl = new URL(url);
1070
1105
  const hostHeader = targetUrl.port ? `${targetUrl.hostname}:${targetUrl.port}` : targetUrl.hostname;
1071
1106
  // Merge proxy headers with request headers
@@ -1079,7 +1114,8 @@ export class AdtHttpClient {
1079
1114
  if (proxy.locationId) {
1080
1115
  proxyHeaders['SAP-Connectivity-SCC-Location_ID'] = proxy.locationId;
1081
1116
  }
1082
- const client = new Client(proxyOrigin);
1117
+ const clientOptions = options?.fetchTimeoutMs === undefined ? undefined : { headersTimeout: 0, bodyTimeout: 0 };
1118
+ const client = new Client(proxyOrigin, clientOptions);
1083
1119
  try {
1084
1120
  const resp = await client.request({
1085
1121
  method: method,
@@ -1087,7 +1123,7 @@ export class AdtHttpClient {
1087
1123
  path: url,
1088
1124
  headers: proxyHeaders,
1089
1125
  body: body ?? undefined,
1090
- signal: AbortSignal.timeout(120_000),
1126
+ signal: requestSignal(options),
1091
1127
  });
1092
1128
  // Convert undici response to a Response-like object that matches
1093
1129
  // what fetch() returns, so the rest of AdtHttpClient works unchanged.