catalyst-relay 0.6.3 → 0.6.5

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
@@ -1898,6 +1898,7 @@ async function updateClassInclude(client, className, includeType, source, lockHa
1898
1898
  // src/core/adt/craud/activation.ts
1899
1899
  var MAX_POLL_ATTEMPTS = 30;
1900
1900
  var POLL_RETRY_DELAY_MS = 1e3;
1901
+ var LONG_POLL_TIMEOUT_MS = 36e5;
1901
1902
  var RUN_ID_REGEX = /\/activation\/runs\/([^?/]+)/;
1902
1903
  var BACKGROUND_RUN_MEDIA_TYPE = "application/vnd.sap.adt.backgroundrun.v1+xml";
1903
1904
  async function activateObjects(client, objects) {
@@ -1960,7 +1961,8 @@ async function activateByReferences(client, references) {
1960
1961
  method: "GET",
1961
1962
  path: `/sap/bc/adt/activation/runs/${runId}`,
1962
1963
  params: { "withLongPolling": "true" },
1963
- headers: { "Accept": BACKGROUND_RUN_MEDIA_TYPE }
1964
+ headers: { "Accept": BACKGROUND_RUN_MEDIA_TYPE },
1965
+ timeout: LONG_POLL_TIMEOUT_MS
1964
1966
  });
1965
1967
  if (pollErr) return err(pollErr);
1966
1968
  debug(`Activation poll attempt ${pollAttempt} status: ${pollRes.status}`);
@@ -2050,6 +2052,192 @@ function extractActivationErrors(objects, xml) {
2050
2052
  return ok(results);
2051
2053
  }
2052
2054
 
2055
+ // src/core/adt/craud/apirelease/helpers.ts
2056
+ var DDLS_ENDPOINT = "ddic/ddl/sources";
2057
+ var CONTRACT_PATH = "c1";
2058
+ var CONTRACT_ELEMENT = "ars:c1Release";
2059
+ var APIRELEASE_MEDIA_TYPE = "application/vnd.sap.adt.apirelease.v10+xml";
2060
+ var APIRELEASE_VALIDATION_CONTENT_TYPE = "application/vnd.sap.adt.apireleasecontractvalidation+xml";
2061
+ var APIRELEASE_VALIDATION_ACCEPT = "application/vnd.sap.adt.apireleasecontractvalidation+xml, application/vnd.sap.adt.apireleasecontractvalidation.v2+xml";
2062
+ function buildReleasableUri(name) {
2063
+ return `/sap/bc/adt/${DDLS_ENDPOINT}/${name.toLowerCase()}`;
2064
+ }
2065
+ function buildApiReleasePath(name) {
2066
+ return `/sap/bc/adt/apireleases/${encodeURIComponent(buildReleasableUri(name))}`;
2067
+ }
2068
+ function buildContractPath(name) {
2069
+ return `${buildApiReleasePath(name)}/${CONTRACT_PATH}`;
2070
+ }
2071
+ function buildValidationRunPath(name) {
2072
+ return `${buildContractPath(name)}/validationrun`;
2073
+ }
2074
+ function buildC1ReleaseBody(status) {
2075
+ return `<?xml version="1.0" encoding="UTF-8"?><ars:apiRelease xmlns:ars="http://www.sap.com/adt/ars">
2076
+ <ars:c1Release ars:comment="" ars:contract="C1" ars:createAuthValues="false" ars:featureToggle="" ars:useInKeyUserApps="true" ars:useInSAPCloudPlatform="true">
2077
+ <ars:status ars:state="${status}"/>
2078
+ <ars:useConceptAsSuccessor>false</ars:useConceptAsSuccessor>
2079
+ <ars:successors/>
2080
+ <ars:successorConceptName/>
2081
+ </ars:c1Release>
2082
+ <ars:apiCatalogData ars:isAnyAssignmentPossible="false" ars:isAnyContractReleased="false">
2083
+ <ars:ApiCatalogs/>
2084
+ </ars:apiCatalogData>
2085
+ </ars:apiRelease>`;
2086
+ }
2087
+ function toStatus(state) {
2088
+ return state;
2089
+ }
2090
+ function findContractElement(doc) {
2091
+ const candidates = doc.getElementsByTagName(CONTRACT_ELEMENT);
2092
+ for (let i = 0; i < candidates.length; i++) {
2093
+ const el = candidates[i];
2094
+ if (!el) continue;
2095
+ if (el.getElementsByTagName("ars:status").length === 0) continue;
2096
+ return el;
2097
+ }
2098
+ return null;
2099
+ }
2100
+ function parseReleaseState(xml, fallbackName) {
2101
+ const [doc, parseErr] = safeParseXml(xml);
2102
+ if (parseErr) return err(parseErr);
2103
+ const contract = findContractElement(doc);
2104
+ if (!contract) return err(new Error("apiRelease response missing C1 contract element"));
2105
+ const statusEl = contract.getElementsByTagName("ars:status")[0];
2106
+ const state = statusEl?.getAttribute("ars:state");
2107
+ if (!state) return err(new Error("apiRelease response missing C1 status"));
2108
+ const statusDescription = statusEl?.getAttribute("ars:stateDescription") ?? "";
2109
+ const allowedTransitions = [];
2110
+ const transitionsEl = contract.getElementsByTagName("ars:stateTransitions")[0];
2111
+ if (transitionsEl) {
2112
+ const transitionStatuses = transitionsEl.getElementsByTagName("ars:status");
2113
+ for (let i = 0; i < transitionStatuses.length; i++) {
2114
+ const transitionState = transitionStatuses[i]?.getAttribute("ars:state");
2115
+ if (transitionState) allowedTransitions.push(toStatus(transitionState));
2116
+ }
2117
+ }
2118
+ const releasable = doc.getElementsByTagName("ars:releasableObject")[0];
2119
+ const name = releasable?.getAttribute("adtcore:name") ?? fallbackName;
2120
+ const uri = releasable?.getAttribute("adtcore:uri") ?? buildReleasableUri(fallbackName);
2121
+ const result = {
2122
+ name,
2123
+ uri,
2124
+ status: toStatus(state),
2125
+ statusDescription,
2126
+ released: state === "RELEASED",
2127
+ allowedTransitions
2128
+ };
2129
+ const changedBy = contract.getAttribute("adtcore:changedBy");
2130
+ if (changedBy) result.changedBy = changedBy;
2131
+ const changedAt = contract.getAttribute("adtcore:changedAt");
2132
+ if (changedAt) result.changedAt = changedAt;
2133
+ return ok(result);
2134
+ }
2135
+ function parseValidationMessages(xml) {
2136
+ const [doc, parseErr] = safeParseXml(xml);
2137
+ if (parseErr) return [];
2138
+ const messages = [];
2139
+ const elements = doc.getElementsByTagName("ars:validationMessage");
2140
+ for (let i = 0; i < elements.length; i++) {
2141
+ const el = elements[i];
2142
+ if (!el) continue;
2143
+ const text = el.getAttribute("text");
2144
+ if (!text) continue;
2145
+ const message = {
2146
+ severity: mapSeverity(el.getAttribute("type")),
2147
+ text
2148
+ };
2149
+ const msgid = el.getAttribute("msgid");
2150
+ if (msgid) message.msgid = msgid;
2151
+ const msgno = el.getAttribute("msgno");
2152
+ if (msgno) message.msgno = msgno;
2153
+ messages.push(message);
2154
+ }
2155
+ return messages;
2156
+ }
2157
+ function collectErrors(messages) {
2158
+ return messages.filter((m) => m.severity === "error");
2159
+ }
2160
+ function mapSeverity(type) {
2161
+ if (type === "E" || type === "A" || type === "X") return "error";
2162
+ if (type === "W") return "warning";
2163
+ return "info";
2164
+ }
2165
+
2166
+ // src/core/adt/craud/apirelease/getState.ts
2167
+ async function getApiReleaseState(client, objectName) {
2168
+ const [response, requestErr] = await client.request({
2169
+ method: "GET",
2170
+ path: buildApiReleasePath(objectName),
2171
+ headers: { "Accept": APIRELEASE_MEDIA_TYPE }
2172
+ });
2173
+ const [text, checkErr] = await checkResponse(
2174
+ response,
2175
+ requestErr,
2176
+ `Failed to read API release state for ${objectName}`
2177
+ );
2178
+ if (checkErr) return err(checkErr);
2179
+ const [state, parseErr] = parseReleaseState(text, objectName);
2180
+ if (parseErr) return err(parseErr);
2181
+ return ok(state);
2182
+ }
2183
+
2184
+ // src/core/adt/craud/apirelease/release.ts
2185
+ async function releaseApi(client, objectName, transport) {
2186
+ return setApiReleaseState(client, objectName, "RELEASED", transport);
2187
+ }
2188
+ async function unreleaseApi(client, objectName, transport) {
2189
+ return setApiReleaseState(client, objectName, "NOT_RELEASED", transport);
2190
+ }
2191
+ async function setApiReleaseState(client, objectName, status, transport) {
2192
+ const body = buildC1ReleaseBody(status);
2193
+ const [validationRes, validationReqErr] = await client.request({
2194
+ method: "POST",
2195
+ path: buildValidationRunPath(objectName),
2196
+ headers: {
2197
+ "Content-Type": APIRELEASE_VALIDATION_CONTENT_TYPE,
2198
+ "Accept": APIRELEASE_VALIDATION_ACCEPT
2199
+ },
2200
+ body
2201
+ });
2202
+ const [validationText, validationCheckErr] = await checkResponse(
2203
+ validationRes,
2204
+ validationReqErr,
2205
+ `API release validation failed for ${objectName}`
2206
+ );
2207
+ if (validationCheckErr) return err(validationCheckErr);
2208
+ const messages = parseValidationMessages(validationText);
2209
+ const errors = collectErrors(messages);
2210
+ if (errors.length > 0) {
2211
+ const detail = errors.map((e) => e.text).join("; ");
2212
+ return err(new Error(`API release validation failed for ${objectName}: ${detail}`));
2213
+ }
2214
+ const params = {};
2215
+ if (transport) params["request"] = transport;
2216
+ const [putRes, putReqErr] = await client.request({
2217
+ method: "PUT",
2218
+ path: buildContractPath(objectName),
2219
+ params,
2220
+ headers: {
2221
+ "Content-Type": APIRELEASE_MEDIA_TYPE,
2222
+ "Accept": APIRELEASE_MEDIA_TYPE
2223
+ },
2224
+ body
2225
+ });
2226
+ const [putText, putCheckErr] = await checkResponse(
2227
+ putRes,
2228
+ putReqErr,
2229
+ `Failed to set API release state for ${objectName}`
2230
+ );
2231
+ if (putCheckErr) return err(putCheckErr);
2232
+ const [state, parseErr] = parseReleaseState(putText, objectName);
2233
+ if (parseErr) return err(parseErr);
2234
+ return ok({
2235
+ name: state.name,
2236
+ status: state.status,
2237
+ messages
2238
+ });
2239
+ }
2240
+
2053
2241
  // src/core/adt/craud/syntaxCheck.ts
2054
2242
  async function checkSyntax(client, objects) {
2055
2243
  if (objects.length === 0) {
@@ -3882,6 +4070,24 @@ async function deleteServiceBinding2(state, requestor, bindingName, transport) {
3882
4070
  return deleteServiceBinding(requestor, bindingName, transport);
3883
4071
  }
3884
4072
 
4073
+ // src/client/methods/apirelease/getApiReleaseState.ts
4074
+ async function getApiReleaseState2(state, requestor, objectName) {
4075
+ if (!state.session) return err(new Error("Not logged in"));
4076
+ return getApiReleaseState(requestor, objectName);
4077
+ }
4078
+
4079
+ // src/client/methods/apirelease/releaseApi.ts
4080
+ async function releaseApi2(state, requestor, objectName, transport) {
4081
+ if (!state.session) return err(new Error("Not logged in"));
4082
+ return releaseApi(requestor, objectName, transport);
4083
+ }
4084
+
4085
+ // src/client/methods/apirelease/unreleaseApi.ts
4086
+ async function unreleaseApi2(state, requestor, objectName, transport) {
4087
+ if (!state.session) return err(new Error("Not logged in"));
4088
+ return unreleaseApi(requestor, objectName, transport);
4089
+ }
4090
+
3885
4091
  // src/client/methods/internal/cookies.ts
3886
4092
  function storeCookies(cookies, response) {
3887
4093
  const setCookieHeader = response.headers.get("set-cookie");
@@ -4272,6 +4478,16 @@ var ADTClientImpl = class {
4272
4478
  async deleteServiceBinding(bindingName, transport) {
4273
4479
  return deleteServiceBinding2(this.state, this.requestor, bindingName, transport);
4274
4480
  }
4481
+ // --- API Release ---
4482
+ async getApiReleaseState(objectName) {
4483
+ return getApiReleaseState2(this.state, this.requestor, objectName);
4484
+ }
4485
+ async releaseApi(objectName, transport) {
4486
+ return releaseApi2(this.state, this.requestor, objectName, transport);
4487
+ }
4488
+ async unreleaseApi(objectName, transport) {
4489
+ return unreleaseApi2(this.state, this.requestor, objectName, transport);
4490
+ }
4275
4491
  // --- Configuration ---
4276
4492
  getObjectConfig() {
4277
4493
  return getObjectConfig();