catalyst-relay 0.4.1 → 0.4.3
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 +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +93 -121
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -121
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -496,6 +496,7 @@ interface ADTClient {
|
|
|
496
496
|
getPackages(filter?: string): AsyncResult<Package[]>;
|
|
497
497
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
498
498
|
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
499
|
+
getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;
|
|
499
500
|
getTransports(packageName: string): AsyncResult<Transport[]>;
|
|
500
501
|
previewData(query: PreviewSQL): AsyncResult<DataFrame>;
|
|
501
502
|
getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -496,6 +496,7 @@ interface ADTClient {
|
|
|
496
496
|
getPackages(filter?: string): AsyncResult<Package[]>;
|
|
497
497
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
498
498
|
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
499
|
+
getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;
|
|
499
500
|
getTransports(packageName: string): AsyncResult<Transport[]>;
|
|
500
501
|
previewData(query: PreviewSQL): AsyncResult<DataFrame>;
|
|
501
502
|
getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;
|
package/dist/index.js
CHANGED
|
@@ -753,56 +753,6 @@ var API_FOLDERS = [
|
|
|
753
753
|
"USE_IN_KEY_USER_APPS"
|
|
754
754
|
];
|
|
755
755
|
|
|
756
|
-
// src/core/adt/discovery/tree/subpackages.ts
|
|
757
|
-
async function getSubpackages(client, packageName) {
|
|
758
|
-
const params = new URLSearchParams([
|
|
759
|
-
["parent_type", "DEVC/K"],
|
|
760
|
-
["withShortDescriptions", "true"]
|
|
761
|
-
]);
|
|
762
|
-
if (packageName) {
|
|
763
|
-
params.append("parent_name", packageName);
|
|
764
|
-
}
|
|
765
|
-
const [response, requestErr] = await client.request({
|
|
766
|
-
method: "POST",
|
|
767
|
-
path: `/sap/bc/adt/repository/nodestructure?${params.toString()}`,
|
|
768
|
-
headers: {
|
|
769
|
-
"Accept": "application/vnd.sap.as+xml"
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
if (requestErr) return err(requestErr);
|
|
773
|
-
if (!response.ok) {
|
|
774
|
-
const text2 = await response.text();
|
|
775
|
-
const errorMsg = extractError(text2);
|
|
776
|
-
return err(new Error(`Nodestructure failed: ${errorMsg}`));
|
|
777
|
-
}
|
|
778
|
-
const text = await response.text();
|
|
779
|
-
return parseNodestructureForPackages(text, packageName);
|
|
780
|
-
}
|
|
781
|
-
function parseNodestructureForPackages(xml, parentPackage) {
|
|
782
|
-
const [doc, parseErr] = safeParseXml(xml);
|
|
783
|
-
if (parseErr) return err(parseErr);
|
|
784
|
-
const packages = [];
|
|
785
|
-
const nodes = doc.getElementsByTagName("SEU_ADT_REPOSITORY_OBJ_NODE");
|
|
786
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
787
|
-
const node = nodes[i];
|
|
788
|
-
if (!node) continue;
|
|
789
|
-
const objectType = node.getElementsByTagName("OBJECT_TYPE")[0]?.textContent?.trim();
|
|
790
|
-
if (objectType !== "DEVC/K") continue;
|
|
791
|
-
const objectName = node.getElementsByTagName("OBJECT_NAME")[0]?.textContent?.trim();
|
|
792
|
-
if (!objectName) continue;
|
|
793
|
-
if (parentPackage && objectName.toUpperCase() === parentPackage.toUpperCase()) continue;
|
|
794
|
-
const description = node.getElementsByTagName("DESCRIPTION")[0]?.textContent?.trim();
|
|
795
|
-
const pkg = {
|
|
796
|
-
name: objectName,
|
|
797
|
-
numContents: 0
|
|
798
|
-
// nodestructure doesn't provide counts
|
|
799
|
-
};
|
|
800
|
-
if (description) pkg.description = description;
|
|
801
|
-
packages.push(pkg);
|
|
802
|
-
}
|
|
803
|
-
return ok(packages);
|
|
804
|
-
}
|
|
805
|
-
|
|
806
756
|
// src/core/adt/discovery/tree/parsers.ts
|
|
807
757
|
function buildQueryFromPath(packageName, path) {
|
|
808
758
|
const query = {
|
|
@@ -928,6 +878,45 @@ function transformToTreeResponse(parsed, queryPackage) {
|
|
|
928
878
|
return { packages, folders, objects };
|
|
929
879
|
}
|
|
930
880
|
|
|
881
|
+
// src/core/adt/discovery/tree/childPackages.ts
|
|
882
|
+
async function fetchChildPackages(client, parentPackage) {
|
|
883
|
+
const query = {
|
|
884
|
+
PACKAGE: {
|
|
885
|
+
name: parentPackage,
|
|
886
|
+
hasChildrenOfSameFacet: true
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
const body = constructTreeBody(query, "*");
|
|
890
|
+
const [response, requestErr] = await client.request({
|
|
891
|
+
method: "POST",
|
|
892
|
+
path: "/sap/bc/adt/repository/informationsystem/virtualfolders/contents",
|
|
893
|
+
headers: {
|
|
894
|
+
"Content-Type": "application/vnd.sap.adt.repository.virtualfolders.request.v1+xml",
|
|
895
|
+
"Accept": "application/vnd.sap.adt.repository.virtualfolders.result.v1+xml"
|
|
896
|
+
},
|
|
897
|
+
body
|
|
898
|
+
});
|
|
899
|
+
if (requestErr) return err(requestErr);
|
|
900
|
+
if (!response.ok) {
|
|
901
|
+
const text2 = await response.text();
|
|
902
|
+
const errorMsg = extractError(text2);
|
|
903
|
+
return err(new Error(`Failed to fetch child packages: ${errorMsg}`));
|
|
904
|
+
}
|
|
905
|
+
const text = await response.text();
|
|
906
|
+
const [parsed, parseErr] = parseTreeXml(text);
|
|
907
|
+
if (parseErr) return err(parseErr);
|
|
908
|
+
const parentUpper = parentPackage.toUpperCase();
|
|
909
|
+
const packages = parsed.folders.filter((f) => f.facet === "PACKAGE" && f.name.toUpperCase() !== parentUpper).map((f) => {
|
|
910
|
+
const pkg = {
|
|
911
|
+
name: f.name,
|
|
912
|
+
numContents: f.count
|
|
913
|
+
};
|
|
914
|
+
if (f.description) pkg.description = f.description;
|
|
915
|
+
return pkg;
|
|
916
|
+
});
|
|
917
|
+
return ok(packages);
|
|
918
|
+
}
|
|
919
|
+
|
|
931
920
|
// src/core/adt/discovery/tree/virtualFolders.ts
|
|
932
921
|
async function fetchVirtualFolders(client, query) {
|
|
933
922
|
const body = constructTreeBody(query, "*");
|
|
@@ -1023,9 +1012,9 @@ async function getTree(client, query = {}) {
|
|
|
1023
1012
|
}
|
|
1024
1013
|
let packages = [];
|
|
1025
1014
|
if (!query.path) {
|
|
1026
|
-
const [
|
|
1027
|
-
if (
|
|
1028
|
-
packages =
|
|
1015
|
+
const [childPkgs, childErr] = await fetchChildPackages(client, query.package);
|
|
1016
|
+
if (childErr) return err(childErr);
|
|
1017
|
+
packages = childPkgs;
|
|
1029
1018
|
}
|
|
1030
1019
|
const internalQuery = buildQueryFromPath(query.package, query.path);
|
|
1031
1020
|
const [parsed, parseErr] = await fetchVirtualFolders(client, internalQuery);
|
|
@@ -1052,48 +1041,55 @@ async function getTree(client, query = {}) {
|
|
|
1052
1041
|
}
|
|
1053
1042
|
|
|
1054
1043
|
// src/core/adt/discovery/tree/packageStats.ts
|
|
1055
|
-
|
|
1056
|
-
const [
|
|
1057
|
-
|
|
1058
|
-
path: `/sap/bc/adt/packages/${packageName.toLowerCase()}`,
|
|
1059
|
-
headers: {
|
|
1060
|
-
"Accept": "application/vnd.sap.adt.packages.v1+xml"
|
|
1061
|
-
}
|
|
1062
|
-
});
|
|
1063
|
-
if (requestErr) return err(requestErr);
|
|
1064
|
-
if (!response.ok) {
|
|
1065
|
-
const text = await response.text();
|
|
1066
|
-
const errorMsg = extractError(text);
|
|
1067
|
-
return err(new Error(`Package metadata fetch failed: ${errorMsg}`));
|
|
1068
|
-
}
|
|
1069
|
-
const xml = await response.text();
|
|
1070
|
-
const [doc, parseErr] = safeParseXml(xml);
|
|
1071
|
-
if (parseErr) return err(parseErr);
|
|
1072
|
-
const packageElements = doc.getElementsByTagName("pak:package");
|
|
1073
|
-
if (packageElements.length === 0) {
|
|
1074
|
-
return err(new Error(`Package ${packageName} not found`));
|
|
1075
|
-
}
|
|
1076
|
-
const pkgEl = packageElements[0];
|
|
1077
|
-
const name = pkgEl.getAttribute("adtcore:name") || pkgEl.getAttributeNS("http://www.sap.com/adt/core", "name") || packageName.toUpperCase();
|
|
1078
|
-
const description = pkgEl.getAttribute("adtcore:description") || pkgEl.getAttributeNS("http://www.sap.com/adt/core", "description");
|
|
1079
|
-
const result = { name };
|
|
1080
|
-
if (description) result.description = description;
|
|
1081
|
-
return ok(result);
|
|
1082
|
-
}
|
|
1083
|
-
function constructCountRequestBody(packageName) {
|
|
1044
|
+
function constructPackageStatsBody(packageNames) {
|
|
1045
|
+
const names = packageNames.length === 1 ? [...packageNames, "SRIS_TEST_DATA_VFS_EMPTY"] : packageNames;
|
|
1046
|
+
const values = names.map((name) => ` <vfs:value>${name}</vfs:value>`).join("\n");
|
|
1084
1047
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1085
1048
|
<vfs:virtualFoldersRequest xmlns:vfs="http://www.sap.com/adt/ris/virtualFolders" objectSearchPattern="*">
|
|
1086
1049
|
<vfs:preselection facet="package">
|
|
1087
|
-
|
|
1050
|
+
${values}
|
|
1088
1051
|
</vfs:preselection>
|
|
1089
|
-
<vfs:facetorder
|
|
1052
|
+
<vfs:facetorder>
|
|
1053
|
+
<vfs:facet>package</vfs:facet>
|
|
1054
|
+
<vfs:facet>group</vfs:facet>
|
|
1055
|
+
<vfs:facet>type</vfs:facet>
|
|
1056
|
+
</vfs:facetorder>
|
|
1090
1057
|
</vfs:virtualFoldersRequest>`;
|
|
1091
1058
|
}
|
|
1092
|
-
|
|
1093
|
-
const
|
|
1059
|
+
function parsePackageStats(xml) {
|
|
1060
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
1061
|
+
if (parseErr) return [];
|
|
1062
|
+
const packages = [];
|
|
1063
|
+
const virtualFolders = doc.getElementsByTagName("vfs:virtualFolder");
|
|
1064
|
+
for (let i = 0; i < virtualFolders.length; i++) {
|
|
1065
|
+
const vf = virtualFolders[i];
|
|
1066
|
+
if (!vf) continue;
|
|
1067
|
+
const facet = vf.getAttribute("facet")?.toUpperCase();
|
|
1068
|
+
if (facet !== "PACKAGE") continue;
|
|
1069
|
+
const name = vf.getAttribute("name");
|
|
1070
|
+
if (!name) continue;
|
|
1071
|
+
const countAttr = vf.getAttribute("counter");
|
|
1072
|
+
const count = countAttr ? parseInt(countAttr, 10) : 0;
|
|
1073
|
+
const description = vf.getAttribute("text");
|
|
1074
|
+
const pkg = {
|
|
1075
|
+
name,
|
|
1076
|
+
numContents: count
|
|
1077
|
+
};
|
|
1078
|
+
if (description) pkg.description = description;
|
|
1079
|
+
packages.push(pkg);
|
|
1080
|
+
}
|
|
1081
|
+
return packages;
|
|
1082
|
+
}
|
|
1083
|
+
async function getPackageStats(client, packageNames) {
|
|
1084
|
+
const isSingle = typeof packageNames === "string";
|
|
1085
|
+
const names = isSingle ? [packageNames] : packageNames;
|
|
1086
|
+
if (names.length === 0) {
|
|
1087
|
+
return ok([]);
|
|
1088
|
+
}
|
|
1089
|
+
const body = constructPackageStatsBody(names);
|
|
1094
1090
|
const [response, requestErr] = await client.request({
|
|
1095
1091
|
method: "POST",
|
|
1096
|
-
path: "/sap/bc/adt/repository/informationsystem/virtualfolders",
|
|
1092
|
+
path: "/sap/bc/adt/repository/informationsystem/virtualfolders/contents",
|
|
1097
1093
|
headers: {
|
|
1098
1094
|
"Content-Type": "application/vnd.sap.adt.repository.virtualfolders.request.v1+xml",
|
|
1099
1095
|
"Accept": "application/vnd.sap.adt.repository.virtualfolders.result.v1+xml"
|
|
@@ -1104,41 +1100,17 @@ async function fetchContentCount(client, packageName) {
|
|
|
1104
1100
|
if (!response.ok) {
|
|
1105
1101
|
const text = await response.text();
|
|
1106
1102
|
const errorMsg = extractError(text);
|
|
1107
|
-
return err(new Error(`Package
|
|
1103
|
+
return err(new Error(`Package stats fetch failed: ${errorMsg}`));
|
|
1108
1104
|
}
|
|
1109
1105
|
const xml = await response.text();
|
|
1110
|
-
const
|
|
1111
|
-
if (
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const resultEl = resultElements[0];
|
|
1117
|
-
const objectCountAttr = resultEl.getAttribute("objectCount");
|
|
1118
|
-
if (!objectCountAttr) {
|
|
1119
|
-
return err(new Error("Invalid virtualfolders response: missing objectCount attribute"));
|
|
1120
|
-
}
|
|
1121
|
-
const count = parseInt(objectCountAttr, 10);
|
|
1122
|
-
if (isNaN(count)) {
|
|
1123
|
-
return err(new Error(`Invalid objectCount value: ${objectCountAttr}`));
|
|
1106
|
+
const packages = parsePackageStats(xml).filter((pkg) => pkg.name !== "SRIS_TEST_DATA_VFS_EMPTY");
|
|
1107
|
+
if (isSingle) {
|
|
1108
|
+
if (packages.length === 0) {
|
|
1109
|
+
return err(new Error(`Package ${packageNames} not found`));
|
|
1110
|
+
}
|
|
1111
|
+
return ok(packages[0]);
|
|
1124
1112
|
}
|
|
1125
|
-
return ok(
|
|
1126
|
-
}
|
|
1127
|
-
async function getPackageStats(client, packageName) {
|
|
1128
|
-
const [metadataResult, countResult] = await Promise.all([
|
|
1129
|
-
fetchPackageMetadata(client, packageName),
|
|
1130
|
-
fetchContentCount(client, packageName)
|
|
1131
|
-
]);
|
|
1132
|
-
const [metadata, metaErr] = metadataResult;
|
|
1133
|
-
if (metaErr) return err(metaErr);
|
|
1134
|
-
const [numContents, countErr] = countResult;
|
|
1135
|
-
if (countErr) return err(countErr);
|
|
1136
|
-
const result = {
|
|
1137
|
-
name: metadata.name,
|
|
1138
|
-
numContents
|
|
1139
|
-
};
|
|
1140
|
-
if (metadata.description) result.description = metadata.description;
|
|
1141
|
-
return ok(result);
|
|
1113
|
+
return ok(packages);
|
|
1142
1114
|
}
|
|
1143
1115
|
|
|
1144
1116
|
// src/core/adt/transports/transports.ts
|
|
@@ -2637,9 +2609,9 @@ var ADTClientImpl = class {
|
|
|
2637
2609
|
if (!this.state.session) return err(new Error("Not logged in"));
|
|
2638
2610
|
return getTree(this.requestor, query);
|
|
2639
2611
|
}
|
|
2640
|
-
async getPackageStats(
|
|
2612
|
+
async getPackageStats(packageNames) {
|
|
2641
2613
|
if (!this.state.session) return err(new Error("Not logged in"));
|
|
2642
|
-
return getPackageStats(this.requestor,
|
|
2614
|
+
return getPackageStats(this.requestor, packageNames);
|
|
2643
2615
|
}
|
|
2644
2616
|
async getTransports(packageName) {
|
|
2645
2617
|
if (!this.state.session) return err(new Error("Not logged in"));
|