@mcp-abap-adt/connection 8.0.1 → 9.0.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/CHANGELOG.md +117 -0
- package/README.md +42 -3
- package/dist/auth/FileCertificateMaterialLoader.d.ts +2 -1
- package/dist/auth/FileCertificateMaterialLoader.d.ts.map +1 -1
- package/dist/auth/providers.d.ts +2 -1
- package/dist/auth/providers.d.ts.map +1 -1
- package/dist/config/sapConfig.d.ts +1 -1
- package/dist/config/sapConfig.d.ts.map +1 -1
- package/dist/connection/AbapConnection.d.ts +1 -1
- package/dist/connection/AbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.d.ts +1 -1
- package/dist/connection/AbstractAbapConnection.d.ts.map +1 -1
- package/dist/connection/AbstractAbapConnection.js +9 -9
- package/dist/connection/AdtCloudConnector.d.ts +1 -1
- package/dist/connection/AdtCloudConnector.d.ts.map +1 -1
- package/dist/connection/AdtOnPremConnector.d.ts +1 -1
- package/dist/connection/AdtOnPremConnector.d.ts.map +1 -1
- package/dist/connection/CredentialAbapConnection.d.ts +1 -1
- package/dist/connection/CredentialAbapConnection.d.ts.map +1 -1
- package/dist/connection/GenericWebSocketTransport.d.ts +1 -1
- package/dist/connection/GenericWebSocketTransport.d.ts.map +1 -1
- package/dist/connection/RfcTransport.d.ts +23 -1
- package/dist/connection/RfcTransport.d.ts.map +1 -1
- package/dist/connection/RfcTransport.js +73 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/session/SessionLifecycle.d.ts +1 -1
- package/dist/session/SessionLifecycle.d.ts.map +1 -1
- package/dist/session/SessionLifecycle.js +2 -2
- package/dist/utils/networkErrors.js +2 -2
- package/dist/utils/timeouts.d.ts +1 -1
- package/dist/utils/timeouts.d.ts.map +1 -1
- package/dist/utils/tokenRefresh.d.ts +1 -1
- package/dist/utils/tokenRefresh.d.ts.map +1 -1
- package/docs/INDEX.md +2 -0
- package/docs/INSTALLATION.md +19 -0
- package/docs/MIGRATION-9.0.md +97 -0
- package/docs/SCOPE.md +3 -3
- package/docs/STATEFUL_SESSION_GUIDE.md +1 -1
- package/docs/USAGE.md +24 -4
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,121 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [9.0.0] - 2026-09-23
|
|
11
|
+
|
|
12
|
+
**The contracts split, and this package follows them rather than the shim left
|
|
13
|
+
behind.** `@mcp-abap-adt/interfaces` became an umbrella whose every export is
|
|
14
|
+
marked `@deprecated`, re-exporting four packages that now hold the contracts.
|
|
15
|
+
Building against the umbrella still works and says so in every editor; it is a
|
|
16
|
+
bridge, and this package has crossed it. No API here changed.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **BREAKING** — the dependency on `@mcp-abap-adt/interfaces` is gone, replaced
|
|
21
|
+
by `@mcp-abap-adt/interfaces-adt`, `-auth`, `-network` and `-utils`. Every
|
|
22
|
+
contract import in `src/` names the package the contract lives in. Nothing was
|
|
23
|
+
renamed and no signature moved, so a consumer using only this package's own
|
|
24
|
+
exports changes nothing; a consumer that imported contract types through the
|
|
25
|
+
umbrella now installs the packages it names. See
|
|
26
|
+
[`docs/MIGRATION-9.0.md`](docs/MIGRATION-9.0.md).
|
|
27
|
+
|
|
28
|
+
Not because a re-export loses anything — it does not: through the umbrella
|
|
29
|
+
and directly, `IAuthProvider` is the same type. The umbrella decides which
|
|
30
|
+
VERSION of each contract package a tree gets, since it carries its own ranges
|
|
31
|
+
(`interfaces-adt: ^6.0.0`, and so on). A consumer naming a contract package
|
|
32
|
+
directly outside those ranges gets two physical copies — `interfaces-adt` has
|
|
33
|
+
published majors 1 through 6, so `@4` plus the umbrella puts 4 at the root and
|
|
34
|
+
6 beneath it. Harmless wherever the shapes agree, because TypeScript is
|
|
35
|
+
structural; a type error at the package boundary, far from the skew that
|
|
36
|
+
caused it, wherever they do not. Depending directly makes the version this
|
|
37
|
+
package's decision and lets `npm ls` answer for it. And every export on the
|
|
38
|
+
umbrella is `@deprecated`, so building on it hands the timing of a breaking
|
|
39
|
+
change to someone else.
|
|
40
|
+
|
|
41
|
+
- `IWebSocketCloseInfo`, `IWebSocketConnectOptions`, `IWebSocketMessageEnvelope`,
|
|
42
|
+
`IWebSocketMessageHandler` and `IWebSocketTransport` are re-exported from
|
|
43
|
+
`@mcp-abap-adt/interfaces-network` instead of the umbrella. Same names, same
|
|
44
|
+
shapes, so an importer of this package's own exports sees no difference.
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- `scripts/check-docs.mjs` exempted the whole `@mcp-abap-adt/` scope from the
|
|
49
|
+
"stands on a package this repo does not install" question, which was true
|
|
50
|
+
while the scope meant one umbrella this package depended on. After the split
|
|
51
|
+
it made a historical migration note — correct about the import a 6.x consumer
|
|
52
|
+
wrote — fail the build. The exemption is now this package alone.
|
|
53
|
+
|
|
54
|
+
- `scripts/check-docs.mjs` built a page's vocabulary from every fence on the
|
|
55
|
+
page regardless of position, so a fence at the BOTTOM could answer for a
|
|
56
|
+
genuinely undefined name at the top and the check would pass. The comment at
|
|
57
|
+
the point of use states the model — "a page is read top to bottom, so a later
|
|
58
|
+
fence may lean on a name an earlier one established" — and the code now
|
|
59
|
+
follows it: a fence sees only what the fences above it bound. Measured: a
|
|
60
|
+
fence using `zzzProbeName` above the fence that binds it passed silently
|
|
61
|
+
before and is reported now.
|
|
62
|
+
|
|
63
|
+
Skipped fences count toward that vocabulary. One skipped because it stands on
|
|
64
|
+
a package this repo does not install still taught the reader a name, and this
|
|
65
|
+
is what lets `docs/MIGRATION-6.0.md` keep showing the import a 6.x consumer
|
|
66
|
+
wrote.
|
|
67
|
+
|
|
68
|
+
The same violation sat one rung lower, where it reached the compiler rather
|
|
69
|
+
than the filter over its output: the imports lent to a fence that shows none
|
|
70
|
+
were hoisted from the WHOLE page, so a later fence's import typed an earlier
|
|
71
|
+
fence. A continuation now borrows only from the fences above it. Measured on
|
|
72
|
+
a name the page does not otherwise bind: a fence calling
|
|
73
|
+
`new SamlAuthProvider(...)` placed above the only fence importing it compiled
|
|
74
|
+
clean before and is reported now.
|
|
75
|
+
|
|
76
|
+
### Documentation
|
|
77
|
+
|
|
78
|
+
- `docs/MIGRATION-9.0.md` (new): which package each contract moved to, what a
|
|
79
|
+
consumer does, and why staying on the deprecated umbrella is a bridge rather
|
|
80
|
+
than a destination.
|
|
81
|
+
- `README.md`, `docs/USAGE.md`, `docs/SCOPE.md` and
|
|
82
|
+
`docs/STATEFUL_SESSION_GUIDE.md` name the package each contract is now in.
|
|
83
|
+
Historical migration notes are left alone: they describe the import that was
|
|
84
|
+
correct for the release they document.
|
|
85
|
+
- `README.md` links the 7.0/8.0 migration note, which 8.0.1 added to
|
|
86
|
+
`docs/INDEX.md` and said it had added to both.
|
|
87
|
+
- `README.md` and `docs/INSTALLATION.md` say what to install. Until now the
|
|
88
|
+
contract packages arrived transitively through the umbrella, so no page had
|
|
89
|
+
to mention them; a consumer following the installation guide and naming
|
|
90
|
+
`IAuthProvider` in their own signature would have found nothing there.
|
|
91
|
+
- `README.md` names the four contract packages under External Dependencies, and
|
|
92
|
+
what this package takes from each.
|
|
93
|
+
- `CLAUDE.md` said `IAuthProvider` comes from `@mcp-abap-adt/interfaces` and
|
|
94
|
+
that external dependencies are reached "through interfaces from
|
|
95
|
+
`@mcp-abap-adt/interfaces`". Both were true before the split and are the
|
|
96
|
+
instructions an agent working in this repository reads first.
|
|
97
|
+
|
|
98
|
+
## [8.1.0] - 2026-09-21
|
|
99
|
+
|
|
100
|
+
**The RFC wire can be asked for its payload, and what it logs is safe to
|
|
101
|
+
paste.** `RFC → METHOD URI` did not show a body that goes missing or gets
|
|
102
|
+
mis-serialised before it reaches `SADT_REST_RFC_ENDPOINT`. Nothing existing
|
|
103
|
+
changes: the channel is off until asked for.
|
|
104
|
+
|
|
105
|
+
### Added
|
|
106
|
+
|
|
107
|
+
- `RfcTransport` can be asked to log the wire: a third constructor argument
|
|
108
|
+
`{ logWire?, maxLoggedBodyChars? }`, off by default, adds the request header
|
|
109
|
+
fields, the request body and the response body to the debug channel. This is
|
|
110
|
+
what shows a payload that was mis-serialised before it reached
|
|
111
|
+
`SADT_REST_RFC_ENDPOINT`. Credential header values (`Authorization`, any
|
|
112
|
+
`Cookie`, anything matching `token`, `secret`, `password`, `credential` or an
|
|
113
|
+
API key) are replaced with `[redacted]` — the names are kept — and a body is
|
|
114
|
+
clipped at `maxLoggedBodyChars`, 2000 by default — `0` logs the size alone,
|
|
115
|
+
`Infinity` asks for the whole body, and a negative or `NaN` ceiling falls
|
|
116
|
+
back to the default rather than throwing. Bodies are not redacted, only
|
|
117
|
+
clipped.
|
|
118
|
+
|
|
119
|
+
It is a flag rather than something inferred from the presence of a logger
|
|
120
|
+
because `ILogger` carries no level predicate: `logger?.debug()` cannot tell
|
|
121
|
+
an enabled debug channel from one that discards, so without the flag every
|
|
122
|
+
caller passing a logger would build a copy of every body on the wire and
|
|
123
|
+
throw it away. `HttpTransport` logs no bodies at any setting.
|
|
124
|
+
|
|
10
125
|
## [8.0.1] - 2026-09-08
|
|
11
126
|
|
|
12
127
|
**Documentation only — 7.0.0 and 8.0.0 shipped without their migration note.**
|
|
@@ -1535,6 +1650,8 @@ const connection = createAbapConnection(config, logger);
|
|
|
1535
1650
|
- Permission errors (403 with "ExceptionResourceNoAccess") no longer trigger JWT refresh loops
|
|
1536
1651
|
- Proper separation: base class handles HTTP/session, concrete classes handle auth-specific errors
|
|
1537
1652
|
[Unreleased]: https://github.com/fr0ster/mcp-abap-connection/compare/v8.0.1...HEAD
|
|
1653
|
+
[9.0.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v8.1.0...v9.0.0
|
|
1654
|
+
[8.1.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v8.0.1...v8.1.0
|
|
1538
1655
|
[8.0.1]: https://github.com/fr0ster/mcp-abap-connection/compare/v8.0.0...v8.0.1
|
|
1539
1656
|
[8.0.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v7.0.0...v8.0.0
|
|
1540
1657
|
[7.0.0]: https://github.com/fr0ster/mcp-abap-connection/compare/v6.1.0...v7.0.0
|
package/README.md
CHANGED
|
@@ -131,10 +131,26 @@ This package interacts with external packages **ONLY through interfaces**:
|
|
|
131
131
|
- **Logger interface**: Uses `ILogger` interface for logging - does not know about concrete logger implementation
|
|
132
132
|
- **No direct dependencies on auth packages**: All token-related operations are handled through configuration (`SapConfig`) passed by consumers
|
|
133
133
|
|
|
134
|
+
The contracts themselves come from four packages, and are the only runtime
|
|
135
|
+
dependencies of this one besides `axios`, `commander` and `open`:
|
|
136
|
+
|
|
137
|
+
| Package | What this package takes from it |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `@mcp-abap-adt/interfaces-adt` | `IAbapConnection`, `ISapConfig`, `ITokenRefresher`, the capability atoms, `ADT_SESSION_ERROR` |
|
|
140
|
+
| `@mcp-abap-adt/interfaces-auth` | `IAuthProvider`, `IRenewableCredential`, `ICertificateMaterial` |
|
|
141
|
+
| `@mcp-abap-adt/interfaces-network` | `ITimeoutConfig`, `NETWORK_ERROR_CODES`, the WebSocket contracts |
|
|
142
|
+
| `@mcp-abap-adt/interfaces-utils` | `ILogger` |
|
|
143
|
+
|
|
144
|
+
Not `@mcp-abap-adt/interfaces`. That name is now an umbrella of deprecated
|
|
145
|
+
re-exports, and this package no longer depends on it — see
|
|
146
|
+
[Migration to 9.0.0](./docs/MIGRATION-9.0.md).
|
|
147
|
+
|
|
134
148
|
## Documentation
|
|
135
149
|
|
|
136
150
|
- 📦 **[Installation Guide](./docs/INSTALLATION.md)** - Setup and installation instructions
|
|
137
151
|
- 📚 **[Usage Guide](./docs/USAGE.md)** - Detailed usage examples and API documentation
|
|
152
|
+
- 🚚 **[Migration to 9.0.0](./docs/MIGRATION-9.0.md)** - the contracts split out of `@mcp-abap-adt/interfaces`; which package each one moved to
|
|
153
|
+
- 🚚 **[Migration to 7.0.0 and 8.0.0](./docs/MIGRATION-8.0.md)** - request headers leave the stateful branch, the contracts floor moves, and `flushGoodbye()`
|
|
138
154
|
- 🚚 **[Migration to 6.0.0](./docs/MIGRATION-6.0.md)** - the factory and the per-credential classes are removed; RFC is a transport, not a class
|
|
139
155
|
- 🚚 **[Migration to 4.0.0](./docs/MIGRATION-4.0.md)** - a 401 refreshes the token, a 403 reaches you with the server's message; the synthesised "JWT token has expired" is gone
|
|
140
156
|
- 🚚 **[Migration: the explicit session lifecycle](./docs/MIGRATION-2.0.md)** - `connect()` is now required; start here if you are coming from 1.x
|
|
@@ -155,6 +171,15 @@ This package interacts with external packages **ONLY through interfaces**:
|
|
|
155
171
|
npm install @mcp-abap-adt/connection
|
|
156
172
|
```
|
|
157
173
|
|
|
174
|
+
That is everything you need to **use** the connectors. If your own code names a
|
|
175
|
+
contract type — `IAuthProvider` for a credential you write, `ISapConfig` for a
|
|
176
|
+
config you build — install the package it lives in as well, because this one no
|
|
177
|
+
longer brings them along:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npm install @mcp-abap-adt/interfaces-adt @mcp-abap-adt/interfaces-auth
|
|
181
|
+
```
|
|
182
|
+
|
|
158
183
|
For detailed installation instructions, see [Installation Guide](./docs/INSTALLATION.md).
|
|
159
184
|
|
|
160
185
|
## Quick Start
|
|
@@ -345,7 +370,7 @@ import {
|
|
|
345
370
|
TokenAuthProvider,
|
|
346
371
|
getTimeout,
|
|
347
372
|
} from "@mcp-abap-adt/connection";
|
|
348
|
-
import type { ITokenRefresher } from "@mcp-abap-adt/interfaces";
|
|
373
|
+
import type { ITokenRefresher } from "@mcp-abap-adt/interfaces-adt";
|
|
349
374
|
|
|
350
375
|
// Token refresher provides token acquisition and refresh
|
|
351
376
|
// (created by @mcp-abap-adt/auth-broker or custom implementation)
|
|
@@ -579,7 +604,7 @@ interface AbapConnection {
|
|
|
579
604
|
```
|
|
580
605
|
|
|
581
606
|
The connectors carry the rest of the session lifecycle. It is on the shared
|
|
582
|
-
contract as a **capability atom** in `@mcp-abap-adt/interfaces` rather than as
|
|
607
|
+
contract as a **capability atom** in `@mcp-abap-adt/interfaces-adt` rather than as
|
|
583
608
|
methods on `IAbapConnection`, so a consumer that only carries requests is
|
|
584
609
|
unaffected by its existence. Note that a connection over RFC has the whole of it
|
|
585
610
|
— what an RFC conversation has none of is a session RESOURCE to open and close
|
|
@@ -592,7 +617,7 @@ isConnected(): boolean;
|
|
|
592
617
|
getSessionIdentity(): string | null; // WHICH SAP session; null is not "disconnected"
|
|
593
618
|
```
|
|
594
619
|
|
|
595
|
-
Import those names from `@mcp-abap-adt/interfaces`, not from this package: a
|
|
620
|
+
Import those names from `@mcp-abap-adt/interfaces-adt`, not from this package: a
|
|
596
621
|
contract type re-exported under a second name is a contract type that can drift.
|
|
597
622
|
|
|
598
623
|
**The connection does not track locks.** Deciding when to disconnect, and
|
|
@@ -656,6 +681,20 @@ const connection = new AdtOnPremConnector(
|
|
|
656
681
|
);
|
|
657
682
|
```
|
|
658
683
|
|
|
684
|
+
A third argument turns on the wire log, which is off by default:
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
new RfcTransport(rfcConversationFrom(config), logger, { logWire: true });
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
It adds three debug lines per request — header fields, request body, response
|
|
691
|
+
body — which is how you see that a payload was mis-serialised before it reached
|
|
692
|
+
`SADT_REST_RFC_ENDPOINT`. Credential header values are replaced with
|
|
693
|
+
`[redacted]` and bodies are clipped at `maxLoggedBodyChars` (2000). The bodies
|
|
694
|
+
themselves are not redacted, so read a captured log before pasting it into an
|
|
695
|
+
issue. `HttpTransport` never logs bodies, so this is the one wire whose debug
|
|
696
|
+
channel can be asked for the payload.
|
|
697
|
+
|
|
659
698
|
#### `CSRF_CONFIG` and `CSRF_ERROR_MESSAGES`
|
|
660
699
|
|
|
661
700
|
**New in 0.1.13+:** Exported constants for consistent CSRF token handling across different connection implementations.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ICertificateMaterialLoader, ISapConfig } from '@mcp-abap-adt/interfaces-adt';
|
|
2
|
+
import type { ICertificateMaterial } from '@mcp-abap-adt/interfaces-auth';
|
|
2
3
|
export declare class FileCertificateMaterialLoader implements ICertificateMaterialLoader {
|
|
3
4
|
load(config: ISapConfig): Promise<ICertificateMaterial>;
|
|
4
5
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileCertificateMaterialLoader.d.ts","sourceRoot":"","sources":["../../src/auth/FileCertificateMaterialLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"FileCertificateMaterialLoader.d.ts","sourceRoot":"","sources":["../../src/auth/FileCertificateMaterialLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0BAA0B,EAC1B,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,qBAAa,6BACX,YAAW,0BAA0B;IAE/B,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAyB9D"}
|
package/dist/auth/providers.d.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* `CertificateAuthProvider` returns are what `CertificateAbapConnection`
|
|
8
8
|
* returned. Nothing about how a credential works changed; only who owns it.
|
|
9
9
|
*/
|
|
10
|
-
import type {
|
|
10
|
+
import type { ICertificateMaterialLoader, ISapConfig, ITokenRefresher } from '@mcp-abap-adt/interfaces-adt';
|
|
11
|
+
import type { IAuthProvider, ICertificateMaterial, IRenewableCredential } from '@mcp-abap-adt/interfaces-auth';
|
|
11
12
|
/** Username and password, as `Basic base64(user:pass)`. */
|
|
12
13
|
export declare class BasicAuthProvider implements IAuthProvider {
|
|
13
14
|
private readonly username;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/auth/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/auth/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,0BAA0B,EAC1B,UAAU,EACV,eAAe,EAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,+BAA+B,CAAC;AAEvC,2DAA2D;AAC3D,qBAAa,iBAAkB,YAAW,aAAa;IAiBnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAjB3B,QAAQ,CAAC,IAAI,WAAW;IAExB,wEAAwE;IAClE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B,yDAAyD;IACzD,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB,gFAAgF;IAChF,iBAAiB,IAAI,oBAAoB;gBAKtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;IAG7B,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAGpD;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,YAAW,oBAAoB;IAyB1D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAxBzB,QAAQ,CAAC,IAAI,WAAW;IAExB,wEAAwE;IAClE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B,yDAAyD;IACzD,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB,gFAAgF;IAChF,iBAAiB,IAAI,oBAAoB;IAIzC;;;;;;;OAOG;gBAEgB,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAG7E;;;;;;;OAOG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUnD;;;;;;;;;;;;;;;;;;OAkBG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAWxC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAV3C,QAAQ,CAAC,IAAI,UAAU;IAEvB,wEAAwE;IAClE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B,gFAAgF;IAChF,iBAAiB,IAAI,oBAAoB;gBAIZ,cAAc,EAAE,MAAM;IAEnD,0EAA0E;IACpE,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAInD,8BAA8B;IAC9B,OAAO,IAAI,MAAM;CAGlB;AAED;;;;;;GAMG;AACH,qBAAa,uBAAwB,YAAW,aAAa;IAWzD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAXzB,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,yDAAyD;IACzD,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB,OAAO,CAAC,QAAQ,CAAqC;gBAGlC,MAAM,EAAE,0BAA0B,EAClC,MAAM,EAAE,UAAU;IAG/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,+DAA+D;IACzD,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAInD,iBAAiB,IAAI,oBAAoB;CAS1C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ISapConfig, SapAuthType, SapConnectionType } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import type { ISapConfig, SapAuthType, SapConnectionType } from '@mcp-abap-adt/interfaces-adt';
|
|
2
2
|
export type { SapAuthType, SapConnectionType };
|
|
3
3
|
export type SapConfig = ISapConfig;
|
|
4
4
|
export declare function sapConfigSignature(config: ISapConfig): string;
|
|
@@ -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,
|
|
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,8BAA8B,CAAC;AAGtC,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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IAbapConnection, IAbapRequestOptions } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import type { IAbapConnection, IAbapRequestOptions } from '@mcp-abap-adt/interfaces-adt';
|
|
2
2
|
export type AbapRequestOptions = IAbapRequestOptions;
|
|
3
3
|
export type AbapConnection = IAbapConnection;
|
|
4
4
|
//# sourceMappingURL=AbapConnection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbapConnection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"AbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbapConnection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IAdtWireResponse, type ICriticalSection, type IRequestProfiling, type ISessionLifecycleAware } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import { type IAdtWireResponse, type ICriticalSection, type IRequestProfiling, type ISessionLifecycleAware } from '@mcp-abap-adt/interfaces-adt';
|
|
2
2
|
import type { SapConfig } from '../config/sapConfig.js';
|
|
3
3
|
import type { ILogger } from '../logger.js';
|
|
4
4
|
import { SessionLifecycle } from '../session/SessionLifecycle.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"AbstractAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/AbstractAbapConnection.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AbstractAbapConnection = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const
|
|
5
|
+
const interfaces_adt_1 = require("@mcp-abap-adt/interfaces-adt");
|
|
6
6
|
const SessionLifecycle_js_1 = require("../session/SessionLifecycle.js");
|
|
7
7
|
const networkErrors_js_1 = require("../utils/networkErrors.js");
|
|
8
8
|
const timeouts_js_1 = require("../utils/timeouts.js");
|
|
@@ -486,7 +486,7 @@ class AbstractAbapConnection {
|
|
|
486
486
|
}
|
|
487
487
|
async establishAndCommit(baselineEpoch) {
|
|
488
488
|
if (this.lifecycle.teardownEpoch !== baselineEpoch) {
|
|
489
|
-
throw (0, SessionLifecycle_js_1.sessionError)(
|
|
489
|
+
throw (0, SessionLifecycle_js_1.sessionError)(interfaces_adt_1.ADT_SESSION_ERROR.NOT_CONNECTED, 'Establishment abandoned: a teardown was requested for this connection');
|
|
490
490
|
}
|
|
491
491
|
// Whatever session arrives from here is one we are deliberately
|
|
492
492
|
// establishing, so it must not read as a replacement: the identity policy
|
|
@@ -561,7 +561,7 @@ class AbstractAbapConnection {
|
|
|
561
561
|
// the CSRF token and the axios instance out from under a request that is
|
|
562
562
|
// still in flight — breaking the guarantee this whole change rests on,
|
|
563
563
|
// from inside the guard meant to protect it.
|
|
564
|
-
throw (0, SessionLifecycle_js_1.sessionError)(
|
|
564
|
+
throw (0, SessionLifecycle_js_1.sessionError)(interfaces_adt_1.ADT_SESSION_ERROR.NOT_CONNECTED, 'Establishment abandoned: a teardown was requested while it was in flight');
|
|
565
565
|
}
|
|
566
566
|
// The session IS the SAP_SESSIONID the server issued; our own session id is
|
|
567
567
|
// a conversation label we generate and says nothing about what exists on
|
|
@@ -612,7 +612,7 @@ class AbstractAbapConnection {
|
|
|
612
612
|
this.invalidateSession();
|
|
613
613
|
this.lifecycle.forgetIdentity();
|
|
614
614
|
this.lifecycle.markDisconnected();
|
|
615
|
-
throw (0, SessionLifecycle_js_1.sessionError)(
|
|
615
|
+
throw (0, SessionLifecycle_js_1.sessionError)(interfaces_adt_1.ADT_SESSION_ERROR.NOT_CONNECTED, `The server authenticated the request but opened no ABAP session: the ${this.transport.kind} wire reports it is on none, so there is nothing for a lock to be bound to. The wire itself is fine — the request was carried and answered — which is why this is not a transport failure and does not look like one. ` +
|
|
616
616
|
'Stateless reads would still work over it, but a lock, and any write under that lock, is dead the moment it is issued. ' +
|
|
617
617
|
'The usual cause is the system declining to open another session for this user: they are limited per user, shared with every other tool logged on as them, and released either by disconnecting or by their own idle timeout. ' +
|
|
618
618
|
'Whether to wait, retry, or release sessions this user still holds is yours to decide — this library does not retry on your behalf.');
|
|
@@ -675,9 +675,9 @@ class AbstractAbapConnection {
|
|
|
675
675
|
*/
|
|
676
676
|
isSessionVerdict(error) {
|
|
677
677
|
const code = error?.code;
|
|
678
|
-
return (code ===
|
|
679
|
-
code ===
|
|
680
|
-
code ===
|
|
678
|
+
return (code === interfaces_adt_1.ADT_SESSION_ERROR.SESSION_REPLACED ||
|
|
679
|
+
code === interfaces_adt_1.ADT_SESSION_ERROR.NOT_CONNECTED ||
|
|
680
|
+
code === interfaces_adt_1.ADT_SESSION_ERROR.RELEASE_PENDING);
|
|
681
681
|
}
|
|
682
682
|
/**
|
|
683
683
|
* Folds a response into the session state AND acts on what it means, in one
|
|
@@ -728,7 +728,7 @@ class AbstractAbapConnection {
|
|
|
728
728
|
if (classification !== 'replaced')
|
|
729
729
|
return;
|
|
730
730
|
this.raiseSessionLost('the session cookie changed under us');
|
|
731
|
-
throw (0, SessionLifecycle_js_1.sessionError)(
|
|
731
|
+
throw (0, SessionLifecycle_js_1.sessionError)(interfaces_adt_1.ADT_SESSION_ERROR.SESSION_REPLACED, 'The SAP session this connection was using is gone and the requests are now on a different one; anything held against the old session — a lock and any write under it — is dead. ' +
|
|
732
732
|
'The server does not swap sessions on a whim: the usual causes are the session idling out (the timeout is idle-based, so a quiet connection loses it while a busy one does not) or a request landing on a different application server. ' +
|
|
733
733
|
'What to do about it is yours: re-establish and redo the work, or fail the operation. Nothing is retried here.');
|
|
734
734
|
}
|
|
@@ -975,7 +975,7 @@ class AbstractAbapConnection {
|
|
|
975
975
|
this.raiseSessionLost('the server reports the session no longer exists');
|
|
976
976
|
// No internal retry: a blind retry here is what produced further locks
|
|
977
977
|
// in the field. The caller decides.
|
|
978
|
-
throw (0, SessionLifecycle_js_1.sessionError)(
|
|
978
|
+
throw (0, SessionLifecycle_js_1.sessionError)(interfaces_adt_1.ADT_SESSION_ERROR.SESSION_REPLACED, 'The SAP session no longer exists; any lock handle from it is dead');
|
|
979
979
|
}
|
|
980
980
|
// Check if this is a network error (connection refused, timeout, DNS, etc.)
|
|
981
981
|
// Don't retry for network errors - these indicate infrastructure/VPN issues
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* inferred — not from the credential, not from the host name, not from what the
|
|
16
16
|
* server answers.
|
|
17
17
|
*/
|
|
18
|
-
import type { IAuthProvider } from '@mcp-abap-adt/interfaces';
|
|
18
|
+
import type { IAuthProvider } from '@mcp-abap-adt/interfaces-auth';
|
|
19
19
|
import type { SapConfig } from '../config/sapConfig.js';
|
|
20
20
|
import type { ILogger } from '../logger.js';
|
|
21
21
|
import type { CloudHttpTransport } from './CloudHttpTransport.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdtCloudConnector.d.ts","sourceRoot":"","sources":["../../src/connection/AdtCloudConnector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"AdtCloudConnector.d.ts","sourceRoot":"","sources":["../../src/connection/AdtCloudConnector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,qBAAa,iBAAiB,CAC5B,WAAW,SAAS,aAAa,GAAG,aAAa;AACjD;;;;GAIG;AACH,UAAU,SAAS,eAAe,GAAG,kBAAkB,CACvD,SAAQ,wBAAwB,CAAC,WAAW,CAAC;IAC7C,SAAiB,SAAS,EAAE,UAAU,CAAC;gBAGrC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,WAAW,EACvB,SAAS,EAAE,UAAU,EACrB,MAAM,GAAE,OAAO,GAAG,IAAW,EAC7B,SAAS,CAAC,EAAE,MAAM;CAIrB"}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* asked for this connector — not because of what is in the header, and not
|
|
17
17
|
* because anything worked out where it was pointing.
|
|
18
18
|
*/
|
|
19
|
-
import type { IAuthProvider } from '@mcp-abap-adt/interfaces';
|
|
19
|
+
import type { IAuthProvider } from '@mcp-abap-adt/interfaces-auth';
|
|
20
20
|
import type { SapConfig } from '../config/sapConfig.js';
|
|
21
21
|
import type { ILogger } from '../logger.js';
|
|
22
22
|
import { CredentialAbapConnection } from './CredentialAbapConnection.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdtOnPremConnector.d.ts","sourceRoot":"","sources":["../../src/connection/AdtOnPremConnector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"AdtOnPremConnector.d.ts","sourceRoot":"","sources":["../../src/connection/AdtOnPremConnector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,qBAAa,kBAAkB,CAC7B,WAAW,SAAS,aAAa,GAAG,aAAa;AACjD;;;;GAIG;AACH,UAAU,SAAS,gBAAgB,GAAG,mBAAmB,CACzD,SAAQ,wBAAwB,CAAC,WAAW,CAAC;IAC7C;;;;;;;OAOG;IACH,SAAiB,SAAS,EAAE,UAAU,CAAC;gBAGrC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,WAAW,EACvB,SAAS,EAAE,UAAU,EACrB,MAAM,GAAE,OAAO,GAAG,IAAW,EAC7B,SAAS,CAAC,EAAE,MAAM;CAIrB"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* chose the subclass, and is never worked out here.
|
|
14
14
|
*/
|
|
15
15
|
import type { AgentOptions } from 'node:https';
|
|
16
|
-
import type { IAuthProvider } from '@mcp-abap-adt/interfaces';
|
|
16
|
+
import type { IAuthProvider } from '@mcp-abap-adt/interfaces-auth';
|
|
17
17
|
import type { SapConfig } from '../config/sapConfig.js';
|
|
18
18
|
import type { ILogger } from '../logger.js';
|
|
19
19
|
import { AbstractAbapConnection } from './AbstractAbapConnection.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/CredentialAbapConnection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"CredentialAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/CredentialAbapConnection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,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;AACrE,OAAO,EAAE,KAAK,aAAa,EAAa,MAAM,oBAAoB,CAAC;AASnE,8BAAsB,wBAAwB,CAC5C,WAAW,SAAS,aAAa,GAAG,aAAa,CACjD,SAAQ,sBAAsB;IAG5B,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,WAAW;gBAFhC,MAAM,EAAE,SAAS;IACjB,6EAA6E;IACpE,UAAU,EAAE,WAAW,EAChC,SAAS,EAAE,aAAa,EACxB,MAAM,GAAE,OAAO,GAAG,IAAW,EAC7B,SAAS,CAAC,EAAE,MAAM;IAKpB;;;;;;;OAOG;IACH,gEAAgE;cAEvC,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3D;;;;;OAKG;IACH,SAAS,CAAC,wBAAwB,IAAI,MAAM;IAI5C;;;;;;OAMG;IACY,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;cAiB7C,oBAAoB,IAAI,YAAY;cAIvC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CAoDlD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IWebSocketCloseInfo, IWebSocketConnectOptions, IWebSocketMessageEnvelope, IWebSocketMessageHandler, IWebSocketTransport } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import type { IWebSocketCloseInfo, IWebSocketConnectOptions, IWebSocketMessageEnvelope, IWebSocketMessageHandler, IWebSocketTransport } from '@mcp-abap-adt/interfaces-network';
|
|
2
2
|
/**
|
|
3
3
|
* Minimal WS-like instance contract to avoid hard dependency on a specific WS library.
|
|
4
4
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenericWebSocketTransport.d.ts","sourceRoot":"","sources":["../../src/connection/GenericWebSocketTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"GenericWebSocketTransport.d.ts","sourceRoot":"","sources":["../../src/connection/GenericWebSocketTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,kCAAkC,CAAC;AAE1C;;GAEG;AACH,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,OAAO,EACH,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC,GACzE,IAAI,CAAC;CACV;AAED,UAAU,iBAAiB;IACzB,MAAM,CACJ,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAC7B,OAAO,CAAC,EAAE,wBAAwB,GACjC,cAAc,CAAC;CACnB;AAID,qBAAa,yBAA0B,YAAW,mBAAmB;IASvD,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,eAAe,CAAgD;IACvE,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,aAAa,CAAqD;IAC1E,OAAO,CAAC,aAAa,CAEd;gBAEsB,OAAO,EAAE,iBAAiB;IAEjD,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,IAAI,CAAC;IAqDV,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzD,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC;IAQhB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,IAAI;IAIlE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIjD,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI3E,WAAW,IAAI,OAAO;YAIR,qBAAqB;IAoBnC,OAAO,CAAC,cAAc;YAUR,QAAQ;YAMR,SAAS;YAMT,SAAS;CAKxB;AAED,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -26,9 +26,29 @@ export interface IRfcConversation {
|
|
|
26
26
|
call(fm: string, params: Record<string, unknown>): Promise<Record<string, any>>;
|
|
27
27
|
readonly alive: boolean;
|
|
28
28
|
}
|
|
29
|
+
/** What this wire does beyond carrying the request. */
|
|
30
|
+
export interface IRfcTransportOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Whether the debug channel also carries the request headers and both
|
|
33
|
+
* bodies. Off by default, and deliberately not inferred from the presence
|
|
34
|
+
* of a logger: `ILogger` has no level predicate, so `logger?.debug()` cannot
|
|
35
|
+
* tell an enabled debug channel from a discarded one — without this flag
|
|
36
|
+
* every caller who passes a logger at all would pay to build and throw away
|
|
37
|
+
* a copy of every body on the wire.
|
|
38
|
+
*/
|
|
39
|
+
logWire?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Ceiling on a logged body, in characters. Defaults to 2000. `0` logs the
|
|
42
|
+
* size and none of the bytes, `Infinity` asks for the whole body, and a
|
|
43
|
+
* negative or `NaN` value falls back to the default rather than throwing —
|
|
44
|
+
* a debug option is not worth failing a connection over.
|
|
45
|
+
*/
|
|
46
|
+
maxLoggedBodyChars?: number;
|
|
47
|
+
}
|
|
29
48
|
export declare class RfcTransport implements IOnPremTransport {
|
|
30
49
|
private readonly connect;
|
|
31
50
|
private readonly logger;
|
|
51
|
+
private readonly options;
|
|
32
52
|
readonly kind = "rfc";
|
|
33
53
|
/** Which system this wire is for. Read by the compiler, never at runtime. */
|
|
34
54
|
readonly system: "onprem";
|
|
@@ -80,7 +100,9 @@ export declare class RfcTransport implements IOnPremTransport {
|
|
|
80
100
|
* that reached for it in its constructor could not be built at all on a
|
|
81
101
|
* machine without it.
|
|
82
102
|
*/
|
|
83
|
-
constructor(connect: () => IRfcConversation, logger?: ILogger | null);
|
|
103
|
+
constructor(connect: () => IRfcConversation, logger?: ILogger | null, options?: IRfcTransportOptions);
|
|
104
|
+
/** Cut a body down to what a log line may carry. */
|
|
105
|
+
private clipped;
|
|
84
106
|
open(): Promise<void>;
|
|
85
107
|
/** Never throws, and a repeat call finds nothing owed. */
|
|
86
108
|
close(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RfcTransport.d.ts","sourceRoot":"","sources":["../../src/connection/RfcTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EACV,oBAAoB,EAEpB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CACF,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"RfcTransport.d.ts","sourceRoot":"","sources":["../../src/connection/RfcTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EACV,oBAAoB,EAEpB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAE5B,sFAAsF;AACtF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CACF,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAgFD,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAKD,qBAAa,YAAa,YAAW,gBAAgB;IA+EjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhF1B,QAAQ,CAAC,IAAI,SAAS;IAEtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAG,QAAQ,CAAU;IAEpC,OAAO,CAAC,YAAY,CAAiC;IACrD,kEAAkE;IAClE,OAAO,CAAC,cAAc,CAAM;IAE5B;;;;;;OAMG;IACH,MAAM,IAAI,IAAI;IAEd,2CAA2C;IAC3C,OAAO,IAAI,IAAI;IAIf;;;;;OAKG;IACG,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9D,+BAA+B;IAC/B,SAAS,IAAI,IAAI;IAIjB;;;OAGG;IACH,cAAc,IAAI,IAAI;IAEtB;;;OAGG;IACH,6EAA6E;IAC7E,kBAAkB,IAAI,OAAO;IAI7B,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAQzC,2EAA2E;IAC3E,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIzC;;;;OAIG;IACH,aAAa,IAAI,IAAI;IAErB;;;;;OAKG;gBAEgB,OAAO,EAAE,MAAM,gBAAgB,EAC/B,MAAM,GAAE,OAAO,GAAG,IAAW,EAC7B,OAAO,GAAE,oBAAyB;IAGrD,oDAAoD;IACpD,OAAO,CAAC,OAAO;IAcT,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B,0DAA0D;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,IAAI,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAkK1E"}
|
|
@@ -48,11 +48,52 @@ function message(e) {
|
|
|
48
48
|
return JSON.stringify(e);
|
|
49
49
|
return String(e);
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Header names whose VALUE must never reach a log.
|
|
53
|
+
*
|
|
54
|
+
* `Authorization` carries the Basic-auth credential in plain (base64, but that
|
|
55
|
+
* is not encryption) form — and it is not the only one. `request.headers`
|
|
56
|
+
* reaches this wire verbatim from the caller, so a consumer's `Cookie`
|
|
57
|
+
* (`SAP_SESSIONID_*`, `MYSAPSSO2`), an `x-csrf-token` or its own `X-Api-Key`
|
|
58
|
+
* arrives here too. A log line advertised as safe to paste into an issue has
|
|
59
|
+
* to be safe for the headers nobody here anticipated, so this matches by
|
|
60
|
+
* pattern rather than by the list we happened to think of.
|
|
61
|
+
*/
|
|
62
|
+
const SECRET_HEADER_PATTERNS = [
|
|
63
|
+
/authorization/i,
|
|
64
|
+
/cookie/i,
|
|
65
|
+
/token/i,
|
|
66
|
+
/secret/i,
|
|
67
|
+
/password/i,
|
|
68
|
+
/credential/i,
|
|
69
|
+
/api[-_]?key/i,
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* The NAME is kept and only the VALUE goes — a redacted header still says it
|
|
73
|
+
* was sent, which is half of what the log is read for.
|
|
74
|
+
*/
|
|
75
|
+
function redactHeaders(fields) {
|
|
76
|
+
return fields.map((field) => SECRET_HEADER_PATTERNS.some((pattern) => pattern.test(field.NAME))
|
|
77
|
+
? { ...field, VALUE: '[redacted]' }
|
|
78
|
+
: field);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* How much of a body a log line carries before it is cut. An ADT payload is
|
|
82
|
+
* an ABAP source or a repository listing: whole ones are megabytes, and a log
|
|
83
|
+
* sink handed a single line that size is a problem of its own.
|
|
84
|
+
*/
|
|
85
|
+
const DEFAULT_MAX_LOGGED_BODY_CHARS = 2000;
|
|
86
|
+
function clip(text, max) {
|
|
87
|
+
return text.length <= max
|
|
88
|
+
? text
|
|
89
|
+
: `${text.slice(0, max)}… (+${text.length - max} more chars)`;
|
|
90
|
+
}
|
|
51
91
|
/** Axios's own default, which the classification above this seam is written against. */
|
|
52
92
|
const admits2xx = (status) => status >= 200 && status < 300;
|
|
53
93
|
class RfcTransport {
|
|
54
94
|
connect;
|
|
55
95
|
logger;
|
|
96
|
+
options;
|
|
56
97
|
kind = 'rfc';
|
|
57
98
|
/** Which system this wire is for. Read by the compiler, never at runtime. */
|
|
58
99
|
system = 'onprem';
|
|
@@ -118,9 +159,22 @@ class RfcTransport {
|
|
|
118
159
|
* that reached for it in its constructor could not be built at all on a
|
|
119
160
|
* machine without it.
|
|
120
161
|
*/
|
|
121
|
-
constructor(connect, logger = null) {
|
|
162
|
+
constructor(connect, logger = null, options = {}) {
|
|
122
163
|
this.connect = connect;
|
|
123
164
|
this.logger = logger;
|
|
165
|
+
this.options = options;
|
|
166
|
+
}
|
|
167
|
+
/** Cut a body down to what a log line may carry. */
|
|
168
|
+
clipped(text) {
|
|
169
|
+
const asked = this.options.maxLoggedBodyChars ?? DEFAULT_MAX_LOGGED_BODY_CHARS;
|
|
170
|
+
// A nonsense ceiling is a typo in a debug option, and a debug option is
|
|
171
|
+
// not worth failing a connection over — but it is worth not honouring. A
|
|
172
|
+
// negative one reaches `slice(0, -n)`, which drops the END of the body
|
|
173
|
+
// while the line still says the rest was merely clipped: a log that lies
|
|
174
|
+
// about what it cut is worse than one that cut too much. `NaN` compares
|
|
175
|
+
// false against every bound, so the test is for the good case.
|
|
176
|
+
const ceiling = asked >= 0 ? Math.floor(asked) : DEFAULT_MAX_LOGGED_BODY_CHARS;
|
|
177
|
+
return clip(text, ceiling);
|
|
124
178
|
}
|
|
125
179
|
async open() {
|
|
126
180
|
if (this.conversation?.alive)
|
|
@@ -187,6 +241,19 @@ class RfcTransport {
|
|
|
187
241
|
});
|
|
188
242
|
}
|
|
189
243
|
this.logger?.debug(`RFC → ${method} ${uri}`);
|
|
244
|
+
// `RFC → METHOD URI` alone was not enough to debug a body that goes
|
|
245
|
+
// missing or gets mis-serialised on the way to `SADT_REST_RFC_ENDPOINT`
|
|
246
|
+
// (found chasing a `superPackage` that disappeared before it reached
|
|
247
|
+
// SAP) — the actual bytes matter, so the debug channel carries them too
|
|
248
|
+
// when the caller asks for it, redacted and clipped so a captured log is
|
|
249
|
+
// safe to paste into an issue and small enough to want to.
|
|
250
|
+
if (this.logger && this.options.logWire) {
|
|
251
|
+
this.logger.debug(`RFC HEADERS: ${JSON.stringify(redactHeaders(headerFields))}`);
|
|
252
|
+
// A GET has no body, and `RFC BODY (0 chars):` says nothing.
|
|
253
|
+
if (body) {
|
|
254
|
+
this.logger.debug(`RFC BODY (${body.length} chars): ${this.clipped(body)}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
190
257
|
// `request.timeout` is deliberately not read, and the absence of the word
|
|
191
258
|
// here is what made that look like an oversight (#42).
|
|
192
259
|
//
|
|
@@ -252,6 +319,11 @@ class RfcTransport {
|
|
|
252
319
|
statusText = statusText || 'OK';
|
|
253
320
|
}
|
|
254
321
|
this.logger?.debug(`RFC ← ${status} ${statusText} (${data.length} bytes)`);
|
|
322
|
+
// The line above already carries the size, so an empty body needs no line
|
|
323
|
+
// of its own.
|
|
324
|
+
if (this.logger && this.options.logWire && data) {
|
|
325
|
+
this.logger.debug(`RFC RESPONSE BODY: ${this.clipped(data)}`);
|
|
326
|
+
}
|
|
255
327
|
const response = {
|
|
256
328
|
status,
|
|
257
329
|
statusText,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { IWebSocketCloseInfo, IWebSocketConnectOptions, IWebSocketMessageEnvelope, IWebSocketMessageHandler, IWebSocketTransport, } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
export type { IWebSocketCloseInfo, IWebSocketConnectOptions, IWebSocketMessageEnvelope, IWebSocketMessageHandler, IWebSocketTransport, } from '@mcp-abap-adt/interfaces-network';
|
|
2
2
|
export { FileCertificateMaterialLoader } from './auth/FileCertificateMaterialLoader.js';
|
|
3
3
|
export { BasicAuthProvider, CertificateAuthProvider, SamlAuthProvider, TokenAuthProvider, } from './auth/providers.js';
|
|
4
4
|
export type { SapAuthType, SapConfig, SapConnectionType, } from './config/sapConfig.js';
|
|
@@ -13,7 +13,7 @@ export { HttpTransport } from './connection/HttpTransport.js';
|
|
|
13
13
|
export type { IAdtEstablishContext, IAdtSessionContext, IAdtTransport, IAdtTransportRequest, IAdtTransportResponse, ICloudTransport, IOnPremTransport, } from './connection/IAdtTransport.js';
|
|
14
14
|
export { LegacyOnPremHttpTransport } from './connection/LegacyOnPremHttpTransport.js';
|
|
15
15
|
export { OnPremHttpTransport } from './connection/OnPremHttpTransport.js';
|
|
16
|
-
export { type IRfcConversation, RfcTransport, } from './connection/RfcTransport.js';
|
|
16
|
+
export { type IRfcConversation, type IRfcTransportOptions, RfcTransport, } from './connection/RfcTransport.js';
|
|
17
17
|
export { type RfcConnectionParams, rfcConversationFrom, rfcParamsFrom, } from './connection/rfcConversation.js';
|
|
18
18
|
export type { ILogger } from './logger.js';
|
|
19
19
|
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":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAKxF,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,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;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAQxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,YAAY,GACb,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,aAAa,GACd,MAAM,iCAAiC,CAAC;AACzC,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,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Types - re-exported from
|
|
2
|
+
// Types - re-exported from the contract packages, under the names this
|
|
3
|
+
// package has always published them by.
|
|
3
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
5
|
exports.getTimeoutConfig = exports.getTimeout = exports.rfcParamsFrom = exports.rfcConversationFrom = exports.RfcTransport = exports.OnPremHttpTransport = exports.LegacyOnPremHttpTransport = exports.HttpTransport = exports.GenericWebSocketTransport = exports.CSRF_ERROR_MESSAGES = exports.CSRF_CONFIG = exports.CloudHttpTransport = exports.AdtOnPremConnector = exports.AdtCloudConnector = exports.sapConfigSignature = exports.TokenAuthProvider = exports.SamlAuthProvider = exports.CertificateAuthProvider = exports.BasicAuthProvider = exports.FileCertificateMaterialLoader = void 0;
|
|
5
6
|
var FileCertificateMaterialLoader_js_1 = require("./auth/FileCertificateMaterialLoader.js");
|
|
6
7
|
Object.defineProperty(exports, "FileCertificateMaterialLoader", { enumerable: true, get: function () { return FileCertificateMaterialLoader_js_1.FileCertificateMaterialLoader; } });
|
|
7
8
|
// IAuthProvider is deliberately NOT re-exported. It lives in
|
|
8
|
-
// @mcp-abap-adt/interfaces and a consumer imports it from there — the same rule
|
|
9
|
+
// @mcp-abap-adt/interfaces-auth and a consumer imports it from there — the same rule
|
|
9
10
|
// the session-lifecycle vocabulary follows below, and for the same reason: two
|
|
10
11
|
// names for one contract let the two drift.
|
|
11
12
|
var providers_js_1 = require("./auth/providers.js");
|
|
@@ -23,7 +24,7 @@ Object.defineProperty(exports, "AdtOnPremConnector", { enumerable: true, get: fu
|
|
|
23
24
|
var CloudHttpTransport_js_1 = require("./connection/CloudHttpTransport.js");
|
|
24
25
|
Object.defineProperty(exports, "CloudHttpTransport", { enumerable: true, get: function () { return CloudHttpTransport_js_1.CloudHttpTransport; } });
|
|
25
26
|
// The session lifecycle vocabulary — ISessionLifecycleAware, ADT_SESSION_ERROR —
|
|
26
|
-
// is deliberately NOT exported here. It lives in @mcp-abap-adt/interfaces, and a
|
|
27
|
+
// is deliberately NOT exported here. It lives in @mcp-abap-adt/interfaces-adt, and a
|
|
27
28
|
// consumer imports it from there: re-exporting a contract type gives it two
|
|
28
29
|
// names and lets the two drift.
|
|
29
30
|
// Connection classes - only final implementations
|
package/dist/logger.d.ts
CHANGED
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAG9D,YAAY,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* anything held against the old one;
|
|
26
26
|
* an unchanged one says nothing about whether the server still has it.
|
|
27
27
|
*/
|
|
28
|
-
import { type AdtSessionErrorCode } from '@mcp-abap-adt/interfaces';
|
|
28
|
+
import { type AdtSessionErrorCode } from '@mcp-abap-adt/interfaces-adt';
|
|
29
29
|
export type TransitionKind = 'connect' | 'disconnect' | 'recover' | 'cleanup';
|
|
30
30
|
export interface RequestLease {
|
|
31
31
|
/** Teardown epoch at admission — the baseline a recovery compares against. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionLifecycle.d.ts","sourceRoot":"","sources":["../../src/session/SessionLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"SessionLifecycle.d.ts","sourceRoot":"","sources":["../../src/session/SessionLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,0FAA0F;IAC1F,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC9B,iFAAiF;IACjF,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,mBAAmB,EACzB,OAAO,CAAC,EAAE,MAAM,GACf,KAAK,GAAG;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,CAMvC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgD;IAC7D,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAK;IAErB,OAAO,CAAC,IAAI,CAAuC;IACnD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,WAAW,CAAiC;IAIpD,4EAA4E;IAC5E,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,0EAA0E;IAC1E,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAM5B;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;;;;;;;;;;OAaG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;;;;OAKG;IACH,aAAa,CAAC,WAAW,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa,GAAG,IAAI;IAOzE;;;;;;OAMG;IACH,cAAc,IAAI,IAAI;IAItB,gBAAgB,IAAI,IAAI;IAKxB;;;;;;OAMG;IACH,OAAO,CACL,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC,WAAW,GAAG,aAAa,GAAG,UAAU;IAiB3C,YAAY,IAAI,IAAI;IAMpB,4EAA4E;IAC5E,YAAY,IAAI,YAAY;IAiB5B,2FAA2F;IAC3F,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,OAAO;IAM3D,aAAa,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,oBAAoB,GAAG,IAAI;IAelE,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAID;;;;;;;;;OASG;IACH,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAuBvE"}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.SessionLifecycle = void 0;
|
|
31
31
|
exports.sessionError = sessionError;
|
|
32
|
-
const
|
|
32
|
+
const interfaces_adt_1 = require("@mcp-abap-adt/interfaces-adt");
|
|
33
33
|
function sessionError(code, message) {
|
|
34
34
|
const error = new Error(message ?? code);
|
|
35
35
|
error.code = code;
|
|
@@ -130,7 +130,7 @@ class SessionLifecycle {
|
|
|
130
130
|
// ------------------------------------------------------------ admission ---
|
|
131
131
|
assertUsable() {
|
|
132
132
|
if (this.state !== 'connected' || this.teardownPending) {
|
|
133
|
-
throw sessionError(
|
|
133
|
+
throw sessionError(interfaces_adt_1.ADT_SESSION_ERROR.NOT_CONNECTED);
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
/** Asserts usability and counts the request in, in one synchronous step. */
|
|
@@ -15,8 +15,8 @@ exports.isNetworkError = isNetworkError;
|
|
|
15
15
|
* infrastructure, and retrying it re-runs the same failure against the same
|
|
16
16
|
* unreachable host.
|
|
17
17
|
*/
|
|
18
|
-
const
|
|
19
|
-
const CODES = new Set(Object.values(
|
|
18
|
+
const interfaces_network_1 = require("@mcp-abap-adt/interfaces-network");
|
|
19
|
+
const CODES = new Set(Object.values(interfaces_network_1.NETWORK_ERROR_CODES));
|
|
20
20
|
function isNetworkError(error) {
|
|
21
21
|
if (!error || typeof error !== 'object')
|
|
22
22
|
return false;
|
package/dist/utils/timeouts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ITimeoutConfig } from '@mcp-abap-adt/interfaces';
|
|
1
|
+
import type { ITimeoutConfig } from '@mcp-abap-adt/interfaces-network';
|
|
2
2
|
export type TimeoutConfig = ITimeoutConfig;
|
|
3
3
|
export declare function getTimeoutConfig(): ITimeoutConfig;
|
|
4
4
|
export declare function getTimeout(type?: 'default' | 'csrf' | 'long' | number): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeouts.d.ts","sourceRoot":"","sources":["../../src/utils/timeouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"timeouts.d.ts","sourceRoot":"","sources":["../../src/utils/timeouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGvE,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC;AAE3C,wBAAgB,gBAAgB,IAAI,cAAc,CAajD;AAED,wBAAgB,UAAU,CACxB,IAAI,GAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAkB,GACrD,MAAM,CAOR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Token refresh utilities for JWT authentication
|
|
3
3
|
*/
|
|
4
|
-
import type { ITokenRefreshResult } from '@mcp-abap-adt/interfaces';
|
|
4
|
+
import type { ITokenRefreshResult } from '@mcp-abap-adt/interfaces-adt';
|
|
5
5
|
export type TokenRefreshResult = ITokenRefreshResult;
|
|
6
6
|
/**
|
|
7
7
|
* Refreshes the access token using refresh token
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../../src/utils/tokenRefresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../../src/utils/tokenRefresh.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAIxE,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,mBAAmB,CAAC,CA0C9B"}
|
package/docs/INDEX.md
CHANGED
|
@@ -15,6 +15,7 @@ mcp-abap-connection/
|
|
|
15
15
|
│ ├── INSTALLATION.md # Setup and installation guide
|
|
16
16
|
│ ├── USAGE.md # API documentation and examples
|
|
17
17
|
│ ├── MIGRATION-2.0.md # Moving to the explicit session lifecycle
|
|
18
|
+
│ ├── MIGRATION-9.0.md # the contracts split out of @mcp-abap-adt/interfaces
|
|
18
19
|
│ ├── MIGRATION-8.0.md # request headers leave the stateful branch; onto interfaces 39; flushGoodbye
|
|
19
20
|
│ ├── MIGRATION-6.0.md # the factory and the per-credential classes go; RFC is a transport
|
|
20
21
|
│ ├── MIGRATION-4.0.md # JWT error classification: 401 refreshes, 403 propagates
|
|
@@ -45,6 +46,7 @@ mcp-abap-connection/
|
|
|
45
46
|
- 🔑 [JWT Auth Tools](./JWT_AUTH_TOOLS.md) - CLI tool for browser-based authentication
|
|
46
47
|
|
|
47
48
|
### Upgrading
|
|
49
|
+
- 🚚 [Migrating to 9.0.0](./MIGRATION-9.0.md) - the contracts split into `interfaces-adt`, `-auth`, `-network` and `-utils`; this package no longer depends on the umbrella
|
|
48
50
|
- 🚚 [Migrating to 7.0.0 and 8.0.0](./MIGRATION-8.0.md) - `sap-adt-request-id` and `X-sap-adt-profiling` on every request, `x-sap-security-session: use` on cloud, the contracts floor at 39, and `flushGoodbye()`
|
|
49
51
|
- 🚚 [Migrating to 6.0.0](./MIGRATION-6.0.md) - the factory and the per-credential classes are removed; the RFC wire is a transport you hand to the on-prem connector
|
|
50
52
|
- 🧱 [Migrating to 4.0.0](./MIGRATION-4.0.md) - JWT error classification: a 401 refreshes, a 403 propagates with the server's message
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -198,6 +198,25 @@ node test-connection.js
|
|
|
198
198
|
npm install --save-dev typescript @types/node
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
+
### Install the contracts you name
|
|
202
|
+
|
|
203
|
+
`@mcp-abap-adt/connection` no longer brings the contract packages along, so
|
|
204
|
+
anything your own signatures name has to be installed. Install the ones you
|
|
205
|
+
actually use:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm install @mcp-abap-adt/interfaces-adt # IAbapConnection, ISapConfig, ITokenRefresher, ADT_SESSION_ERROR
|
|
209
|
+
npm install @mcp-abap-adt/interfaces-auth # IAuthProvider, IRenewableCredential
|
|
210
|
+
npm install @mcp-abap-adt/interfaces-network # ITimeoutConfig, the WebSocket contracts
|
|
211
|
+
npm install @mcp-abap-adt/interfaces-utils # ILogger
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Nothing is needed here if you only call what this package exports — the types
|
|
215
|
+
travel with it. Do **not** reach for `@mcp-abap-adt/interfaces`: that name is an
|
|
216
|
+
umbrella of deprecated re-exports, and installing it alongside a contract
|
|
217
|
+
package at a different major puts two copies of the same contract in your tree.
|
|
218
|
+
[Migration to 9.0.0](./MIGRATION-9.0.md) has the details.
|
|
219
|
+
|
|
201
220
|
### Create `tsconfig.json`
|
|
202
221
|
|
|
203
222
|
```json
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Migration to 9.0
|
|
2
|
+
|
|
3
|
+
**No code of yours that only uses this package's own exports has to change.**
|
|
4
|
+
Nothing was renamed here, no signature moved, no behaviour is different. What
|
|
5
|
+
changed is where the *contracts* come from.
|
|
6
|
+
|
|
7
|
+
`@mcp-abap-adt/interfaces` split. The contracts now live in four packages:
|
|
8
|
+
|
|
9
|
+
| Package | What is in it |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `@mcp-abap-adt/interfaces-adt` | The ADT vocabulary: `IAbapConnection`, `IAbapRequestOptions`, `IAdtWireResponse`, `IAdtResponse`, `ISapConfig`, `SapAuthType`, `SapConnectionType`, `ITokenRefresher`, `ITokenRefreshResult`, `ITokenProvider`, `ICertificateMaterialLoader`, and the capability atoms — `ISessionLifecycleAware`, `ICriticalSection`, `IRequestProfiling` — with `ADT_SESSION_ERROR` and `AdtSessionErrorCode` |
|
|
12
|
+
| `@mcp-abap-adt/interfaces-auth` | The credential axis: `IAuthProvider`, `IRenewableCredential`, `ICertificateMaterial` |
|
|
13
|
+
| `@mcp-abap-adt/interfaces-network` | The wire: `ITimeoutConfig`, `NETWORK_ERROR_CODES`, and the WebSocket contracts — `IWebSocketTransport`, `IWebSocketConnectOptions`, `IWebSocketCloseInfo`, `IWebSocketMessageEnvelope`, `IWebSocketMessageHandler` |
|
|
14
|
+
| `@mcp-abap-adt/interfaces-utils` | `ILogger` |
|
|
15
|
+
|
|
16
|
+
This package now depends on those four and **no longer depends on
|
|
17
|
+
`@mcp-abap-adt/interfaces` at all**. That is the breaking part, and it is the
|
|
18
|
+
only breaking part: a consumer who was getting the umbrella transitively through
|
|
19
|
+
this package stops getting it.
|
|
20
|
+
|
|
21
|
+
## What you do
|
|
22
|
+
|
|
23
|
+
If you never import contract types yourself — you take what
|
|
24
|
+
`@mcp-abap-adt/connection` exports and nothing else — install and carry on.
|
|
25
|
+
|
|
26
|
+
If you do import them, move each import to the package it now lives in. Install
|
|
27
|
+
the ones you name:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @mcp-abap-adt/interfaces-adt @mcp-abap-adt/interfaces-auth
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Before:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import type { IAuthProvider, ITokenRefresher } from '@mcp-abap-adt/interfaces';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
After:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import type { IAuthProvider } from '@mcp-abap-adt/interfaces-auth';
|
|
43
|
+
import type { ITokenRefresher } from '@mcp-abap-adt/interfaces-adt';
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The table above says which package each name went to. Nothing was renamed, so
|
|
47
|
+
the names themselves are the same ones you already use.
|
|
48
|
+
|
|
49
|
+
## You can also do nothing yet
|
|
50
|
+
|
|
51
|
+
The umbrella still exists and still re-exports every one of these names, so code
|
|
52
|
+
importing from `@mcp-abap-adt/interfaces` keeps compiling — as long as you
|
|
53
|
+
install it yourself, which you now must, since this package no longer brings it
|
|
54
|
+
along.
|
|
55
|
+
|
|
56
|
+
Every one of those re-exports is marked `@deprecated`. They are a bridge, not a
|
|
57
|
+
destination: a build that is green on them is green on something advertised as
|
|
58
|
+
going away, and the compiler will keep saying so. Moving the imports is a
|
|
59
|
+
mechanical change and it is better done while it is only an import line.
|
|
60
|
+
|
|
61
|
+
## Why this package stopped using the umbrella
|
|
62
|
+
|
|
63
|
+
Not because a re-export loses anything. It does not: imported through the
|
|
64
|
+
umbrella and imported directly, `IAuthProvider` is the *same type* — a
|
|
65
|
+
re-export names the same declaration, and TypeScript agrees.
|
|
66
|
+
|
|
67
|
+
The reason is that the umbrella decides **which version** of each contract
|
|
68
|
+
package you get. It carries its own ranges — `interfaces-adt: ^6.0.0`,
|
|
69
|
+
`interfaces-auth: ^1.0.0`, and so on. A consumer who also names a contract
|
|
70
|
+
package directly, at a version outside those ranges, ends up with two physical
|
|
71
|
+
copies in the tree: the direct one at the root, the umbrella's nested beneath
|
|
72
|
+
it. That is observable today — `interfaces-adt` has published majors 1 through
|
|
73
|
+
6, so a project on `interfaces-adt@4` plus the umbrella gets 4 at the root and 6
|
|
74
|
+
underneath.
|
|
75
|
+
|
|
76
|
+
Two copies are harmless everywhere their shapes agree, because TypeScript is
|
|
77
|
+
structural. They stop being harmless exactly where the shapes differ — and then
|
|
78
|
+
the error lands at the boundary between two packages rather than at the version
|
|
79
|
+
skew that caused it.
|
|
80
|
+
|
|
81
|
+
Depending on the packages directly makes the version this package's own
|
|
82
|
+
decision, and makes `npm ls` able to answer the question.
|
|
83
|
+
|
|
84
|
+
The second reason is simpler: every export on the umbrella is marked
|
|
85
|
+
`@deprecated`. Building on it means its eventual removal becomes a breaking
|
|
86
|
+
change for this package at a moment chosen by someone else.
|
|
87
|
+
|
|
88
|
+
## Checking what you ended up with
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm ls @mcp-abap-adt/interfaces-adt # should print one version, deduped
|
|
92
|
+
npm ls @mcp-abap-adt/interfaces-auth
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Two versions of a contract package in one tree is the failure this release is
|
|
96
|
+
avoiding. If `npm ls` shows a nested copy, something in your dependency graph is
|
|
97
|
+
still pinning an older range.
|
package/docs/SCOPE.md
CHANGED
|
@@ -14,9 +14,9 @@ This package is **one component of the `@mcp-abap-adt/*` family**. Each package
|
|
|
14
14
|
| Concern | Belongs in |
|
|
15
15
|
|---|---|
|
|
16
16
|
| Token acquisition (SAML/OAuth2 flows, browser login, PKCE) | `@mcp-abap-adt/auth-broker` |
|
|
17
|
-
| Token validation, refresh, re-authentication, expiry tracking | consumer via `ITokenProvider` (from `@mcp-abap-adt/interfaces`) |
|
|
17
|
+
| Token validation, refresh, re-authentication, expiry tracking | consumer via `ITokenProvider` (from `@mcp-abap-adt/interfaces-adt`) |
|
|
18
18
|
| Session state persistence across processes | `@mcp-abap-adt/auth-broker` |
|
|
19
|
-
| Auth-type constants, provider error codes, auth lifecycle contracts | `@mcp-abap-adt/interfaces` |
|
|
19
|
+
| Auth-type constants, provider error codes, auth lifecycle contracts | `@mcp-abap-adt/interfaces-adt`, `@mcp-abap-adt/interfaces-auth` |
|
|
20
20
|
|
|
21
21
|
The rule: **if it is about *acquiring* or *refreshing* credentials, it is not our job.** We receive credentials that are valid at call time and use them. The consumer is responsible for handing us fresh ones — they know their IdP, their refresh cadence, their re-auth UX.
|
|
22
22
|
|
|
@@ -41,4 +41,4 @@ It forwards every `(name, value)` pair from the JS `Client(params)` object to `R
|
|
|
41
41
|
|
|
42
42
|
- [`INSTALLATION.md`](./INSTALLATION.md)
|
|
43
43
|
- [`USAGE.md`](./USAGE.md)
|
|
44
|
-
- Sibling packages: `@mcp-abap-adt/interfaces`, `@mcp-abap-adt/sap-rfc-lite`, `@mcp-abap-adt/auth-broker`
|
|
44
|
+
- Sibling packages: `@mcp-abap-adt/interfaces-adt`, `@mcp-abap-adt/interfaces-auth`, `@mcp-abap-adt/interfaces-network`, `@mcp-abap-adt/interfaces-utils`, `@mcp-abap-adt/sap-rfc-lite`, `@mcp-abap-adt/auth-broker`
|
|
@@ -206,7 +206,7 @@ lock is still very much held. That — not any teardown — is why
|
|
|
206
206
|
duration of a `lock → modify → unlock` chain.
|
|
207
207
|
|
|
208
208
|
Since 8.0.0 you reach it through the contract rather than the class: it is
|
|
209
|
-
`ICriticalSection` in `@mcp-abap-adt/interfaces`, which this connection declares.
|
|
209
|
+
`ICriticalSection` in `@mcp-abap-adt/interfaces-adt`, which this connection declares.
|
|
210
210
|
What it promises is narrow and worth stating exactly — inside a section the
|
|
211
211
|
*ordinary* per-request deadline does not apply. Not that no request can be cut
|
|
212
212
|
short: the ceiling is `SAP_TIMEOUT_CRITICAL`, ten minutes by default, and a
|
package/docs/USAGE.md
CHANGED
|
@@ -299,7 +299,7 @@ implied. Four things follow from it.
|
|
|
299
299
|
|
|
300
300
|
> **Availability.** `connect()` is on the shared `IAbapConnection` contract and
|
|
301
301
|
> works on every connection. The rest of this section is on the contract too, but
|
|
302
|
-
> as a **capability atom** in `@mcp-abap-adt/interfaces` rather than as methods on
|
|
302
|
+
> as a **capability atom** in `@mcp-abap-adt/interfaces-adt` rather than as methods on
|
|
303
303
|
> `IAbapConnection`: `ISessionLifecycleAware` — `disconnect()`, `isConnected()`,
|
|
304
304
|
> `getSessionIdentity()`.
|
|
305
305
|
>
|
|
@@ -404,10 +404,10 @@ establishment rather than opening a session each.
|
|
|
404
404
|
|
|
405
405
|
Match on the code rather than the message, so a rename is a compile error on your
|
|
406
406
|
side instead of a condition that silently stops matching. The codes live in
|
|
407
|
-
`@mcp-abap-adt/interfaces` — import them from there, not from this package:
|
|
407
|
+
`@mcp-abap-adt/interfaces-adt` — import them from there, not from this package:
|
|
408
408
|
|
|
409
409
|
```typescript
|
|
410
|
-
import { ADT_SESSION_ERROR } from '@mcp-abap-adt/interfaces';
|
|
410
|
+
import { ADT_SESSION_ERROR } from '@mcp-abap-adt/interfaces-adt';
|
|
411
411
|
import { getTimeout } from '@mcp-abap-adt/connection';
|
|
412
412
|
|
|
413
413
|
const options = {
|
|
@@ -794,7 +794,7 @@ establishing, and whatever session state it keeps.
|
|
|
794
794
|
|
|
795
795
|
```text
|
|
796
796
|
new HttpTransport(agentOptions?, logger?, { client?, baseUrl? })
|
|
797
|
-
new RfcTransport(connect: () => IRfcConversation, logger?)
|
|
797
|
+
new RfcTransport(connect: () => IRfcConversation, logger?, { logWire?, maxLoggedBodyChars? })
|
|
798
798
|
```
|
|
799
799
|
|
|
800
800
|
`HttpTransport` is the ordinary wire, and you name it because the connector
|
|
@@ -804,6 +804,26 @@ what the connectors' type parameters admit. `RfcTransport`
|
|
|
804
804
|
you build with `rfcConversationFrom(config)`, which derives `ashost` and `sysnr`
|
|
805
805
|
and loads the SAP NW RFC SDK only when a conversation opens.
|
|
806
806
|
|
|
807
|
+
**`logWire` dumps the wire, and is off.** With it on, `RfcTransport` adds three
|
|
808
|
+
debug lines per request — the header fields, the request body and the response
|
|
809
|
+
body — which is what tells you a payload was mis-serialised before it reached
|
|
810
|
+
`SADT_REST_RFC_ENDPOINT`. Credential header values (`Authorization`, any
|
|
811
|
+
`Cookie`, anything matching `token`, `secret`, `password`, `credential` or an
|
|
812
|
+
API key) are replaced with `[redacted]`, the names are kept, and a body is cut
|
|
813
|
+
at `maxLoggedBodyChars` (2000 by default) so a class source does not arrive as
|
|
814
|
+
one multi-megabyte line — `0` logs the size alone, `Infinity` asks for the
|
|
815
|
+
whole body, and a negative or `NaN` ceiling falls back to the default instead
|
|
816
|
+
of throwing. Read what you captured before pasting it anywhere: a
|
|
817
|
+
body is not redacted, only clipped.
|
|
818
|
+
|
|
819
|
+
It is a flag and not something inferred from the logger, because `ILogger` has
|
|
820
|
+
no level predicate — `logger?.debug()` cannot tell an enabled debug channel
|
|
821
|
+
from one that discards. Without the flag, every caller who passes a logger at
|
|
822
|
+
all would pay to build a copy of every body on the wire and throw it away.
|
|
823
|
+
`HttpTransport` logs no bodies at any setting, so "turn debug on" means
|
|
824
|
+
different things on the two wires; this is the only one that can be asked for
|
|
825
|
+
the payload.
|
|
826
|
+
|
|
807
827
|
The two differ in what they have, not in what they are asked:
|
|
808
828
|
|
|
809
829
|
| | HTTP | RFC |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/connection",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.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",
|
|
@@ -53,7 +53,10 @@
|
|
|
53
53
|
"node": ">=18.0.0"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@mcp-abap-adt/interfaces": "^
|
|
56
|
+
"@mcp-abap-adt/interfaces-adt": "^6.0.0",
|
|
57
|
+
"@mcp-abap-adt/interfaces-auth": "^1.1.0",
|
|
58
|
+
"@mcp-abap-adt/interfaces-network": "^1.0.0",
|
|
59
|
+
"@mcp-abap-adt/interfaces-utils": "^1.0.0",
|
|
57
60
|
"axios": "^1.16.0",
|
|
58
61
|
"commander": "^14.0.3",
|
|
59
62
|
"open": "^11.0.0"
|