UNPKG

abap-adt-api

Version:

Interface to Abap Developer Tools webservice

441 lines (440 loc) 18.6 kB
"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;