UNPKG

@sap/cli-core

Version:

Command-Line Interface (CLI) Core Module

143 lines (139 loc) 5.23 kB
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, "_");