UNPKG

@sap/cli-core

Version:

Command-Line Interface (CLI) Core Module

234 lines (233 loc) 9.48 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildHttpConfig = exports.configRequiresBody = exports.handleResponse = exports.handleResponseData = exports.buildParameters = exports.handleParameterMapping = exports.getValueFromMappping = exports.handleMappingIn = exports.removeLeadingPathSegmentForPasscode = exports.checkConfiguration = void 0; exports.getOutputFileName = getOutputFileName; exports.checkResponseDataForInvalidLoginData = checkResponseDataForInvalidLoginData; exports.handleResponseHeaders = handleResponseHeaders; const os_1 = require("os"); const url_1 = require("url"); const lodash_1 = __importDefault(require("lodash")); const fs_extra_1 = __importDefault(require("fs-extra")); const constants_1 = require("../../../constants"); const logger_1 = require("../../../logger"); const config_1 = require("../../../config"); const utils_1 = require("../utils"); const ResultHandlerFactory_1 = require("../../../result/ResultHandlerFactory"); const CURLY_OPEN_ENCODED = encodeURIComponent("{"); const CURLY_CLOSED_ENCODED = encodeURIComponent("}"); const checkConfiguration = (config) => { if (!config.authorization) { throw new Error("no authorization header"); } if (!config.host) { throw new Error("no host"); } if (!config.publicfqdn) { throw new Error("no publicfqdn"); } }; exports.checkConfiguration = checkConfiguration; const removeLeadingPathSegmentForPasscode = (path) => { const authenticationMethod = (0, utils_1.getAuthenticationMethod)(); if (authenticationMethod === constants_1.AuthenticationMethod.passcode) { const segments = path.split("/"); if (constants_1.SEGMENTS_TO_REMOVE_FOR_PASSCODE_AUTH.includes(segments[1])) { segments.splice(1, 1); return segments.join("/"); } } return path; }; exports.removeLeadingPathSegmentForPasscode = removeLeadingPathSegmentForPasscode; const getUrl = (path) => { if (path.startsWith("http")) { return new url_1.URL(path); } const pathInt = (0, exports.removeLeadingPathSegmentForPasscode)(path); const targetHost = (0, utils_1.getTargetHost)(); return new url_1.URL(`${targetHost}${pathInt}`); }; const handleMappingIn = (mapping, url, value, headers, bodyWrapper) => { if (mapping.in === "query") { url.searchParams.append(mapping.name, value); } else if (mapping.in === "header") { // eslint-disable-next-line no-param-reassign headers[mapping.name] = value; } else if (mapping.in === "path") { // eslint-disable-next-line no-param-reassign url.pathname = url.pathname.replace(new RegExp(`${CURLY_OPEN_ENCODED}${mapping.name}${CURLY_CLOSED_ENCODED}`, "g"), encodeURIComponent(value)); } else { if (!bodyWrapper.body) { // eslint-disable-next-line no-param-reassign bodyWrapper.body = {}; } lodash_1.default.set(bodyWrapper.body, mapping.name, value); } }; exports.handleMappingIn = handleMappingIn; const getValueFromMappping = (mapping, config) => { if (mapping.source.type === "value") { return mapping.source.value; } if ( // mapping.source.type === "option" config.options[mapping.source.name] === undefined && mapping.source.dataType === "boolean") { return false; } // mapping.source.type === "option" return config.options[mapping.source.name]; }; exports.getValueFromMappping = getValueFromMappping; const handleParameterMapping = (config, url, headers, bodyWrapper) => (mapping) => { const value = (0, exports.getValueFromMappping)(mapping, config); if (value === undefined || value === null) { return; } (0, exports.handleMappingIn)(mapping, url, value, headers, bodyWrapper); }; exports.handleParameterMapping = handleParameterMapping; const buildParameters = (path, parameterMappings) => { const config = (0, config_1.get)(); const bodyWrapper = { body: undefined, }; let headers = {}; if (config.data?.type === "file") { // stackoverflow.com/a/59177066 headers = config.data.content.getHeaders(); bodyWrapper.body = config.data.content; } else if (config.data?.type === "json") { headers = { "Content-Type": "application/json" }; bodyWrapper.body = config.data.content; } const url = getUrl(path); parameterMappings?.forEach((0, exports.handleParameterMapping)(config, url, headers, bodyWrapper)); return { url, headers, body: bodyWrapper.body, }; }; exports.buildParameters = buildParameters; /** * If --output is present: Return value of --output if defined, otherwise take value from outputPath. * If --output is not present, print response to console * @param outputPath Optional path defined by server * @returns Path to output file */ function getOutputFileName(outputPath = "") { const config = (0, config_1.get)(); if (typeof config.options[constants_1.OPTION_OUTPUT.longName] === "boolean" && config.options[constants_1.OPTION_OUTPUT.longName]) { return outputPath; } return config.options[constants_1.OPTION_OUTPUT.longName]; } function checkResponseDataForInvalidLoginData(response) { if ( // jira.tools.sap/browse/DW101-73607 typeof response === "string" && response.includes("Please contact your system administrator and ensure you have an active account on this system.")) { const logger = (0, logger_1.get)("checkResponseDataForInvalidLoginData"); logger.output("WARNING: You are using an access token which is not known to the tenant. Please check your login credentials."); logger.debug(response); return true; } return false; } const handleResponseData = async (data, outputPath) => { checkResponseDataForInvalidLoginData(data); const config = (0, config_1.get)(); if (!config.doNotStoreResult) { ResultHandlerFactory_1.ResultHandlerFactory.get().setResult(data); } if (config.doNotProcessResponseData) { return; } const { output } = (0, logger_1.get)("handler.fetch"); const formatted = config.options.pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data); const outputFileName = getOutputFileName(outputPath); if (outputFileName) { await fs_extra_1.default.writeFile(outputFileName, formatted); } else { output(formatted); } }; exports.handleResponseData = handleResponseData; function handleResponseHeaders(headers) { const { error, output } = (0, logger_1.get)("handler.fetch.handleResponseHeaders"); if (headers[constants_1.X_DSP_API_DEPRECATED_PROPERTIES]) { try { const deprecatedProperties = JSON.parse(headers[constants_1.X_DSP_API_DEPRECATED_PROPERTIES]); const deprecatedPropertiesStr = deprecatedProperties .map((dp) => { let msg = dp.name; if (dp.deprecatedWithWave) { msg += `. Deprecated since version ${dp.deprecatedWithWave}`; } if (dp.decommissionedAfterWave) { msg += `. Decommissioned after version ${dp.decommissionedAfterWave}`; } if (dp.sapHelpUrl) { msg += `. See the SAP Help documentation at ${dp.sapHelpUrl} for more information`; } if (dp.customMessage) { msg += `. ${dp.customMessage}`; } return msg; }) .reduce((prev, curr) => `${prev}${os_1.EOL}\t${curr}`, ""); output(`WARNING: the following properties are deprecated:${deprecatedPropertiesStr}`); } catch (err) { error(`failed to parse deprecated properties via header ${constants_1.X_DSP_API_DEPRECATED_PROPERTIES}`, err); } } } const handleResponse = async (data, headers) => { if (headers?.[constants_1.X_CSRF_TOKEN]) { (0, config_1.set)({ [constants_1.X_CSRF_TOKEN]: headers[constants_1.X_CSRF_TOKEN] }); } else { if (data) { await (0, exports.handleResponseData)(data, headers?.[constants_1.X_OUTPUT_FILE_NAME]); } if (headers) { handleResponseHeaders(headers); } } }; exports.handleResponse = handleResponse; const configRequiresBody = (method) => ["POST", "PUT", "PATCH"].includes(method.toUpperCase()); exports.configRequiresBody = configRequiresBody; const buildHttpConfig = async (method, path, parameterMappings) => { const config = (0, config_1.get)(); const { url, body, headers } = (0, exports.buildParameters)(path, parameterMappings); const httpConfig = { url: url.toString(), method, data: (0, exports.configRequiresBody)(method) ? body : undefined, headers: { ...config.authorization, ...headers, ...config.headers, publicfqdn: config.publicfqdn, }, }; if ((0, utils_1.getAuthenticationMethod)() === constants_1.AuthenticationMethod.oauth) { delete httpConfig.headers.publicfqdn; } return httpConfig; }; exports.buildHttpConfig = buildHttpConfig;