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.d.mts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +217 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +217 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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();
|