catalyst-relay 0.6.2 → 0.6.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.mjs CHANGED
@@ -1025,22 +1025,6 @@ function escapeXml(str) {
1025
1025
  }
1026
1026
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
1027
1027
  }
1028
- function dictToAbapXml(data, root = "DATA") {
1029
- const innerElements = Object.entries(data).map(([key, value]) => {
1030
- if (value) {
1031
- return `<${key}>${escapeXml(value)}</${key}>`;
1032
- }
1033
- return `<${key}/>`;
1034
- }).join("\n ");
1035
- return `<?xml version="1.0" encoding="UTF-8"?>
1036
- <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
1037
- <asx:values>
1038
- <${root}>
1039
- ${innerElements}
1040
- </${root}>
1041
- </asx:values>
1042
- </asx:abap>`;
1043
- }
1044
1028
 
1045
1029
  // src/core/utils/csrf.ts
1046
1030
  var FETCH_CSRF_TOKEN = "fetch";
@@ -3062,35 +3046,102 @@ function parseSearchResults(xml) {
3062
3046
  return ok(results);
3063
3047
  }
3064
3048
 
3065
- // src/core/adt/transports/createTransport.ts
3066
- async function createTransport(client, config) {
3067
- const body = dictToAbapXml({
3068
- DEVCLASS: config.package,
3069
- REQUEST_TEXT: config.description,
3070
- REF: "",
3071
- OPERATION: "I"
3049
+ // src/core/adt/transports/getTransportTargets.ts
3050
+ var TARGET_VALUEHELP_PATH = "/sap/bc/adt/cts/transportrequests/valuehelp/target?name=*";
3051
+ var NAMEDITEM_CONTENT_TYPE = "application/vnd.sap.adt.nameditems.v1+xml";
3052
+ var NAMEDITEM_NS = "http://www.sap.com/adt/nameditem";
3053
+ async function getTransportTargets(client) {
3054
+ const [response, requestErr] = await client.request({
3055
+ method: "GET",
3056
+ path: TARGET_VALUEHELP_PATH,
3057
+ headers: { Accept: NAMEDITEM_CONTENT_TYPE }
3072
3058
  });
3059
+ if (requestErr) return err(requestErr);
3060
+ if (!response.ok) {
3061
+ const text2 = await response.text();
3062
+ return err(new Error(`Failed to fetch transport targets: ${extractError(text2)}`));
3063
+ }
3064
+ const text = await response.text();
3065
+ const [targets, parseErr] = extractTargets(text);
3066
+ if (parseErr) return err(parseErr);
3067
+ return ok(targets);
3068
+ }
3069
+ function extractTargets(xml) {
3070
+ const [doc, parseErr] = safeParseXml(xml);
3071
+ if (parseErr) return err(parseErr);
3072
+ const targets = [];
3073
+ const items = doc.getElementsByTagNameNS(NAMEDITEM_NS, "namedItem");
3074
+ for (let i = 0; i < items.length; i++) {
3075
+ const item = items[i];
3076
+ if (!item) continue;
3077
+ const name = item.getElementsByTagNameNS(NAMEDITEM_NS, "name")[0]?.textContent;
3078
+ if (!name || !name.trim()) continue;
3079
+ const description = item.getElementsByTagNameNS(NAMEDITEM_NS, "description")[0]?.textContent;
3080
+ targets.push({ name: name.trim(), description: (description ?? "").trim() });
3081
+ }
3082
+ return ok(targets);
3083
+ }
3084
+
3085
+ // src/core/adt/transports/createTransport.ts
3086
+ var TRANSPORTREQUESTS_PATH = "/sap/bc/adt/cts/transportrequests";
3087
+ var TM_CONTENT_TYPE = "application/vnd.sap.adt.transportorganizer.v1+xml";
3088
+ var TM_NS = "http://www.sap.com/cts/adt/tm";
3089
+ var TRANSPORT_TYPE_CODES = {
3090
+ workbench: "K",
3091
+ customizing: "W"
3092
+ };
3093
+ async function createTransport(client, config, owner) {
3094
+ const [target, targetErr] = await resolveTarget(client, config.target);
3095
+ if (targetErr) return err(targetErr);
3096
+ const typeCode = TRANSPORT_TYPE_CODES[config.type ?? "workbench"];
3097
+ const body = `<?xml version="1.0" encoding="UTF-8"?>
3098
+ <tm:root xmlns:tm="${TM_NS}" tm:useraction="newrequest">
3099
+ <tm:request tm:desc="${escapeXml(config.description)}" tm:type="${typeCode}" tm:target="${escapeXml(target)}" tm:cts_project="">
3100
+ <tm:task tm:owner="${escapeXml(owner)}"/>
3101
+ </tm:request>
3102
+ </tm:root>`;
3073
3103
  const [response, requestErr] = await client.request({
3074
3104
  method: "POST",
3075
- path: "/sap/bc/adt/cts/transports",
3105
+ path: TRANSPORTREQUESTS_PATH,
3076
3106
  headers: {
3077
- "Content-Type": "application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.CreateCorrectionRequest",
3078
- "Accept": "text/plain"
3107
+ "Content-Type": TM_CONTENT_TYPE,
3108
+ "Accept": TM_CONTENT_TYPE
3079
3109
  },
3080
3110
  body
3081
3111
  });
3082
3112
  if (requestErr) return err(requestErr);
3083
3113
  if (!response.ok) {
3084
3114
  const text2 = await response.text();
3085
- const errorMsg = extractError(text2);
3086
- return err(new Error(`Failed to create transport for ${config.package}: ${errorMsg}`));
3115
+ return err(new Error(`Failed to create transport: ${extractError(text2)}`));
3087
3116
  }
3088
3117
  const text = await response.text();
3089
- const transportId = text.trim().split("/").pop();
3090
- if (!transportId) {
3091
- return err(new Error("Failed to parse transport ID from response"));
3118
+ return extractTransportNumber(text);
3119
+ }
3120
+ async function resolveTarget(client, explicit) {
3121
+ if (explicit) return ok(explicit);
3122
+ const [targets, targetsErr] = await getTransportTargets(client);
3123
+ if (targetsErr) return err(targetsErr);
3124
+ if (targets.length === 0) {
3125
+ return err(new Error("No transport targets available; pass an explicit target."));
3126
+ }
3127
+ if (targets.length === 1) {
3128
+ return ok(targets[0].name);
3129
+ }
3130
+ const options = targets.map((t) => `${t.name} (${t.description})`).join(", ");
3131
+ return err(new Error(
3132
+ `Multiple transport targets available; pass an explicit target. Options: ${options}`
3133
+ ));
3134
+ }
3135
+ function extractTransportNumber(xml) {
3136
+ const [doc, parseErr] = safeParseXml(xml);
3137
+ if (parseErr) return err(parseErr);
3138
+ const request4 = doc.getElementsByTagNameNS(TM_NS, "request")[0];
3139
+ if (!request4) return err(new Error("Failed to parse transport number from response"));
3140
+ const number = request4.getAttributeNS(TM_NS, "number") || request4.getAttribute("tm:number");
3141
+ if (!number || !number.trim()) {
3142
+ return err(new Error("Failed to parse transport number from response"));
3092
3143
  }
3093
- return ok(transportId);
3144
+ return ok(number.trim());
3094
3145
  }
3095
3146
 
3096
3147
  // src/core/adt/transports/parseTransportTasks.ts
@@ -3757,7 +3808,7 @@ async function whereUsed(state, requestor, object) {
3757
3808
  // src/client/methods/transport/createTransport.ts
3758
3809
  async function createTransport2(state, requestor, transportConfig) {
3759
3810
  if (!state.session) return err(new Error("Not logged in"));
3760
- return createTransport(requestor, transportConfig);
3811
+ return createTransport(requestor, transportConfig, state.session.username);
3761
3812
  }
3762
3813
 
3763
3814
  // src/client/methods/transport/deleteTransport.ts