abap-adt-api
Version:
Interface to Abap Developer Tools webservice
441 lines (440 loc) • 18.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.atcChangeContact = exports.atcContactUri = exports.atcRequestExemption = exports.atcExemptProposal = exports.atcUsers = exports.atcWorklists = exports.createAtcRun = exports.atcCheckVariant = exports.atcCustomizing = exports.isProposalMessage = void 0;
const utilities_1 = require("../utilities");
const t = __importStar(require("io-ts"));
const __1 = require("..");
const urlparser_1 = require("./urlparser");
const exemptionKind = t.union([
t.literal("A"),
t.literal("I"),
t.literal(""),
t.string
]); // SATC_AC_RSLT_XMPT_KIND Atc based/Inline/none
const proposalFinding = (0, utilities_1.mixed)({
uri: t.string,
type: t.string,
name: t.string,
location: t.string,
processor: t.string,
lastChangedBy: t.string,
priority: t.number,
checkId: t.string,
checkTitle: t.string,
messageId: t.string,
messageTitle: t.string,
exemptionApproval: t.string,
exemptionKind,
checksum: t.number,
quickfixInfo: t.string
}, {
quickfixes: t.partial({
automatic: t.boolean,
manual: t.boolean,
pseudo: t.boolean
})
});
const restriction = t.type({
enabled: t.boolean,
singlefinding: t.boolean,
rangeOfFindings: t.type({
enabled: t.boolean,
restrictByObject: t.type({
object: t.boolean,
package: t.boolean,
subobject: t.boolean,
target: t.union([
t.literal("subobject"),
t.literal("object"),
t.literal("package"),
t.literal("")
])
}),
restrictByCheck: t.type({
check: t.boolean,
message: t.boolean,
target: t.union([t.literal("message"), t.literal("check"), t.literal("")])
})
})
});
const atcProposal = (0, utilities_1.mixed)({
finding: t.union([proposalFinding, t.string]),
package: t.string,
subObject: t.string,
subObjectType: t.string,
subObjectTypeDescr: t.string,
objectTypeDescr: t.string,
approver: t.string,
reason: t.union([t.literal("FPOS"), t.literal("OTHR"), t.literal("")]),
justification: t.string,
notify: t.union([
t.literal("never"),
t.literal("on_rejection"),
t.literal("always")
]),
restriction: restriction
}, {
apprIsArea: t.string,
checkClass: t.string,
validUntil: t.string
});
const atcProposalMessage = t.type({
type: t.string,
message: t.string
});
const atcRunResultInfo = t.type({
type: t.string,
description: t.string
});
const atcRunResult = t.type({
id: t.string,
timestamp: t.number,
infos: t.array(atcRunResultInfo)
});
const atcExcemption = t.type({
id: t.string,
justificationMandatory: t.boolean,
title: t.string
});
const atcProperty = t.type({
name: t.string,
value: t.union([t.boolean, t.string])
});
const atcCustomizingi = t.type({
properties: t.array(atcProperty),
excemptions: t.array(atcExcemption)
});
const objectSet = t.type({
name: t.string,
title: t.string,
kind: t.string
});
const link = t.type({
href: t.string,
rel: t.string,
type: t.string
});
const finding = t.type({
uri: t.string,
location: urlparser_1.uriParts,
priority: t.number,
checkId: t.string,
checkTitle: t.string,
messageId: t.string,
messageTitle: t.string,
exemptionApproval: t.string,
exemptionKind,
quickfixInfo: (0, utilities_1.orUndefined)(t.string),
link: link
});
const object = t.type({
uri: t.string,
type: t.string,
name: t.string,
packageName: t.string,
author: t.string,
objectTypeId: (0, utilities_1.orUndefined)(t.string),
findings: t.array(finding)
});
const atcWorklist = t.type({
id: t.string,
timestamp: t.number,
usedObjectSet: t.string,
objectSetIsComplete: t.boolean,
objectSets: t.array(objectSet),
objects: t.array(object)
});
const atcUser = t.type({
id: t.string,
title: t.string
});
exports.isProposalMessage = atcProposalMessage.is;
async function atcCustomizing(h) {
const headers = {
Accept: "application/xml, application/vnd.sap.atc.customizing-v1+xml"
};
const response = await h.request("/sap/bc/adt/atc/customizing", { headers });
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false
});
const properties = (0, utilities_1.xmlArray)(raw, "customizing", "properties", "property").map(utilities_1.xmlNodeAttr);
const excemptions = (0, utilities_1.xmlArray)(raw, "customizing", "exemption", "reasons", "reason").map(utilities_1.xmlNodeAttr);
const retval = { properties, excemptions };
return (0, __1.validateParseResult)(atcCustomizingi.decode(retval));
}
exports.atcCustomizing = atcCustomizing;
async function atcCheckVariant(h, variant) {
const headers = { Accept: "text/plain" };
const response = await h.request(`/sap/bc/adt/atc/worklists?checkVariant=${variant}`, { method: "POST", headers });
return response.body;
}
exports.atcCheckVariant = atcCheckVariant;
async function createAtcRun(h, variant, mainUrl, maxResults = 100) {
const body = `xml version="1.0" encoding="UTF-8"
<atc:run maximumVerdicts="${maxResults}" xmlns:atc="http://www.sap.com/adt/atc">
<objectSets xmlns:adtcore="http://www.sap.com/adt/core">
<objectSet kind="inclusive">
<adtcore:objectReferences>
<adtcore:objectReference adtcore:uri="${mainUrl}"/>
</adtcore:objectReferences>
</objectSet>
</objectSets>
</atc:run>`;
const headers = {
Accept: "application/xml",
"Content-Type": "application/xml"
};
const response = await h.request(`/sap/bc/adt/atc/runs?worklistId=${variant}`, { method: "POST", headers, body });
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false
});
const id = (0, utilities_1.xmlNode)(raw, "worklistRun", "worklistId");
const ts = (0, utilities_1.xmlNode)(raw, "worklistRun", "worklistTimestamp");
const infos = (0, utilities_1.xmlArray)(raw, "worklistRun", "infos", "info");
const retval = { id, timestamp: new Date(ts).getTime() / 1000, infos };
return (0, __1.validateParseResult)(atcRunResult.decode(retval));
}
exports.createAtcRun = createAtcRun;
async function atcWorklists(h, runResultId, timestamp, usedObjectSet, includeExemptedFindings = false) {
const headers = { Accept: "application/atc.worklist.v1+xml" };
const qs = { timestamp, usedObjectSet, includeExemptedFindings };
const response = await h.request(`/sap/bc/adt/atc/worklists/${runResultId}`, {
headers,
qs
});
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false,
numberParseOptions: utilities_1.numberParseOptions
});
const root = (0, utilities_1.xmlNode)(raw, "worklist");
const attrs = (0, utilities_1.xmlNodeAttr)(root);
const objectSets = (0, utilities_1.xmlArray)(root, "objectSets", "objectSet").map(utilities_1.xmlNodeAttr);
const objects = (0, utilities_1.xmlArray)(root, "objects", "object").map(o => {
const oa = (0, utilities_1.xmlNodeAttr)(o);
const findings = (0, utilities_1.xmlArray)(o, "findings", "finding").map(f => {
const fa = (0, utilities_1.xmlNodeAttr)(f);
const priority = (0, utilities_1.toInt)(fa.priority);
const link = (0, utilities_1.xmlNodeAttr)((0, utilities_1.xmlNode)(f, "link"));
const location = (0, urlparser_1.parseUri)(fa.location);
const messageTitle = fa.messageTitle;
const checkTitle = fa.checkTitle;
return {
...fa,
priority,
messageTitle,
checkTitle,
location,
messageId: `${fa.messageId}`,
link
};
});
return { ...oa, findings };
});
const ts = new Date(attrs.timestamp).getTime() / 1000;
const result = { ...attrs, timestamp: ts, objectSets, objects };
return (0, __1.validateParseResult)(atcWorklist.decode(result));
}
exports.atcWorklists = atcWorklists;
async function atcUsers(h) {
const headers = { Accept: "application/atom+xml;type=feed" };
const response = await h.request(`/sap/bc/adt/system/users`, { headers });
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false,
parseAttributeValue: false
});
const users = (0, utilities_1.xmlArray)(raw, "feed", "entry");
return (0, __1.validateParseResult)(t.array(atcUser).decode(users));
}
exports.atcUsers = atcUsers;
async function atcExemptProposal(h, markerId) {
const headers = {
Accept: "application/atc.xmpt.v1+xml, application/atc.xmptapp.v1+xml"
};
const qs = { markerId };
const response = await h.request(`/sap/bc/adt/atc/exemptions/apply`, {
headers,
qs
});
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false,
parseAttributeValue: false
});
const root = (0, utilities_1.xmlNode)(raw, "exemptionApply", "exemptionProposal");
const { message, type } = (0, utilities_1.xmlNode)(raw, "exemptionApply", "status") || {};
if ((0, __1.isErrorMessageType)(type))
throw (0, __1.adtException)(message);
if (message && type)
return (0, __1.validateParseResult)(atcProposalMessage.decode({ message, type }));
const finding = (0, utilities_1.isString)(root.finding)
? root.finding
: (0, utilities_1.xmlNodeAttr)((0, utilities_1.xmlNode)(root, "finding"));
if (!(0, utilities_1.isString)(finding)) {
finding.priority = (0, utilities_1.toInt)(finding.priority);
finding.checksum = (0, utilities_1.toInt)(finding.checksum);
const qf = (0, utilities_1.xmlNodeAttr)((0, utilities_1.xmlNode)(root, "finding", "quickfixes"));
finding.quickfixes = {
automatic: qf.automatic === "true",
manual: qf.manual === "true",
pseudo: qf.pseudo === "true"
};
}
const { package: pa, subObject, subObjectType, subObjectTypeDescr, objectTypeDescr, approver, reason, justification, notify, apprIsArea, checkClass, validUntil } = root;
const { thisFinding, rangeOfFindings } = (0, utilities_1.xmlNode)(root, "restriction");
const { restrictByObject, restrictByCheck } = rangeOfFindings;
const result = {
finding,
package: pa,
subObject,
subObjectType,
subObjectTypeDescr,
objectTypeDescr,
approver,
reason,
justification,
notify,
apprIsArea,
checkClass,
validUntil,
restriction: {
enabled: thisFinding["@_enabled"] === "true",
singlefinding: thisFinding["#text"] === "true",
rangeOfFindings: {
enabled: rangeOfFindings["@_enabled"] === "true",
restrictByObject: {
object: restrictByObject["@_object"] === "true",
package: restrictByObject["@_package"] === "true",
subobject: restrictByObject["@_subobject"] === "true",
target: restrictByObject["#text"] || ""
},
restrictByCheck: {
check: restrictByCheck["@_check"] === "true",
message: restrictByCheck["@_message"] === "true",
target: restrictByCheck["#text"] || ""
}
}
}
};
return (0, __1.validateParseResult)(atcProposal.decode(result));
}
exports.atcExemptProposal = atcExemptProposal;
async function atcRequestExemption(h, proposal) {
const headers = {
"Content-Type": "application/atc.xmptprop.v1+xml",
Accept: "application/atc.xmpt.v1+xml, application/atc.xmptprop.v1+xml"
};
const { finding, restriction: { rangeOfFindings: { restrictByCheck, restrictByObject } }, restriction } = proposal;
const qs = { markerId: (0, utilities_1.isString)(finding) ? finding : finding.quickfixInfo };
const findingXml = (0, utilities_1.isString)(finding)
? `<atcexmpt:finding>${finding}</atcexmpt:finding>`
: `<atcfinding:finding adtcore:name="${finding.name}" adtcore:type="${finding.type}" adtcore:uri="${finding.uri}"
atcfinding:checkId="${finding.checkId}" atcfinding:checksum="${finding.checksum}" atcfinding:checkTitle="${(0, utilities_1.encodeEntity)(finding.checkTitle)}"
atcfinding:exemptionApproval="${finding.exemptionApproval}" atcfinding:exemptionKind="${finding.exemptionKind}"
atcfinding:lastChangedBy="${finding.lastChangedBy}"
atcfinding:location="${finding.location}" atcfinding:messageId="${finding.messageId}" atcfinding:messageTitle="${(0, utilities_1.encodeEntity)(finding.messageTitle)}"
atcfinding:priority="${finding.priority}" atcfinding:processor="${finding.processor}" atcfinding:quickfixInfo="${finding.quickfixInfo}">
<atcfinding:quickfixes atcfinding:automatic="false" atcfinding:manual="false" atcfinding:pseudo="false" />
</atcfinding:finding>`;
const body = `xml version="1.0" encoding="ASCII"
<atcexmpt:exemptionProposal xmlns:adtcore="http://www.sap.com/adt/core" xmlns:atcexmpt="http://www.sap.com/adt/atc/exemption" xmlns:atcfinding="http://www.sap.com/adt/atc/finding">
${findingXml}
<atcexmpt:package>${proposal.package}</atcexmpt:package>
<atcexmpt:subObject>${proposal.subObject}</atcexmpt:subObject>
<atcexmpt:subObjectType>${proposal.subObjectType}</atcexmpt:subObjectType>
<atcexmpt:subObjectTypeDescr>${proposal.subObjectTypeDescr}</atcexmpt:subObjectTypeDescr>
<atcexmpt:objectTypeDescr>${proposal.objectTypeDescr}</atcexmpt:objectTypeDescr>
<atcexmpt:restriction>
<atcexmpt:thisFinding enabled="${restriction.enabled}">${restriction.singlefinding}</atcexmpt:thisFinding>
<atcexmpt:rangeOfFindings enabled="${restriction.rangeOfFindings.enabled}">
<atcexmpt:restrictByObject object="${restrictByObject.object}" package="${restrictByObject.package}" subobject="${restrictByObject.subobject}">
${restrictByObject.target}</atcexmpt:restrictByObject>
<atcexmpt:restrictByCheck check="${restrictByCheck.check}" message="${restrictByCheck.message}">
${restrictByCheck.target}</atcexmpt:restrictByCheck>
</atcexmpt:rangeOfFindings>
</atcexmpt:restriction>
<atcexmpt:approver>${proposal.approver}</atcexmpt:approver>
<atcexmpt:reason>${proposal.reason}</atcexmpt:reason>
<atcexmpt:justification>${(0, utilities_1.encodeEntity)(proposal.justification)}</atcexmpt:justification>
<atcexmpt:notify>${proposal.notify}</atcexmpt:notify>
<atcexmpt:apprIsArea>${proposal.apprIsArea || ""}</atcexmpt:apprIsArea>
<atcexmpt:checkClass>${proposal.checkClass || ""}</atcexmpt:checkClass>
<atcexmpt:validUntil>${proposal.validUntil || ""}</atcexmpt:validUntil>
</atcexmpt:exemptionProposal>`;
const response = await h.request(`/sap/bc/adt/atc/exemptions/apply`, {
headers,
body,
qs,
method: "POST"
});
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false,
parseAttributeValue: false
});
const result = (0, __1.validateParseResult)(atcProposalMessage.decode(raw === null || raw === void 0 ? void 0 : raw.status));
if ((0, __1.isErrorMessageType)(result.type))
throw (0, __1.adtException)(result.message);
return (0, __1.validateParseResult)(atcProposalMessage.decode(result));
}
exports.atcRequestExemption = atcRequestExemption;
async function atcContactUri(h, findingUri) {
const headers = {
"Content-Type": "application/vnd.sap.adt.atc.findingreferences.v1+xml",
Accept: "application/vnd.sap.adt.atc.items.v1+xml"
};
const qs = { step: "proposal" };
const body = `xml version="1.0" encoding="ASCII"
<atcfinding:findingReferences xmlns:adtcore="http://www.sap.com/adt/core" xmlns:atcfinding="http://www.sap.com/adt/atc/finding">
<atcfinding:findingReference adtcore:uri="${findingUri}"/>
</atcfinding:findingReferences>`;
const response = await h.request(`/sap/bc/adt/atc/items`, {
headers,
body,
method: "POST",
qs
});
const raw = (0, utilities_1.fullParse)(response.body, {
removeNSPrefix: true,
parseTagValue: false,
parseAttributeValue: false
});
const { uri } = (0, utilities_1.xmlNodeAttr)((0, utilities_1.xmlNode)(raw, "items", "item"));
return (0, __1.validateParseResult)(t.string.decode(uri));
}
exports.atcContactUri = atcContactUri;
async function atcChangeContact(h, itemUri, userId) {
const headers = { "Content-Type": "application/vnd.sap.adt.atc.items.v1+xml" };
const body = `xml version="1.0" encoding="ASCII"
<atcfinding:items xmlns:adtcore="http://www.sap.com/adt/core" xmlns:atcfinding="http://www.sap.com/adt/atc/finding">
<atcfinding:item adtcore:uri="${itemUri}" atcfinding:processor="${userId}" atcfinding:status="2"/>
</atcfinding:items>`;
await h.request(`/sap/bc/adt/atc/items`, { headers, body, method: "PUT" });
}
exports.atcChangeContact = atcChangeContact;