catalyst-relay 0.5.10 → 0.5.12
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 +32 -17
- package/dist/index.d.ts +32 -17
- package/dist/index.js +273 -140
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +272 -140
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -182,7 +182,7 @@ type ApiResponse<T> = SuccessResponse<T> | ErrorResponse;
|
|
|
182
182
|
/**
|
|
183
183
|
* Machine-readable error codes
|
|
184
184
|
*/
|
|
185
|
-
type ErrorCode = 'AUTH_FAILED' | 'SESSION_EXPIRED' | 'SESSION_NOT_FOUND' | 'CSRF_INVALID' | 'OBJECT_LOCKED' | 'OBJECT_NOT_FOUND' | 'TRANSPORT_REQUIRED' | 'ACTIVATION_FAILED' | 'CHECK_FAILED' | 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'UNKNOWN_ERROR';
|
|
185
|
+
type ErrorCode = 'AUTH_FAILED' | 'SESSION_EXPIRED' | 'SESSION_NOT_FOUND' | 'CSRF_INVALID' | 'OBJECT_LOCKED' | 'OBJECT_NOT_FOUND' | 'TRANSPORT_REQUIRED' | 'ACTIVATION_FAILED' | 'CHECK_FAILED' | 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'EXTERNAL_REFERENCES' | 'UNKNOWN_ERROR';
|
|
186
186
|
|
|
187
187
|
/**
|
|
188
188
|
* Session management type definitions
|
|
@@ -308,6 +308,35 @@ interface ActivationMessage {
|
|
|
308
308
|
column?: number;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Where-Used — Find object dependencies
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Where-used dependency
|
|
317
|
+
*/
|
|
318
|
+
interface Dependency {
|
|
319
|
+
name: string;
|
|
320
|
+
extension: string;
|
|
321
|
+
package: string;
|
|
322
|
+
usageType: string;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface DeleteResult {
|
|
326
|
+
name: string;
|
|
327
|
+
extension: string;
|
|
328
|
+
status: 'success' | 'error';
|
|
329
|
+
message?: string;
|
|
330
|
+
}
|
|
331
|
+
interface ExternalReference {
|
|
332
|
+
object: ObjectRef;
|
|
333
|
+
referencedBy: Dependency;
|
|
334
|
+
}
|
|
335
|
+
declare class ExternalReferencesError extends Error {
|
|
336
|
+
references: ExternalReference[];
|
|
337
|
+
constructor(references: ExternalReference[]);
|
|
338
|
+
}
|
|
339
|
+
|
|
311
340
|
interface CheckResult {
|
|
312
341
|
name: string;
|
|
313
342
|
extension: string;
|
|
@@ -528,20 +557,6 @@ interface SearchOptions {
|
|
|
528
557
|
includePackages?: boolean;
|
|
529
558
|
}
|
|
530
559
|
|
|
531
|
-
/**
|
|
532
|
-
* Where-Used — Find object dependencies
|
|
533
|
-
*/
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Where-used dependency
|
|
537
|
-
*/
|
|
538
|
-
interface Dependency {
|
|
539
|
-
name: string;
|
|
540
|
-
extension: string;
|
|
541
|
-
package: string;
|
|
542
|
-
usageType: string;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
560
|
/**
|
|
546
561
|
* Create Transport — Create a new transport request for a package
|
|
547
562
|
*/
|
|
@@ -649,7 +664,7 @@ interface ADTClient {
|
|
|
649
664
|
upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]>;
|
|
650
665
|
activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]>;
|
|
651
666
|
checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]>;
|
|
652
|
-
delete(objects: ObjectRef[], transport?: string): AsyncResult<
|
|
667
|
+
delete(objects: ObjectRef[], transport?: string): AsyncResult<DeleteResult[]>;
|
|
653
668
|
getPackages(options?: GetPackagesOptions): AsyncResult<Package[]>;
|
|
654
669
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
655
670
|
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
@@ -691,4 +706,4 @@ declare function activateLogging(): void;
|
|
|
691
706
|
*/
|
|
692
707
|
declare function deactivateLogging(): void;
|
|
693
708
|
|
|
694
|
-
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type AsyncResult, type AuthConfig, type AuthType, type BasicAuthConfig, type BasicFilter, type BetweenFilter, type ClientConfig, type ColumnInfo, type DataFrame, type DataPreviewQuery, type Dependency, type DiffResult, type DistinctResult, type ErrorCode, type ErrorResponse, type ExportableSessionState, type FolderNode, type InactiveEntry, type InactiveObject, type InactiveRef, type InactiveTransport, type ListFilter, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectNode, type ObjectRef, type ObjectWithContent, type Package, type PackageNode, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchOptions, type SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type TaskContents, type Transport, type TransportConfig, type TransportObject, type TreeQuery, type TreeResponse, type UpsertResult, activateLogging, buildSQLQuery, createClient, deactivateLogging, err, ok };
|
|
709
|
+
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type AsyncResult, type AuthConfig, type AuthType, type BasicAuthConfig, type BasicFilter, type BetweenFilter, type CheckResult, type ClientConfig, type ColumnInfo, type DataFrame, type DataPreviewQuery, type DeleteResult, type Dependency, type DiffHunk, type DiffResult, type DistinctResult, type ErrorCode, type ErrorResponse, type ExportableSessionState, type ExternalReference, ExternalReferencesError, type FolderNode, type GetPackagesOptions, type InactiveEntry, type InactiveObject, type InactiveRef, type InactiveTransport, type ListFilter, type ModifiedDiffHunk, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectNode, type ObjectRef, type ObjectWithContent, type Package, type PackageNode, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchOptions, type SearchResult, type Session, type SimpleDiffHunk, type Sorting, type SsoAuthConfig, type SuccessResponse, type TaskContents, type Transport, type TransportConfig, type TransportObject, type TreeQuery, type TreeResponse, type UpsertResult, activateLogging, buildSQLQuery, createClient, deactivateLogging, err, ok };
|
package/dist/index.d.ts
CHANGED
|
@@ -182,7 +182,7 @@ type ApiResponse<T> = SuccessResponse<T> | ErrorResponse;
|
|
|
182
182
|
/**
|
|
183
183
|
* Machine-readable error codes
|
|
184
184
|
*/
|
|
185
|
-
type ErrorCode = 'AUTH_FAILED' | 'SESSION_EXPIRED' | 'SESSION_NOT_FOUND' | 'CSRF_INVALID' | 'OBJECT_LOCKED' | 'OBJECT_NOT_FOUND' | 'TRANSPORT_REQUIRED' | 'ACTIVATION_FAILED' | 'CHECK_FAILED' | 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'UNKNOWN_ERROR';
|
|
185
|
+
type ErrorCode = 'AUTH_FAILED' | 'SESSION_EXPIRED' | 'SESSION_NOT_FOUND' | 'CSRF_INVALID' | 'OBJECT_LOCKED' | 'OBJECT_NOT_FOUND' | 'TRANSPORT_REQUIRED' | 'ACTIVATION_FAILED' | 'CHECK_FAILED' | 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'EXTERNAL_REFERENCES' | 'UNKNOWN_ERROR';
|
|
186
186
|
|
|
187
187
|
/**
|
|
188
188
|
* Session management type definitions
|
|
@@ -308,6 +308,35 @@ interface ActivationMessage {
|
|
|
308
308
|
column?: number;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Where-Used — Find object dependencies
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Where-used dependency
|
|
317
|
+
*/
|
|
318
|
+
interface Dependency {
|
|
319
|
+
name: string;
|
|
320
|
+
extension: string;
|
|
321
|
+
package: string;
|
|
322
|
+
usageType: string;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface DeleteResult {
|
|
326
|
+
name: string;
|
|
327
|
+
extension: string;
|
|
328
|
+
status: 'success' | 'error';
|
|
329
|
+
message?: string;
|
|
330
|
+
}
|
|
331
|
+
interface ExternalReference {
|
|
332
|
+
object: ObjectRef;
|
|
333
|
+
referencedBy: Dependency;
|
|
334
|
+
}
|
|
335
|
+
declare class ExternalReferencesError extends Error {
|
|
336
|
+
references: ExternalReference[];
|
|
337
|
+
constructor(references: ExternalReference[]);
|
|
338
|
+
}
|
|
339
|
+
|
|
311
340
|
interface CheckResult {
|
|
312
341
|
name: string;
|
|
313
342
|
extension: string;
|
|
@@ -528,20 +557,6 @@ interface SearchOptions {
|
|
|
528
557
|
includePackages?: boolean;
|
|
529
558
|
}
|
|
530
559
|
|
|
531
|
-
/**
|
|
532
|
-
* Where-Used — Find object dependencies
|
|
533
|
-
*/
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Where-used dependency
|
|
537
|
-
*/
|
|
538
|
-
interface Dependency {
|
|
539
|
-
name: string;
|
|
540
|
-
extension: string;
|
|
541
|
-
package: string;
|
|
542
|
-
usageType: string;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
560
|
/**
|
|
546
561
|
* Create Transport — Create a new transport request for a package
|
|
547
562
|
*/
|
|
@@ -649,7 +664,7 @@ interface ADTClient {
|
|
|
649
664
|
upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]>;
|
|
650
665
|
activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]>;
|
|
651
666
|
checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]>;
|
|
652
|
-
delete(objects: ObjectRef[], transport?: string): AsyncResult<
|
|
667
|
+
delete(objects: ObjectRef[], transport?: string): AsyncResult<DeleteResult[]>;
|
|
653
668
|
getPackages(options?: GetPackagesOptions): AsyncResult<Package[]>;
|
|
654
669
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
655
670
|
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
@@ -691,4 +706,4 @@ declare function activateLogging(): void;
|
|
|
691
706
|
*/
|
|
692
707
|
declare function deactivateLogging(): void;
|
|
693
708
|
|
|
694
|
-
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type AsyncResult, type AuthConfig, type AuthType, type BasicAuthConfig, type BasicFilter, type BetweenFilter, type ClientConfig, type ColumnInfo, type DataFrame, type DataPreviewQuery, type Dependency, type DiffResult, type DistinctResult, type ErrorCode, type ErrorResponse, type ExportableSessionState, type FolderNode, type InactiveEntry, type InactiveObject, type InactiveRef, type InactiveTransport, type ListFilter, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectNode, type ObjectRef, type ObjectWithContent, type Package, type PackageNode, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchOptions, type SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type TaskContents, type Transport, type TransportConfig, type TransportObject, type TreeQuery, type TreeResponse, type UpsertResult, activateLogging, buildSQLQuery, createClient, deactivateLogging, err, ok };
|
|
709
|
+
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type AsyncResult, type AuthConfig, type AuthType, type BasicAuthConfig, type BasicFilter, type BetweenFilter, type CheckResult, type ClientConfig, type ColumnInfo, type DataFrame, type DataPreviewQuery, type DeleteResult, type Dependency, type DiffHunk, type DiffResult, type DistinctResult, type ErrorCode, type ErrorResponse, type ExportableSessionState, type ExternalReference, ExternalReferencesError, type FolderNode, type GetPackagesOptions, type InactiveEntry, type InactiveObject, type InactiveRef, type InactiveTransport, type ListFilter, type ModifiedDiffHunk, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectNode, type ObjectRef, type ObjectWithContent, type Package, type PackageNode, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchOptions, type SearchResult, type Session, type SimpleDiffHunk, type Sorting, type SsoAuthConfig, type SuccessResponse, type TaskContents, type Transport, type TransportConfig, type TransportObject, type TreeQuery, type TreeResponse, type UpsertResult, activateLogging, buildSQLQuery, createClient, deactivateLogging, err, ok };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ExternalReferencesError: () => ExternalReferencesError,
|
|
33
34
|
activateLogging: () => activateLogging,
|
|
34
35
|
buildSQLQuery: () => buildSQLQuery,
|
|
35
36
|
createClient: () => createClient,
|
|
@@ -1226,6 +1227,14 @@ var OBJECT_CONFIG_MAP = {
|
|
|
1226
1227
|
type: "PROG/P",
|
|
1227
1228
|
label: "ABAP Program" /* PROGRAM */,
|
|
1228
1229
|
extension: "asprog"
|
|
1230
|
+
},
|
|
1231
|
+
"asinc": {
|
|
1232
|
+
endpoint: "programs/includes",
|
|
1233
|
+
nameSpace: 'xmlns:include="http://www.sap.com/adt/programs/includes"',
|
|
1234
|
+
rootName: "include:abapInclude",
|
|
1235
|
+
type: "PROG/I",
|
|
1236
|
+
label: "ABAP Include" /* INCLUDE */,
|
|
1237
|
+
extension: "asinc"
|
|
1229
1238
|
}
|
|
1230
1239
|
};
|
|
1231
1240
|
function getConfigByExtension(extension) {
|
|
@@ -1287,6 +1296,80 @@ async function readObject(client, object) {
|
|
|
1287
1296
|
return ok(result);
|
|
1288
1297
|
}
|
|
1289
1298
|
|
|
1299
|
+
// src/core/adt/discovery/whereUsed.ts
|
|
1300
|
+
async function findWhereUsed(client, object) {
|
|
1301
|
+
const config = getConfigByExtension(object.extension);
|
|
1302
|
+
if (!config) {
|
|
1303
|
+
return err(new Error(`Unsupported extension: ${object.extension}`));
|
|
1304
|
+
}
|
|
1305
|
+
const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;
|
|
1306
|
+
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1307
|
+
<usagereferences:usageReferenceRequest xmlns:usagereferences="http://www.sap.com/adt/ris/usageReferences">
|
|
1308
|
+
<usagereferences:affectedObjects/>
|
|
1309
|
+
</usagereferences:usageReferenceRequest>`;
|
|
1310
|
+
const [response, requestErr] = await client.request({
|
|
1311
|
+
method: "POST",
|
|
1312
|
+
path: "/sap/bc/adt/repository/informationsystem/usageReferences",
|
|
1313
|
+
params: {
|
|
1314
|
+
"uri": uri,
|
|
1315
|
+
"ris_request_type": "usageReferences"
|
|
1316
|
+
},
|
|
1317
|
+
headers: {
|
|
1318
|
+
"Content-Type": "application/vnd.sap.adt.repository.usagereferences.request.v1+xml",
|
|
1319
|
+
"Accept": "application/vnd.sap.adt.repository.usagereferences.result.v1+xml"
|
|
1320
|
+
},
|
|
1321
|
+
body
|
|
1322
|
+
});
|
|
1323
|
+
if (requestErr) {
|
|
1324
|
+
return err(requestErr);
|
|
1325
|
+
}
|
|
1326
|
+
if (!response.ok) {
|
|
1327
|
+
const text2 = await response.text();
|
|
1328
|
+
const errorMsg = extractError(text2);
|
|
1329
|
+
return err(new Error(`Where-used query failed: ${errorMsg}`));
|
|
1330
|
+
}
|
|
1331
|
+
const text = await response.text();
|
|
1332
|
+
const [dependencies, parseErr] = parseWhereUsed(text);
|
|
1333
|
+
if (parseErr) {
|
|
1334
|
+
return err(parseErr);
|
|
1335
|
+
}
|
|
1336
|
+
return ok(dependencies);
|
|
1337
|
+
}
|
|
1338
|
+
function parseWhereUsed(xml) {
|
|
1339
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
1340
|
+
if (parseErr) {
|
|
1341
|
+
return err(parseErr);
|
|
1342
|
+
}
|
|
1343
|
+
const dependencies = [];
|
|
1344
|
+
const referencedObjects = doc.getElementsByTagNameNS(
|
|
1345
|
+
"http://www.sap.com/adt/ris/usageReferences",
|
|
1346
|
+
"referencedObject"
|
|
1347
|
+
);
|
|
1348
|
+
for (let i = 0; i < referencedObjects.length; i++) {
|
|
1349
|
+
const refObj = referencedObjects[i];
|
|
1350
|
+
if (!refObj) continue;
|
|
1351
|
+
const adtObject = refObj.getElementsByTagNameNS(
|
|
1352
|
+
"http://www.sap.com/adt/ris/usageReferences",
|
|
1353
|
+
"adtObject"
|
|
1354
|
+
)[0];
|
|
1355
|
+
if (!adtObject) continue;
|
|
1356
|
+
const name = adtObject.getAttributeNS("http://www.sap.com/adt/core", "name") || adtObject.getAttribute("adtcore:name");
|
|
1357
|
+
const type = adtObject.getAttributeNS("http://www.sap.com/adt/core", "type") || adtObject.getAttribute("adtcore:type");
|
|
1358
|
+
if (!name || !type) continue;
|
|
1359
|
+
const config = getConfigByType(type);
|
|
1360
|
+
if (!config) continue;
|
|
1361
|
+
const packageRef = adtObject.getElementsByTagNameNS("http://www.sap.com/adt/core", "packageRef")[0];
|
|
1362
|
+
const packageName = packageRef ? packageRef.getAttributeNS("http://www.sap.com/adt/core", "name") || packageRef.getAttribute("adtcore:name") : "";
|
|
1363
|
+
dependencies.push({
|
|
1364
|
+
name,
|
|
1365
|
+
extension: config.extension,
|
|
1366
|
+
package: packageName || "",
|
|
1367
|
+
usageType: "reference"
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
return ok(dependencies);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1290
1373
|
// src/core/adt/craud/lock.ts
|
|
1291
1374
|
async function lockObject(client, object) {
|
|
1292
1375
|
const [config, configErr] = requireConfig(object.extension);
|
|
@@ -1335,6 +1418,135 @@ async function unlockObject(client, object, lockHandle) {
|
|
|
1335
1418
|
return ok(void 0);
|
|
1336
1419
|
}
|
|
1337
1420
|
|
|
1421
|
+
// src/core/adt/craud/delete.ts
|
|
1422
|
+
async function deleteObject(client, object, lockHandle, transport) {
|
|
1423
|
+
const [config, configErr] = requireConfig(object.extension);
|
|
1424
|
+
if (configErr) return err(configErr);
|
|
1425
|
+
const params = {
|
|
1426
|
+
"lockHandle": lockHandle
|
|
1427
|
+
};
|
|
1428
|
+
if (transport) {
|
|
1429
|
+
params["corrNr"] = transport;
|
|
1430
|
+
}
|
|
1431
|
+
const [response, requestErr] = await client.request({
|
|
1432
|
+
method: "DELETE",
|
|
1433
|
+
path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,
|
|
1434
|
+
params,
|
|
1435
|
+
headers: { "Accept": "text/plain" }
|
|
1436
|
+
});
|
|
1437
|
+
const [_, checkErr] = await checkResponse(
|
|
1438
|
+
response,
|
|
1439
|
+
requestErr,
|
|
1440
|
+
`Failed to delete ${config.label} ${object.name}`
|
|
1441
|
+
);
|
|
1442
|
+
if (checkErr) return err(checkErr);
|
|
1443
|
+
return ok(void 0);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
// src/core/adt/craud/multiDelete.ts
|
|
1447
|
+
var ExternalReferencesError = class extends Error {
|
|
1448
|
+
constructor(references) {
|
|
1449
|
+
super(`Cannot delete: ${references.length} external reference(s) prevent the operation`);
|
|
1450
|
+
this.references = references;
|
|
1451
|
+
this.name = "ExternalReferencesError";
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
function objKey(o) {
|
|
1455
|
+
return `${o.name.toLowerCase()}|${o.extension}`;
|
|
1456
|
+
}
|
|
1457
|
+
async function multiDeleteObjects(client, objects, transport) {
|
|
1458
|
+
if (objects.length === 0) return ok([]);
|
|
1459
|
+
for (const obj of objects) {
|
|
1460
|
+
if (!getConfigByExtension(obj.extension)) {
|
|
1461
|
+
return err(new Error(`Unsupported extension: ${obj.extension}`));
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
const setKeys = /* @__PURE__ */ new Set();
|
|
1465
|
+
const unique = [];
|
|
1466
|
+
for (const obj of objects) {
|
|
1467
|
+
const key = objKey(obj);
|
|
1468
|
+
if (setKeys.has(key)) continue;
|
|
1469
|
+
setKeys.add(key);
|
|
1470
|
+
unique.push(obj);
|
|
1471
|
+
}
|
|
1472
|
+
const whereUsedResults = await Promise.all(
|
|
1473
|
+
unique.map((obj) => findWhereUsed(client, obj))
|
|
1474
|
+
);
|
|
1475
|
+
for (let i = 0; i < whereUsedResults.length; i++) {
|
|
1476
|
+
const [, e] = whereUsedResults[i];
|
|
1477
|
+
if (e) return err(new Error(`where-used failed for ${unique[i].name}: ${e.message}`));
|
|
1478
|
+
}
|
|
1479
|
+
const referencers = /* @__PURE__ */ new Map();
|
|
1480
|
+
const dependents = /* @__PURE__ */ new Map();
|
|
1481
|
+
const externalRefs = [];
|
|
1482
|
+
for (const obj of unique) {
|
|
1483
|
+
referencers.set(objKey(obj), []);
|
|
1484
|
+
dependents.set(objKey(obj), []);
|
|
1485
|
+
}
|
|
1486
|
+
for (let i = 0; i < unique.length; i++) {
|
|
1487
|
+
const obj = unique[i];
|
|
1488
|
+
const oKey = objKey(obj);
|
|
1489
|
+
const [deps] = whereUsedResults[i];
|
|
1490
|
+
for (const dep of deps) {
|
|
1491
|
+
const dKey = objKey(dep);
|
|
1492
|
+
if (dKey === oKey) continue;
|
|
1493
|
+
if (!setKeys.has(dKey)) {
|
|
1494
|
+
externalRefs.push({
|
|
1495
|
+
object: { name: obj.name, extension: obj.extension },
|
|
1496
|
+
referencedBy: dep
|
|
1497
|
+
});
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
referencers.get(oKey).push(dKey);
|
|
1501
|
+
dependents.get(dKey).push(oKey);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
if (externalRefs.length > 0) {
|
|
1505
|
+
return err(new ExternalReferencesError(externalRefs));
|
|
1506
|
+
}
|
|
1507
|
+
const objByKey = /* @__PURE__ */ new Map();
|
|
1508
|
+
for (const obj of unique) objByKey.set(objKey(obj), obj);
|
|
1509
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
1510
|
+
for (const [k, refs] of referencers.entries()) {
|
|
1511
|
+
inDegree.set(k, refs.length);
|
|
1512
|
+
}
|
|
1513
|
+
const remaining = new Set(setKeys);
|
|
1514
|
+
const results = [];
|
|
1515
|
+
const deleteOne = async (obj) => {
|
|
1516
|
+
const [lockHandle, lockErr] = await lockObject(client, obj);
|
|
1517
|
+
if (lockErr) {
|
|
1518
|
+
return { name: obj.name, extension: obj.extension, status: "error", message: lockErr.message };
|
|
1519
|
+
}
|
|
1520
|
+
const [, deleteErr] = await deleteObject(client, obj, lockHandle, transport);
|
|
1521
|
+
if (deleteErr) {
|
|
1522
|
+
await unlockObject(client, obj, lockHandle);
|
|
1523
|
+
return { name: obj.name, extension: obj.extension, status: "error", message: deleteErr.message };
|
|
1524
|
+
}
|
|
1525
|
+
return { name: obj.name, extension: obj.extension, status: "success" };
|
|
1526
|
+
};
|
|
1527
|
+
while (remaining.size > 0) {
|
|
1528
|
+
const ready = [];
|
|
1529
|
+
for (const key of remaining) {
|
|
1530
|
+
if ((inDegree.get(key) ?? 0) === 0) ready.push(key);
|
|
1531
|
+
}
|
|
1532
|
+
const waveKeys = ready.length > 0 ? ready : [...remaining];
|
|
1533
|
+
const waveObjects = waveKeys.map((k) => objByKey.get(k));
|
|
1534
|
+
const waveResults = await Promise.all(waveObjects.map(deleteOne));
|
|
1535
|
+
for (let i = 0; i < waveResults.length; i++) {
|
|
1536
|
+
const result = waveResults[i];
|
|
1537
|
+
const key = waveKeys[i];
|
|
1538
|
+
results.push(result);
|
|
1539
|
+
remaining.delete(key);
|
|
1540
|
+
if (result.status === "success") {
|
|
1541
|
+
for (const o of dependents.get(key) ?? []) {
|
|
1542
|
+
inDegree.set(o, (inDegree.get(o) ?? 0) - 1);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
return ok(results);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1338
1550
|
// src/core/adt/craud/create.ts
|
|
1339
1551
|
async function createObject(client, object, packageName, transport, username) {
|
|
1340
1552
|
const [config, configErr] = requireConfig(object.extension);
|
|
@@ -1400,59 +1612,31 @@ async function updateObject(client, object, lockHandle, transport) {
|
|
|
1400
1612
|
return ok(void 0);
|
|
1401
1613
|
}
|
|
1402
1614
|
|
|
1403
|
-
// src/core/adt/craud/delete.ts
|
|
1404
|
-
async function deleteObject(client, object, lockHandle, transport) {
|
|
1405
|
-
const [config, configErr] = requireConfig(object.extension);
|
|
1406
|
-
if (configErr) return err(configErr);
|
|
1407
|
-
const params = {
|
|
1408
|
-
"lockHandle": lockHandle
|
|
1409
|
-
};
|
|
1410
|
-
if (transport) {
|
|
1411
|
-
params["corrNr"] = transport;
|
|
1412
|
-
}
|
|
1413
|
-
const [response, requestErr] = await client.request({
|
|
1414
|
-
method: "DELETE",
|
|
1415
|
-
path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,
|
|
1416
|
-
params,
|
|
1417
|
-
headers: { "Accept": "text/plain" }
|
|
1418
|
-
});
|
|
1419
|
-
const [_, checkErr] = await checkResponse(
|
|
1420
|
-
response,
|
|
1421
|
-
requestErr,
|
|
1422
|
-
`Failed to delete ${config.label} ${object.name}`
|
|
1423
|
-
);
|
|
1424
|
-
if (checkErr) return err(checkErr);
|
|
1425
|
-
return ok(void 0);
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
1615
|
// src/core/adt/craud/activation.ts
|
|
1616
|
+
var MAX_POLL_ATTEMPTS = 30;
|
|
1617
|
+
var RUN_ID_REGEX = /\/activation\/runs\/([^?/]+)/;
|
|
1429
1618
|
async function activateObjects(client, objects) {
|
|
1430
1619
|
if (objects.length === 0) {
|
|
1431
1620
|
return ok([]);
|
|
1432
1621
|
}
|
|
1433
|
-
const extension = objects[0].extension;
|
|
1434
|
-
const config = getConfigByExtension(extension);
|
|
1435
|
-
if (!config) return err(new Error(`Unsupported extension: ${extension}`));
|
|
1436
1622
|
for (const obj of objects) {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
}
|
|
1623
|
+
const config = getConfigByExtension(obj.extension);
|
|
1624
|
+
if (!config) return err(new Error(`Unsupported extension: ${obj.extension}`));
|
|
1440
1625
|
}
|
|
1441
|
-
const objectRefs = objects.map((obj) =>
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
adtcore:description="*"/>`).join("\n ");
|
|
1626
|
+
const objectRefs = objects.map((obj) => {
|
|
1627
|
+
const config = getConfigByExtension(obj.extension);
|
|
1628
|
+
return `<adtcore:objectReference adtcore:uri="/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}" adtcore:type="${config.type}" adtcore:name="${obj.name}"/>`;
|
|
1629
|
+
}).join("\n ");
|
|
1446
1630
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
const [
|
|
1631
|
+
<adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core">
|
|
1632
|
+
${objectRefs}
|
|
1633
|
+
</adtcore:objectReferences>`;
|
|
1634
|
+
const [startRes, startErr] = await client.request({
|
|
1451
1635
|
method: "POST",
|
|
1452
|
-
path: "/sap/bc/adt/activation",
|
|
1636
|
+
path: "/sap/bc/adt/activation/runs",
|
|
1453
1637
|
params: {
|
|
1454
1638
|
"method": "activate",
|
|
1455
|
-
"
|
|
1639
|
+
"preauditRequested": "false"
|
|
1456
1640
|
},
|
|
1457
1641
|
headers: {
|
|
1458
1642
|
"Content-Type": "application/xml",
|
|
@@ -1460,23 +1644,54 @@ async function activateObjects(client, objects) {
|
|
|
1460
1644
|
},
|
|
1461
1645
|
body
|
|
1462
1646
|
});
|
|
1463
|
-
if (
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1647
|
+
if (startErr) return err(startErr);
|
|
1648
|
+
debug(`Activation run start status: ${startRes.status}`);
|
|
1649
|
+
if (!startRes.ok) {
|
|
1650
|
+
const errText = await startRes.text();
|
|
1651
|
+
return err(new Error(`Activation start failed: ${extractError(errText)}`));
|
|
1652
|
+
}
|
|
1653
|
+
const location = startRes.headers.get("location");
|
|
1654
|
+
if (!location) return err(new Error("Activation start response missing Location header"));
|
|
1655
|
+
const runIdMatch = RUN_ID_REGEX.exec(location);
|
|
1656
|
+
if (!runIdMatch || !runIdMatch[1]) {
|
|
1657
|
+
return err(new Error(`Could not extract run ID from Location header: ${location}`));
|
|
1658
|
+
}
|
|
1659
|
+
const runId = runIdMatch[1];
|
|
1660
|
+
debug(`Activation run ID: ${runId}`);
|
|
1661
|
+
let pollAttempt = 0;
|
|
1662
|
+
while (pollAttempt < MAX_POLL_ATTEMPTS) {
|
|
1663
|
+
const [pollRes, pollErr] = await client.request({
|
|
1664
|
+
method: "GET",
|
|
1665
|
+
path: `/sap/bc/adt/activation/runs/${runId}`,
|
|
1666
|
+
params: { "withLongPolling": "true" },
|
|
1667
|
+
headers: { "Accept": "application/xml" }
|
|
1668
|
+
});
|
|
1669
|
+
if (pollErr) return err(pollErr);
|
|
1670
|
+
debug(`Activation poll attempt ${pollAttempt + 1} status: ${pollRes.status}`);
|
|
1671
|
+
if (pollRes.ok) break;
|
|
1672
|
+
pollAttempt++;
|
|
1673
|
+
if (pollAttempt >= MAX_POLL_ATTEMPTS) {
|
|
1674
|
+
const errText = await pollRes.text();
|
|
1675
|
+
return err(new Error(`Activation run ${runId} did not complete: ${extractError(errText)}`));
|
|
1676
|
+
}
|
|
1476
1677
|
}
|
|
1678
|
+
const [resultsRes, resultsErr] = await client.request({
|
|
1679
|
+
method: "GET",
|
|
1680
|
+
path: `/sap/bc/adt/activation/results/${runId}`,
|
|
1681
|
+
headers: { "Accept": "application/xml" }
|
|
1682
|
+
});
|
|
1683
|
+
if (resultsErr) return err(resultsErr);
|
|
1684
|
+
const resultsText = await resultsRes.text();
|
|
1685
|
+
debug(`Activation results status: ${resultsRes.status}`);
|
|
1686
|
+
debug(`Activation results body: ${resultsText.substring(0, 500)}`);
|
|
1687
|
+
if (!resultsRes.ok) {
|
|
1688
|
+
return err(new Error(`Failed to fetch activation results: ${extractError(resultsText)}`));
|
|
1689
|
+
}
|
|
1690
|
+
const [results, parseErr] = extractActivationErrors(objects, resultsText);
|
|
1691
|
+
if (parseErr) return err(parseErr);
|
|
1477
1692
|
return ok(results);
|
|
1478
1693
|
}
|
|
1479
|
-
function extractActivationErrors(objects, xml
|
|
1694
|
+
function extractActivationErrors(objects, xml) {
|
|
1480
1695
|
const [doc, parseErr] = safeParseXml(xml);
|
|
1481
1696
|
if (parseErr) {
|
|
1482
1697
|
return err(parseErr);
|
|
@@ -2478,80 +2693,6 @@ function parseSearchResults(xml) {
|
|
|
2478
2693
|
return ok(results);
|
|
2479
2694
|
}
|
|
2480
2695
|
|
|
2481
|
-
// src/core/adt/discovery/whereUsed.ts
|
|
2482
|
-
async function findWhereUsed(client, object) {
|
|
2483
|
-
const config = getConfigByExtension(object.extension);
|
|
2484
|
-
if (!config) {
|
|
2485
|
-
return err(new Error(`Unsupported extension: ${object.extension}`));
|
|
2486
|
-
}
|
|
2487
|
-
const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;
|
|
2488
|
-
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
2489
|
-
<usagereferences:usageReferenceRequest xmlns:usagereferences="http://www.sap.com/adt/ris/usageReferences">
|
|
2490
|
-
<usagereferences:affectedObjects/>
|
|
2491
|
-
</usagereferences:usageReferenceRequest>`;
|
|
2492
|
-
const [response, requestErr] = await client.request({
|
|
2493
|
-
method: "POST",
|
|
2494
|
-
path: "/sap/bc/adt/repository/informationsystem/usageReferences",
|
|
2495
|
-
params: {
|
|
2496
|
-
"uri": uri,
|
|
2497
|
-
"ris_request_type": "usageReferences"
|
|
2498
|
-
},
|
|
2499
|
-
headers: {
|
|
2500
|
-
"Content-Type": "application/vnd.sap.adt.repository.usagereferences.request.v1+xml",
|
|
2501
|
-
"Accept": "application/vnd.sap.adt.repository.usagereferences.result.v1+xml"
|
|
2502
|
-
},
|
|
2503
|
-
body
|
|
2504
|
-
});
|
|
2505
|
-
if (requestErr) {
|
|
2506
|
-
return err(requestErr);
|
|
2507
|
-
}
|
|
2508
|
-
if (!response.ok) {
|
|
2509
|
-
const text2 = await response.text();
|
|
2510
|
-
const errorMsg = extractError(text2);
|
|
2511
|
-
return err(new Error(`Where-used query failed: ${errorMsg}`));
|
|
2512
|
-
}
|
|
2513
|
-
const text = await response.text();
|
|
2514
|
-
const [dependencies, parseErr] = parseWhereUsed(text);
|
|
2515
|
-
if (parseErr) {
|
|
2516
|
-
return err(parseErr);
|
|
2517
|
-
}
|
|
2518
|
-
return ok(dependencies);
|
|
2519
|
-
}
|
|
2520
|
-
function parseWhereUsed(xml) {
|
|
2521
|
-
const [doc, parseErr] = safeParseXml(xml);
|
|
2522
|
-
if (parseErr) {
|
|
2523
|
-
return err(parseErr);
|
|
2524
|
-
}
|
|
2525
|
-
const dependencies = [];
|
|
2526
|
-
const referencedObjects = doc.getElementsByTagNameNS(
|
|
2527
|
-
"http://www.sap.com/adt/ris/usageReferences",
|
|
2528
|
-
"referencedObject"
|
|
2529
|
-
);
|
|
2530
|
-
for (let i = 0; i < referencedObjects.length; i++) {
|
|
2531
|
-
const refObj = referencedObjects[i];
|
|
2532
|
-
if (!refObj) continue;
|
|
2533
|
-
const adtObject = refObj.getElementsByTagNameNS(
|
|
2534
|
-
"http://www.sap.com/adt/ris/usageReferences",
|
|
2535
|
-
"adtObject"
|
|
2536
|
-
)[0];
|
|
2537
|
-
if (!adtObject) continue;
|
|
2538
|
-
const name = adtObject.getAttributeNS("http://www.sap.com/adt/core", "name") || adtObject.getAttribute("adtcore:name");
|
|
2539
|
-
const type = adtObject.getAttributeNS("http://www.sap.com/adt/core", "type") || adtObject.getAttribute("adtcore:type");
|
|
2540
|
-
if (!name || !type) continue;
|
|
2541
|
-
const config = getConfigByType(type);
|
|
2542
|
-
if (!config) continue;
|
|
2543
|
-
const packageRef = adtObject.getElementsByTagNameNS("http://www.sap.com/adt/core", "packageRef")[0];
|
|
2544
|
-
const packageName = packageRef ? packageRef.getAttributeNS("http://www.sap.com/adt/core", "name") || packageRef.getAttribute("adtcore:name") : "";
|
|
2545
|
-
dependencies.push({
|
|
2546
|
-
name,
|
|
2547
|
-
extension: config.extension,
|
|
2548
|
-
package: packageName || "",
|
|
2549
|
-
usageType: "reference"
|
|
2550
|
-
});
|
|
2551
|
-
}
|
|
2552
|
-
return ok(dependencies);
|
|
2553
|
-
}
|
|
2554
|
-
|
|
2555
2696
|
// src/core/adt/transports/createTransport.ts
|
|
2556
2697
|
async function createTransport(client, config) {
|
|
2557
2698
|
const body = dictToAbapXml({
|
|
@@ -2944,16 +3085,7 @@ async function activate(state, requestor, objects) {
|
|
|
2944
3085
|
// src/client/methods/craud/delete.ts
|
|
2945
3086
|
async function deleteObjects(state, requestor, objects, transport) {
|
|
2946
3087
|
if (!state.session) return err(new Error("Not logged in"));
|
|
2947
|
-
|
|
2948
|
-
const [lockHandle, lockErr] = await lockObject(requestor, obj);
|
|
2949
|
-
if (lockErr) return err(lockErr);
|
|
2950
|
-
const [, deleteErr] = await deleteObject(requestor, obj, lockHandle, transport);
|
|
2951
|
-
if (deleteErr) {
|
|
2952
|
-
await unlockObject(requestor, obj, lockHandle);
|
|
2953
|
-
return err(deleteErr);
|
|
2954
|
-
}
|
|
2955
|
-
}
|
|
2956
|
-
return ok(void 0);
|
|
3088
|
+
return multiDeleteObjects(requestor, objects, transport);
|
|
2957
3089
|
}
|
|
2958
3090
|
|
|
2959
3091
|
// src/client/methods/craud/checkSyntax.ts
|
|
@@ -3455,6 +3587,7 @@ function createClient(config) {
|
|
|
3455
3587
|
}
|
|
3456
3588
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3457
3589
|
0 && (module.exports = {
|
|
3590
|
+
ExternalReferencesError,
|
|
3458
3591
|
activateLogging,
|
|
3459
3592
|
buildSQLQuery,
|
|
3460
3593
|
createClient,
|