@mcp-abap-adt/adt-clients 23.0.0 → 23.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/core/package/AdtPackage.d.ts +13 -45
- package/dist/core/package/AdtPackage.d.ts.map +1 -1
- package/dist/core/package/AdtPackage.js +13 -45
- package/dist/core/package/types.d.ts +3 -4
- package/dist/core/package/types.d.ts.map +1 -1
- package/dist/core/package/update.js +4 -4
- package/docs/README.md +3 -0
- package/docs/usage/ANSWER_SHAPES.md +2 -0
- package/docs/usage/OBJECT_LIFECYCLE.md +19 -67
- package/docs/usage/RFC_CONNECTION.md +6 -10
- package/docs/usage/STATEFUL_SESSION_GUIDE.md +6 -5
- package/docs/usage/TROUBLESHOOTING.md +27 -89
- package/docs/usage/WORKAROUNDS.md +750 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -940,6 +940,7 @@ member uses it on your behalf; `create()` and `update()` issue one request each.
|
|
|
940
940
|
- **[Documentation index](docs/README.md)**
|
|
941
941
|
- **[Migrating to 23.0.0](docs/usage/MIGRATION-23.md)** – the replacing code for every removed behaviour
|
|
942
942
|
- **[Client API reference](docs/usage/CLIENT_API_REFERENCE.md)** – every client, member and result set
|
|
943
|
+
- **[Workarounds](docs/usage/WORKAROUNDS.md)** – SAP-side behaviour a consumer has to work around, with the evidence for each
|
|
943
944
|
- **[Architecture](docs/architecture/ARCHITECTURE.md)** – package structure and design decisions
|
|
944
945
|
- **[Decisions](docs/architecture/DECISIONS.md)** – the choices that could have gone the other way, and why
|
|
945
946
|
- **[Operation Delays](docs/usage/OPERATION_DELAYS.md)** – configurable delays for SAP operations in tests
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* Every member answers `IAdtResponse<T>`, where T is what the result set given
|
|
8
8
|
* at construction makes of that endpoint's answer.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* The sequences Eclipse follows — each step is its own member here, one
|
|
11
|
+
* request each, and the caller composes them:
|
|
11
12
|
* - Create: validate → create → check
|
|
12
13
|
* - Update: lock → check → update → unlock
|
|
13
14
|
* - Delete: check(deletion) → delete
|
|
@@ -38,12 +39,16 @@ export declare class AdtPackage<R extends IPackageResults = typeof packageDocume
|
|
|
38
39
|
/** Validate the package's configuration before creating it. */
|
|
39
40
|
validate<E extends IAdtError = IAdtError>(config: Partial<IPackageConfig>, options?: IAdtOperationOptions<E>): Promise<IAdtResponse<ReturnType<R['validation']>, E>>;
|
|
40
41
|
/**
|
|
41
|
-
* Create the package:
|
|
42
|
+
* Create the package: one POST. Eclipse validates before it and runs a
|
|
43
|
+
* check after it; both are members of their own here.
|
|
42
44
|
*
|
|
43
|
-
*
|
|
45
|
+
* That check is a checkrun on the new object, the way Eclipse does it, not a
|
|
44
46
|
* second call to the validation endpoint — captured 2026-08-31, which
|
|
45
47
|
* validates, creates, then posts `/sap/bc/adt/checkruns` on the created
|
|
46
48
|
* package before it is ever locked.
|
|
49
|
+
*
|
|
50
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
51
|
+
* docs/usage/WORKAROUNDS.md. Over RFC the create counts as that save.
|
|
47
52
|
*/
|
|
48
53
|
create<E extends IAdtError = IAdtError>(config: Omit<IPackageConfig, 'source'> & {
|
|
49
54
|
source?: never;
|
|
@@ -57,40 +62,8 @@ export declare class AdtPackage<R extends IPackageResults = typeof packageDocume
|
|
|
57
62
|
/**
|
|
58
63
|
* Update the package's metadata.
|
|
59
64
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* call". Measured 2026-08-31, that is wrong: the PUT reads the
|
|
63
|
-
* parameter, validates the handle, and accepts ours. Four answers from the
|
|
64
|
-
* same endpoint, same session, same package, over rfc:
|
|
65
|
-
*
|
|
66
|
-
* PUT with no lockHandle 400 ExceptionParameterNotFound
|
|
67
|
-
* SADT_RESOURCE/017 "Parameter lockHandle
|
|
68
|
-
* could not be found"
|
|
69
|
-
* PUT with a made-up handle 423 ExceptionResourceInvalidLockHandle
|
|
70
|
-
* SADT_RESOURCE/026 "is not locked
|
|
71
|
-
* (invalid lock handle: DEADBEEF…)"
|
|
72
|
-
* a second _action=LOCK 403 ExceptionResourceNoAccess
|
|
73
|
-
* EU/510 "User … is currently editing"
|
|
74
|
-
* PUT with OUR handle 400 ExceptionResourceAlreadyExists
|
|
75
|
-
* PAK/058 "Package … is already locked"
|
|
76
|
-
*
|
|
77
|
-
* The first two say the lock handle is read and checked, and ours passes both
|
|
78
|
-
* checks — a PUT that could not see the lock would answer 423, exactly as the
|
|
79
|
-
* made-up handle does. The third says the ADT resource lock is ours and is
|
|
80
|
-
* recognised as ours.
|
|
81
|
-
*
|
|
82
|
-
* So the refusal comes from a layer past the ADT lock. PAK is the package
|
|
83
|
-
* framework's own message class, and PAK/058 is what it answers when its own
|
|
84
|
-
* lock cannot be taken. That state does not survive the hop between internal
|
|
85
|
-
* contexts that SADT_REST_RFC_ENDPOINT makes per call; the enqueue handle
|
|
86
|
-
* does, which is why UNLOCK afterwards answers 200.
|
|
87
|
-
*
|
|
88
|
-
* It is packages alone. In the same rfc run 31 other updates pass — classes,
|
|
89
|
-
* interfaces, domains, data elements, tables, structures, DDL, behaviour
|
|
90
|
-
* definitions — and no PAK message appears anywhere else in the log. Not
|
|
91
|
-
* critical for release: http is the primary transport for modern on-premise
|
|
92
|
-
* systems, and rfc exists for BASIS < 7.50, where package CRUD is not
|
|
93
|
-
* supported regardless.
|
|
65
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
66
|
+
* docs/usage/WORKAROUNDS.md. Opening a new session is the caller's.
|
|
94
67
|
*
|
|
95
68
|
* **The whole content, every time.** This is a replace, never a merge. Read
|
|
96
69
|
* what the object holds, change what you mean to change, and pass the result:
|
|
@@ -108,14 +81,9 @@ export declare class AdtPackage<R extends IPackageResults = typeof packageDocume
|
|
|
108
81
|
/**
|
|
109
82
|
* Delete the package.
|
|
110
83
|
*
|
|
111
|
-
* A package
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* PAK/058, "package is already locked", even though the UNLOCK moments
|
|
115
|
-
* earlier answered 200. It is not a delay: retried for 30 seconds inside the
|
|
116
|
-
* run it never succeeds, and the same request one second after the run ends
|
|
117
|
-
* deletes it on the first attempt. The PAK lock belongs to the ABAP session
|
|
118
|
-
* and goes with it.
|
|
84
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
85
|
+
* docs/usage/WORKAROUNDS.md. A delete from a session that saved the package
|
|
86
|
+
* is refused; from a new session it succeeds.
|
|
119
87
|
*
|
|
120
88
|
* The answer is a 200 either way, and `isDeleted="false"` is in its body: a
|
|
121
89
|
* caller who wants that read as a failure passes `analyseDeletion` (from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdtPackage.d.ts","sourceRoot":"","sources":["../../../src/core/package/AdtPackage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"AdtPackage.d.ts","sourceRoot":"","sources":["../../../src/core/package/AdtPackage.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* Every member answers `IAdtResponse<T>`, where T is what the result set given
|
|
9
9
|
* at construction makes of that endpoint's answer.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* The sequences Eclipse follows — each step is its own member here, one
|
|
12
|
+
* request each, and the caller composes them:
|
|
12
13
|
* - Create: validate → create → check
|
|
13
14
|
* - Update: lock → check → update → unlock
|
|
14
15
|
* - Delete: check(deletion) → delete
|
|
@@ -76,12 +77,16 @@ class AdtPackage {
|
|
|
76
77
|
}), this.results.validation, options?.analyse);
|
|
77
78
|
}
|
|
78
79
|
/**
|
|
79
|
-
* Create the package:
|
|
80
|
+
* Create the package: one POST. Eclipse validates before it and runs a
|
|
81
|
+
* check after it; both are members of their own here.
|
|
80
82
|
*
|
|
81
|
-
*
|
|
83
|
+
* That check is a checkrun on the new object, the way Eclipse does it, not a
|
|
82
84
|
* second call to the validation endpoint — captured 2026-08-31, which
|
|
83
85
|
* validates, creates, then posts `/sap/bc/adt/checkruns` on the created
|
|
84
86
|
* package before it is ever locked.
|
|
87
|
+
*
|
|
88
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
89
|
+
* docs/usage/WORKAROUNDS.md. Over RFC the create counts as that save.
|
|
85
90
|
*/
|
|
86
91
|
async create(config, options) {
|
|
87
92
|
// **No guard here, unlike every other create.**
|
|
@@ -128,40 +133,8 @@ class AdtPackage {
|
|
|
128
133
|
/**
|
|
129
134
|
* Update the package's metadata.
|
|
130
135
|
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* call". Measured 2026-08-31, that is wrong: the PUT reads the
|
|
134
|
-
* parameter, validates the handle, and accepts ours. Four answers from the
|
|
135
|
-
* same endpoint, same session, same package, over rfc:
|
|
136
|
-
*
|
|
137
|
-
* PUT with no lockHandle 400 ExceptionParameterNotFound
|
|
138
|
-
* SADT_RESOURCE/017 "Parameter lockHandle
|
|
139
|
-
* could not be found"
|
|
140
|
-
* PUT with a made-up handle 423 ExceptionResourceInvalidLockHandle
|
|
141
|
-
* SADT_RESOURCE/026 "is not locked
|
|
142
|
-
* (invalid lock handle: DEADBEEF…)"
|
|
143
|
-
* a second _action=LOCK 403 ExceptionResourceNoAccess
|
|
144
|
-
* EU/510 "User … is currently editing"
|
|
145
|
-
* PUT with OUR handle 400 ExceptionResourceAlreadyExists
|
|
146
|
-
* PAK/058 "Package … is already locked"
|
|
147
|
-
*
|
|
148
|
-
* The first two say the lock handle is read and checked, and ours passes both
|
|
149
|
-
* checks — a PUT that could not see the lock would answer 423, exactly as the
|
|
150
|
-
* made-up handle does. The third says the ADT resource lock is ours and is
|
|
151
|
-
* recognised as ours.
|
|
152
|
-
*
|
|
153
|
-
* So the refusal comes from a layer past the ADT lock. PAK is the package
|
|
154
|
-
* framework's own message class, and PAK/058 is what it answers when its own
|
|
155
|
-
* lock cannot be taken. That state does not survive the hop between internal
|
|
156
|
-
* contexts that SADT_REST_RFC_ENDPOINT makes per call; the enqueue handle
|
|
157
|
-
* does, which is why UNLOCK afterwards answers 200.
|
|
158
|
-
*
|
|
159
|
-
* It is packages alone. In the same rfc run 31 other updates pass — classes,
|
|
160
|
-
* interfaces, domains, data elements, tables, structures, DDL, behaviour
|
|
161
|
-
* definitions — and no PAK message appears anywhere else in the log. Not
|
|
162
|
-
* critical for release: http is the primary transport for modern on-premise
|
|
163
|
-
* systems, and rfc exists for BASIS < 7.50, where package CRUD is not
|
|
164
|
-
* supported regardless.
|
|
136
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
137
|
+
* docs/usage/WORKAROUNDS.md. Opening a new session is the caller's.
|
|
165
138
|
*
|
|
166
139
|
* **The whole content, every time.** This is a replace, never a merge. Read
|
|
167
140
|
* what the object holds, change what you mean to change, and pass the result:
|
|
@@ -215,14 +188,9 @@ class AdtPackage {
|
|
|
215
188
|
/**
|
|
216
189
|
* Delete the package.
|
|
217
190
|
*
|
|
218
|
-
* A package
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
* PAK/058, "package is already locked", even though the UNLOCK moments
|
|
222
|
-
* earlier answered 200. It is not a delay: retried for 30 seconds inside the
|
|
223
|
-
* run it never succeeds, and the same request one second after the run ends
|
|
224
|
-
* deletes it on the first attempt. The PAK lock belongs to the ABAP session
|
|
225
|
-
* and goes with it.
|
|
191
|
+
* A package can be saved only once per ABAP session: PAK/058 — see
|
|
192
|
+
* docs/usage/WORKAROUNDS.md. A delete from a session that saved the package
|
|
193
|
+
* is refused; from a new session it succeeds.
|
|
226
194
|
*
|
|
227
195
|
* The answer is a 200 either way, and `isDeleted="false"` is in its body: a
|
|
228
196
|
* caller who wants that read as a failure passes `analyseDeletion` (from
|
|
@@ -41,10 +41,9 @@ export type PackageValidationResult = string;
|
|
|
41
41
|
/**
|
|
42
42
|
* What the deletion answers.
|
|
43
43
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* "package is already locked" — so the document, not the status, is the verdict.
|
|
44
|
+
* A refusal arrives as **200** carrying `isDeleted="false"`, so the document,
|
|
45
|
+
* not the status, is the verdict. A package can be saved only once per ABAP
|
|
46
|
+
* session: PAK/058 — see docs/usage/WORKAROUNDS.md.
|
|
48
47
|
*/
|
|
49
48
|
export type PackageDeletionResult = string;
|
|
50
49
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/package/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/package/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACnD,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC7C,0DAA0D;IAC1D,QAAQ,CAAC,aAAa,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;CAUF,CAAC;AAE5B;;;;;;;;;GASG;AAEH,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -22,10 +22,10 @@ const timeouts_1 = require("../../utils/timeouts");
|
|
|
22
22
|
*/
|
|
23
23
|
async function updatePackage(connection, params, document, lockHandle) {
|
|
24
24
|
const encodedName = (0, internalUtils_1.encodeSapObjectName)(params.package_name.toLowerCase());
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const url = `/sap/bc/adt/packages/${encodedName}
|
|
25
|
+
// `writeQuery`, like every other write: interpolating the handle directly
|
|
26
|
+
// sent `?lockHandle=undefined` when there was none, and SAP answered a
|
|
27
|
+
// refusal about a handle nobody passed.
|
|
28
|
+
const url = `/sap/bc/adt/packages/${encodedName}${(0, internalUtils_1.writeQuery)(lockHandle, params.transport_request)}`;
|
|
29
29
|
return connection.makeAdtRequest({
|
|
30
30
|
url,
|
|
31
31
|
method: 'PUT',
|
package/docs/README.md
CHANGED
|
@@ -25,6 +25,7 @@ Complete documentation for the `@mcp-abap-adt/adt-clients` package.
|
|
|
25
25
|
- [**STATEFUL_SESSION_GUIDE.md**](usage/STATEFUL_SESSION_GUIDE.md) - Guide for stateful session management
|
|
26
26
|
- [**CHECK_LOCAL_TEST_CLASS.md**](usage/CHECK_LOCAL_TEST_CLASS.md) - Guide for validating ABAP Unit test classes
|
|
27
27
|
- [**DEBUG.md**](usage/DEBUG.md) - Debugging and troubleshooting guide
|
|
28
|
+
- [**WORKAROUNDS.md**](usage/WORKAROUNDS.md) — SAP-side behaviour a consumer has to work around (PAK/058, refusals inside a `200`, empty `200` reads, activation flags, transport search, …): symptom, cause, rule, workaround and evidence for each
|
|
28
29
|
- [TROUBLESHOOTING.md](usage/TROUBLESHOOTING.md) — what ADT answers when it refuses, and why the message is often accurate about the wrong thing
|
|
29
30
|
- [**OPERATION_DELAYS.md**](usage/OPERATION_DELAYS.md) - Detailed guide on operation delays and timing
|
|
30
31
|
- [**OPERATION_DELAYS_SUMMARY.md**](usage/OPERATION_DELAYS_SUMMARY.md) - Quick reference for operation delays
|
|
@@ -54,6 +55,8 @@ docs/
|
|
|
54
55
|
│ ├── OBJECT_LIFECYCLE.md # The create → … → activate flow and its exceptions
|
|
55
56
|
│ ├── CLIENT_API_REFERENCE.md # Client API reference
|
|
56
57
|
│ ├── STATEFUL_SESSION_GUIDE.md # Session management
|
|
58
|
+
│ ├── WORKAROUNDS.md # SAP-side behaviour and its workarounds
|
|
59
|
+
│ ├── TROUBLESHOOTING.md # Refusals that name the wrong cause
|
|
57
60
|
│ ├── CHECK_LOCAL_TEST_CLASS.md # Local test class validation
|
|
58
61
|
│ ├── DEBUG.md # Debugging guide
|
|
59
62
|
│ ├── OPERATION_DELAYS.md # Operation delays (detailed)
|
|
@@ -126,6 +126,8 @@ caller who asks for those shapes rather than the document.
|
|
|
126
126
|
- [`MIGRATION-23.md`](MIGRATION-23.md) — the readings and verdicts that moved
|
|
127
127
|
to `@mcp-abap-adt/adt-strategies` in 23.0.0
|
|
128
128
|
- [`MIGRATION-19.md`](MIGRATION-19.md) — what moved to the consumer in 19.0.0
|
|
129
|
+
- [`WORKAROUNDS.md`](WORKAROUNDS.md) — the SAP-side behaviour behind several of
|
|
130
|
+
these answers, and what a consumer does about it
|
|
129
131
|
- [`TROUBLESHOOTING.md`](TROUBLESHOOTING.md) — answers that are accurate about
|
|
130
132
|
the wrong thing, including the `S_ABPLNGVS` language-version refusal
|
|
131
133
|
- [`../../examples`](../../examples) — the sequences, written out
|
|
@@ -391,11 +391,11 @@ verdict and this library does not look for one in the body either: reading an
|
|
|
391
391
|
activation checklist is your `analyse`, written from the responses your own
|
|
392
392
|
system gives.
|
|
393
393
|
|
|
394
|
-
Two things worth knowing while you write it
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
394
|
+
Two things worth knowing while you write it: `activationExecuted="false"` with
|
|
395
|
+
no message means "nothing to do", and a locked object refuses with HTTP 403,
|
|
396
|
+
which never reaches a body-reading strategy at all — see
|
|
397
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#activationexecuted-false-is-not-a-failure).
|
|
398
|
+
`analyseActivation` in `@mcp-abap-adt/adt-strategies` reads both.
|
|
399
399
|
|
|
400
400
|
## How to check a created object, and when
|
|
401
401
|
|
|
@@ -524,56 +524,14 @@ all: it is changed and deleted directly.
|
|
|
524
524
|
|
|
525
525
|
## What a bare `create()` actually leaves, per type
|
|
526
526
|
|
|
527
|
-
A POST sometimes builds a minimal working object and sometimes builds nothing
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
| `class` | a generated skeleton | **refused**, `400`, "wrong input data" |
|
|
536
|
-
| `ddl` | an object with no content | `200`, empty |
|
|
537
|
-
| `serviceDefinition` | **nothing — the create itself is refused** | — |
|
|
538
|
-
|
|
539
|
-
`serviceDefinition` is the clearest case of the second kind: there is nothing to
|
|
540
|
-
generate a service from, so the POST answers *"Check of condition failed"* and
|
|
541
|
-
no object is made. `program` could not be measured here — an ABAP Cloud system
|
|
542
|
-
refuses it outright with `S_DEVELOP`.
|
|
543
|
-
|
|
544
|
-
### The class has a skeleton; you just cannot read it yet
|
|
545
|
-
|
|
546
|
-
The class row above is the one to be careful with, because the refusal invites
|
|
547
|
-
the wrong conclusion. SAP *did* generate a minimal class. It is stored as the
|
|
548
|
-
active version, and it becomes readable the moment the first source is written:
|
|
549
|
-
|
|
550
|
-
```
|
|
551
|
-
GET …/source/main?version=active 200 class ZAC_PROBE_INACT definition ← SAP's, lower case
|
|
552
|
-
GET …/source/main?version=inactive 200 CLASS zac_probe_inact DEFINITION … ← ours, as written
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
Before that first write, every read refuses — `active`, `inactive`, neither,
|
|
556
|
-
metadata, source. And nothing else lifts it:
|
|
557
|
-
|
|
558
|
-
```
|
|
559
|
-
create ok
|
|
560
|
-
read after create refused, wrong input data
|
|
561
|
-
read after 30s refused ← not timing
|
|
562
|
-
lock ok
|
|
563
|
-
read while locked refused
|
|
564
|
-
read after unlock refused ← not the lock either
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
So the object is not empty and it is not broken. It is unfinished, and the first
|
|
568
|
-
`update()` is what finishes it. Activation is a separate matter again: it
|
|
569
|
-
promotes what you wrote into the active version, replacing the skeleton.
|
|
570
|
-
|
|
571
|
-
**`getVersions()` will not tell you any of this.** It answers `ok` in every state
|
|
572
|
-
above — the feed, which `objectVersions` in `@mcp-abap-adt/adt-strategies`
|
|
573
|
-
reads — listing version slots rather than content — `99999` for the inactive,
|
|
574
|
-
`00000` for the active — so it reports two entries for the class nothing can
|
|
575
|
-
read. The count drops to one when activation consumes the inactive slot, which
|
|
576
|
-
is real but is not an answer to "is there anything to read".
|
|
527
|
+
A POST sometimes builds a minimal working object and sometimes builds nothing,
|
|
528
|
+
and which one you get is a property of the type: a domain is complete, an
|
|
529
|
+
interface has a generated skeleton, a DDL source answers `200` with an empty
|
|
530
|
+
body, a class has a skeleton that **no read can see until its first source
|
|
531
|
+
write**, and a service definition's create is refused outright.
|
|
532
|
+
`getVersions()` answers `ok` in every one of those states. The measured table,
|
|
533
|
+
the class's read sequence and what to do are in
|
|
534
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#what-a-bare-create-leaves-depends-on-the-type).
|
|
577
535
|
|
|
578
536
|
## The name is taken from the POST onward, and `validate()` may not say so
|
|
579
537
|
|
|
@@ -607,18 +565,12 @@ its package.
|
|
|
607
565
|
|
|
608
566
|
## Absence does not have one wording
|
|
609
567
|
|
|
610
|
-
Deleting
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
```
|
|
617
|
-
|
|
618
|
-
All three are refusals and all three mean the same thing. None of them is worth
|
|
619
|
-
matching on: the text is the server's, it is language-dependent, and it varies
|
|
620
|
-
by type. If you need to branch on absence, branch on the failure your own
|
|
621
|
-
`analyse` decided, not on the sentence.
|
|
568
|
+
Deleting an object and reading it again answers a different sentence per type —
|
|
569
|
+
*"Error while importing object … from the database"* for a domain, *"Resource
|
|
570
|
+
INTERFACE … does not exist."*, *"Data definition … of version does not
|
|
571
|
+
exist"*. All mean the same thing, and none is worth matching on: branch on the
|
|
572
|
+
failure your own `analyse` decided. See
|
|
573
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#what-a-bare-create-leaves-depends-on-the-type).
|
|
622
574
|
|
|
623
575
|
Reproduce with `npx ts-node scripts/probe-inactive-metadata.ts` and
|
|
624
576
|
`npx ts-node scripts/probe-unfinished-create.ts`.
|
|
@@ -183,14 +183,10 @@ Some endpoints via RFC don't support specific Accept content types. The library
|
|
|
183
183
|
|
|
184
184
|
RFC returns base64 lock handles that may contain spaces, `+`, `=`. All lock handles are encoded with `encodeURIComponent()` when placed in URL query parameters.
|
|
185
185
|
|
|
186
|
-
##
|
|
186
|
+
## Packages: one save per ABAP session
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
The evidence and the four endpoint answers that place it are in
|
|
195
|
-
[`docs/development/RFC_TESTING.md`](../development/RFC_TESTING.md#known-limitation-package-update).
|
|
196
|
-
Use HTTP for package changes on a system that supports it.
|
|
188
|
+
A package can be saved only once per ABAP session: the next update or delete
|
|
189
|
+
from that session is refused with `PAK/058`. Over RFC every call shares one
|
|
190
|
+
session, so an update straight after a create is already refused. The rule for
|
|
191
|
+
both transports and the workaround are in
|
|
192
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#a-package-can-be-saved-only-once-per-abap-session).
|
|
@@ -84,11 +84,12 @@ middle of one operation would take every other caller down with it. The library
|
|
|
84
84
|
goes as far as `setSessionType('stateful' | 'stateless')` and no further.
|
|
85
85
|
|
|
86
86
|
Some ADT operations cannot be done twice in one ABAP session, and this is where
|
|
87
|
-
that lands on you rather than on us. The clearest case: a package
|
|
88
|
-
|
|
89
|
-
`PAK/058`, and the same
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
that lands on you rather than on us. The clearest case: a package can be saved
|
|
88
|
+
only once per ABAP session — the next update or delete from that session is
|
|
89
|
+
refused with `PAK/058`, and the same request from any other session succeeds at
|
|
90
|
+
once. It is `CL_PACKAGE`'s session buffer, not a delay: retrying never helps.
|
|
91
|
+
The rule for HTTP and RFC, the evidence and the workaround are in
|
|
92
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#a-package-can-be-saved-only-once-per-abap-session).
|
|
92
93
|
|
|
93
94
|
So when an operation refuses in a way that names editing or locking, and the
|
|
94
95
|
object is one your session has just changed, the fix is a different session —
|
|
@@ -4,6 +4,10 @@ ADT answers are often accurate about the wrong thing. Everything below was
|
|
|
4
4
|
observed against a running system, and each entry says what the message looks
|
|
5
5
|
like, what it actually means, and how to tell the two apart.
|
|
6
6
|
|
|
7
|
+
SAP-side behaviour with a consumer-side workaround is collected in
|
|
8
|
+
[WORKAROUNDS.md](WORKAROUNDS.md); the entries below that belong there are short
|
|
9
|
+
and link to it.
|
|
10
|
+
|
|
7
11
|
## "You are not authorized to make changes (authorization object S_ABPLNGVS)"
|
|
8
12
|
|
|
9
13
|
Arrives as a `403` with an `<exc:exception>` document, `adtType`
|
|
@@ -54,76 +58,30 @@ language version its software component fixes; whether the user holds that value
|
|
|
54
58
|
in `ABP_LNG_VS`; and whether they hold the specific `ACTVT` for the operation
|
|
55
59
|
that failed rather than for the one that succeeded.
|
|
56
60
|
|
|
57
|
-
**The trap.** It is raised
|
|
58
|
-
|
|
59
|
-
package
|
|
60
|
-
found": with no package there is no software component, so there is no language
|
|
61
|
-
version to check against, and the refusal surfaces as an authorization failure.
|
|
62
|
-
|
|
63
|
-
Before going to PFCG, check that the package in the request exists and that its
|
|
64
|
-
software component allows the language version you are writing.
|
|
61
|
+
**The trap.** It is also raised for a create into a package **that does not
|
|
62
|
+
exist** — before going to PFCG, check the package. See
|
|
63
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#s_abplngvs-refuses-a-create-into-a-package-that-does-not-exist).
|
|
65
64
|
|
|
66
65
|
## A read of an object that is not there returns 200 and an empty body
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
So "the object is not there" and "the object is there and empty" arrive as the
|
|
73
|
-
identical answer, and neither the status nor the body can tell them apart.
|
|
74
|
-
|
|
75
|
-
**Why it matters more than it looks.** A read-modify-write that trusts the status
|
|
76
|
-
reads nothing, writes nothing back, and erases the object. A listing that treats
|
|
77
|
-
the same answer as a failure reports an error for an empty package.
|
|
78
|
-
|
|
79
|
-
Neither reading can be the library's, which is why it is a decision you supply:
|
|
80
|
-
pass `analyse` in the operation options to say which one applies to your call.
|
|
67
|
+
`source/main` never answers 404, and a not-yet-ready metadata read answers the
|
|
68
|
+
same `200` with zero bytes, so "not there" and "there and empty" are one answer.
|
|
69
|
+
A read-modify-write that trusts the status erases the object. See
|
|
70
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#a-read-answers-200-with-an-empty-body-instead-of-404).
|
|
81
71
|
|
|
82
72
|
## "Resource ZCL_X: wrong input data for processing" on a read
|
|
83
73
|
|
|
84
|
-
A `400`
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
It means **a class was created and no source has been written to it yet**. Every
|
|
90
|
-
read of one refuses this way — `active`, `inactive`, or neither, metadata or
|
|
91
|
-
source. Waiting thirty seconds does not help, and neither does a lock/unlock
|
|
92
|
-
cycle. Writing the source does, immediately and without any activation.
|
|
93
|
-
|
|
94
|
-
The object is not empty and it is not broken: SAP generated a minimal class and
|
|
95
|
-
stored it as the active version, and you can read it back the moment the first
|
|
96
|
-
write lands. It is unfinished, not absent.
|
|
97
|
-
|
|
98
|
-
Specific to classes. An interface created the same way reads its generated
|
|
99
|
-
skeleton at once, a domain is complete on creation, a DDL source answers 200
|
|
100
|
-
with an empty body, and a service definition cannot be created bare at all —
|
|
101
|
-
its POST is refused with "Check of condition failed".
|
|
102
|
-
|
|
103
|
-
The trap is that it reads as "your request is malformed", so the natural
|
|
104
|
-
response is to retry, and retrying never works. This library's own suite spent
|
|
105
|
-
sixteen seconds a run on eight such retries before anyone measured it, and the
|
|
106
|
-
assertion after them had never once executed.
|
|
107
|
-
|
|
108
|
-
**What to do:** write the source. A class reads at `version=inactive` while
|
|
109
|
-
still under its lock, long before any activation. Do not reach for
|
|
110
|
-
`getVersions()` to test readiness — it answers `ok` in this state too, listing
|
|
111
|
-
version slots rather than content. See
|
|
112
|
-
[OBJECT_LIFECYCLE.md](OBJECT_LIFECYCLE.md#what-a-bare-create-actually-leaves-per-type).
|
|
74
|
+
A `400 ExceptionResourceWrongData`, `SADT_RESOURCE/007`, on every read of a
|
|
75
|
+
class that was created and has no source written yet. It is unfinished, not
|
|
76
|
+
absent or broken: write the source, do not retry. See
|
|
77
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#what-a-bare-create-leaves-depends-on-the-type).
|
|
113
78
|
|
|
114
79
|
## "Class ZCL_X does not have a TMDIR entry" on an activation
|
|
115
80
|
|
|
116
|
-
A `200` carrying `<msg type="E" code="OO(045)"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
It means **the object does not exist**. The activation went straight to
|
|
121
|
-
generation, looked for the class in the method directory, and found nothing.
|
|
122
|
-
It does not say "not found", so it reads like a corrupt object; it is an absent
|
|
123
|
-
one. The same message serves interfaces, with `Interface` in `T100KEY-V1`.
|
|
124
|
-
|
|
125
|
-
Distinguish it from the entry above: `wrong input data` is an object that exists
|
|
126
|
-
with nothing in it, `TMDIR` is an object that is not there at all.
|
|
81
|
+
A `200` carrying `<msg type="E" code="OO(045)">`: the object **does not exist**.
|
|
82
|
+
Distinguish it from the entry above — `wrong input data` is an object that
|
|
83
|
+
exists with nothing in it, `TMDIR` is an object that is not there at all. See
|
|
84
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#activationexecuted-false-is-not-a-failure).
|
|
127
85
|
|
|
128
86
|
## A message class exists; its messages do not
|
|
129
87
|
|
|
@@ -201,31 +159,15 @@ an object already in this state is SAP GUI territory.
|
|
|
201
159
|
|
|
202
160
|
## A refusal can arrive with a 2xx
|
|
203
161
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
Measured on a trial: five of seven probed operations reported no errors
|
|
209
|
-
while SAP had refused, three of them writes — a caller believed an object existed
|
|
210
|
-
that did not, and that one had been deleted that had not.
|
|
211
|
-
|
|
212
|
-
**The status is the channel; the document is the verdict.** There are at least
|
|
213
|
-
three refusal shapes and they are not interchangeable:
|
|
214
|
-
|
|
215
|
-
| shape | resource |
|
|
216
|
-
|---|---|
|
|
217
|
-
| `<exc:exception>` | most resources, any status including 200 |
|
|
218
|
-
| `<del:message del:type="E">` in `del:checkResponse` | `/deletion/check` |
|
|
219
|
-
| `<msg type="E">` in `chkl:messages` | `/activation` |
|
|
162
|
+
The status is the channel; the document is the verdict. ADT has at least three
|
|
163
|
+
refusal shapes, and a `200` can carry any of them. See
|
|
164
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#a-refusal-can-arrive-with-a-2xx-and-an-error-status-names-the-fix).
|
|
220
165
|
|
|
221
166
|
## Activation reports `activationExecuted="false"` and nothing is wrong
|
|
222
167
|
|
|
223
|
-
The flag says whether ADT did any work, not whether
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
**Only `<msg type="E">` is the verdict.** An object locked by another session is
|
|
228
|
-
a `403` and never reaches this document at all.
|
|
168
|
+
The flag says whether ADT did any work, not whether it succeeded; only
|
|
169
|
+
`<msg type="E">` is the verdict. See
|
|
170
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#activationexecuted-false-is-not-a-failure).
|
|
229
171
|
|
|
230
172
|
## A deletion check that says "no" is not a failure
|
|
231
173
|
|
|
@@ -237,12 +179,8 @@ the objects are still on the system, and that is a failure.
|
|
|
237
179
|
|
|
238
180
|
## 406 and 415 name the exact content type in their text
|
|
239
181
|
|
|
240
|
-
The status number says nothing actionable; the sentence names the header
|
|
241
|
-
|
|
242
|
-
- `406` — "Accepted content types: application/vnd.sap.adt.deletion.check.response.v1+xml"
|
|
243
|
-
- `415` — "Supported Media Types: …check.request.v1+xml"
|
|
244
|
-
|
|
245
|
-
Reading the body is cheaper than guessing content types from a status.
|
|
182
|
+
The status number says nothing actionable; the sentence names the header. See
|
|
183
|
+
[WORKAROUNDS.md](WORKAROUNDS.md#a-refusal-can-arrive-with-a-2xx-and-an-error-status-names-the-fix).
|
|
246
184
|
|
|
247
185
|
## "No URI-Mapping defined for URI", inside a 200
|
|
248
186
|
|