catalyst-relay 0.5.9 → 0.5.11
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/dist/index.d.mts +66 -17
- package/dist/index.d.ts +66 -17
- package/dist/index.js +357 -140
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +357 -140
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1192,6 +1192,14 @@ var OBJECT_CONFIG_MAP = {
|
|
|
1192
1192
|
type: "PROG/P",
|
|
1193
1193
|
label: "ABAP Program" /* PROGRAM */,
|
|
1194
1194
|
extension: "asprog"
|
|
1195
|
+
},
|
|
1196
|
+
"asinc": {
|
|
1197
|
+
endpoint: "programs/includes",
|
|
1198
|
+
nameSpace: 'xmlns:include="http://www.sap.com/adt/programs/includes"',
|
|
1199
|
+
rootName: "include:abapInclude",
|
|
1200
|
+
type: "PROG/I",
|
|
1201
|
+
label: "ABAP Include" /* INCLUDE */,
|
|
1202
|
+
extension: "asinc"
|
|
1195
1203
|
}
|
|
1196
1204
|
};
|
|
1197
1205
|
function getConfigByExtension(extension) {
|
|
@@ -1253,6 +1261,80 @@ async function readObject(client, object) {
|
|
|
1253
1261
|
return ok(result);
|
|
1254
1262
|
}
|
|
1255
1263
|
|
|
1264
|
+
// src/core/adt/discovery/whereUsed.ts
|
|
1265
|
+
async function findWhereUsed(client, object) {
|
|
1266
|
+
const config = getConfigByExtension(object.extension);
|
|
1267
|
+
if (!config) {
|
|
1268
|
+
return err(new Error(`Unsupported extension: ${object.extension}`));
|
|
1269
|
+
}
|
|
1270
|
+
const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;
|
|
1271
|
+
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1272
|
+
<usagereferences:usageReferenceRequest xmlns:usagereferences="http://www.sap.com/adt/ris/usageReferences">
|
|
1273
|
+
<usagereferences:affectedObjects/>
|
|
1274
|
+
</usagereferences:usageReferenceRequest>`;
|
|
1275
|
+
const [response, requestErr] = await client.request({
|
|
1276
|
+
method: "POST",
|
|
1277
|
+
path: "/sap/bc/adt/repository/informationsystem/usageReferences",
|
|
1278
|
+
params: {
|
|
1279
|
+
"uri": uri,
|
|
1280
|
+
"ris_request_type": "usageReferences"
|
|
1281
|
+
},
|
|
1282
|
+
headers: {
|
|
1283
|
+
"Content-Type": "application/vnd.sap.adt.repository.usagereferences.request.v1+xml",
|
|
1284
|
+
"Accept": "application/vnd.sap.adt.repository.usagereferences.result.v1+xml"
|
|
1285
|
+
},
|
|
1286
|
+
body
|
|
1287
|
+
});
|
|
1288
|
+
if (requestErr) {
|
|
1289
|
+
return err(requestErr);
|
|
1290
|
+
}
|
|
1291
|
+
if (!response.ok) {
|
|
1292
|
+
const text2 = await response.text();
|
|
1293
|
+
const errorMsg = extractError(text2);
|
|
1294
|
+
return err(new Error(`Where-used query failed: ${errorMsg}`));
|
|
1295
|
+
}
|
|
1296
|
+
const text = await response.text();
|
|
1297
|
+
const [dependencies, parseErr] = parseWhereUsed(text);
|
|
1298
|
+
if (parseErr) {
|
|
1299
|
+
return err(parseErr);
|
|
1300
|
+
}
|
|
1301
|
+
return ok(dependencies);
|
|
1302
|
+
}
|
|
1303
|
+
function parseWhereUsed(xml) {
|
|
1304
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
1305
|
+
if (parseErr) {
|
|
1306
|
+
return err(parseErr);
|
|
1307
|
+
}
|
|
1308
|
+
const dependencies = [];
|
|
1309
|
+
const referencedObjects = doc.getElementsByTagNameNS(
|
|
1310
|
+
"http://www.sap.com/adt/ris/usageReferences",
|
|
1311
|
+
"referencedObject"
|
|
1312
|
+
);
|
|
1313
|
+
for (let i = 0; i < referencedObjects.length; i++) {
|
|
1314
|
+
const refObj = referencedObjects[i];
|
|
1315
|
+
if (!refObj) continue;
|
|
1316
|
+
const adtObject = refObj.getElementsByTagNameNS(
|
|
1317
|
+
"http://www.sap.com/adt/ris/usageReferences",
|
|
1318
|
+
"adtObject"
|
|
1319
|
+
)[0];
|
|
1320
|
+
if (!adtObject) continue;
|
|
1321
|
+
const name = adtObject.getAttributeNS("http://www.sap.com/adt/core", "name") || adtObject.getAttribute("adtcore:name");
|
|
1322
|
+
const type = adtObject.getAttributeNS("http://www.sap.com/adt/core", "type") || adtObject.getAttribute("adtcore:type");
|
|
1323
|
+
if (!name || !type) continue;
|
|
1324
|
+
const config = getConfigByType(type);
|
|
1325
|
+
if (!config) continue;
|
|
1326
|
+
const packageRef = adtObject.getElementsByTagNameNS("http://www.sap.com/adt/core", "packageRef")[0];
|
|
1327
|
+
const packageName = packageRef ? packageRef.getAttributeNS("http://www.sap.com/adt/core", "name") || packageRef.getAttribute("adtcore:name") : "";
|
|
1328
|
+
dependencies.push({
|
|
1329
|
+
name,
|
|
1330
|
+
extension: config.extension,
|
|
1331
|
+
package: packageName || "",
|
|
1332
|
+
usageType: "reference"
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
return ok(dependencies);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1256
1338
|
// src/core/adt/craud/lock.ts
|
|
1257
1339
|
async function lockObject(client, object) {
|
|
1258
1340
|
const [config, configErr] = requireConfig(object.extension);
|
|
@@ -1301,6 +1383,135 @@ async function unlockObject(client, object, lockHandle) {
|
|
|
1301
1383
|
return ok(void 0);
|
|
1302
1384
|
}
|
|
1303
1385
|
|
|
1386
|
+
// src/core/adt/craud/delete.ts
|
|
1387
|
+
async function deleteObject(client, object, lockHandle, transport) {
|
|
1388
|
+
const [config, configErr] = requireConfig(object.extension);
|
|
1389
|
+
if (configErr) return err(configErr);
|
|
1390
|
+
const params = {
|
|
1391
|
+
"lockHandle": lockHandle
|
|
1392
|
+
};
|
|
1393
|
+
if (transport) {
|
|
1394
|
+
params["corrNr"] = transport;
|
|
1395
|
+
}
|
|
1396
|
+
const [response, requestErr] = await client.request({
|
|
1397
|
+
method: "DELETE",
|
|
1398
|
+
path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,
|
|
1399
|
+
params,
|
|
1400
|
+
headers: { "Accept": "text/plain" }
|
|
1401
|
+
});
|
|
1402
|
+
const [_, checkErr] = await checkResponse(
|
|
1403
|
+
response,
|
|
1404
|
+
requestErr,
|
|
1405
|
+
`Failed to delete ${config.label} ${object.name}`
|
|
1406
|
+
);
|
|
1407
|
+
if (checkErr) return err(checkErr);
|
|
1408
|
+
return ok(void 0);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// src/core/adt/craud/multiDelete.ts
|
|
1412
|
+
var ExternalReferencesError = class extends Error {
|
|
1413
|
+
constructor(references) {
|
|
1414
|
+
super(`Cannot delete: ${references.length} external reference(s) prevent the operation`);
|
|
1415
|
+
this.references = references;
|
|
1416
|
+
this.name = "ExternalReferencesError";
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
function objKey(o) {
|
|
1420
|
+
return `${o.name.toLowerCase()}|${o.extension}`;
|
|
1421
|
+
}
|
|
1422
|
+
async function multiDeleteObjects(client, objects, transport) {
|
|
1423
|
+
if (objects.length === 0) return ok([]);
|
|
1424
|
+
for (const obj of objects) {
|
|
1425
|
+
if (!getConfigByExtension(obj.extension)) {
|
|
1426
|
+
return err(new Error(`Unsupported extension: ${obj.extension}`));
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
const setKeys = /* @__PURE__ */ new Set();
|
|
1430
|
+
const unique = [];
|
|
1431
|
+
for (const obj of objects) {
|
|
1432
|
+
const key = objKey(obj);
|
|
1433
|
+
if (setKeys.has(key)) continue;
|
|
1434
|
+
setKeys.add(key);
|
|
1435
|
+
unique.push(obj);
|
|
1436
|
+
}
|
|
1437
|
+
const whereUsedResults = await Promise.all(
|
|
1438
|
+
unique.map((obj) => findWhereUsed(client, obj))
|
|
1439
|
+
);
|
|
1440
|
+
for (let i = 0; i < whereUsedResults.length; i++) {
|
|
1441
|
+
const [, e] = whereUsedResults[i];
|
|
1442
|
+
if (e) return err(new Error(`where-used failed for ${unique[i].name}: ${e.message}`));
|
|
1443
|
+
}
|
|
1444
|
+
const referencers = /* @__PURE__ */ new Map();
|
|
1445
|
+
const dependents = /* @__PURE__ */ new Map();
|
|
1446
|
+
const externalRefs = [];
|
|
1447
|
+
for (const obj of unique) {
|
|
1448
|
+
referencers.set(objKey(obj), []);
|
|
1449
|
+
dependents.set(objKey(obj), []);
|
|
1450
|
+
}
|
|
1451
|
+
for (let i = 0; i < unique.length; i++) {
|
|
1452
|
+
const obj = unique[i];
|
|
1453
|
+
const oKey = objKey(obj);
|
|
1454
|
+
const [deps] = whereUsedResults[i];
|
|
1455
|
+
for (const dep of deps) {
|
|
1456
|
+
const dKey = objKey(dep);
|
|
1457
|
+
if (dKey === oKey) continue;
|
|
1458
|
+
if (!setKeys.has(dKey)) {
|
|
1459
|
+
externalRefs.push({
|
|
1460
|
+
object: { name: obj.name, extension: obj.extension },
|
|
1461
|
+
referencedBy: dep
|
|
1462
|
+
});
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
referencers.get(oKey).push(dKey);
|
|
1466
|
+
dependents.get(dKey).push(oKey);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (externalRefs.length > 0) {
|
|
1470
|
+
return err(new ExternalReferencesError(externalRefs));
|
|
1471
|
+
}
|
|
1472
|
+
const objByKey = /* @__PURE__ */ new Map();
|
|
1473
|
+
for (const obj of unique) objByKey.set(objKey(obj), obj);
|
|
1474
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
1475
|
+
for (const [k, refs] of referencers.entries()) {
|
|
1476
|
+
inDegree.set(k, refs.length);
|
|
1477
|
+
}
|
|
1478
|
+
const remaining = new Set(setKeys);
|
|
1479
|
+
const results = [];
|
|
1480
|
+
const deleteOne = async (obj) => {
|
|
1481
|
+
const [lockHandle, lockErr] = await lockObject(client, obj);
|
|
1482
|
+
if (lockErr) {
|
|
1483
|
+
return { name: obj.name, extension: obj.extension, status: "error", message: lockErr.message };
|
|
1484
|
+
}
|
|
1485
|
+
const [, deleteErr] = await deleteObject(client, obj, lockHandle, transport);
|
|
1486
|
+
if (deleteErr) {
|
|
1487
|
+
await unlockObject(client, obj, lockHandle);
|
|
1488
|
+
return { name: obj.name, extension: obj.extension, status: "error", message: deleteErr.message };
|
|
1489
|
+
}
|
|
1490
|
+
return { name: obj.name, extension: obj.extension, status: "success" };
|
|
1491
|
+
};
|
|
1492
|
+
while (remaining.size > 0) {
|
|
1493
|
+
const ready = [];
|
|
1494
|
+
for (const key of remaining) {
|
|
1495
|
+
if ((inDegree.get(key) ?? 0) === 0) ready.push(key);
|
|
1496
|
+
}
|
|
1497
|
+
const waveKeys = ready.length > 0 ? ready : [...remaining];
|
|
1498
|
+
const waveObjects = waveKeys.map((k) => objByKey.get(k));
|
|
1499
|
+
const waveResults = await Promise.all(waveObjects.map(deleteOne));
|
|
1500
|
+
for (let i = 0; i < waveResults.length; i++) {
|
|
1501
|
+
const result = waveResults[i];
|
|
1502
|
+
const key = waveKeys[i];
|
|
1503
|
+
results.push(result);
|
|
1504
|
+
remaining.delete(key);
|
|
1505
|
+
if (result.status === "success") {
|
|
1506
|
+
for (const o of dependents.get(key) ?? []) {
|
|
1507
|
+
inDegree.set(o, (inDegree.get(o) ?? 0) - 1);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
return ok(results);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1304
1515
|
// src/core/adt/craud/create.ts
|
|
1305
1516
|
async function createObject(client, object, packageName, transport, username) {
|
|
1306
1517
|
const [config, configErr] = requireConfig(object.extension);
|
|
@@ -1366,59 +1577,31 @@ async function updateObject(client, object, lockHandle, transport) {
|
|
|
1366
1577
|
return ok(void 0);
|
|
1367
1578
|
}
|
|
1368
1579
|
|
|
1369
|
-
// src/core/adt/craud/delete.ts
|
|
1370
|
-
async function deleteObject(client, object, lockHandle, transport) {
|
|
1371
|
-
const [config, configErr] = requireConfig(object.extension);
|
|
1372
|
-
if (configErr) return err(configErr);
|
|
1373
|
-
const params = {
|
|
1374
|
-
"lockHandle": lockHandle
|
|
1375
|
-
};
|
|
1376
|
-
if (transport) {
|
|
1377
|
-
params["corrNr"] = transport;
|
|
1378
|
-
}
|
|
1379
|
-
const [response, requestErr] = await client.request({
|
|
1380
|
-
method: "DELETE",
|
|
1381
|
-
path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,
|
|
1382
|
-
params,
|
|
1383
|
-
headers: { "Accept": "text/plain" }
|
|
1384
|
-
});
|
|
1385
|
-
const [_, checkErr] = await checkResponse(
|
|
1386
|
-
response,
|
|
1387
|
-
requestErr,
|
|
1388
|
-
`Failed to delete ${config.label} ${object.name}`
|
|
1389
|
-
);
|
|
1390
|
-
if (checkErr) return err(checkErr);
|
|
1391
|
-
return ok(void 0);
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
1580
|
// src/core/adt/craud/activation.ts
|
|
1581
|
+
var MAX_POLL_ATTEMPTS = 30;
|
|
1582
|
+
var RUN_ID_REGEX = /\/activation\/runs\/([^?/]+)/;
|
|
1395
1583
|
async function activateObjects(client, objects) {
|
|
1396
1584
|
if (objects.length === 0) {
|
|
1397
1585
|
return ok([]);
|
|
1398
1586
|
}
|
|
1399
|
-
const extension = objects[0].extension;
|
|
1400
|
-
const config = getConfigByExtension(extension);
|
|
1401
|
-
if (!config) return err(new Error(`Unsupported extension: ${extension}`));
|
|
1402
1587
|
for (const obj of objects) {
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
}
|
|
1588
|
+
const config = getConfigByExtension(obj.extension);
|
|
1589
|
+
if (!config) return err(new Error(`Unsupported extension: ${obj.extension}`));
|
|
1406
1590
|
}
|
|
1407
|
-
const objectRefs = objects.map((obj) =>
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
adtcore:description="*"/>`).join("\n ");
|
|
1591
|
+
const objectRefs = objects.map((obj) => {
|
|
1592
|
+
const config = getConfigByExtension(obj.extension);
|
|
1593
|
+
return `<adtcore:objectReference adtcore:uri="/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}" adtcore:type="${config.type}" adtcore:name="${obj.name}"/>`;
|
|
1594
|
+
}).join("\n ");
|
|
1412
1595
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
const [
|
|
1596
|
+
<adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core">
|
|
1597
|
+
${objectRefs}
|
|
1598
|
+
</adtcore:objectReferences>`;
|
|
1599
|
+
const [startRes, startErr] = await client.request({
|
|
1417
1600
|
method: "POST",
|
|
1418
|
-
path: "/sap/bc/adt/activation",
|
|
1601
|
+
path: "/sap/bc/adt/activation/runs",
|
|
1419
1602
|
params: {
|
|
1420
1603
|
"method": "activate",
|
|
1421
|
-
"
|
|
1604
|
+
"preauditRequested": "false"
|
|
1422
1605
|
},
|
|
1423
1606
|
headers: {
|
|
1424
1607
|
"Content-Type": "application/xml",
|
|
@@ -1426,23 +1609,54 @@ async function activateObjects(client, objects) {
|
|
|
1426
1609
|
},
|
|
1427
1610
|
body
|
|
1428
1611
|
});
|
|
1429
|
-
if (
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1612
|
+
if (startErr) return err(startErr);
|
|
1613
|
+
debug(`Activation run start status: ${startRes.status}`);
|
|
1614
|
+
if (!startRes.ok) {
|
|
1615
|
+
const errText = await startRes.text();
|
|
1616
|
+
return err(new Error(`Activation start failed: ${extractError(errText)}`));
|
|
1617
|
+
}
|
|
1618
|
+
const location = startRes.headers.get("location");
|
|
1619
|
+
if (!location) return err(new Error("Activation start response missing Location header"));
|
|
1620
|
+
const runIdMatch = RUN_ID_REGEX.exec(location);
|
|
1621
|
+
if (!runIdMatch || !runIdMatch[1]) {
|
|
1622
|
+
return err(new Error(`Could not extract run ID from Location header: ${location}`));
|
|
1623
|
+
}
|
|
1624
|
+
const runId = runIdMatch[1];
|
|
1625
|
+
debug(`Activation run ID: ${runId}`);
|
|
1626
|
+
let pollAttempt = 0;
|
|
1627
|
+
while (pollAttempt < MAX_POLL_ATTEMPTS) {
|
|
1628
|
+
const [pollRes, pollErr] = await client.request({
|
|
1629
|
+
method: "GET",
|
|
1630
|
+
path: `/sap/bc/adt/activation/runs/${runId}`,
|
|
1631
|
+
params: { "withLongPolling": "true" },
|
|
1632
|
+
headers: { "Accept": "application/xml" }
|
|
1633
|
+
});
|
|
1634
|
+
if (pollErr) return err(pollErr);
|
|
1635
|
+
debug(`Activation poll attempt ${pollAttempt + 1} status: ${pollRes.status}`);
|
|
1636
|
+
if (pollRes.ok) break;
|
|
1637
|
+
pollAttempt++;
|
|
1638
|
+
if (pollAttempt >= MAX_POLL_ATTEMPTS) {
|
|
1639
|
+
const errText = await pollRes.text();
|
|
1640
|
+
return err(new Error(`Activation run ${runId} did not complete: ${extractError(errText)}`));
|
|
1641
|
+
}
|
|
1442
1642
|
}
|
|
1643
|
+
const [resultsRes, resultsErr] = await client.request({
|
|
1644
|
+
method: "GET",
|
|
1645
|
+
path: `/sap/bc/adt/activation/results/${runId}`,
|
|
1646
|
+
headers: { "Accept": "application/xml" }
|
|
1647
|
+
});
|
|
1648
|
+
if (resultsErr) return err(resultsErr);
|
|
1649
|
+
const resultsText = await resultsRes.text();
|
|
1650
|
+
debug(`Activation results status: ${resultsRes.status}`);
|
|
1651
|
+
debug(`Activation results body: ${resultsText.substring(0, 500)}`);
|
|
1652
|
+
if (!resultsRes.ok) {
|
|
1653
|
+
return err(new Error(`Failed to fetch activation results: ${extractError(resultsText)}`));
|
|
1654
|
+
}
|
|
1655
|
+
const [results, parseErr] = extractActivationErrors(objects, resultsText);
|
|
1656
|
+
if (parseErr) return err(parseErr);
|
|
1443
1657
|
return ok(results);
|
|
1444
1658
|
}
|
|
1445
|
-
function extractActivationErrors(objects, xml
|
|
1659
|
+
function extractActivationErrors(objects, xml) {
|
|
1446
1660
|
const [doc, parseErr] = safeParseXml(xml);
|
|
1447
1661
|
if (parseErr) {
|
|
1448
1662
|
return err(parseErr);
|
|
@@ -2041,6 +2255,83 @@ function extractTransports(xml) {
|
|
|
2041
2255
|
return ok(transports);
|
|
2042
2256
|
}
|
|
2043
2257
|
|
|
2258
|
+
// src/core/adt/discovery/inactiveObjects.ts
|
|
2259
|
+
var IOC_NS = "http://www.sap.com/abapxml/inactiveCtsObjects";
|
|
2260
|
+
var ADTCORE_NS = "http://www.sap.com/adt/core";
|
|
2261
|
+
async function getInactiveObjects(client) {
|
|
2262
|
+
const [response, requestErr] = await client.request({
|
|
2263
|
+
method: "GET",
|
|
2264
|
+
path: "/sap/bc/adt/activation/inactiveobjects",
|
|
2265
|
+
headers: {
|
|
2266
|
+
"Accept": "application/vnd.sap.adt.inactivectsobjects.v1+xml, application/xml;q=0.8"
|
|
2267
|
+
}
|
|
2268
|
+
});
|
|
2269
|
+
if (requestErr) return err(requestErr);
|
|
2270
|
+
if (!response.ok) {
|
|
2271
|
+
const text2 = await response.text();
|
|
2272
|
+
const errorMsg = extractError(text2);
|
|
2273
|
+
return err(new Error(`Failed to fetch inactive objects: ${errorMsg}`));
|
|
2274
|
+
}
|
|
2275
|
+
const text = await response.text();
|
|
2276
|
+
return parseInactiveObjects(text);
|
|
2277
|
+
}
|
|
2278
|
+
function parseInactiveObjects(xml) {
|
|
2279
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
2280
|
+
if (parseErr) return err(parseErr);
|
|
2281
|
+
const entries = [];
|
|
2282
|
+
const entryElements = doc.getElementsByTagNameNS(IOC_NS, "entry");
|
|
2283
|
+
for (let i = 0; i < entryElements.length; i++) {
|
|
2284
|
+
const entryEl = entryElements[i];
|
|
2285
|
+
if (!entryEl) continue;
|
|
2286
|
+
const entry = {};
|
|
2287
|
+
const objectEls = entryEl.getElementsByTagNameNS(IOC_NS, "object");
|
|
2288
|
+
if (objectEls.length > 0) {
|
|
2289
|
+
const objectEl = objectEls[0];
|
|
2290
|
+
const objectRef = extractRef(objectEl);
|
|
2291
|
+
if (objectRef) {
|
|
2292
|
+
const user = objectEl.getAttributeNS(IOC_NS, "user") || objectEl.getAttribute("ioc:user") || "";
|
|
2293
|
+
const deletedStr = objectEl.getAttributeNS(IOC_NS, "deleted") || objectEl.getAttribute("ioc:deleted") || "false";
|
|
2294
|
+
entry.object = {
|
|
2295
|
+
user,
|
|
2296
|
+
deleted: deletedStr === "true",
|
|
2297
|
+
ref: objectRef
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
const transportEls = entryEl.getElementsByTagNameNS(IOC_NS, "transport");
|
|
2302
|
+
if (transportEls.length > 0) {
|
|
2303
|
+
const transportEl = transportEls[0];
|
|
2304
|
+
const transportRef = extractRef(transportEl);
|
|
2305
|
+
if (transportRef) {
|
|
2306
|
+
const user = transportEl.getAttributeNS(IOC_NS, "user") || transportEl.getAttribute("ioc:user") || "";
|
|
2307
|
+
const linkedStr = transportEl.getAttributeNS(IOC_NS, "linked") || transportEl.getAttribute("ioc:linked") || "false";
|
|
2308
|
+
entry.transport = {
|
|
2309
|
+
user,
|
|
2310
|
+
linked: linkedStr === "true",
|
|
2311
|
+
ref: transportRef
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
if (entry.object || entry.transport) {
|
|
2316
|
+
entries.push(entry);
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
return ok(entries);
|
|
2320
|
+
}
|
|
2321
|
+
function extractRef(parent) {
|
|
2322
|
+
const refs = parent.getElementsByTagNameNS(IOC_NS, "ref");
|
|
2323
|
+
if (refs.length === 0) return null;
|
|
2324
|
+
const ref = refs[0];
|
|
2325
|
+
const uri = ref.getAttributeNS(ADTCORE_NS, "uri") || ref.getAttribute("adtcore:uri") || "";
|
|
2326
|
+
const type = ref.getAttributeNS(ADTCORE_NS, "type") || ref.getAttribute("adtcore:type") || "";
|
|
2327
|
+
const name = ref.getAttributeNS(ADTCORE_NS, "name") || ref.getAttribute("adtcore:name") || "";
|
|
2328
|
+
const description = ref.getAttributeNS(ADTCORE_NS, "description") || ref.getAttribute("adtcore:description") || void 0;
|
|
2329
|
+
if (!uri && !name) return null;
|
|
2330
|
+
const result = { uri, type, name };
|
|
2331
|
+
if (description) result.description = description;
|
|
2332
|
+
return result;
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2044
2335
|
// src/core/adt/data_extraction/previewParser.ts
|
|
2045
2336
|
function parseDataPreview(xml, maxRows, isTable) {
|
|
2046
2337
|
const [doc, parseErr] = safeParseXml(xml);
|
|
@@ -2367,80 +2658,6 @@ function parseSearchResults(xml) {
|
|
|
2367
2658
|
return ok(results);
|
|
2368
2659
|
}
|
|
2369
2660
|
|
|
2370
|
-
// src/core/adt/discovery/whereUsed.ts
|
|
2371
|
-
async function findWhereUsed(client, object) {
|
|
2372
|
-
const config = getConfigByExtension(object.extension);
|
|
2373
|
-
if (!config) {
|
|
2374
|
-
return err(new Error(`Unsupported extension: ${object.extension}`));
|
|
2375
|
-
}
|
|
2376
|
-
const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;
|
|
2377
|
-
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
2378
|
-
<usagereferences:usageReferenceRequest xmlns:usagereferences="http://www.sap.com/adt/ris/usageReferences">
|
|
2379
|
-
<usagereferences:affectedObjects/>
|
|
2380
|
-
</usagereferences:usageReferenceRequest>`;
|
|
2381
|
-
const [response, requestErr] = await client.request({
|
|
2382
|
-
method: "POST",
|
|
2383
|
-
path: "/sap/bc/adt/repository/informationsystem/usageReferences",
|
|
2384
|
-
params: {
|
|
2385
|
-
"uri": uri,
|
|
2386
|
-
"ris_request_type": "usageReferences"
|
|
2387
|
-
},
|
|
2388
|
-
headers: {
|
|
2389
|
-
"Content-Type": "application/vnd.sap.adt.repository.usagereferences.request.v1+xml",
|
|
2390
|
-
"Accept": "application/vnd.sap.adt.repository.usagereferences.result.v1+xml"
|
|
2391
|
-
},
|
|
2392
|
-
body
|
|
2393
|
-
});
|
|
2394
|
-
if (requestErr) {
|
|
2395
|
-
return err(requestErr);
|
|
2396
|
-
}
|
|
2397
|
-
if (!response.ok) {
|
|
2398
|
-
const text2 = await response.text();
|
|
2399
|
-
const errorMsg = extractError(text2);
|
|
2400
|
-
return err(new Error(`Where-used query failed: ${errorMsg}`));
|
|
2401
|
-
}
|
|
2402
|
-
const text = await response.text();
|
|
2403
|
-
const [dependencies, parseErr] = parseWhereUsed(text);
|
|
2404
|
-
if (parseErr) {
|
|
2405
|
-
return err(parseErr);
|
|
2406
|
-
}
|
|
2407
|
-
return ok(dependencies);
|
|
2408
|
-
}
|
|
2409
|
-
function parseWhereUsed(xml) {
|
|
2410
|
-
const [doc, parseErr] = safeParseXml(xml);
|
|
2411
|
-
if (parseErr) {
|
|
2412
|
-
return err(parseErr);
|
|
2413
|
-
}
|
|
2414
|
-
const dependencies = [];
|
|
2415
|
-
const referencedObjects = doc.getElementsByTagNameNS(
|
|
2416
|
-
"http://www.sap.com/adt/ris/usageReferences",
|
|
2417
|
-
"referencedObject"
|
|
2418
|
-
);
|
|
2419
|
-
for (let i = 0; i < referencedObjects.length; i++) {
|
|
2420
|
-
const refObj = referencedObjects[i];
|
|
2421
|
-
if (!refObj) continue;
|
|
2422
|
-
const adtObject = refObj.getElementsByTagNameNS(
|
|
2423
|
-
"http://www.sap.com/adt/ris/usageReferences",
|
|
2424
|
-
"adtObject"
|
|
2425
|
-
)[0];
|
|
2426
|
-
if (!adtObject) continue;
|
|
2427
|
-
const name = adtObject.getAttributeNS("http://www.sap.com/adt/core", "name") || adtObject.getAttribute("adtcore:name");
|
|
2428
|
-
const type = adtObject.getAttributeNS("http://www.sap.com/adt/core", "type") || adtObject.getAttribute("adtcore:type");
|
|
2429
|
-
if (!name || !type) continue;
|
|
2430
|
-
const config = getConfigByType(type);
|
|
2431
|
-
if (!config) continue;
|
|
2432
|
-
const packageRef = adtObject.getElementsByTagNameNS("http://www.sap.com/adt/core", "packageRef")[0];
|
|
2433
|
-
const packageName = packageRef ? packageRef.getAttributeNS("http://www.sap.com/adt/core", "name") || packageRef.getAttribute("adtcore:name") : "";
|
|
2434
|
-
dependencies.push({
|
|
2435
|
-
name,
|
|
2436
|
-
extension: config.extension,
|
|
2437
|
-
package: packageName || "",
|
|
2438
|
-
usageType: "reference"
|
|
2439
|
-
});
|
|
2440
|
-
}
|
|
2441
|
-
return ok(dependencies);
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
2661
|
// src/core/adt/transports/createTransport.ts
|
|
2445
2662
|
async function createTransport(client, config) {
|
|
2446
2663
|
const body = dictToAbapXml({
|
|
@@ -2833,16 +3050,7 @@ async function activate(state, requestor, objects) {
|
|
|
2833
3050
|
// src/client/methods/craud/delete.ts
|
|
2834
3051
|
async function deleteObjects(state, requestor, objects, transport) {
|
|
2835
3052
|
if (!state.session) return err(new Error("Not logged in"));
|
|
2836
|
-
|
|
2837
|
-
const [lockHandle, lockErr] = await lockObject(requestor, obj);
|
|
2838
|
-
if (lockErr) return err(lockErr);
|
|
2839
|
-
const [, deleteErr] = await deleteObject(requestor, obj, lockHandle, transport);
|
|
2840
|
-
if (deleteErr) {
|
|
2841
|
-
await unlockObject(requestor, obj, lockHandle);
|
|
2842
|
-
return err(deleteErr);
|
|
2843
|
-
}
|
|
2844
|
-
}
|
|
2845
|
-
return ok(void 0);
|
|
3053
|
+
return multiDeleteObjects(requestor, objects, transport);
|
|
2846
3054
|
}
|
|
2847
3055
|
|
|
2848
3056
|
// src/client/methods/craud/checkSyntax.ts
|
|
@@ -2875,6 +3083,12 @@ async function getTransports2(state, requestor, packageName) {
|
|
|
2875
3083
|
return getTransports(requestor, packageName);
|
|
2876
3084
|
}
|
|
2877
3085
|
|
|
3086
|
+
// src/client/methods/discovery/getInactiveObjects.ts
|
|
3087
|
+
async function getInactiveObjects2(state, requestor) {
|
|
3088
|
+
if (!state.session) return err(new Error("Not logged in"));
|
|
3089
|
+
return getInactiveObjects(requestor);
|
|
3090
|
+
}
|
|
3091
|
+
|
|
2878
3092
|
// src/client/methods/preview/previewData.ts
|
|
2879
3093
|
async function previewData2(state, requestor, query) {
|
|
2880
3094
|
if (!state.session) return err(new Error("Not logged in"));
|
|
@@ -3284,6 +3498,9 @@ var ADTClientImpl = class {
|
|
|
3284
3498
|
async getTransports(packageName) {
|
|
3285
3499
|
return getTransports2(this.state, this.requestor, packageName);
|
|
3286
3500
|
}
|
|
3501
|
+
async getInactiveObjects() {
|
|
3502
|
+
return getInactiveObjects2(this.state, this.requestor);
|
|
3503
|
+
}
|
|
3287
3504
|
// --- Data Preview ---
|
|
3288
3505
|
async previewData(query) {
|
|
3289
3506
|
return previewData2(this.state, this.requestor, query);
|