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.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
- <asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml">
784
- <asx:values>
785
- <DATA>
786
- <PGMID></PGMID>
787
- <OBJECT></OBJECT>
788
- <OBJECTNAME></OBJECTNAME>
789
- <DEVCLASS>${packageName}</DEVCLASS>
790
- <SUPER_PACKAGE></SUPER_PACKAGE>
791
- <OPERATION>I</OPERATION>
792
- <URI>/sap/bc/adt/ddic/ddl/sources/transport_check</URI>
793
- </DATA>
794
- </asx:values>
795
- </asx:abap>`;
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 trkorrElement = header.getElementsByTagName("TRKORR")[0];
831
- const userElement = header.getElementsByTagName("AS4USER")[0];
832
- const textElement = header.getElementsByTagName("AS4TEXT")[0];
833
- if (!trkorrElement || !userElement || !textElement) continue;
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
- owner,
841
- description,
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) {