trm-core
Version:
TRM (Transport Request Manager) Core
714 lines (713 loc) • 28.4 kB
JavaScript
;
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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Manifest = void 0;
const xml = __importStar(require("xml-js"));
const semver = __importStar(require("semver"));
const commons_1 = require("../commons");
const trmPackage_1 = require("../trmPackage");
const registry_1 = require("../registry");
const normalize_url_1 = __importDefault(require("@esm2cjs/normalize-url"));
const email_validator_1 = require("email-validator");
const SpdxLicenseIds = __importStar(require("spdx-license-ids/index.json"));
const xmldom_1 = require("xmldom");
const lodash_1 = __importDefault(require("lodash"));
const xml_beautify_1 = __importDefault(require("xml-beautify"));
const logger_1 = require("../logger");
function getManifestAuthor(sAuthor) {
var author = {};
const emailRegex = new RegExp("<([^>]*)>");
const email = emailRegex.exec(sAuthor);
if (email) {
author.email = email[1].toLowerCase();
sAuthor = sAuthor.replace(`<${email[1]}>`, '');
}
author.name = sAuthor.trim();
return author;
}
class Manifest {
constructor(_manifest) {
this._manifest = _manifest;
}
get(keepRuntimeValues = false) {
return Manifest.normalize(this._manifest, keepRuntimeValues);
}
getKey(keepVersion = true) {
const manifest = this.get();
const registryEndpoint = this._manifest.registry;
return `${manifest.name}${keepVersion ? manifest.version : ''}${registryEndpoint}`;
}
setDistFolder(dist) {
this._manifest.distFolder = dist;
return this;
}
setLinkedTransport(transport) {
this._manifest.linkedTransport = transport;
return this;
}
getLinkedTransport() {
return this._manifest.linkedTransport;
}
setRegistryEndpoint(endpoint) {
this._manifest.registry = endpoint;
}
getAbapXml() {
const manifest = this.get();
var oAbapXml = {
"_declaration": {
"_attributes": {
"version": "1.0",
"encoding": "utf-8"
}
},
"asx:abap": {
"_attributes": {
"xmlns:asx": "http://www.sap.com/abapxml",
"version": "1.0"
},
"asx:values": {
"TRM_MANIFEST": {
"NAME": {
"_text": manifest.name
},
"VERSION": {
"_text": manifest.version
}
}
}
}
};
if (manifest.description) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['DESCRIPTION'] = {
"_text": manifest.description
};
}
if (manifest.private) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['PRIVATE'] = {
"_text": "X"
};
}
if (manifest.backwardsCompatible) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['BACKWARDS_COMPATIBLE'] = {
"_text": "X"
};
}
if (manifest.git) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['GIT'] = {
"_text": manifest.git
};
}
if (manifest.website) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['WEBSITE'] = {
"_text": manifest.website
};
}
if (manifest.license) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['LICENSE'] = {
"_text": manifest.license
};
}
if (manifest.namespace) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['REPLICENSE'] = {
"_text": manifest.namespace.replicense
};
if (Array.isArray(manifest.namespace.texts)) {
var texts = [];
manifest.namespace.texts.forEach(o => {
var obj = {};
if (o.description) {
obj['DESCRIPTION'] = {
"_text": o.description
};
}
if (o.language) {
obj['LANGUAGE'] = {
"_text": o.language
};
}
if (o.owner) {
obj['OWNER'] = {
"_text": o.owner
};
}
if (Object.keys(obj).length > 0) {
texts.push(obj);
}
});
if (texts.length > 0) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['REPLICENSE_T'] = {
"item": texts
};
}
}
}
if (manifest.authors) {
var authors = [];
manifest.authors.forEach(o => {
var obj = {};
if (o.name) {
obj['NAME'] = {
"_text": o.name
};
}
if (o.email) {
obj['EMAIL'] = {
"_text": o.email
};
}
if (Object.keys(obj).length > 0) {
authors.push(obj);
}
});
if (authors.length > 0) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['AUTHORS'] = {
"item": authors
};
}
}
if (manifest.keywords) {
var keywords = manifest.keywords.map(o => {
return {
"_text": o
};
});
if (keywords.length > 0) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['KEYWORDS'] = {
"item": keywords
};
}
}
if (manifest.dependencies) {
var dependencies = [];
manifest.dependencies.forEach((o) => {
var obj = {};
if (o.name) {
obj['NAME'] = {
"_text": o.name
};
}
if (o.version) {
obj['VERSION'] = {
"_text": o.version
};
}
if (o.registry) {
obj['REGISTRY'] = {
"_text": o.registry
};
}
if (o.integrity) {
obj['INTEGRITY'] = {
"_text": o.integrity
};
}
if (Object.keys(obj).length > 0) {
dependencies.push(obj);
}
});
if (dependencies.length > 0) {
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['DEPENDENCIES'] = {
"item": dependencies
};
}
}
if (manifest.sapEntries) {
var sapEntries = [];
Object.keys(manifest.sapEntries).forEach(table => {
try {
var tableItems = [];
manifest.sapEntries[table].forEach(r => {
var record = {};
Object.keys(r).forEach(k => {
record[k] = {
"_text": r[k]
};
});
if (Object.keys(record).length > 0) {
tableItems.push(record);
}
});
sapEntries.push({
"TABLE": table,
"ENTRIES": {
"item": tableItems
}
});
}
catch (e) { }
});
oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['SAP_ENTRIES'] = {
"item": sapEntries
};
}
const sXml = xml.js2xml(oAbapXml, { compact: true });
return sXml ? new xml_beautify_1.default({ useSelfClosingElement: true, parser: xmldom_1.DOMParser }).beautify(sXml) : null;
}
getPackage() {
const manifest = this.get(true);
const registry = new registry_1.Registry(manifest.registry || registry_1.PUBLIC_RESERVED_KEYWORD);
return new trmPackage_1.TrmPackage(manifest.name, registry, this);
}
static normalize(manifest, keepRuntimeValues) {
var manifestClone = lodash_1.default.cloneDeep(manifest);
if (!keepRuntimeValues) {
delete manifestClone.linkedTransport;
delete manifestClone.registry;
}
if (!manifestClone.name) {
throw new Error('Package name missing.');
}
else {
manifestClone.name = manifestClone.name.trim().toLowerCase().replace(/\s/g, '');
}
if (!manifestClone.version) {
throw new Error('Package version missing.');
}
else {
manifestClone.version = semver.clean(manifestClone.version);
if (!manifestClone.version) {
throw new Error('Invalid package version declared.');
}
}
manifestClone.private = manifestClone.private ? true : false;
manifestClone.backwardsCompatible = manifestClone.backwardsCompatible ? true : false;
if (manifestClone.git) {
try {
manifestClone.git = (0, normalize_url_1.default)(manifestClone.git);
}
catch (e) {
delete manifestClone.git;
}
}
else {
delete manifestClone.git;
}
if (manifestClone.website) {
try {
manifestClone.website = (0, normalize_url_1.default)(manifestClone.website);
}
catch (e) {
delete manifestClone.website;
}
}
else {
delete manifestClone.website;
}
if (manifestClone.license) {
try {
const spdxLicenseIdsWrapper = SpdxLicenseIds;
const aSpdxLicenseIds = spdxLicenseIdsWrapper.default;
const inLicense = manifestClone.license.trim();
const lLicense = inLicense.toLowerCase();
const uLicense = inLicense.toUpperCase();
if (aSpdxLicenseIds.includes(inLicense)) {
manifestClone.license = inLicense;
}
else if (aSpdxLicenseIds.includes(lLicense)) {
manifestClone.license = lLicense;
}
else if (aSpdxLicenseIds.includes(uLicense)) {
manifestClone.license = uLicense;
}
else {
delete manifestClone.license;
}
}
catch (e) {
delete manifestClone.license;
}
}
else {
delete manifestClone.license;
}
if (manifestClone.namespace) {
if (!manifestClone.namespace.replicense) {
throw new Error('Missing namespace repair license.');
}
manifestClone.namespace.replicense = manifestClone.namespace.replicense.trim();
if (!/^\d+$/.test(manifestClone.namespace.replicense)) {
throw new Error('Invalid characters in namespace repair license.');
}
if (manifestClone.namespace.replicense.length !== 20) {
throw new Error(`Namespace has invalid repair license: length must be 20`);
}
if (!manifestClone.namespace.texts || manifestClone.namespace.texts.length === 0) {
throw new Error('Invalid namespace data: missing texts.');
}
manifestClone.namespace.texts.forEach(o => {
if (!o.language || !o.description || !o.owner) {
throw new Error('Missing namespace data.');
}
if (o.language.length !== 1) {
throw new Error(`Namespace has invalid language ${o.language}`);
}
if (o.description.length > 60) {
throw new Error(`Namespace has invalid description: maximum length is 60`);
}
if (o.owner.length > 20) {
throw new Error(`Namespace has invalid owner: maximum length is 20`);
}
});
}
else {
delete manifestClone.namespace;
}
if (manifestClone.authors) {
var aAuthors;
if (typeof (manifestClone.authors) === 'string') {
aAuthors = this.stringAuthorsToArray(manifestClone.authors);
}
else {
aAuthors = manifestClone.authors;
}
for (var i = 0; i < aAuthors.length; i++) {
try {
var author;
if (typeof (aAuthors[i]) === 'string') {
author = getManifestAuthor(aAuthors[i]);
}
if (author.email) {
if (!(0, email_validator_1.validate)(author.email)) {
delete author.email;
}
}
else {
delete author.email;
}
aAuthors[i] = author;
}
catch (e) { }
}
aAuthors = aAuthors.filter(o => !(!o.name && !o.email));
manifestClone.authors = Array.from(new Map(aAuthors.map(o => [`${o.name}${o.email}`, o])).values());
if (manifestClone.authors.length === 0) {
delete manifestClone.authors;
}
}
else {
delete manifestClone.authors;
}
if (manifestClone.keywords) {
var originalKeywords;
if (typeof (manifestClone.keywords) === 'string') {
originalKeywords = this.stringKeywordsToArray(manifestClone.keywords);
}
else {
originalKeywords = manifestClone.keywords;
}
manifestClone.keywords = [];
for (var originalKeyword of originalKeywords) {
try {
originalKeyword = originalKeyword.replace(/\s/g, '').toLowerCase();
if (!originalKeyword || !manifestClone.keywords.includes(originalKeyword)) {
manifestClone.keywords.push(originalKeyword);
}
}
catch (e) { }
}
if (manifestClone.keywords.length === 0) {
delete manifestClone.keywords;
}
}
else {
delete manifestClone.keywords;
}
if (manifestClone.dependencies) {
const originalDependencies = manifestClone.dependencies;
manifestClone.dependencies = [];
for (var originalDependency of originalDependencies) {
try {
var dependency = {};
if (originalDependency.name) {
dependency.name = originalDependency.name.trim().toLowerCase().replace(/\s/g, '');
if (semver.validRange(originalDependency.version)) {
dependency.version = originalDependency.version;
dependency.integrity = originalDependency.integrity;
if (!dependency.integrity) {
throw new Error(`Dependency ${dependency.name} is missing its integrity.`);
}
if (originalDependency.registry) {
dependency.registry = originalDependency.registry;
}
if (!manifestClone.dependencies.find(o => o.name === dependency.name && o.registry === dependency.registry)) {
manifestClone.dependencies.push(dependency);
}
}
}
}
catch (e) { }
}
if (manifestClone.dependencies.length === 0) {
delete manifestClone.dependencies;
}
}
else {
delete manifestClone.dependencies;
}
if (!manifestClone.sapEntries || typeof manifestClone.sapEntries !== 'object') {
delete manifestClone.sapEntries;
}
else {
for (const key in manifestClone.sapEntries) {
if (!Array.isArray(manifestClone.sapEntries[key])) {
throw new Error(`Invalid structure in SAP entries declaration.`);
}
for (const item of manifestClone.sapEntries[key]) {
if (typeof item !== 'object' || item === null) {
throw new Error(`Invalid structure in SAP entries declaration.`);
}
}
}
}
if (manifestClone.distFolder) {
try {
manifestClone.distFolder = manifestClone.distFolder.replace(/^\//, '');
manifestClone.distFolder = manifestClone.distFolder.replace(/\/$/, '');
}
catch (e) {
delete manifestClone.distFolder;
}
}
else {
delete manifestClone.distFolder;
}
return manifestClone;
}
static fromAbapXml(sXml) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
var manifest;
sXml = sXml.replace(/&/g, "&").replace(/-/g, "-");
const oAbapXml = xml.xml2js(sXml, { compact: true });
var oAbapManifest;
var sapEntries;
try {
oAbapManifest = (0, commons_1.normalize)(lodash_1.default.cloneDeep(oAbapXml)['asx:abap']['asx:values']['TRM_MANIFEST']);
manifest = {
name: oAbapManifest.name.text,
version: oAbapManifest.version.text,
backwardsCompatible: false,
private: false,
registry: registry_1.PUBLIC_RESERVED_KEYWORD
};
}
catch (e) {
throw new Error('XML Manifest is corrupted.');
}
try {
sapEntries = oAbapXml['asx:abap']['asx:values']['TRM_MANIFEST']['SAP_ENTRIES'];
}
catch (e) {
logger_1.Logger.error(e.toString(), true);
logger_1.Logger.error(`Couldn't parse sapEntries in abap xml manifest`, true);
}
if (oAbapManifest.description && oAbapManifest.description.text) {
manifest.description = oAbapManifest.description.text;
}
if (oAbapManifest.backwardsCompatible && oAbapManifest.backwardsCompatible.text) {
manifest.backwardsCompatible = oAbapManifest.backwardsCompatible.text === 'X';
}
if (oAbapManifest.private && oAbapManifest.private.text) {
manifest.private = oAbapManifest.private.text === 'X';
}
if (oAbapManifest.registry && oAbapManifest.registry.text) {
manifest.registry = oAbapManifest.registry;
}
if (oAbapManifest.git && oAbapManifest.git.text) {
manifest.git = oAbapManifest.git.text;
}
if (oAbapManifest.website && oAbapManifest.website.text) {
manifest.website = oAbapManifest.website.text;
}
if (oAbapManifest.license && oAbapManifest.license.text) {
manifest.license = oAbapManifest.license.text;
}
if (oAbapManifest.replicense) {
manifest.namespace = {
replicense: oAbapManifest.replicense.text,
texts: []
};
if (oAbapManifest.replicenseT && oAbapManifest.replicenseT.item) {
if (Array.isArray(oAbapManifest.replicenseT.item)) {
manifest.namespace.texts = oAbapManifest.replicenseT.item.map(o => {
var _a, _b, _c;
return {
description: (_a = o.description) === null || _a === void 0 ? void 0 : _a.text,
language: (_b = o.language) === null || _b === void 0 ? void 0 : _b.text,
owner: (_c = o.owner) === null || _c === void 0 ? void 0 : _c.text
};
});
}
else {
manifest.namespace.texts = [{
description: (_a = oAbapManifest.replicenseT.item.description) === null || _a === void 0 ? void 0 : _a.text,
language: (_b = oAbapManifest.replicenseT.item.language) === null || _b === void 0 ? void 0 : _b.text,
owner: (_c = oAbapManifest.replicenseT.item.owner) === null || _c === void 0 ? void 0 : _c.text
}];
}
}
}
if (oAbapManifest.keywords && oAbapManifest.keywords.item) {
if (Array.isArray(oAbapManifest.keywords.item)) {
manifest.keywords = oAbapManifest.keywords.item.map(o => o.text);
}
else {
manifest.keywords = [oAbapManifest.keywords.item.text];
}
}
if (oAbapManifest.authors && oAbapManifest.authors.item) {
if (Array.isArray(oAbapManifest.authors.item)) {
manifest.authors = oAbapManifest.authors.item.map(o => {
var _a, _b;
return {
name: (_a = o.name) === null || _a === void 0 ? void 0 : _a.text,
email: (_b = o.email) === null || _b === void 0 ? void 0 : _b.text
};
});
}
else {
manifest.authors = [{
name: (_d = oAbapManifest.authors.item.name) === null || _d === void 0 ? void 0 : _d.text,
email: (_e = oAbapManifest.authors.item.email) === null || _e === void 0 ? void 0 : _e.text
}];
}
}
if (oAbapManifest.dependencies && oAbapManifest.dependencies.item) {
if (Array.isArray(oAbapManifest.dependencies.item)) {
manifest.dependencies = oAbapManifest.dependencies.item.map(o => {
var _a, _b, _c, _d;
return {
name: (_a = o.name) === null || _a === void 0 ? void 0 : _a.text,
integrity: (_b = o.integrity) === null || _b === void 0 ? void 0 : _b.text,
version: (_c = o.version) === null || _c === void 0 ? void 0 : _c.text,
registry: (_d = o.registry) === null || _d === void 0 ? void 0 : _d.text
};
});
}
else {
manifest.dependencies = [{
name: (_f = oAbapManifest.dependencies.item.name) === null || _f === void 0 ? void 0 : _f.text,
integrity: (_g = oAbapManifest.dependencies.item.integrity) === null || _g === void 0 ? void 0 : _g.text,
version: (_h = oAbapManifest.dependencies.item.version) === null || _h === void 0 ? void 0 : _h.text,
registry: (_j = oAbapManifest.dependencies.item.registry) === null || _j === void 0 ? void 0 : _j.text
}];
}
}
if (sapEntries && sapEntries.item) {
manifest.sapEntries = {};
try {
const aParsedXml = this._parseAbapXmlSapEntriesArray(sapEntries.item);
aParsedXml.forEach(o => {
manifest.sapEntries[o.TABLE] = [];
o.ENTRIES.forEach(e => {
var parsedEntry = {};
Object.keys(e).forEach(field => {
var parsedField = field.toUpperCase();
parsedEntry[parsedField] = e[field];
});
if (Object.keys(parsedEntry).length > 0) {
manifest.sapEntries[o.TABLE].push(parsedEntry);
}
});
});
}
catch (e) { }
}
return new Manifest(Manifest.normalize(manifest, false));
}
static _parseAbapXmlSapEntriesArray(input) {
var array = [];
if (Array.isArray(input)) {
input.forEach(o => {
array = array.concat(this._parseAbapXmlSapEntriesArray(o));
});
}
else {
var obj = {};
Object.keys(input).forEach(k => {
if (input[k]._text) {
obj[k] = input[k]._text;
}
else {
if (input[k].item) {
obj[k] = this._parseAbapXmlSapEntriesArray(input[k].item);
}
}
});
array.push(obj);
}
return array;
}
static fromJson(sJson) {
return new Manifest(Manifest.normalize(JSON.parse(sJson), false));
}
static compare(o1, o2, checkVersion = false) {
const s1 = o1.getKey(checkVersion);
const s2 = o2.getKey(checkVersion);
return s1 === s2;
}
static stringAuthorsToArray(sAuthors) {
var authors = [];
if (sAuthors) {
sAuthors.split(',').forEach(s => {
if (s) {
const match = s.trim().match(/^(.*?)(?:\s*<([^>]+)>)?$/);
if (match && match.length >= 3) {
authors.push({
name: match[1] ? match[1].trim() : undefined,
email: match[2] ? match[2].trim() : undefined
});
}
}
});
}
return authors;
}
static stringKeywordsToArray(sKeywords) {
if (sKeywords) {
return sKeywords.split(',').map(s => {
if (s) {
return s.trim();
}
}).filter(k => k !== undefined);
}
else {
return [];
}
}
}
exports.Manifest = Manifest;