@sap/cli-core
Version:
Command-Line Interface (CLI) Core Module
143 lines (139 loc) • 5.23 kB
JavaScript
import * as crypto from "crypto";
import path from "path";
import { upperCase } from "lodash-es";
import fs from "fs";
import { get as getLoggerOrig } from "../logger/index.js";
import { getShortFlagForLongName } from "./commands.js";
let pgk;
const getLogger = () => getLoggerOrig("utils.utils");
const REGEX_HTTPS = /http(s)*:\/\//;
export function buildOptionName(command, option) {
const shortFlag = getShortFlagForLongName(command, option);
return `-${shortFlag}, --${option.longName}`;
}
export const parseVersion = (version) => {
const segments = version.split(".");
return { major: parseInt(segments[0], 10), minor: parseInt(segments[1], 10) };
};
export const requireFile = (p) => {
const content = fs.readFileSync(p, "utf-8");
return JSON.parse(content);
};
export const readPackageJson = (cwd = "", force = false) => {
if (!pgk || force) {
const cwdPath = cwd || import.meta.dirname;
const { trace } = getLogger();
try {
const p = path.join(cwdPath, "./package.json");
trace(`reading ${p}`);
pgk = requireFile(p);
}
catch (err) {
trace("failed to read package.json first time", err.stack);
try {
const p = path.join(cwdPath, "../package.json");
trace(`reading ${p}`);
pgk = requireFile(p);
}
catch (err2) {
trace("failed to read package.json second time", err.stack);
const p = path.join(cwdPath, "../../package.json");
trace(`reading ${p}`);
pgk = requireFile(p);
}
}
}
return pgk;
};
export const getVersion = (cwd = "") => {
return readPackageJson(cwd, true).version;
};
export const getName = (cwd = "") => {
const segments = readPackageJson(cwd, true).name.split(/^@.*\//);
return segments[segments.length - 1];
};
export const getPackageName = (cwd = "") => {
return readPackageJson(cwd, true).name;
};
export const getDescription = (cwd = "") => {
return readPackageJson(cwd, true).description;
};
export const getEngines = (cwd = "") => {
return readPackageJson(cwd, true).engines;
};
export const getBin = (cwd = "") => {
const keys = Object.keys(readPackageJson(cwd, true).bin || {});
if (keys.length === 0) {
throw new Error("no bin property defined in package.json or bin property is empty");
}
return keys[0];
};
export const removeScopeFromPackageName = (packageName) => packageName.split("/").pop();
const removeProtocol = (tenant) => tenant.replace(REGEX_HTTPS, "");
export const parseTenant = (tenant) => {
const t = REGEX_HTTPS.test(tenant) ? tenant : `https://${tenant}`;
/*
One can enter the tenant in different ways, for example
<protocol>://<fqdn>.<landscape>.cloud.sap/
<fqdn>.<landscape>.cloud.sap/
<fqdn>.<landscape>.cloud.sap
<protocol>://<fqdn>.<landscape>.cloud.sap/dwaas-ui/index.html#/
However, we want the tenant in this format, eventually:
<protocol>://<fqdn>.<landscape>.cloud.sap
*/
return new URL(t).host;
};
export function isValidURL(url) {
const { debug, error } = getLogger();
try {
// eslint-disable-next-line no-new
new URL(url);
debug(`url ${url} is valid`);
return true;
}
catch (err) {
error(`url ${url} is no valid url`, err);
return false;
}
}
export const getInfoFromTenant = (tenant, verbose, printOutput = true) => {
let protocol;
try {
protocol = new URL(tenant).protocol;
}
catch {
protocol = "https:";
}
const publicfqdn = removeProtocol(tenant);
const segments = publicfqdn.split(".");
const hostname = segments[0];
const region = segments[1];
if (!region) {
const { output, error } = getLogger();
if (printOutput) {
output("error: invalid value '%s' for option '-H, --host <host>'", tenant);
}
if (verbose) {
output("value '%s' does not match pattern https://<prefix>.<landscape>.hcs.sap.cloud", tenant);
}
error("invalid region", region);
throw new Error("invalid region");
}
const parsedTenant = parseTenant(tenant);
return {
host: `${protocol}//dwaas-core.sac${region}.cfapps.orca.net.sap`,
publicfqdn: parsedTenant,
passcodeUrl: `https://${hostname}.authentication.${region}.hana.ondemand.com/passcode`,
authorizationUrl: `${protocol}//${hostname}.authentication.${region}.hana.ondemand.com/oauth/authorize`,
tokenUrl: `${protocol}//${hostname}.authentication.${region}.hana.ondemand.com/oauth/token`,
tenantUrl: `${protocol}//${parsedTenant}`,
};
};
export function removeQueryParametersFromUrl(sUrl) {
const url = new URL(sUrl);
return `${url.protocol}//${url.host}${url.pathname}`;
}
export const sha256 = (string) =>
// NOSONAR actually sha256 (or SHA-256) is considered secure according to SonarQube
crypto.createHash("sha256").update(string).digest("base64");
export const toConstantCase = (string) => upperCase(string).replace(/ /g, "_");