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 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 [subpkgs, subErr] = await getSubpackages(client, query.package);
1027
- if (subErr) return err(subErr);
1028
- packages = subpkgs;
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
- async function fetchPackageMetadata(client, packageName) {
1056
- const [response, requestErr] = await client.request({
1057
- method: "GET",
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
- <vfs:value>${packageName}</vfs:value>
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
- async function fetchContentCount(client, packageName) {
1093
- const body = constructCountRequestBody(packageName);
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 count fetch failed: ${errorMsg}`));
1103
+ return err(new Error(`Package stats fetch failed: ${errorMsg}`));
1108
1104
  }
1109
1105
  const xml = await response.text();
1110
- const [doc, parseErr] = safeParseXml(xml);
1111
- if (parseErr) return err(parseErr);
1112
- const resultElements = doc.getElementsByTagName("vfs:virtualFoldersResult");
1113
- if (resultElements.length === 0) {
1114
- return err(new Error("Invalid virtualfolders response: missing result element"));
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(count);
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(packageName) {
2612
+ async getPackageStats(packageNames) {
2641
2613
  if (!this.state.session) return err(new Error("Not logged in"));
2642
- return getPackageStats(this.requestor, packageName);
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"));