@mcp-abap-adt/adt-backup 0.1.1 → 1.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/README.md +34 -0
- package/dist/bin/adt-backup.js +0 -0
- package/dist/lib/auth/createTokenProvider.d.ts +1 -1
- package/dist/lib/auth/createTokenProvider.d.ts.map +1 -1
- package/dist/lib/auth/createTokenProvider.js +2 -1
- package/dist/lib/auth/getSapConfigFromBroker.d.ts +1 -0
- package/dist/lib/auth/getSapConfigFromBroker.d.ts.map +1 -1
- package/dist/lib/auth/getSapConfigFromBroker.js +94 -95
- package/dist/lib/backup/backupObject.d.ts.map +1 -1
- package/dist/lib/backup/backupObject.js +19 -5
- package/dist/lib/backup/readMetadataXmlForType.d.ts +1 -1
- package/dist/lib/backup/readMetadataXmlForType.d.ts.map +1 -1
- package/dist/lib/backup/readMetadataXmlForType.js +113 -92
- package/dist/lib/backup/readSourceText.d.ts +1 -1
- package/dist/lib/backup/readSourceText.d.ts.map +1 -1
- package/dist/lib/backup/readSourceText.js +96 -87
- package/dist/lib/cli/createLogger.d.ts.map +1 -1
- package/dist/lib/cli/createLogger.js +18 -0
- package/dist/lib/cli/parseArgs.d.ts +1 -1
- package/dist/lib/cli/parseArgs.d.ts.map +1 -1
- package/dist/lib/cli/parseArgs.js +25 -10
- package/dist/lib/cli/usage.d.ts.map +1 -1
- package/dist/lib/cli/usage.js +92 -87
- package/dist/lib/constants/typeOrder.d.ts.map +1 -1
- package/dist/lib/constants/typeOrder.js +1 -0
- package/dist/lib/dependencies/collectTreeDependencies.d.ts.map +1 -1
- package/dist/lib/dependencies/collectTreeDependencies.js +1 -0
- package/dist/lib/restore/analyzeDependencies.d.ts +13 -0
- package/dist/lib/restore/analyzeDependencies.d.ts.map +1 -0
- package/dist/lib/restore/analyzeDependencies.js +187 -0
- package/dist/lib/restore/restoreObject.d.ts.map +1 -1
- package/dist/lib/restore/restoreObject.js +13 -0
- package/dist/lib/restore/restoreObjects.d.ts.map +1 -1
- package/dist/lib/restore/restoreObjects.js +49 -10
- package/dist/lib/restore/restoreTreeBackup.d.ts +1 -1
- package/dist/lib/restore/restoreTreeBackup.d.ts.map +1 -1
- package/dist/lib/restore/restoreTreeBackup.js +192 -42
- package/dist/lib/restore/restoreTreeNode.d.ts +1 -1
- package/dist/lib/restore/restoreTreeNode.d.ts.map +1 -1
- package/dist/lib/restore/restoreTreeNode.js +128 -36
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +393 -559
- package/dist/lib/tree/buildConfigForNode.d.ts.map +1 -1
- package/dist/lib/tree/buildConfigForNode.js +19 -0
- package/dist/lib/tree/buildPackageBackupTree.d.ts.map +1 -1
- package/dist/lib/tree/buildPackageBackupTree.js +9 -3
- package/dist/lib/tree/enrichTreeNode.d.ts.map +1 -1
- package/dist/lib/tree/enrichTreeNode.js +17 -1
- package/dist/lib/tree/isRestoreImplemented.d.ts.map +1 -1
- package/dist/lib/tree/isRestoreImplemented.js +2 -0
- package/dist/lib/tree/mapAdtTypeToSupported.d.ts.map +1 -1
- package/dist/lib/tree/mapAdtTypeToSupported.js +6 -0
- package/dist/lib/tree/readPayloadForType.d.ts.map +1 -1
- package/dist/lib/tree/readPayloadForType.js +5 -3
- package/dist/lib/types.d.ts +22 -2
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/utils/applyConfigName.d.ts.map +1 -1
- package/dist/lib/utils/applyConfigName.js +6 -0
- package/dist/lib/utils/normalizeType.d.ts.map +1 -1
- package/dist/lib/utils/normalizeType.js +2 -0
- package/dist/lib/utils/parseBdefSource.d.ts +9 -0
- package/dist/lib/utils/parseBdefSource.d.ts.map +1 -0
- package/dist/lib/utils/parseBdefSource.js +18 -0
- package/dist/lib/verify/findOtherType.d.ts.map +1 -1
- package/dist/lib/verify/findOtherType.js +1 -0
- package/dist/lib/verify/formatVerifyResultsText.d.ts +1 -1
- package/dist/lib/verify/formatVerifyResultsText.d.ts.map +1 -1
- package/dist/lib/verify/formatVerifyResultsText.js +76 -14
- package/dist/lib/verify/types.d.ts +3 -0
- package/dist/lib/verify/types.d.ts.map +1 -1
- package/dist/lib/verify/verifyBackup.d.ts +4 -2
- package/dist/lib/verify/verifyBackup.d.ts.map +1 -1
- package/dist/lib/verify/verifyBackup.js +67 -32
- package/dist/lib/verify/verifyObjectInSystem.d.ts +1 -1
- package/dist/lib/verify/verifyObjectInSystem.d.ts.map +1 -1
- package/dist/lib/verify/verifyObjectInSystem.js +39 -105
- package/dist/lib/xml/index.d.ts +1 -0
- package/dist/lib/xml/index.d.ts.map +1 -1
- package/dist/lib/xml/index.js +1 -0
- package/dist/lib/xml/parseServiceBindingConfig.d.ts +3 -0
- package/dist/lib/xml/parseServiceBindingConfig.d.ts.map +1 -0
- package/dist/lib/xml/parseServiceBindingConfig.js +70 -0
- package/package.json +12 -12
|
@@ -5,13 +5,34 @@ const logVerbose_1 = require("../cli/logVerbose");
|
|
|
5
5
|
const decodeBase64_1 = require("../crypto/decodeBase64");
|
|
6
6
|
const asConfig_1 = require("../utils/asConfig");
|
|
7
7
|
const ensureDescription_1 = require("../utils/ensureDescription");
|
|
8
|
+
const parseBdefSource_1 = require("../utils/parseBdefSource");
|
|
9
|
+
const parsePackageConfig_1 = require("../xml/parsePackageConfig");
|
|
8
10
|
const applyTransportRequest_1 = require("./applyTransportRequest");
|
|
9
|
-
async function restoreTreeNode(client, node, mode, activate, transportRequest, softwareComponentOverride, backupPackageNames) {
|
|
11
|
+
async function restoreTreeNode(client, node, mode, activate, transportRequest, softwareComponentOverride, backupPackageNames, superPackageOverride, transportLayerOverride) {
|
|
12
|
+
if (mode === 'skip') {
|
|
13
|
+
(0, logVerbose_1.logVerbose)(2, ` [SKIP] ${node.type}:${node.name}`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
10
16
|
if (!node.type || node.restoreStatus !== 'ok') {
|
|
11
17
|
return;
|
|
12
18
|
}
|
|
13
|
-
|
|
19
|
+
// Use existing config or try to extract from XML if missing
|
|
20
|
+
let nodeConfig = node.config;
|
|
21
|
+
if (!nodeConfig &&
|
|
22
|
+
node.codeBase64 &&
|
|
23
|
+
node.codeFormat === 'xml' &&
|
|
24
|
+
node.type === 'package') {
|
|
25
|
+
try {
|
|
26
|
+
const xml = (0, decodeBase64_1.decodeBase64)(node.codeBase64);
|
|
27
|
+
nodeConfig = (0, parsePackageConfig_1.parsePackageConfig)(xml);
|
|
28
|
+
}
|
|
29
|
+
catch (_e) {
|
|
30
|
+
(0, logVerbose_1.logVerbose)(2, ` Could not parse XML config for package ${node.name}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const config = (0, applyTransportRequest_1.applyTransportRequest)((0, ensureDescription_1.ensureDescription)(nodeConfig || {}, node.name), transportRequest);
|
|
14
34
|
const payload = node.codeBase64 ? (0, decodeBase64_1.decodeBase64)(node.codeBase64) : undefined;
|
|
35
|
+
// Standard options for most objects
|
|
15
36
|
const options = {
|
|
16
37
|
activateOnCreate: activate,
|
|
17
38
|
activateOnUpdate: activate,
|
|
@@ -20,30 +41,48 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
20
41
|
switch (node.type) {
|
|
21
42
|
case 'package': {
|
|
22
43
|
const pkgConfig = (0, asConfig_1.asConfig)(config);
|
|
23
|
-
|
|
24
|
-
|
|
44
|
+
if (!pkgConfig.packageName) {
|
|
45
|
+
pkgConfig.packageName = node.name;
|
|
46
|
+
}
|
|
25
47
|
if (pkgConfig.responsible) {
|
|
26
48
|
delete pkgConfig.responsible;
|
|
27
49
|
}
|
|
28
|
-
// Check if this package's superPackage is within our backup tree
|
|
29
50
|
const superPackageInBackup = pkgConfig.superPackage &&
|
|
30
51
|
backupPackageNames?.has(pkgConfig.superPackage);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// For sub-packages, use CLI override to ensure consistency with parent
|
|
52
|
+
if (!superPackageInBackup && superPackageOverride) {
|
|
53
|
+
pkgConfig.superPackage = superPackageOverride;
|
|
54
|
+
}
|
|
35
55
|
if (softwareComponentOverride) {
|
|
36
56
|
pkgConfig.softwareComponent = softwareComponentOverride;
|
|
37
57
|
}
|
|
38
58
|
else if (!pkgConfig.softwareComponent) {
|
|
39
59
|
pkgConfig.softwareComponent = 'ZLOCAL';
|
|
40
60
|
}
|
|
41
|
-
|
|
61
|
+
// Fix for the transport layer mapping issue in adt-clients
|
|
62
|
+
if (transportLayerOverride) {
|
|
63
|
+
pkgConfig.transportLayer = transportLayerOverride;
|
|
64
|
+
pkgConfig.transport_layer = transportLayerOverride;
|
|
65
|
+
}
|
|
66
|
+
pkgConfig.recordChanges = true;
|
|
42
67
|
if (mode !== 'update') {
|
|
68
|
+
if (!pkgConfig.superPackage && node.type === 'package') {
|
|
69
|
+
throw new Error(`Package ${node.name} cannot be created: superPackage is missing.`);
|
|
70
|
+
}
|
|
71
|
+
(0, logVerbose_1.logVerbose)(3, ` Creating package ${node.name} (Layer: ${pkgConfig.transportLayer}, SoftwareComp: ${pkgConfig.softwareComponent})`);
|
|
43
72
|
await client.getPackage().create(pkgConfig, options);
|
|
73
|
+
// Wait for SAP to commit the package to the database
|
|
74
|
+
// ADT has no event subscription for creation completion
|
|
75
|
+
await delay(2000);
|
|
44
76
|
}
|
|
45
77
|
if (mode !== 'create') {
|
|
46
|
-
|
|
78
|
+
try {
|
|
79
|
+
await client.getPackage().update(pkgConfig, options);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
83
|
+
(0, logVerbose_1.logVerbose)(1, ` [SKIP] Package ${node.name} update skipped`);
|
|
84
|
+
(0, logVerbose_1.logVerbose)(3, ` Reason: ${msg.slice(0, 200)}`);
|
|
85
|
+
}
|
|
47
86
|
}
|
|
48
87
|
return;
|
|
49
88
|
}
|
|
@@ -53,11 +92,10 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
53
92
|
.getDomain()
|
|
54
93
|
.create((0, asConfig_1.asConfig)(config), options);
|
|
55
94
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
95
|
+
// Always update to set datatype/length/decimals (create only registers the name)
|
|
96
|
+
await client
|
|
97
|
+
.getDomain()
|
|
98
|
+
.update((0, asConfig_1.asConfig)(config), options);
|
|
61
99
|
return;
|
|
62
100
|
}
|
|
63
101
|
case 'dataElement': {
|
|
@@ -66,11 +104,10 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
66
104
|
.getDataElement()
|
|
67
105
|
.create((0, asConfig_1.asConfig)(config), options);
|
|
68
106
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
107
|
+
// Always update to set typeKind/typeName/dataType (create only registers the name)
|
|
108
|
+
await client
|
|
109
|
+
.getDataElement()
|
|
110
|
+
.update((0, asConfig_1.asConfig)(config), options);
|
|
74
111
|
return;
|
|
75
112
|
}
|
|
76
113
|
case 'structure': {
|
|
@@ -159,11 +196,10 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
159
196
|
.getFunctionGroup()
|
|
160
197
|
.create((0, asConfig_1.asConfig)(config), options);
|
|
161
198
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
199
|
+
// Always update to set properties (create only registers the name)
|
|
200
|
+
await client
|
|
201
|
+
.getFunctionGroup()
|
|
202
|
+
.update((0, asConfig_1.asConfig)(config), options);
|
|
167
203
|
return;
|
|
168
204
|
}
|
|
169
205
|
case 'functionModule': {
|
|
@@ -194,6 +230,37 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
194
230
|
}
|
|
195
231
|
return;
|
|
196
232
|
}
|
|
233
|
+
case 'serviceBinding': {
|
|
234
|
+
if (mode !== 'update') {
|
|
235
|
+
await client
|
|
236
|
+
.getServiceBinding()
|
|
237
|
+
.create((0, asConfig_1.asConfig)(config), options);
|
|
238
|
+
}
|
|
239
|
+
// Always update to set properties (create only registers the name)
|
|
240
|
+
try {
|
|
241
|
+
await client
|
|
242
|
+
.getServiceBinding()
|
|
243
|
+
.update((0, asConfig_1.asConfig)(config));
|
|
244
|
+
}
|
|
245
|
+
catch (updateError) {
|
|
246
|
+
const msg = updateError instanceof Error
|
|
247
|
+
? updateError.message
|
|
248
|
+
: String(updateError);
|
|
249
|
+
if (mode === 'update' && msg.includes('404')) {
|
|
250
|
+
// Object missing despite verify — fallback to create + update
|
|
251
|
+
await client
|
|
252
|
+
.getServiceBinding()
|
|
253
|
+
.create((0, asConfig_1.asConfig)(config), options);
|
|
254
|
+
await client
|
|
255
|
+
.getServiceBinding()
|
|
256
|
+
.update((0, asConfig_1.asConfig)(config));
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
throw updateError;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
197
264
|
case 'metadataExtension': {
|
|
198
265
|
if (mode !== 'update') {
|
|
199
266
|
await client
|
|
@@ -210,9 +277,19 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
210
277
|
}
|
|
211
278
|
case 'behaviorDefinition': {
|
|
212
279
|
if (mode !== 'update') {
|
|
280
|
+
// Fill rootEntity/implementationType from source if missing in config
|
|
281
|
+
let bdefConfig = config;
|
|
282
|
+
if (payload && (!config.rootEntity || !config.implementationType)) {
|
|
283
|
+
const parsed = (0, parseBdefSource_1.parseBdefSource)(payload);
|
|
284
|
+
bdefConfig = {
|
|
285
|
+
...config,
|
|
286
|
+
rootEntity: config.rootEntity || parsed.rootEntity,
|
|
287
|
+
implementationType: config.implementationType || parsed.implementationType,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
213
290
|
await client
|
|
214
291
|
.getBehaviorDefinition()
|
|
215
|
-
.create((0, asConfig_1.asConfig)(
|
|
292
|
+
.create((0, asConfig_1.asConfig)(bdefConfig), options);
|
|
216
293
|
}
|
|
217
294
|
if (payload) {
|
|
218
295
|
await client.getBehaviorDefinition().update((0, asConfig_1.asConfig)({
|
|
@@ -250,28 +327,43 @@ async function restoreTreeNode(client, node, mode, activate, transportRequest, s
|
|
|
250
327
|
}
|
|
251
328
|
return;
|
|
252
329
|
}
|
|
253
|
-
case '
|
|
330
|
+
case 'accessControl': {
|
|
254
331
|
if (mode !== 'update') {
|
|
255
332
|
await client
|
|
256
|
-
.
|
|
333
|
+
.getAccessControl()
|
|
257
334
|
.create((0, asConfig_1.asConfig)(config), options);
|
|
258
335
|
}
|
|
259
|
-
if (
|
|
336
|
+
if (payload) {
|
|
337
|
+
await client.getAccessControl().update((0, asConfig_1.asConfig)({
|
|
338
|
+
...config,
|
|
339
|
+
sourceCode: payload,
|
|
340
|
+
}), options);
|
|
341
|
+
}
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
case 'tableType': {
|
|
345
|
+
if (mode !== 'update') {
|
|
260
346
|
await client
|
|
261
347
|
.getTableType()
|
|
262
|
-
.
|
|
348
|
+
.create((0, asConfig_1.asConfig)(config), options);
|
|
263
349
|
}
|
|
350
|
+
// Always update to set properties (create only registers the name)
|
|
351
|
+
await client
|
|
352
|
+
.getTableType()
|
|
353
|
+
.update((0, asConfig_1.asConfig)(config), options);
|
|
264
354
|
return;
|
|
265
355
|
}
|
|
266
356
|
}
|
|
267
357
|
}
|
|
268
358
|
catch (error) {
|
|
269
|
-
const
|
|
270
|
-
if (
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
: JSON.stringify(err.response.data, null, 2));
|
|
359
|
+
const data = error.response?.data;
|
|
360
|
+
if (data) {
|
|
361
|
+
const errorMsg = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
362
|
+
console.error(`Error restoring ${node.type}:${node.name}:\n${errorMsg}`);
|
|
274
363
|
}
|
|
275
364
|
throw error;
|
|
276
365
|
}
|
|
277
366
|
}
|
|
367
|
+
function delay(ms) {
|
|
368
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
369
|
+
}
|
package/dist/lib/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"AAiDA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAsoBzC"}
|