text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.groupVulnerabilities = exports.dockerUserCTA = exports.getDisplayedOutput = exports.createErrorMappedResultsForJsonOutput = exports.extractDataToSendFromResults = exports.formatJsonOutput = void 0;
  const format_reachability_1 = require("../format-reachability");
  const chalk_1 = require("chalk");
  const config = require("../../config");
  const cloneDeep = require('lodash.clonedeep');
  const orderBy = require('lodash.orderby');
  const analytics = require("../../analytics");
  const remediation_based_format_issues_1 = require("../remediation-based-format-issues");
  const legacy_format_issue_1 = require("../legacy-format-issue");
  const docker_1 = require("../docker");
  const sarif_output_1 = require("../sarif-output");
  const iac_output_1 = require("../iac-output");
  const vuln_helpers_1 = require("../../vuln-helpers");
  const json_1 = require("../../json");
  const open_source_sarif_output_1 = require("../open-source-sarif-output");
  const get_severity_value_1 = require("../get-severity-value");
  const show_fix_tip_1 = require("../show-fix-tip");
  const dist_1 = require("snyk-docker-plugin/dist");
  function formatJsonOutput(jsonData, options) {
      const jsonDataClone = cloneDeep(jsonData);
      if (options['group-issues']) {
          jsonDataClone.vulnerabilities = Object.values((jsonDataClone.vulnerabilities || []).reduce((acc, vuln) => {
              var _a, _b;
              vuln.from = [vuln.from].concat(((_a = acc[vuln.id]) === null || _a === void 0 ? void 0 : _a.from) || []);
              vuln.name = [vuln.name].concat(((_b = acc[vuln.id]) === null || _b === void 0 ? void 0 : _b.name) || []);
              acc[vuln.id] = vuln;
              return acc;
          }, {}));
      }
      if (jsonDataClone.vulnerabilities) {
          jsonDataClone.vulnerabilities.forEach((vuln) => {
              if (vuln.reachability) {
                  vuln.reachability = format_reachability_1.getReachabilityJson(vuln.reachability);
              }
          });
      }
      return jsonDataClone;
  }
  exports.formatJsonOutput = formatJsonOutput;
  function extractDataToSendFromResults(results, jsonData, options) {
      let sarifData = {};
      let stringifiedSarifData = '';
      if (options.sarif || options['sarif-file-output']) {
          if (options.iac) {
              sarifData = iac_output_1.createSarifOutputForIac(results);
          }
          else if (options.docker) {
              sarifData = sarif_output_1.createSarifOutputForContainers(results);
          }
          else {
              sarifData = open_source_sarif_output_1.createSarifOutputForOpenSource(results);
          }
          stringifiedSarifData = json_1.jsonStringifyLargeObject(sarifData);
      }
      let stringifiedJsonData = '';
      if (options.json || options['json-file-output']) {
          stringifiedJsonData = json_1.jsonStringifyLargeObject(formatJsonOutput(jsonData, options));
      }
      const dataToSend = options.sarif ? sarifData : jsonData;
      const stringifiedData = options.sarif
          ? stringifiedSarifData
          : stringifiedJsonData;
      return {
          stdout: dataToSend,
          stringifiedData,
          stringifiedJsonData,
          stringifiedSarifData,
      };
  }
  exports.extractDataToSendFromResults = extractDataToSendFromResults;
  function createErrorMappedResultsForJsonOutput(results) {
      const errorMappedResults = results.map((result) => {
          // add json for when thrown exception
          if (result instanceof Error) {
              return {
                  ok: false,
                  error: result.message,
                  path: result.path,
              };
          }
          return result;
      });
      return errorMappedResults;
  }
  exports.createErrorMappedResultsForJsonOutput = createErrorMappedResultsForJsonOutput;
  function getDisplayedOutput(res, options, testedInfoText, localPackageTest, projectType, meta, prefix, multiProjAdvice, dockerAdvice) {
      const vulnCount = res.vulnerabilities && res.vulnerabilities.length;
      const singleVulnText = res.licensesPolicy ? 'issue' : 'vulnerability';
      const multipleVulnsText = res.licensesPolicy ? 'issues' : 'vulnerabilities';
      // Text will look like so:
      // 'found 232 vulnerabilities, 404 vulnerable paths.'
      let vulnCountText = `found ${res.uniqueCount} ` +
          (res.uniqueCount === 1 ? singleVulnText : multipleVulnsText);
      // Docker is currently not supported as num of paths is inaccurate due to trimming of paths to reduce size.
      if (options.showVulnPaths && !options.docker) {
          vulnCountText += `, ${vulnCount} vulnerable `;
          if (vulnCount === 1) {
              vulnCountText += 'path.';
          }
          else {
              vulnCountText += 'paths.';
          }
      }
      else {
          vulnCountText += '.';
      }
      const reachableVulnsText = options.reachableVulns && vulnCount > 0
          ? ` ${format_reachability_1.summariseReachableVulns(res.vulnerabilities)}`
          : '';
      const summary = testedInfoText +
          ', ' +
          chalk_1.default.red.bold(vulnCountText) +
          chalk_1.default.blue.bold(reachableVulnsText);
      const fixTip = show_fix_tip_1.showFixTip(projectType, res, options);
      const fixAdvice = fixTip ? `\n\n${fixTip}` : '';
      const dockerfileWarning = getDockerfileWarning(res.scanResult);
      const dockerSuggestion = getDockerSuggestionText(options, config);
      const vulns = res.vulnerabilities || [];
      const groupedVulns = groupVulnerabilities(vulns);
      const sortedGroupedVulns = orderBy(groupedVulns, ['metadata.severityValue', 'metadata.name'], ['asc', 'desc']);
      const filteredSortedGroupedVulns = sortedGroupedVulns.filter((vuln) => vuln.metadata.packageManager !== 'upstream');
      const binariesSortedGroupedVulns = sortedGroupedVulns.filter((vuln) => vuln.metadata.packageManager === 'upstream');
      let groupedVulnInfoOutput;
      if (res.remediation) {
          analytics.add('actionableRemediation', true);
          groupedVulnInfoOutput = remediation_based_format_issues_1.formatIssuesWithRemediation(filteredSortedGroupedVulns, res.remediation, options);
      }
      else {
          analytics.add('actionableRemediation', false);
          groupedVulnInfoOutput = filteredSortedGroupedVulns.map((vuln) => legacy_format_issue_1.formatIssues(vuln, options));
      }
      const groupedDockerBinariesVulnInfoOutput = res.docker && binariesSortedGroupedVulns.length
          ? docker_1.formatDockerBinariesIssues(binariesSortedGroupedVulns, res.docker.binariesVulns, options)
          : [];
      let body = groupedVulnInfoOutput.join('\n\n') +
          '\n\n' +
          groupedDockerBinariesVulnInfoOutput.join('\n\n') +
          '\n\n' +
          meta;
      if (res.remediation) {
          body = summary + body + fixAdvice;
      }
      else {
          body = body + '\n\n' + summary + fixAdvice;
      }
      const ignoredIssues = '';
      const dockerCTA = dockerUserCTA(options);
      return (prefix +
          body +
          multiProjAdvice +
          ignoredIssues +
          dockerAdvice +
          dockerfileWarning +
          dockerSuggestion +
          dockerCTA);
  }
  exports.getDisplayedOutput = getDisplayedOutput;
  function dockerUserCTA(options) {
      if (options.isDockerUser) {
          return '\n\nFor more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp';
      }
      return '';
  }
  exports.dockerUserCTA = dockerUserCTA;
  function getDockerSuggestionText(options, config) {
      if (!options.docker || options.isDockerUser) {
          return '';
      }
      let dockerSuggestion = '';
      if (config && config.disableSuggestions !== 'true') {
          const optOutSuggestions = '\n\nTo remove this message in the future, please run `snyk config set disableSuggestions=true`';
          if (!options.file) {
              dockerSuggestion +=
                  chalk_1.default.bold.white('\n\nPro tip: use `--file` option to get base image remediation advice.' +
                      `\nExample: $ snyk test --docker ${options.path} --file=path/to/Dockerfile`) + optOutSuggestions;
          }
          else if (!options['exclude-base-image-vulns']) {
              dockerSuggestion +=
                  chalk_1.default.bold.white('\n\nPro tip: use `--exclude-base-image-vulns` to exclude from display Docker base image vulnerabilities.') + optOutSuggestions;
          }
      }
      return dockerSuggestion;
  }
  function getDockerfileWarning(scanResult) {
      if (!scanResult) {
          return '';
      }
      const fact = scanResult.facts.find((fact) => fact.type === 'dockerfileAnalysis');
      if (!fact) {
          return '';
      }
      const dockerfileAnalysisFact = fact;
      if (!dockerfileAnalysisFact.data.error) {
          return '';
      }
      let userMessage = chalk_1.default.yellow('\n\nWarning: Unable to analyse Dockerfile provided through `--file`.');
      switch (dockerfileAnalysisFact.data.error.code) {
          case dist_1.DockerFileAnalysisErrorCode.BASE_IMAGE_NAME_NOT_FOUND:
              userMessage += chalk_1.default.yellow('\n         Dockerfile must begin with a FROM instruction. This may be after parser directives, comments, and globally scoped ARGs.');
              break;
          case dist_1.DockerFileAnalysisErrorCode.BASE_IMAGE_NON_RESOLVABLE:
              userMessage += chalk_1.default.yellow('\n         Dockerfile must have default values for all ARG instructions.');
              break;
      }
      return userMessage;
  }
  function groupVulnerabilities(vulns) {
      return vulns.reduce((map, curr) => {
          if (!map[curr.id]) {
              map[curr.id] = {};
              map[curr.id].list = [];
              map[curr.id].metadata = metadataForVuln(curr);
              map[curr.id].isIgnored = false;
              map[curr.id].isPatched = false;
              // Extra added fields for ease of handling
              map[curr.id].title = curr.title;
              map[curr.id].note = curr.note;
              map[curr.id].severity = curr.severity;
              map[curr.id].originalSeverity = curr.originalSeverity;
              map[curr.id].isNew = vuln_helpers_1.isNewVuln(curr);
              map[curr.id].name = curr.name;
              map[curr.id].version = curr.version;
              map[curr.id].fixedIn = curr.fixedIn;
              map[curr.id].dockerfileInstruction = curr.dockerfileInstruction;
              map[curr.id].dockerBaseImage = curr.dockerBaseImage;
              map[curr.id].nearestFixedInVersion = curr.nearestFixedInVersion;
              map[curr.id].legalInstructionsArray = curr.legalInstructionsArray;
              map[curr.id].reachability = curr.reachability;
          }
          map[curr.id].list.push(curr);
          if (!map[curr.id].isFixable) {
              map[curr.id].isFixable = vuln_helpers_1.isVulnFixable(curr);
          }
          if (!map[curr.id].note) {
              map[curr.id].note = !!curr.note;
          }
          return map;
      }, {});
  }
  exports.groupVulnerabilities = groupVulnerabilities;
  function metadataForVuln(vuln) {
      return {
          id: vuln.id,
          title: vuln.title,
          description: vuln.description,
          type: vuln.type,
          name: vuln.name,
          info: vuln.info,
          severity: vuln.severity,
          severityValue: get_severity_value_1.getSeverityValue(vuln.severity),
          isNew: vuln_helpers_1.isNewVuln(vuln),
          version: vuln.version,
          packageManager: vuln.packageManager,
      };
  }
  //# sourceMappingURL=format-test-results.js.map