catalyst-relay 0.2.5 → 0.3.0
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 +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +85 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -171,6 +171,7 @@ var clientConfigSchema = z.object({
|
|
|
171
171
|
type: z.literal("saml"),
|
|
172
172
|
username: z.string().min(1),
|
|
173
173
|
password: z.string().min(1),
|
|
174
|
+
sapUser: z.string().min(1),
|
|
174
175
|
providerConfig: samlProviderConfigSchema.optional()
|
|
175
176
|
}),
|
|
176
177
|
z.object({
|
|
@@ -244,8 +245,9 @@ function getSessionTimeout(authType) {
|
|
|
244
245
|
function extractUsername(auth) {
|
|
245
246
|
switch (auth.type) {
|
|
246
247
|
case "basic":
|
|
247
|
-
case "saml":
|
|
248
248
|
return auth.username;
|
|
249
|
+
case "saml":
|
|
250
|
+
return auth.sapUser;
|
|
249
251
|
case "sso":
|
|
250
252
|
return process.env["USERNAME"] ?? process.env["USER"] ?? "SSO_USER";
|
|
251
253
|
default: {
|
|
@@ -650,6 +652,46 @@ function extractActivationErrors(objects, xml, _extension) {
|
|
|
650
652
|
return ok(results);
|
|
651
653
|
}
|
|
652
654
|
|
|
655
|
+
// src/core/adt/discovery/packages.ts
|
|
656
|
+
async function getPackages(client, filter = "*") {
|
|
657
|
+
const params = new URLSearchParams([
|
|
658
|
+
["operation", "quickSearch"],
|
|
659
|
+
["query", filter],
|
|
660
|
+
["maxResults", "10001"],
|
|
661
|
+
["objectType", "DEVC/K"]
|
|
662
|
+
]);
|
|
663
|
+
const [response, requestErr] = await client.request({
|
|
664
|
+
method: "GET",
|
|
665
|
+
path: `/sap/bc/adt/repository/informationsystem/search?${params.toString()}`
|
|
666
|
+
});
|
|
667
|
+
if (requestErr) {
|
|
668
|
+
return err(requestErr);
|
|
669
|
+
}
|
|
670
|
+
if (!response.ok) {
|
|
671
|
+
const text2 = await response.text();
|
|
672
|
+
const errorMsg = extractError(text2);
|
|
673
|
+
return err(new Error(`Package search failed: ${errorMsg}`));
|
|
674
|
+
}
|
|
675
|
+
const text = await response.text();
|
|
676
|
+
const [doc, parseErr] = safeParseXml(text);
|
|
677
|
+
if (parseErr) {
|
|
678
|
+
return err(parseErr);
|
|
679
|
+
}
|
|
680
|
+
const packages = [];
|
|
681
|
+
const objectRefs = doc.getElementsByTagNameNS("http://www.sap.com/adt/core", "objectReference");
|
|
682
|
+
for (let i = 0; i < objectRefs.length; i++) {
|
|
683
|
+
const obj = objectRefs[i];
|
|
684
|
+
if (!obj) return err(new Error("Invalid object reference in package search results"));
|
|
685
|
+
const name = obj.getAttributeNS("http://www.sap.com/adt/core", "name") || obj.getAttribute("adtcore:name");
|
|
686
|
+
const description = obj.getAttributeNS("http://www.sap.com/adt/core", "description") || obj.getAttribute("adtcore:description");
|
|
687
|
+
if (!name) return err(new Error("Package name missing in object reference"));
|
|
688
|
+
const pkg = { name };
|
|
689
|
+
if (description) pkg.description = description;
|
|
690
|
+
packages.push(pkg);
|
|
691
|
+
}
|
|
692
|
+
return ok(packages);
|
|
693
|
+
}
|
|
694
|
+
|
|
653
695
|
// src/core/adt/discovery/tree.ts
|
|
654
696
|
async function getTree(client, query) {
|
|
655
697
|
const internalQuery = {};
|
|
@@ -767,32 +809,23 @@ function parseTreeResponse(xml) {
|
|
|
767
809
|
return ok({ nodes, packages });
|
|
768
810
|
}
|
|
769
811
|
|
|
770
|
-
// src/core/adt/discovery/packages.ts
|
|
771
|
-
async function getPackages(client, filter = "*") {
|
|
772
|
-
const [treeResult, treeErr] = await getTreeInternal(client, {}, filter);
|
|
773
|
-
if (treeErr) {
|
|
774
|
-
return err(treeErr);
|
|
775
|
-
}
|
|
776
|
-
return ok(treeResult.packages);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
812
|
// src/core/adt/transports/transports.ts
|
|
780
813
|
async function getTransports(client, packageName) {
|
|
781
814
|
const contentType = "application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.transport.service.checkData";
|
|
782
815
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
816
|
+
<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml">
|
|
817
|
+
<asx:values>
|
|
818
|
+
<DATA>
|
|
819
|
+
<PGMID></PGMID>
|
|
820
|
+
<OBJECT></OBJECT>
|
|
821
|
+
<OBJECTNAME></OBJECTNAME>
|
|
822
|
+
<DEVCLASS>${packageName}</DEVCLASS>
|
|
823
|
+
<SUPER_PACKAGE></SUPER_PACKAGE>
|
|
824
|
+
<OPERATION>I</OPERATION>
|
|
825
|
+
<URI>/sap/bc/adt/ddic/ddl/sources/zsnap_test4transports</URI>
|
|
826
|
+
</DATA>
|
|
827
|
+
</asx:values>
|
|
828
|
+
</asx:abap>`;
|
|
796
829
|
const [response, requestErr] = await client.request({
|
|
797
830
|
method: "POST",
|
|
798
831
|
path: "/sap/bc/adt/cts/transportchecks",
|
|
@@ -802,44 +835,33 @@ async function getTransports(client, packageName) {
|
|
|
802
835
|
},
|
|
803
836
|
body
|
|
804
837
|
});
|
|
805
|
-
if (requestErr)
|
|
806
|
-
return err(requestErr);
|
|
807
|
-
}
|
|
838
|
+
if (requestErr) return err(requestErr);
|
|
808
839
|
if (!response.ok) {
|
|
809
840
|
const text2 = await response.text();
|
|
810
841
|
const errorMsg = extractError(text2);
|
|
811
|
-
return err(new Error(`Failed to fetch transports for ${packageName}: ${errorMsg}`));
|
|
842
|
+
return err(new Error(`Failed to fetch transports for package ${packageName}: ${errorMsg}`));
|
|
812
843
|
}
|
|
813
844
|
const text = await response.text();
|
|
814
845
|
const [transports, parseErr] = extractTransports(text);
|
|
815
|
-
if (parseErr)
|
|
816
|
-
return err(parseErr);
|
|
817
|
-
}
|
|
846
|
+
if (parseErr) return err(parseErr);
|
|
818
847
|
return ok(transports);
|
|
819
848
|
}
|
|
820
849
|
function extractTransports(xml) {
|
|
821
850
|
const [doc, parseErr] = safeParseXml(xml);
|
|
822
|
-
if (parseErr)
|
|
823
|
-
return err(parseErr);
|
|
824
|
-
}
|
|
851
|
+
if (parseErr) return err(parseErr);
|
|
825
852
|
const transports = [];
|
|
826
853
|
const reqHeaders = doc.getElementsByTagName("REQ_HEADER");
|
|
827
854
|
for (let i = 0; i < reqHeaders.length; i++) {
|
|
828
855
|
const header = reqHeaders[i];
|
|
829
856
|
if (!header) continue;
|
|
830
|
-
const
|
|
831
|
-
const
|
|
832
|
-
const
|
|
833
|
-
if (!
|
|
834
|
-
const id = trkorrElement.textContent;
|
|
835
|
-
const owner = userElement.textContent;
|
|
836
|
-
const description = textElement.textContent;
|
|
837
|
-
if (!id || !owner || !description) continue;
|
|
857
|
+
const id = header.getElementsByTagName("TRKORR")[0]?.textContent;
|
|
858
|
+
const owner = header.getElementsByTagName("AS4USER")[0]?.textContent;
|
|
859
|
+
const description = header.getElementsByTagName("AS4TEXT")[0]?.textContent;
|
|
860
|
+
if (!id) continue;
|
|
838
861
|
transports.push({
|
|
839
862
|
id,
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
status: "modifiable"
|
|
863
|
+
description: description || "",
|
|
864
|
+
owner: owner || ""
|
|
843
865
|
});
|
|
844
866
|
}
|
|
845
867
|
return ok(transports);
|
|
@@ -1800,11 +1822,22 @@ var SamlAuth = class {
|
|
|
1800
1822
|
if (!config.username || !config.password) {
|
|
1801
1823
|
throw new Error("SamlAuth requires both username and password");
|
|
1802
1824
|
}
|
|
1825
|
+
if (!config.sapUser) {
|
|
1826
|
+
throw new Error("SamlAuth requires sapUser (SAP system username for object creation)");
|
|
1827
|
+
}
|
|
1803
1828
|
if (!config.baseUrl) {
|
|
1804
1829
|
throw new Error("SamlAuth requires baseUrl");
|
|
1805
1830
|
}
|
|
1806
1831
|
this.config = config;
|
|
1807
1832
|
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Get SAP system username
|
|
1835
|
+
*
|
|
1836
|
+
* Used for object creation (adtcore:responsible) instead of the SAML email.
|
|
1837
|
+
*/
|
|
1838
|
+
getSapUser() {
|
|
1839
|
+
return this.config.sapUser;
|
|
1840
|
+
}
|
|
1808
1841
|
/**
|
|
1809
1842
|
* Get auth headers for SAML
|
|
1810
1843
|
*
|
|
@@ -1868,6 +1901,7 @@ function createAuthStrategy(options) {
|
|
|
1868
1901
|
return new SamlAuth({
|
|
1869
1902
|
username: config.username,
|
|
1870
1903
|
password: config.password,
|
|
1904
|
+
sapUser: config.sapUser,
|
|
1871
1905
|
baseUrl,
|
|
1872
1906
|
...config.providerConfig && { providerConfig: config.providerConfig }
|
|
1873
1907
|
});
|
|
@@ -2060,6 +2094,13 @@ var ADTClientImpl = class {
|
|
|
2060
2094
|
return err(loginErr);
|
|
2061
2095
|
}
|
|
2062
2096
|
}
|
|
2097
|
+
if (authStrategy.type === "saml" && authStrategy.getCookies) {
|
|
2098
|
+
const cookies = authStrategy.getCookies();
|
|
2099
|
+
for (const cookie of cookies) {
|
|
2100
|
+
this.state.cookies.set(cookie.name, cookie.value);
|
|
2101
|
+
}
|
|
2102
|
+
debug(`Transferred ${cookies.length} SAML cookies to client`);
|
|
2103
|
+
}
|
|
2063
2104
|
if (authStrategy.type === "sso" && authStrategy.getCertificates) {
|
|
2064
2105
|
const certs = authStrategy.getCertificates();
|
|
2065
2106
|
if (certs) {
|