catalyst-relay 0.4.0 → 0.4.2
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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +147 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -495,6 +495,7 @@ interface ADTClient {
|
|
|
495
495
|
delete(objects: ObjectRef[], transport?: string): AsyncResult<void>;
|
|
496
496
|
getPackages(filter?: string): AsyncResult<Package[]>;
|
|
497
497
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
498
|
+
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
498
499
|
getTransports(packageName: string): AsyncResult<Transport[]>;
|
|
499
500
|
previewData(query: PreviewSQL): AsyncResult<DataFrame>;
|
|
500
501
|
getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;
|
|
@@ -507,4 +508,4 @@ interface ADTClient {
|
|
|
507
508
|
}
|
|
508
509
|
declare function createClient(config: ClientConfig): Result<ADTClient, Error>;
|
|
509
510
|
|
|
510
|
-
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 ListFilter, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectRef, type ObjectWithContent, type Package, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type Transport, type TransportConfig, type TreeQuery, type UpsertResult, buildSQLQuery, createClient, err, ok };
|
|
511
|
+
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type ApiState, 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 FolderNode, 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 SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type Transport, type TransportConfig, type TreeQuery, type TreeResponse, type UpsertResult, buildSQLQuery, createClient, err, ok };
|
package/dist/index.d.ts
CHANGED
|
@@ -495,6 +495,7 @@ interface ADTClient {
|
|
|
495
495
|
delete(objects: ObjectRef[], transport?: string): AsyncResult<void>;
|
|
496
496
|
getPackages(filter?: string): AsyncResult<Package[]>;
|
|
497
497
|
getTree(query: TreeQuery): AsyncResult<TreeResponse>;
|
|
498
|
+
getPackageStats(packageName: string): AsyncResult<PackageNode>;
|
|
498
499
|
getTransports(packageName: string): AsyncResult<Transport[]>;
|
|
499
500
|
previewData(query: PreviewSQL): AsyncResult<DataFrame>;
|
|
500
501
|
getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;
|
|
@@ -507,4 +508,4 @@ interface ADTClient {
|
|
|
507
508
|
}
|
|
508
509
|
declare function createClient(config: ClientConfig): Result<ADTClient, Error>;
|
|
509
510
|
|
|
510
|
-
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 ListFilter, type ObjectConfig, type ObjectContent, type ObjectMetadata, type ObjectRef, type ObjectWithContent, type Package, type Parameter, type PreviewSQL, type QueryFilter, type Result, type SamlAuthConfig, type SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type Transport, type TransportConfig, type TreeQuery, type UpsertResult, buildSQLQuery, createClient, err, ok };
|
|
511
|
+
export { type ADTClient, type ActivationMessage, type ActivationResult, type Aggregation, type ApiResponse, type ApiState, 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 FolderNode, 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 SearchResult, type Session, type Sorting, type SsoAuthConfig, type SuccessResponse, type Transport, type TransportConfig, type TreeQuery, type TreeResponse, type UpsertResult, buildSQLQuery, createClient, err, ok };
|
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 = {
|
|
@@ -870,7 +820,7 @@ function parseTreeXml(xml) {
|
|
|
870
820
|
if (!validFacets.includes(facet)) continue;
|
|
871
821
|
const countAttr = vf.getAttribute("counter");
|
|
872
822
|
const count = countAttr ? parseInt(countAttr, 10) : 0;
|
|
873
|
-
const desc = vf.getAttribute("
|
|
823
|
+
const desc = vf.getAttribute("text");
|
|
874
824
|
const displayNameAttr = vf.getAttribute("displayName");
|
|
875
825
|
const technicalName = name.startsWith("..") ? name.substring(2) : name;
|
|
876
826
|
const displayName = displayNameAttr || technicalName;
|
|
@@ -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, "*");
|
|
@@ -1005,8 +994,16 @@ async function fetchObjectsWithApiState(client, packageName, pathSegments, apiFo
|
|
|
1005
994
|
// src/core/adt/discovery/tree/index.ts
|
|
1006
995
|
async function getTree(client, query = {}) {
|
|
1007
996
|
if (!query.package) {
|
|
1008
|
-
const [
|
|
1009
|
-
if (
|
|
997
|
+
const [parsed2, parseErr2] = await fetchVirtualFolders(client, {});
|
|
998
|
+
if (parseErr2) return err(parseErr2);
|
|
999
|
+
const packages2 = parsed2.folders.filter((f) => f.facet === "PACKAGE").map((f) => {
|
|
1000
|
+
const pkg = {
|
|
1001
|
+
name: f.name,
|
|
1002
|
+
numContents: f.count
|
|
1003
|
+
};
|
|
1004
|
+
if (f.description) pkg.description = f.description;
|
|
1005
|
+
return pkg;
|
|
1006
|
+
});
|
|
1010
1007
|
return ok({
|
|
1011
1008
|
packages: packages2,
|
|
1012
1009
|
folders: [],
|
|
@@ -1015,9 +1012,9 @@ async function getTree(client, query = {}) {
|
|
|
1015
1012
|
}
|
|
1016
1013
|
let packages = [];
|
|
1017
1014
|
if (!query.path) {
|
|
1018
|
-
const [
|
|
1019
|
-
if (
|
|
1020
|
-
packages =
|
|
1015
|
+
const [childPkgs, childErr] = await fetchChildPackages(client, query.package);
|
|
1016
|
+
if (childErr) return err(childErr);
|
|
1017
|
+
packages = childPkgs;
|
|
1021
1018
|
}
|
|
1022
1019
|
const internalQuery = buildQueryFromPath(query.package, query.path);
|
|
1023
1020
|
const [parsed, parseErr] = await fetchVirtualFolders(client, internalQuery);
|
|
@@ -1043,6 +1040,96 @@ async function getTree(client, query = {}) {
|
|
|
1043
1040
|
return ok(result);
|
|
1044
1041
|
}
|
|
1045
1042
|
|
|
1043
|
+
// src/core/adt/discovery/tree/packageStats.ts
|
|
1044
|
+
async function fetchPackageMetadata(client, packageName) {
|
|
1045
|
+
const [response, requestErr] = await client.request({
|
|
1046
|
+
method: "GET",
|
|
1047
|
+
path: `/sap/bc/adt/packages/${packageName.toLowerCase()}`,
|
|
1048
|
+
headers: {
|
|
1049
|
+
"Accept": "application/vnd.sap.adt.packages.v1+xml"
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
if (requestErr) return err(requestErr);
|
|
1053
|
+
if (!response.ok) {
|
|
1054
|
+
const text = await response.text();
|
|
1055
|
+
const errorMsg = extractError(text);
|
|
1056
|
+
return err(new Error(`Package metadata fetch failed: ${errorMsg}`));
|
|
1057
|
+
}
|
|
1058
|
+
const xml = await response.text();
|
|
1059
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
1060
|
+
if (parseErr) return err(parseErr);
|
|
1061
|
+
const packageElements = doc.getElementsByTagName("pak:package");
|
|
1062
|
+
if (packageElements.length === 0) {
|
|
1063
|
+
return err(new Error(`Package ${packageName} not found`));
|
|
1064
|
+
}
|
|
1065
|
+
const pkgEl = packageElements[0];
|
|
1066
|
+
const name = pkgEl.getAttribute("adtcore:name") || pkgEl.getAttributeNS("http://www.sap.com/adt/core", "name") || packageName.toUpperCase();
|
|
1067
|
+
const description = pkgEl.getAttribute("adtcore:description") || pkgEl.getAttributeNS("http://www.sap.com/adt/core", "description");
|
|
1068
|
+
const result = { name };
|
|
1069
|
+
if (description) result.description = description;
|
|
1070
|
+
return ok(result);
|
|
1071
|
+
}
|
|
1072
|
+
function constructCountRequestBody(packageName) {
|
|
1073
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1074
|
+
<vfs:virtualFoldersRequest xmlns:vfs="http://www.sap.com/adt/ris/virtualFolders" objectSearchPattern="*">
|
|
1075
|
+
<vfs:preselection facet="package">
|
|
1076
|
+
<vfs:value>${packageName}</vfs:value>
|
|
1077
|
+
</vfs:preselection>
|
|
1078
|
+
<vfs:facetorder/>
|
|
1079
|
+
</vfs:virtualFoldersRequest>`;
|
|
1080
|
+
}
|
|
1081
|
+
async function fetchContentCount(client, packageName) {
|
|
1082
|
+
const body = constructCountRequestBody(packageName);
|
|
1083
|
+
const [response, requestErr] = await client.request({
|
|
1084
|
+
method: "POST",
|
|
1085
|
+
path: "/sap/bc/adt/repository/informationsystem/virtualfolders",
|
|
1086
|
+
headers: {
|
|
1087
|
+
"Content-Type": "application/vnd.sap.adt.repository.virtualfolders.request.v1+xml",
|
|
1088
|
+
"Accept": "application/vnd.sap.adt.repository.virtualfolders.result.v1+xml"
|
|
1089
|
+
},
|
|
1090
|
+
body
|
|
1091
|
+
});
|
|
1092
|
+
if (requestErr) return err(requestErr);
|
|
1093
|
+
if (!response.ok) {
|
|
1094
|
+
const text = await response.text();
|
|
1095
|
+
const errorMsg = extractError(text);
|
|
1096
|
+
return err(new Error(`Package count fetch failed: ${errorMsg}`));
|
|
1097
|
+
}
|
|
1098
|
+
const xml = await response.text();
|
|
1099
|
+
const [doc, parseErr] = safeParseXml(xml);
|
|
1100
|
+
if (parseErr) return err(parseErr);
|
|
1101
|
+
const resultElements = doc.getElementsByTagName("vfs:virtualFoldersResult");
|
|
1102
|
+
if (resultElements.length === 0) {
|
|
1103
|
+
return err(new Error("Invalid virtualfolders response: missing result element"));
|
|
1104
|
+
}
|
|
1105
|
+
const resultEl = resultElements[0];
|
|
1106
|
+
const objectCountAttr = resultEl.getAttribute("objectCount");
|
|
1107
|
+
if (!objectCountAttr) {
|
|
1108
|
+
return err(new Error("Invalid virtualfolders response: missing objectCount attribute"));
|
|
1109
|
+
}
|
|
1110
|
+
const count = parseInt(objectCountAttr, 10);
|
|
1111
|
+
if (isNaN(count)) {
|
|
1112
|
+
return err(new Error(`Invalid objectCount value: ${objectCountAttr}`));
|
|
1113
|
+
}
|
|
1114
|
+
return ok(count);
|
|
1115
|
+
}
|
|
1116
|
+
async function getPackageStats(client, packageName) {
|
|
1117
|
+
const [metadataResult, countResult] = await Promise.all([
|
|
1118
|
+
fetchPackageMetadata(client, packageName),
|
|
1119
|
+
fetchContentCount(client, packageName)
|
|
1120
|
+
]);
|
|
1121
|
+
const [metadata, metaErr] = metadataResult;
|
|
1122
|
+
if (metaErr) return err(metaErr);
|
|
1123
|
+
const [numContents, countErr] = countResult;
|
|
1124
|
+
if (countErr) return err(countErr);
|
|
1125
|
+
const result = {
|
|
1126
|
+
name: metadata.name,
|
|
1127
|
+
numContents
|
|
1128
|
+
};
|
|
1129
|
+
if (metadata.description) result.description = metadata.description;
|
|
1130
|
+
return ok(result);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1046
1133
|
// src/core/adt/transports/transports.ts
|
|
1047
1134
|
async function getTransports(client, packageName) {
|
|
1048
1135
|
const contentType = "application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.transport.service.checkData";
|
|
@@ -2539,6 +2626,10 @@ var ADTClientImpl = class {
|
|
|
2539
2626
|
if (!this.state.session) return err(new Error("Not logged in"));
|
|
2540
2627
|
return getTree(this.requestor, query);
|
|
2541
2628
|
}
|
|
2629
|
+
async getPackageStats(packageName) {
|
|
2630
|
+
if (!this.state.session) return err(new Error("Not logged in"));
|
|
2631
|
+
return getPackageStats(this.requestor, packageName);
|
|
2632
|
+
}
|
|
2542
2633
|
async getTransports(packageName) {
|
|
2543
2634
|
if (!this.state.session) return err(new Error("Not logged in"));
|
|
2544
2635
|
return getTransports(this.requestor, packageName);
|