diff --git a/.eslintrc.json b/.eslintrc.json index b69baecdfb..9f5d9903b2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,10 @@ "@typescript-eslint/no-unused-vars": "error", "no-prototype-builtins": "off", "require-atomic-updates": "off", + "no-restricted-imports": [ + "error", + { "paths": ["lodash"], "patterns": ["lodash/*"] } + ], "no-buffer-constructor": "error" }, "overrides": [ diff --git a/package.json b/package.json index e0850d8fa0..e813e202b0 100644 --- a/package.json +++ b/package.json @@ -65,9 +65,11 @@ "dependencies": { "@open-policy-agent/opa-wasm": "^1.2.0", "@snyk/cli-interface": "2.11.0", - "@snyk/dep-graph": "1.21.0", + "@snyk/dep-graph": "1.23.1", "@snyk/gemfile": "1.2.0", - "@snyk/snyk-cocoapods-plugin": "2.5.1", + "@snyk/graphlib": "^2.1.9-patch.3", + "@snyk/inquirer": "^7.3.3-patch", + "@snyk/snyk-cocoapods-plugin": "2.5.2", "abbrev": "^1.1.1", "ansi-escapes": "3.2.0", "chalk": "^2.4.2", @@ -75,9 +77,23 @@ "configstore": "^5.0.1", "debug": "^4.1.1", "diff": "^4.0.1", - "graphlib": "^2.1.8", - "inquirer": "^7.3.3", - "lodash": "^4.17.20", + "lodash.assign": "^4.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.endswith": "^4.2.1", + "lodash.flatten": "^4.4.0", + "lodash.flattendeep": "^4.4.0", + "lodash.get": "^4.4.2", + "lodash.groupby": "^4.6.0", + "lodash.isempty": "^4.4.0", + "lodash.isobject": "^3.0.2", + "lodash.map": "^4.6.0", + "lodash.omit": "^4.5.0", + "lodash.orderby": "^4.6.0", + "lodash.sortby": "^4.7.0", + "lodash.uniq": "^4.5.0", + "lodash.upperfirst": "^4.3.1", + "lodash.values": "^4.3.0", "micromatch": "4.0.2", "needle": "2.5.0", "open": "^7.0.3", @@ -88,13 +104,13 @@ "semver": "^6.0.0", "snyk-config": "4.0.0-rc.2", "snyk-cpp-plugin": "2.2.1", - "snyk-docker-plugin": "4.16.0", - "snyk-go-plugin": "1.16.4", - "snyk-gradle-plugin": "3.12.3", + "snyk-docker-plugin": "4.17.2", + "snyk-go-plugin": "1.16.5", + "snyk-gradle-plugin": "3.12.5", "snyk-module": "3.1.0", - "snyk-mvn-plugin": "2.25.1", - "snyk-nodejs-lockfile-parser": "1.30.1", - "snyk-nuget-plugin": "1.20.0", + "snyk-mvn-plugin": "2.25.3", + "snyk-nodejs-lockfile-parser": "1.30.2", + "snyk-nuget-plugin": "1.21.0", "snyk-php-plugin": "1.9.2", "snyk-policy": "1.14.1", "snyk-python-plugin": "1.19.4", @@ -113,7 +129,6 @@ "devDependencies": { "@types/agent-base": "^4.2.1", "@types/diff": "^3.5.2", - "@types/graphlib": "^2.1.7", "@types/jest": "^25.2.3", "@types/lodash": "^4.14.161", "@types/needle": "^2.0.4", @@ -127,6 +142,9 @@ "eslint": "6.8.0", "eslint-config-prettier": "^6.1.0", "jest": "^25.5.4", + "lodash": "^4.17.20", + "lodash.countby": "^4.6.0", + "lodash.every": "^4.6.0", "madge": "^3.4.4", "nock": "^10.0.6", "npm-run-all": "^4.1.5", diff --git a/src/cli/commands/monitor/formatters/format-monitor-response.ts b/src/cli/commands/monitor/formatters/format-monitor-response.ts index 15016aa44f..6986c5b451 100644 --- a/src/cli/commands/monitor/formatters/format-monitor-response.ts +++ b/src/cli/commands/monitor/formatters/format-monitor-response.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const assign = require('lodash.assign'); import chalk from 'chalk'; import * as url from 'url'; @@ -63,7 +63,7 @@ export function formatMonitorOutput( return options.json ? JSON.stringify( - _.assign({}, res, { + assign({}, res, { manageUrl, packageManager, }), diff --git a/src/cli/commands/protect/index.ts b/src/cli/commands/protect/index.ts index bdf9c2c534..857cb7aa53 100644 --- a/src/cli/commands/protect/index.ts +++ b/src/cli/commands/protect/index.ts @@ -1,7 +1,7 @@ import * as debugModule from 'debug'; import * as snyk from '../../../lib/'; import * as types from '../../../lib/types'; -import * as protect from '../../../lib/protect'; +const protect = require('../../../lib/protect'); import * as analytics from '../../../lib/analytics'; import * as detect from '../../../lib/detect'; import * as pm from '../../../lib/package-managers'; diff --git a/src/cli/commands/protect/prompts.ts b/src/cli/commands/protect/prompts.ts index a5336286c6..7cf36f31b8 100644 --- a/src/cli/commands/protect/prompts.ts +++ b/src/cli/commands/protect/prompts.ts @@ -9,11 +9,12 @@ export { startOver, }; -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); +const get = require('lodash.get'); import * as semver from 'semver'; import { format as fmt } from 'util'; import * as debugModule from 'debug'; -import * as protect from '../../../lib/protect'; +const protect = require('../../../lib/protect'); import { parsePackageString as moduleToObject } from 'snyk-module'; import * as config from '../../../lib/config'; import * as snykPolicy from 'snyk-policy'; @@ -191,7 +192,7 @@ function getPatchPrompts( return []; } - let res = stripInvalidPatches(_.cloneDeep(vulns)).filter((vuln) => { + let res = stripInvalidPatches(cloneDeep(vulns)).filter((vuln) => { // if there's any upgrade available, then remove it return canBeUpgraded(vuln) || vuln.type === 'license' ? false : true; }) as AnnotatedIssue[]; @@ -256,7 +257,7 @@ function getPatchPrompts( if (!acc[last]) { // only copy the biggest change - copy[last] = _.cloneDeep(curr); + copy[last] = cloneDeep(curr); acc[last] = curr; return acc; } @@ -350,7 +351,7 @@ function getIgnorePrompts(vulns, policy, options?) { return []; } - const res = stripInvalidPatches(_.cloneDeep(vulns)).filter((vuln) => { + const res = stripInvalidPatches(cloneDeep(vulns)).filter((vuln) => { // remove all patches and updates // if there's any upgrade available @@ -390,7 +391,7 @@ function getUpdatePrompts(vulns: AnnotatedIssue[], policy, options?): Prompt[] { return []; } - let res = stripInvalidPatches(_.cloneDeep(vulns)).filter((vuln) => { + let res = stripInvalidPatches(cloneDeep(vulns)).filter((vuln) => { // only keep upgradeable return canBeUpgraded(vuln); }) as AnnotatedIssueWithGrouping[]; @@ -410,7 +411,7 @@ function getUpdatePrompts(vulns: AnnotatedIssue[], policy, options?): Prompt[] { if (!acc[from]) { // only copy the biggest change - copy = _.cloneDeep(curr); + copy = cloneDeep(curr); acc[from] = curr; return acc; } @@ -588,10 +589,10 @@ function generatePrompt( id += '-' + prefix + i; // make complete copies of the actions, otherwise we'll mutate the object - const ignore = _.cloneDeep(ignoreAction); - const skip = _.cloneDeep(skipAction); - const patch = _.cloneDeep(patchAction); - const update = _.cloneDeep(updateAction); + const ignore = cloneDeep(ignoreAction); + const skip = cloneDeep(skipAction); + const patch = cloneDeep(patchAction); + const update = cloneDeep(updateAction); const review: Action = { value: 'review', short: 'Review', @@ -974,7 +975,7 @@ function nextSteps(pkg, prevAnswers) { const prompts: Prompt[] = []; let i; - i = _.get(pkg, 'scripts.test', '').indexOf('snyk test'); + i = get(pkg, 'scripts.test', '').indexOf('snyk test'); if (i === -1) { prompts.push({ name: 'misc-add-test', @@ -992,7 +993,7 @@ function nextSteps(pkg, prevAnswers) { return prompts; } - i = _.get(pkg, 'scripts.prepublish', '').indexOf('snyk-pro'); + i = get(pkg, 'scripts.prepublish', '').indexOf('snyk-pro'); // if `snyk protect` doesn't already appear, then check if we need to add it if (i === -1) { diff --git a/src/cli/commands/protect/tasks.ts b/src/cli/commands/protect/tasks.ts index a9304e0cfe..837a852c99 100644 --- a/src/cli/commands/protect/tasks.ts +++ b/src/cli/commands/protect/tasks.ts @@ -2,7 +2,7 @@ export = answersToTasks; import * as debugModule from 'debug'; const debug = debugModule('snyk'); -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); function answersToTasks(answers) { const tasks = { @@ -43,7 +43,7 @@ function answersToTasks(answers) { const additional = vuln.grouped.upgrades.slice(1); additional.forEach((upgrade) => { - const copy = _.cloneDeep(vuln); + const copy = cloneDeep(vuln); copy.from = upgrade.from; copy.__filename = upgrade.filename; copy.patches = upgrade.patches; diff --git a/src/cli/commands/protect/wizard.ts b/src/cli/commands/protect/wizard.ts index 6acb1b99ac..e800ee1c82 100644 --- a/src/cli/commands/protect/wizard.ts +++ b/src/cli/commands/protect/wizard.ts @@ -10,12 +10,13 @@ import * as debugModule from 'debug'; const debug = debugModule('snyk'); import * as path from 'path'; -import * as inquirer from 'inquirer'; +import * as inquirer from '@snyk/inquirer'; import * as fs from 'fs'; import * as tryRequire from 'snyk-try-require'; import chalk from 'chalk'; import * as url from 'url'; -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); +const get = require('lodash.get'); import { exec } from 'child_process'; import { apiTokenExists } from '../../../lib/api-token'; import * as auth from '../auth/is-authed'; @@ -25,7 +26,7 @@ import answersToTasks = require('./tasks'); import * as snyk from '../../../lib/'; import { monitor as snykMonitor } from '../../../lib/monitor'; import { isCI } from '../../../lib/is-ci'; -import * as protect from '../../../lib/protect'; +const protect = require('../../../lib/protect'); import * as authorization from '../../../lib/authorization'; import * as config from '../../../lib/config'; import * as spinner from '../../../lib/spinner'; @@ -141,7 +142,7 @@ async function processWizardFlow(options) { } }) .then(() => { - return new Promise((resolve) => { + return new Promise((resolve) => { if (options.newPolicy) { return resolve(); // don't prompt to start over } @@ -261,7 +262,7 @@ function inquire(prompts, answers): Promise<{}> { }); return new Promise((resolve) => { inquirer.prompt(prompts).then((theseAnswers) => { - _.extend(answers, theseAnswers); + answers = { ...answers, ...theseAnswers }; Object.keys(answers).forEach((answerName) => { if (answerName.indexOf('--DOT--') > -1) { const newName = answerName.replace(/--DOT--/g, '.'); @@ -286,7 +287,7 @@ function getNewScriptContent(scriptContent, cmd) { } function addProtectScripts(existingScripts, npmVersion, options) { - const scripts = existingScripts ? _.cloneDeep(existingScripts) : {}; + const scripts = existingScripts ? cloneDeep(existingScripts) : {}; scripts['snyk-protect'] = 'snyk protect'; let cmd = 'npm run snyk-protect'; @@ -378,7 +379,7 @@ function processAnswers(answers, policy, options) { return Promise.resolve(); } - return new Promise((resolve) => { + return new Promise((resolve) => { exec( 'git add .snyk', { @@ -479,9 +480,9 @@ function processAnswers(answers, policy, options) { debug('updating %s', packageFile); if ( - _.get(pkg, 'dependencies.snyk') || - _.get(pkg, 'peerDependencies.snyk') || - _.get(pkg, 'optionalDependencies.snyk') + get(pkg, 'dependencies.snyk') || + get(pkg, 'peerDependencies.snyk') || + get(pkg, 'optionalDependencies.snyk') ) { // nothing to do as the user already has Snyk // TODO decide whether we should update the version being used @@ -489,7 +490,7 @@ function processAnswers(answers, policy, options) { // than the local version? } else { const addSnykToProdDeps = answers['misc-add-protect']; - const snykIsInDevDeps = _.get(pkg, 'devDependencies.snyk'); + const snykIsInDevDeps = get(pkg, 'devDependencies.snyk'); if (addSnykToProdDeps) { if (!pkg.dependencies) { diff --git a/src/cli/commands/test/formatters/docker/format-docker-binary-heading.ts b/src/cli/commands/test/formatters/docker/format-docker-binary-heading.ts index c8f648f083..8fe92b2336 100644 --- a/src/cli/commands/test/formatters/docker/format-docker-binary-heading.ts +++ b/src/cli/commands/test/formatters/docker/format-docker-binary-heading.ts @@ -1,10 +1,10 @@ -import * as _ from 'lodash'; +const values = require('lodash.values'); import chalk from 'chalk'; export function createDockerBinaryHeading(pkgInfo): string { const binaryName = pkgInfo.pkg.name; const binaryVersion = pkgInfo.pkg.version; - const numOfVulns = _.values(pkgInfo.issues).length; + const numOfVulns = values(pkgInfo.issues).length; const vulnCountText = numOfVulns > 1 ? 'vulnerabilities' : 'vulnerability'; return numOfVulns ? chalk.bold.white( diff --git a/src/cli/commands/test/formatters/docker/format-docker-binary-issues.ts b/src/cli/commands/test/formatters/docker/format-docker-binary-issues.ts index e256115fa9..4b71fa4914 100644 --- a/src/cli/commands/test/formatters/docker/format-docker-binary-issues.ts +++ b/src/cli/commands/test/formatters/docker/format-docker-binary-issues.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const values = require('lodash.values'); import { createDockerBinaryHeading } from './format-docker-binary-heading'; import { Options, TestOptions } from '../../../../../lib/types'; import { formatIssues } from '../legacy-format-issue'; @@ -9,7 +9,7 @@ export function formatDockerBinariesIssues( options: Options & TestOptions, ): string[] { const binariesIssuesOutput = [] as string[]; - for (const pkgInfo of _.values(binariesVulns.affectedPkgs)) { + for (const pkgInfo of values(binariesVulns.affectedPkgs)) { binariesIssuesOutput.push(createDockerBinaryHeading(pkgInfo)); const binaryIssues = dockerBinariesSortedGroupedVulns.filter( (vuln) => vuln.metadata.name === pkgInfo.pkg.name, diff --git a/src/cli/commands/test/formatters/format-test-results.ts b/src/cli/commands/test/formatters/format-test-results.ts index dcb5a93494..fdc3c65f96 100644 --- a/src/cli/commands/test/formatters/format-test-results.ts +++ b/src/cli/commands/test/formatters/format-test-results.ts @@ -15,7 +15,8 @@ import { WIZARD_SUPPORTED_PACKAGE_MANAGERS, } from '../../../../lib/package-managers'; import * as config from '../../../../lib/config'; -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); +const orderBy = require('lodash.orderby'); import * as analytics from '../../../../lib/analytics'; import { formatIssuesWithRemediation, @@ -30,7 +31,7 @@ import { jsonStringifyLargeObject } from '../../../../lib/json'; import { createSarifOutputForOpenSource } from '../open-source-sarif-output'; export function formatJsonOutput(jsonData, options: Options) { - const jsonDataClone = _.cloneDeep(jsonData); + const jsonDataClone = cloneDeep(jsonData); if (options['group-issues']) { jsonDataClone.vulnerabilities = Object.values( @@ -170,7 +171,7 @@ export function getDisplayedOutput( const vulns = res.vulnerabilities || []; const groupedVulns: GroupedVuln[] = groupVulnerabilities(vulns); - const sortedGroupedVulns = _.orderBy( + const sortedGroupedVulns = orderBy( groupedVulns, ['metadata.severityValue', 'metadata.name'], ['asc', 'desc'], diff --git a/src/cli/commands/test/formatters/legacy-format-issue.ts b/src/cli/commands/test/formatters/legacy-format-issue.ts index 0aeda76a5c..39945e27f8 100644 --- a/src/cli/commands/test/formatters/legacy-format-issue.ts +++ b/src/cli/commands/test/formatters/legacy-format-issue.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const uniq = require('lodash.uniq'); import chalk from 'chalk'; import * as config from '../../../../lib/config'; import { Options, TestOptions, ShowVulnPaths } from '../../../../lib/types'; @@ -26,7 +26,7 @@ export function formatIssues( const vulnID = vuln.list[0].id; const packageManager = options.packageManager!; const localPackageTest = isLocalFolder(options.path); - const uniquePackages = _.uniq( + const uniquePackages = uniq( vuln.list.map((i) => { if (i.from[1]) { return i.from && i.from[1]; @@ -234,7 +234,7 @@ function createRemediationText( } if (vuln.isFixable === true) { - const upgradePathsArray = _.uniq( + const upgradePathsArray = uniq( vuln.list.map((v) => { const shouldUpgradeItself = !!v.upgradePath[0]; const shouldUpgradeDirectDep = !!v.upgradePath[1]; diff --git a/src/cli/commands/test/iac-output.ts b/src/cli/commands/test/iac-output.ts index 484bb34193..d95575935f 100644 --- a/src/cli/commands/test/iac-output.ts +++ b/src/cli/commands/test/iac-output.ts @@ -11,7 +11,7 @@ import { titleCaseText } from './formatters/legacy-format-issue'; import * as sarif from 'sarif'; import { SEVERITY } from '../../../lib/snyk-test/legacy'; import { IacFileInDirectory } from '../../../lib/types'; -import upperFirst = require('lodash/upperFirst'); +import upperFirst = require('lodash.upperfirst'); const debug = Debug('iac-output'); function formatIacIssue( diff --git a/src/cli/commands/test/index.ts b/src/cli/commands/test/index.ts index f40a3b97f2..8fdfb9e738 100644 --- a/src/cli/commands/test/index.ts +++ b/src/cli/commands/test/index.ts @@ -1,6 +1,7 @@ export = test; -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); +const assign = require('lodash.assign'); import chalk from 'chalk'; import * as snyk from '../../../lib'; import * as config from '../../../lib/config'; @@ -128,7 +129,7 @@ async function test(...args: MethodArgs): Promise { // Create a copy of the options so a specific test can // modify them i.e. add `options.file` etc. We'll need // these options later. - const testOpts = _.cloneDeep(options); + const testOpts = cloneDeep(options); testOpts.path = path; testOpts.projectName = testOpts['project-name']; @@ -180,16 +181,14 @@ async function test(...args: MethodArgs): Promise { path, resArray[i], ); - results.push( - _.assign(resArray[i], { path: pathWithOptionalProjectName }), - ); + results.push(assign(resArray[i], { path: pathWithOptionalProjectName })); // currently testOpts are identical for each test result returned even if it's for multiple projects. // we want to return the project names, so will need to be crafty in a way that makes sense. if (!testOpts.projectNames) { resultOptions.push(testOpts); } else { resultOptions.push( - _.assign(_.cloneDeep(testOpts), { + assign(cloneDeep(testOpts), { projectName: testOpts.projectNames[i], }), ); diff --git a/src/cli/commands/test/open-source-sarif-output.ts b/src/cli/commands/test/open-source-sarif-output.ts index df7f9a0229..107f6ab712 100644 --- a/src/cli/commands/test/open-source-sarif-output.ts +++ b/src/cli/commands/test/open-source-sarif-output.ts @@ -1,6 +1,8 @@ import * as sarif from 'sarif'; -import * as _ from 'lodash'; -import { upperFirst } from 'lodash'; +const upperFirst = require('lodash.upperfirst'); +const groupBy = require('lodash.groupby'); +const map = require('lodash.map'); + import { TestResult, SEVERITY, @@ -50,27 +52,26 @@ function replaceLockfileWithManifest(testResult: TestResult): TestResult { } export function getRules(testResult: TestResult): sarif.ReportingDescriptor[] { - return _.chain(testResult.vulnerabilities) - .groupBy('id') - .values() - .map( - ([vuln, ...moreVulns]): sarif.ReportingDescriptor => { - const cves = vuln.identifiers?.CVE?.join(); - return { - id: vuln.id, - shortDescription: { - text: `${upperFirst(vuln.severity)} severity - ${ - vuln.title - } vulnerability in ${vuln.packageName}`, - }, - fullDescription: { - text: cves - ? `(${cves}) ${vuln.name}@${vuln.version}` - : `${vuln.name}@${vuln.version}`, - }, - help: { - text: '', - markdown: `* Package Manager: ${testResult.packageManager} + const groupedVulnerabilities = groupBy(testResult.vulnerabilities, 'id'); + return map( + groupedVulnerabilities, + ([vuln, ...moreVulns]): sarif.ReportingDescriptor => { + const cves = vuln.identifiers?.CVE?.join(); + return { + id: vuln.id, + shortDescription: { + text: `${upperFirst(vuln.severity)} severity - ${ + vuln.title + } vulnerability in ${vuln.packageName}`, + }, + fullDescription: { + text: cves + ? `(${cves}) ${vuln.name}@${vuln.version}` + : `${vuln.name}@${vuln.version}`, + }, + help: { + text: '', + markdown: `* Package Manager: ${testResult.packageManager} * ${vuln.type === 'license' ? 'Module' : 'Vulnerable module'}: ${vuln.name} * Introduced through: ${getIntroducedThrough(vuln)} #### Detailed paths @@ -78,19 +79,18 @@ ${[vuln, ...moreVulns] .map((item) => `* _Introduced through_: ${item.from.join(' › ')}`) .join('\n')} ${vuln.description}`.replace(/##\s/g, '# '), - }, - properties: { - tags: [ - 'security', - ...(vuln.identifiers?.CWE || []), - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - testResult.packageManager!, - ], - }, - }; - }, - ) - .value(); + }, + properties: { + tags: [ + 'security', + ...(vuln.identifiers?.CWE || []), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + testResult.packageManager!, + ], + }, + }; + }, + ); } export function getResults(testResult): sarif.Result[] { diff --git a/src/cli/commands/test/sarif-output.ts b/src/cli/commands/test/sarif-output.ts index 1e027b41ad..742a94fed1 100644 --- a/src/cli/commands/test/sarif-output.ts +++ b/src/cli/commands/test/sarif-output.ts @@ -1,5 +1,5 @@ import * as sarif from 'sarif'; -import { upperFirst } from 'lodash'; +const upperFirst = require('lodash.upperfirst'); export function createSarifOutputForContainers(testResult): sarif.Log { const sarifRes: sarif.Log = { diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 77fd347e73..f65d2acfce 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as pathLib from 'path'; import * as debugLib from 'debug'; -import * as _ from 'lodash'; +const endsWith = require('lodash.endswith'); import { NoSupportedManifestsFoundError } from './errors'; import { SupportedPackageManagers } from './package-managers'; @@ -96,7 +96,7 @@ const DETECTABLE_PACKAGE_MANAGERS: { export function isPathToPackageFile(path) { for (const fileName of DETECTABLE_FILES) { - if (_.endsWith(path, fileName)) { + if (endsWith(path, fileName)) { return true; } } diff --git a/src/lib/find-files.ts b/src/lib/find-files.ts index c28232a3e2..99705b9052 100644 --- a/src/lib/find-files.ts +++ b/src/lib/find-files.ts @@ -1,6 +1,7 @@ import * as fs from 'fs'; import * as pathLib from 'path'; -import * as _ from 'lodash'; +const sortBy = require('lodash.sortby'); +const groupBy = require('lodash.groupby'); import { detectPackageManagerFromFile } from './detect'; import * as debugModule from 'debug'; const debug = debugModule('snyk:find-files'); @@ -158,24 +159,22 @@ function filterForDefaultManifests(files: string[]): string[] { const filteredFiles: string[] = []; - const foundFiles = _(files) + const beforeSort = files .filter(Boolean) .filter((p) => fs.existsSync(p)) .map((p) => ({ path: p, ...pathLib.parse(p), packageManager: detectProjectTypeFromFile(p), - })) - .sortBy('dir') - .groupBy('dir') - .value(); + })); + const sorted = sortBy(beforeSort, 'dir'); + const foundFiles = groupBy(sorted, 'dir'); for (const directory of Object.keys(foundFiles)) { const filesInDirectory = foundFiles[directory]; - const groupedFiles = _(filesInDirectory) - .filter((p) => !!p.packageManager) - .groupBy('packageManager') - .value(); + const beforeGroup = filesInDirectory.filter((p) => !!p.packageManager); + + const groupedFiles = groupBy(beforeGroup, 'packageManager'); for (const packageManager of Object.keys(groupedFiles)) { const filesPerPackageManager = groupedFiles[packageManager]; diff --git a/src/lib/module-info/index.ts b/src/lib/module-info/index.ts index 24ba35df7e..9b3cc6b2e9 100644 --- a/src/lib/module-info/index.ts +++ b/src/lib/module-info/index.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const merge = require('lodash.merge'); import * as Debug from 'debug'; import { legacyPlugin as pluginApi } from '@snyk/cli-interface'; @@ -11,7 +11,7 @@ export function ModuleInfo(plugin, policy) { targetFile, options, ): Promise { - const pluginOptions = _.merge( + const pluginOptions = merge( { args: options._doubleDashArgs, }, diff --git a/src/lib/monitor/index.ts b/src/lib/monitor/index.ts index a55e08f893..cc108e8e6a 100644 --- a/src/lib/monitor/index.ts +++ b/src/lib/monitor/index.ts @@ -7,7 +7,8 @@ import { apiTokenExists } from '../api-token'; import request = require('../request'); import * as config from '../config'; import * as os from 'os'; -import * as _ from 'lodash'; +const get = require('lodash.get'); +const camelCase = require('lodash.camelcase'); import { isCI } from '../is-ci'; import * as analytics from '../analytics'; import { @@ -118,7 +119,7 @@ export async function monitor( // TODO @boost: delete this once 'experimental-dep-graph' ff is deleted if (GRAPH_SUPPORTED_PACKAGE_MANAGERS.includes(packageManager)) { const monitorGraphSupportedRes = await isFeatureFlagSupportedForOrg( - _.camelCase('experimental-dep-graph'), + camelCase('experimental-dep-graph'), options.org || config.org, ); @@ -248,7 +249,7 @@ async function monitorDepTree( `Adding call graph to payload, node count: ${nodeCount}, edge count: ${edgeCount}`, ); - const callGraphMetrics = _.get(pluginMeta, 'meta.callGraphMetrics', {}); + const callGraphMetrics = get(pluginMeta, 'meta.callGraphMetrics', {}); analytics.add('callGraphMetrics', { callGraphEdgeCount: edgeCount, callGraphNodeCount: nodeCount, @@ -418,7 +419,7 @@ export async function monitorDepGraph( `Adding call graph to payload, node count: ${nodeCount}, edge count: ${edgeCount}`, ); - const callGraphMetrics = _.get(pluginMeta, 'meta.callGraphMetrics', {}); + const callGraphMetrics = get(pluginMeta, 'meta.callGraphMetrics', {}); analytics.add('callGraphMetrics', { callGraphEdgeCount: edgeCount, callGraphNodeCount: nodeCount, diff --git a/src/lib/plugins/get-multi-plugin-result.ts b/src/lib/plugins/get-multi-plugin-result.ts index 833dd34e50..969865f2e1 100644 --- a/src/lib/plugins/get-multi-plugin-result.ts +++ b/src/lib/plugins/get-multi-plugin-result.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const cloneDeep = require('lodash.clonedeep'); import * as path from 'path'; import * as cliInterface from '@snyk/cli-interface'; import chalk from 'chalk'; @@ -42,7 +42,7 @@ export async function getMultiPluginResult( const failedResults: FailedProjectScanError[] = []; for (const targetFile of targetFiles) { - const optionsClone = _.cloneDeep(options); + const optionsClone = cloneDeep(options); optionsClone.file = path.relative(root, targetFile); optionsClone.packageManager = detectPackageManagerFromFile( path.basename(targetFile), diff --git a/src/lib/plugins/nodejs-plugin/npm-modules-parser.ts b/src/lib/plugins/nodejs-plugin/npm-modules-parser.ts index da3d9833bf..f88c56e899 100644 --- a/src/lib/plugins/nodejs-plugin/npm-modules-parser.ts +++ b/src/lib/plugins/nodejs-plugin/npm-modules-parser.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as resolveNodeDeps from 'snyk-resolve-deps'; import * as baseDebug from 'debug'; -import * as _ from 'lodash'; +const isEmpty = require('lodash.isempty'); import * as spinner from '../../spinner'; import * as analytics from '../../analytics'; @@ -38,7 +38,7 @@ export async function parse( if (options.dev) { dependencies = { ...dependencies, ...packageJson.devDependencies }; } - if (_.isEmpty(dependencies)) { + if (isEmpty(dependencies)) { return new Promise((resolve) => resolve({ name: packageJson.name, diff --git a/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts b/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts index df95c1cb50..08a102a18d 100644 --- a/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts +++ b/src/lib/plugins/nodejs-plugin/yarn-workspaces-parser.ts @@ -1,6 +1,8 @@ import * as baseDebug from 'debug'; import * as pathUtil from 'path'; -import * as _ from 'lodash'; +// import * as _ from 'lodash'; +const sortBy = require('lodash.sortby'); +const groupBy = require('lodash.groupby'); import * as micromatch from 'micromatch'; const debug = baseDebug('snyk-yarn-workspaces'); @@ -23,18 +25,33 @@ export async function processYarnWorkspaces( ): Promise { // the order of folders is important // must have the root level most folders at the top + // const yarnTargetFiles: { + // [dir: string]: Array<{ + // path: string; + // base: string; + // dir: string; + // }>; + // } = targetFiles + // .map((p) => ({ path: p, ...pathUtil.parse(p) })) + // .filter((res) => ['package.json'].includes(res.base)) + // .sortBy('dir') + // .groupBy('dir') + // .value(); + + const mappedAndFiltered = targetFiles + .map((p) => ({ path: p, ...pathUtil.parse(p) })) + .filter((res) => ['package.json'].includes(res.base)); + + const sorted = sortBy(mappedAndFiltered, 'dir'); + const grouped = groupBy(sorted, 'dir'); + const yarnTargetFiles: { [dir: string]: Array<{ path: string; base: string; dir: string; }>; - } = _(targetFiles) - .map((p) => ({ path: p, ...pathUtil.parse(p) })) - .filter((res) => ['package.json'].includes(res.base)) - .sortBy('dir') - .groupBy('dir') - .value(); + } = grouped; debug(`Processing potential Yarn workspaces (${targetFiles.length})`); if (Object.keys(yarnTargetFiles).length === 0) { diff --git a/src/lib/plugins/rubygems/index.ts b/src/lib/plugins/rubygems/index.ts index 5eacadfb07..54fa9f0818 100644 --- a/src/lib/plugins/rubygems/index.ts +++ b/src/lib/plugins/rubygems/index.ts @@ -1,7 +1,7 @@ import { inspectors, Spec } from './inspectors'; import { MissingTargetFileError } from '../../errors/missing-targetfile-error'; import gemfileLockToDependencies = require('./gemfile-lock-to-dependencies'); -import * as _ from 'lodash'; +const get = require('lodash.get'); import { MultiProjectResult } from '@snyk/cli-interface/legacy/plugin'; export async function inspect( @@ -31,8 +31,8 @@ export async function inspect( } function getDependenciesFromSpecs(specs) { - const gemfileLockBase64 = _.get(specs, 'files.gemfileLock.contents'); - const gemspecBase64 = _.get(specs, 'files.gemspec.contents'); + const gemfileLockBase64 = get(specs, 'files.gemfileLock.contents'); + const gemspecBase64 = get(specs, 'files.gemspec.contents'); const contents = Buffer.from( gemfileLockBase64 || gemspecBase64, 'base64', diff --git a/src/lib/policy/pluck-policies.ts b/src/lib/policy/pluck-policies.ts index c48cbdbb92..8a6d83ef9f 100644 --- a/src/lib/policy/pluck-policies.ts +++ b/src/lib/policy/pluck-policies.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const flatten = require('lodash.flatten'); import { PackageExpanded } from 'snyk-resolve-deps'; export function pluckPolicies(pkg: PackageExpanded): string[] | string { @@ -14,7 +14,7 @@ export function pluckPolicies(pkg: PackageExpanded): string[] | string { return []; } - return _.flatten( + return flatten( Object.keys(pkg.dependencies) .map((name: string) => pluckPolicies(pkg.dependencies[name])) .filter(Boolean), diff --git a/src/lib/protect/index.js b/src/lib/protect/index.js index bf9b7775e7..a971347545 100644 --- a/src/lib/protect/index.js +++ b/src/lib/protect/index.js @@ -9,7 +9,9 @@ const protect = (module.exports = { }); const debug = require('debug')('snyk'); -const _ = require('lodash'); + +const flattenDeep = require('lodash.flattendeep'); +const merge = require('lodash.merge'); function generatePolicy(policy, tasks, live, packageManager) { const promises = ['ignore', 'update', 'patch'] @@ -23,12 +25,12 @@ function generatePolicy(policy, tasks, live, packageManager) { return Promise.all(promises).then((res) => { // we're squashing the arrays of arrays into a flat structure // with only non-false values - const results = _.flattenDeep(res).filter(Boolean); + const results = flattenDeep(res).filter(Boolean); // then we merge the configs together using the original config // as the baseline (this lets us retain the user's existing config) results.unshift(policy); - const newPolicy = _.merge(...results); + const newPolicy = merge(...results); debug(JSON.stringify(newPolicy, '', 2)); diff --git a/src/lib/protect/patch.js b/src/lib/protect/patch.js index 9f0a908102..832388da43 100644 --- a/src/lib/protect/patch.js +++ b/src/lib/protect/patch.js @@ -8,7 +8,8 @@ const glob = require('glob'); const tempfile = require('tempfile'); const fs = require('fs'); const path = require('path'); -const _ = require('lodash'); +const flatten = require('lodash.flatten'); +const cloneDeep = require('lodash.clonedeep'); const applyPatch = require('./apply-patch'); const stripVersions = require('./strip-versions'); const getVulnSource = require('./get-vuln-source'); @@ -149,7 +150,7 @@ function patch(vulns, live) { const promise = promises .then((res) => { - const patched = _.flatten(res).filter(Boolean); + const patched = flatten(res).filter(Boolean); if (!live) { debug('[skipping - dry run]'); @@ -169,7 +170,7 @@ function patch(vulns, live) { const vuln = patched[i]; if (vuln.grouped && vuln.grouped.includes) { vuln.grouped.includes.forEach((id) => { - const rule = _.cloneDeep(curr); + const rule = cloneDeep(curr); rule.vulnId = id; acc.push(rule); }); diff --git a/src/lib/protect/update.js b/src/lib/protect/update.js index 3d0b32742f..101ac31b72 100644 --- a/src/lib/protect/update.js +++ b/src/lib/protect/update.js @@ -4,7 +4,8 @@ module.exports.installDev = installDev; const debug = require('debug')('snyk'); const chalk = require('chalk'); -const _ = require('lodash'); +const uniq = require('lodash.uniq'); +const isEmpty = require('lodash.isempty'); const { parsePackageString: moduleToObject } = require('snyk-module'); const semver = require('semver'); const errors = require('../errors/legacy-errors'); @@ -72,10 +73,10 @@ function update(packages, live, pkgManager) { (upgrade.prod && upgrade.prod.map(stripVersion)) || []; const devToUninstall = (upgrade.dev && upgrade.dev.map(stripVersion)) || []; - const toUninstall = _.uniq(prodToUninstall.concat(devToUninstall)); + const toUninstall = uniq(prodToUninstall.concat(devToUninstall)); debug('to uninstall', toUninstall); - if (!_.isEmpty(toUninstall)) { + if (!isEmpty(toUninstall)) { return uninstall(pkgManager, toUninstall, live); } }) diff --git a/src/lib/reachable-vulns.ts b/src/lib/reachable-vulns.ts index 9d7f555143..4ee3996cbd 100644 --- a/src/lib/reachable-vulns.ts +++ b/src/lib/reachable-vulns.ts @@ -1,4 +1,4 @@ -import * as graphlib from 'graphlib'; +import * as graphlib from '@snyk/graphlib'; import { CallGraph } from '@snyk/cli-interface/legacy/common'; import { diff --git a/src/lib/snyk-test/legacy.ts b/src/lib/snyk-test/legacy.ts index d88b777ccd..2aec4a68db 100644 --- a/src/lib/snyk-test/legacy.ts +++ b/src/lib/snyk-test/legacy.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const values = require('lodash.values'); import * as depGraphLib from '@snyk/dep-graph'; import { SupportedPackageManagers } from '../package-managers'; import { SupportedProjectTypes } from '../types'; @@ -339,8 +339,8 @@ function convertTestDepGraphResultToLegacy( const upgradePathsMap = new Map(); - for (const pkgInfo of _.values(result.affectedPkgs)) { - for (const pkgIssue of _.values(pkgInfo.issues)) { + for (const pkgInfo of values(result.affectedPkgs)) { + for (const pkgIssue of values(pkgInfo.issues)) { if (pkgIssue.fixInfo && pkgIssue.fixInfo.upgradePaths) { for (const upgradePath of pkgIssue.fixInfo.upgradePaths) { const legacyFromPath = pkgPathToLegacyPath(upgradePath.path); @@ -360,10 +360,10 @@ function convertTestDepGraphResultToLegacy( // use the upgradePathsMap to find available upgrade-paths const vulns: AnnotatedIssue[] = []; - for (const pkgInfo of _.values(result.affectedPkgs)) { + for (const pkgInfo of values(result.affectedPkgs)) { for (const vulnPkgPath of depGraph.pkgPathsToRoot(pkgInfo.pkg)) { const legacyFromPath = pkgPathToLegacyPath(vulnPkgPath.reverse()); - for (const pkgIssue of _.values(pkgInfo.issues)) { + for (const pkgIssue of values(pkgInfo.issues)) { const vulnPathString = getVulnPathString( pkgIssue.issueId, legacyFromPath, @@ -396,8 +396,8 @@ function convertTestDepGraphResultToLegacy( if (dockerRes && dockerRes.binariesVulns) { const binariesVulns = dockerRes.binariesVulns; - for (const pkgInfo of _.values(binariesVulns.affectedPkgs)) { - for (const pkgIssue of _.values(pkgInfo.issues)) { + for (const pkgInfo of values(binariesVulns.affectedPkgs)) { + for (const pkgIssue of values(pkgInfo.issues)) { const pkgAndVersion = (pkgInfo.pkg.name + '@' + pkgInfo.pkg.version) as string; diff --git a/src/lib/snyk-test/run-test.ts b/src/lib/snyk-test/run-test.ts index 19e88377fe..893465f857 100644 --- a/src/lib/snyk-test/run-test.ts +++ b/src/lib/snyk-test/run-test.ts @@ -1,5 +1,5 @@ import * as fs from 'fs'; -import * as _ from 'lodash'; +const get = require('lodash.get'); import * as path from 'path'; import * as pathUtil from 'path'; import * as debugModule from 'debug'; @@ -575,12 +575,12 @@ async function assembleLocalPayloads( } } analytics.add('pluginName', deps.plugin.name); - const javaVersion = _.get( + const javaVersion = get( deps.plugin, 'meta.versionBuildInfo.metaBuildVersion.javaVersion', null, ); - const mvnVersion = _.get( + const mvnVersion = get( deps.plugin, 'meta.versionBuildInfo.metaBuildVersion.mvnVersion', null, @@ -769,11 +769,7 @@ async function assembleLocalPayloads( `Adding call graph to payload, node count: ${nodeCount}, edge count: ${edgeCount}`, ); - const callGraphMetrics = _.get( - deps.plugin, - 'meta.callGraphMetrics', - {}, - ); + const callGraphMetrics = get(deps.plugin, 'meta.callGraphMetrics', {}); analytics.add('callGraphMetrics', { callGraphEdgeCount: edgeCount, callGraphNodeCount: nodeCount, diff --git a/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts b/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts index 32f279a987..40a1d4802c 100644 --- a/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts +++ b/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts @@ -9,7 +9,9 @@ import * as subProcess from '../../../src/lib/sub-process'; import { getVersion } from '../../../src/lib/version'; import { config as userConfig } from '../../../src/lib/user-config'; import { chdirWorkspaces, getWorkspaceJSON } from '../workspace-helper'; -import * as _ from 'lodash'; +const isEmpty = require('lodash.isempty'); +const isObject = require('lodash.isobject'); +const get = require('lodash.get'); // ensure this is required *after* the demo server, since this will // configure our fake configuration too @@ -225,7 +227,7 @@ if (!isWindows) { }); const req = server.popRequest(); t.match(req.url, '/monitor/npm/graph', 'puts at correct url'); - t.true(!_.isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); + t.true(!isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); t.deepEqual( req.body.meta.missingDeps, ['body-parser@^1.18.2'], @@ -323,7 +325,7 @@ if (!isWindows) { const req = server.popRequest(); t.equal(req.method, 'PUT', 'makes PUT request'); t.match(req.url, '/monitor/npm/graph', 'puts at correct url'); - t.true(!_.isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); + t.true(!isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); }); test('`monitor npm-package-pruneable --experimental-dep-graph`', async (t) => { @@ -335,7 +337,7 @@ if (!isWindows) { const req = server.popRequest(); t.equal(req.method, 'PUT', 'makes PUT request'); t.match(req.url, '/monitor/npm/graph', 'puts at correct url'); - t.true(!_.isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); + t.true(!isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); }); test('`monitor npm-package-pruneable experimental for no-flag org`', async (t) => { @@ -377,7 +379,7 @@ if (!isWindows) { const req = server.popRequest(); t.equal(req.method, 'PUT', 'makes PUT request'); t.match(req.url, '/monitor/sbt/graph', 'puts at correct url'); - t.true(!_.isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); + t.true(!isEmpty(req.body.depGraphJSON), 'sends depGraphJSON'); if (process.platform === 'win32') { t.true( req.body.targetFileRelativePath.endsWith( @@ -1904,7 +1906,7 @@ if (!isWindows) { json: true, }); const res = JSON.parse(response); - if (_.isObject(res)) { + if (isObject(res)) { t.pass('monitor outputted JSON'); } else { t.fail('Failed parsing monitor JSON output'); @@ -1914,7 +1916,7 @@ if (!isWindows) { t.equal(res.length, 2, 'Two monitor responses in the array'); res.forEach((project) => { keyList.forEach((k) => { - !_.get(project, k) ? t.fail(k + 'not found') : t.pass(k + ' found'); + !get(project, k) ? t.fail(k + 'not found') : t.pass(k + ' found'); }); }); } catch (error) { diff --git a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts index c350d9ac9d..b353d293f5 100644 --- a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts +++ b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts @@ -1,5 +1,6 @@ import * as sinon from 'sinon'; -import * as _ from 'lodash'; +const get = require('lodash.get'); +const isObject = require('lodash.isobject'); import * as path from 'path'; import * as depGraphLib from '@snyk/dep-graph'; @@ -421,7 +422,7 @@ export const AllProjectsTests: AcceptanceTests = { ); jsonResponse.forEach((res) => { - if (_.isObject(res)) { + if (isObject(res)) { t.pass('monitor outputted JSON'); } else { t.fail('Failed parsing monitor JSON output'); @@ -436,7 +437,7 @@ export const AllProjectsTests: AcceptanceTests = { ]; keyList.forEach((k) => { - !_.get(res, k) ? t.fail(k + ' not found') : t.pass(k + ' found'); + !get(res, k) ? t.fail(k + ' not found') : t.pass(k + ' found'); }); }); } catch (error) { diff --git a/test/acceptance/cli-test/cli-test.ruby.spec.ts b/test/acceptance/cli-test/cli-test.ruby.spec.ts index 163bc96a83..0a27935196 100644 --- a/test/acceptance/cli-test/cli-test.ruby.spec.ts +++ b/test/acceptance/cli-test/cli-test.ruby.spec.ts @@ -1,4 +1,5 @@ -import * as _ from 'lodash'; +const omit = require('lodash.omit'); +const sortBy = require('lodash.sortby'); import { AcceptanceTests } from './cli-test.acceptance.test'; import { getWorkspaceJSON } from '../workspace-helper'; import { CommandResult } from '../../../src/cli/commands/types'; @@ -269,13 +270,13 @@ export const RubyTests: AcceptanceTests = { ); t.deepEqual( - _.omit(res, ['vulnerabilities']), - _.omit(expected, ['vulnerabilities']), + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), 'metadata is ok', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } @@ -368,13 +369,13 @@ export const RubyTests: AcceptanceTests = { ); t.deepEqual( - _.omit(res, ['vulnerabilities']), - _.omit(expected, ['vulnerabilities']), + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), 'metadata is ok', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } @@ -443,13 +444,13 @@ export const RubyTests: AcceptanceTests = { ); t.deepEqual( - _.omit(res, ['vulnerabilities']), - _.omit(expected, ['vulnerabilities']), + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), 'metadata is ok', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } @@ -476,13 +477,13 @@ export const RubyTests: AcceptanceTests = { ); t.deepEqual( - _.omit(res, ['vulnerabilities']), - _.omit(expected, ['vulnerabilities']), + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), 'metadata is ok', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } @@ -514,13 +515,13 @@ export const RubyTests: AcceptanceTests = { ); t.deepEqual( - _.omit(res, ['vulnerabilities']), - _.omit(expected, ['vulnerabilities']), + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), 'metadata is ok', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } diff --git a/test/acceptance/cli-test/cli-test.sbt.spec.ts b/test/acceptance/cli-test/cli-test.sbt.spec.ts index 4d6c1a0ddd..6c9a27ae47 100644 --- a/test/acceptance/cli-test/cli-test.sbt.spec.ts +++ b/test/acceptance/cli-test/cli-test.sbt.spec.ts @@ -1,7 +1,8 @@ import * as sinon from 'sinon'; import { AcceptanceTests } from './cli-test.acceptance.test'; -import * as _ from 'lodash'; +const omit = require('lodash.omit'); +const sortBy = require('lodash.sortby'); export const SbtTests: AcceptanceTests = { language: 'SBT', @@ -38,8 +39,8 @@ export const SbtTests: AcceptanceTests = { const expected = require('../workspaces/sbt-simple-struts/legacy-res-json.json'); t.deepEqual( - _.omit(res, ['vulnerabilities', 'packageManager']), - _.omit(expected, ['vulnerabilities', 'packageManager']), + omit(res, ['vulnerabilities', 'packageManager']), + omit(expected, ['vulnerabilities', 'packageManager']), 'metadata is ok', ); // NOTE: decided to keep this discrepancy @@ -49,8 +50,8 @@ export const SbtTests: AcceptanceTests = { 'pacakgeManager is sbt, altough it was mavn with the legacy api', ); t.deepEqual( - _.sortBy(res.vulnerabilities, 'id'), - _.sortBy(expected.vulnerabilities, 'id'), + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), 'vulns are the same', ); } diff --git a/test/acceptance/cli-test/iac/cli-test.iac-k8s.spec.ts b/test/acceptance/cli-test/iac/cli-test.iac-k8s.spec.ts index eaa100b639..51db1cf86c 100644 --- a/test/acceptance/cli-test/iac/cli-test.iac-k8s.spec.ts +++ b/test/acceptance/cli-test/iac/cli-test.iac-k8s.spec.ts @@ -1,4 +1,3 @@ -import * as _ from 'lodash'; import { iacTest, iacTestJson, diff --git a/test/acceptance/cli-test/iac/cli-test.iac-utils.ts b/test/acceptance/cli-test/iac/cli-test.iac-utils.ts index c692822b9d..e8b23c6f77 100644 --- a/test/acceptance/cli-test/iac/cli-test.iac-utils.ts +++ b/test/acceptance/cli-test/iac/cli-test.iac-utils.ts @@ -1,4 +1,4 @@ -import * as _ from 'lodash'; +const sortBy = require('lodash.sortby'); import { mapIacTestResult, AnnotatedIacIssue, @@ -208,8 +208,8 @@ export function iacTestJsonAssertions( t.equal(results.cloudConfigResults, undefined); if (foundIssues) { t.deepEqual( - _.sortBy(results.infrastructureAsCodeIssues, 'id'), - _.sortBy(expectedResults.infrastructureAsCodeIssues, 'id'), + sortBy(results.infrastructureAsCodeIssues, 'id'), + sortBy(expectedResults.infrastructureAsCodeIssues, 'id'), 'issues are the same', ); } else { diff --git a/test/deduped-package-patch.test.ts b/test/deduped-package-patch.test.ts index 70917d1585..41c9a24b0d 100644 --- a/test/deduped-package-patch.test.ts +++ b/test/deduped-package-patch.test.ts @@ -1,5 +1,5 @@ import { test } from 'tap'; -import * as protect from '../src/lib/protect'; +const protect = require('../src/lib/protect'); import * as fs from 'fs'; test('npm deduped packages are found and patched correctly', async (t) => { diff --git a/test/monitor-target.test.ts b/test/monitor-target.test.ts index e4c209353f..de0cd94160 100644 --- a/test/monitor-target.test.ts +++ b/test/monitor-target.test.ts @@ -2,7 +2,7 @@ import { test, afterEach, afterAll } from 'tap'; import * as requestLib from 'needle'; import * as path from 'path'; -import * as _ from 'lodash'; +const isEmpty = require('lodash.isempty'); import * as sinon from 'sinon'; import * as cli from '../src/cli/commands'; @@ -52,9 +52,9 @@ test('Make sure that target is sent correctly', async (t) => { const { data } = await getFakeServerRequestBody(); t.true(requestSpy.calledTwice, 'needle.request was called once'); - t.true(!_.isEmpty(data.target), 'target passed to request'); + t.true(!isEmpty(data.target), 'target passed to request'); t.true( - !_.isEmpty(data.targetFileRelativePath), + !isEmpty(data.targetFileRelativePath), 'targetFileRelativePath passed to request', ); t.equals(data.target.branch, 'master', 'correct branch passed to request'); @@ -79,7 +79,7 @@ test("Make sure it's not failing monitor for non git projects", async (t) => { const { data } = await getFakeServerRequestBody(); t.true(requestSpy.calledTwice, 'needle.request was called once'); - t.true(_.isEmpty(data.target), 'empty target passed to request'); + t.true(isEmpty(data.target), 'empty target passed to request'); t.match( data.targetFileRelativePath, 'snyk' + path.sep + 'package.json', @@ -96,7 +96,7 @@ test("Make sure it's not failing if there is no remote configured", async (t) => const { data } = await getFakeServerRequestBody(); t.true(requestSpy.calledTwice, 'needle.request was called once'); - t.true(_.isEmpty(data.target), 'empty target passed to request'); + t.true(isEmpty(data.target), 'empty target passed to request'); t.match( data.targetFileRelativePath, 'snyk' + path.sep + 'package.json', diff --git a/test/prompts.test.ts b/test/prompts.test.ts index 317b8199cb..498c0b4978 100644 --- a/test/prompts.test.ts +++ b/test/prompts.test.ts @@ -1,9 +1,9 @@ import * as fs from 'fs'; import { test } from 'tap'; -import * as _ from 'lodash'; +const flattenDeep = require('lodash.flattendeep'); import * as path from 'path'; import * as sinon from 'sinon'; -import * as inquirer from 'inquirer'; +import * as inquirer from '@snyk/inquirer'; import wizard = require('../src/cli/commands/protect/wizard'); @@ -40,7 +40,7 @@ async function run(t, filename, offset = 0) { if (vulns.ok) { offset--; // since protect will be skipped if there's no vulns } - const prompts = _.flattenDeep(spy.args); + const prompts = flattenDeep(spy.args); t.equal( prompts.length, vulns.vulnerabilities.length * 2 + offset, diff --git a/test/protect-config.test.ts b/test/protect-config.test.ts index 969b6ae132..344cc669ea 100644 --- a/test/protect-config.test.ts +++ b/test/protect-config.test.ts @@ -1,4 +1,4 @@ -import * as protect from '../src/lib/protect'; +const protect = require('../src/lib/protect'); import { test } from 'tap'; import { loadJson } from './utils'; const plan = loadJson(__dirname + '/fixtures/protect-interactive.json'); diff --git a/test/protect-patch-skip.test.ts b/test/protect-patch-skip.test.ts index ba5aa13965..97a1f4b590 100644 --- a/test/protect-patch-skip.test.ts +++ b/test/protect-patch-skip.test.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import { exec } from 'child_process'; import { test } from 'tap'; -import * as protect from '../src/lib/protect'; +const protect = require('../src/lib/protect'); import { loadJson } from './utils'; const vulns = loadJson(__dirname + '/fixtures/lodash@4.17.11-vuln.json') diff --git a/test/protect-patch.test.ts b/test/protect-patch.test.ts index bcb274106d..06894d39b5 100644 --- a/test/protect-patch.test.ts +++ b/test/protect-patch.test.ts @@ -1,4 +1,4 @@ -import * as protect from '../src/lib/protect'; +const protect = require('../src/lib/protect'); import * as path from 'path'; import { test } from 'tap'; import * as fs from 'fs'; diff --git a/test/protect-semver-patch.test.ts b/test/protect-semver-patch.test.ts index 4e8848e0d0..a41e0c7928 100644 --- a/test/protect-semver-patch.test.ts +++ b/test/protect-semver-patch.test.ts @@ -1,6 +1,6 @@ import * as debugModule from 'debug'; const debug = debugModule('snyk'); -import * as protect from '../src/lib/protect'; +const protect = require('../src/lib/protect'); import * as path from 'path'; import { test } from 'tap'; // tslint:disable-next-line: no-var-requires diff --git a/test/utils.ts b/test/utils.ts index 5fd6269fe8..b7a8e11217 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,7 +1,7 @@ import { tmpdir } from 'os'; import { join } from 'path'; import { mkdir, readFileSync } from 'fs'; -import * as graphlib from 'graphlib'; +import * as graphlib from '@snyk/graphlib'; import { CallGraph } from '@snyk/cli-interface/legacy/common'; export function silenceLog() { diff --git a/test/wizard-instrumented.js b/test/wizard-instrumented.js index 4b70b48f6c..87080553b3 100644 --- a/test/wizard-instrumented.js +++ b/test/wizard-instrumented.js @@ -4,7 +4,7 @@ var proxyquire = require('proxyquire'); var sinon = require('sinon'); var spy; var wizard = proxyquire('../src/cli/commands/protect/wizard', { - inquirer: { + '@snyk/inquirer': { prompt: function(q, cb) { if (!cb) { cb = (_) => Promise.resolve(_); diff --git a/test/wizard-prepare.test.js b/test/wizard-prepare.test.js index f328650262..3c1ac4dee7 100644 --- a/test/wizard-prepare.test.js +++ b/test/wizard-prepare.test.js @@ -2,12 +2,12 @@ const test = require('tap').test; const proxyquire = require('proxyquire'); const sinon = require('sinon'); const spy = sinon.spy(); -const _ = require('lodash'); +const cloneDeep = require('lodash.clonedeep'); const dir = __dirname + '/fixtures/protect-via-snyk/'; const fixture = require('./fixtures/protect-via-snyk/package.json'); const wizard = proxyquire('../src/cli/commands/protect/wizard', { - inquirer: { + '@snyk/inquirer': { prompt: function(q, cb) { cb(q); }, @@ -34,7 +34,7 @@ const wizard = proxyquire('../src/cli/commands/protect/wizard', { }); test('npm - prepare is added and postinstall is removed', function(t) { - const expectedResults = _.cloneDeep(fixture); + const expectedResults = cloneDeep(fixture); process.chdir(dir); return wizard @@ -61,7 +61,7 @@ test('npm - prepare is added and postinstall is removed', function(t) { }); test('yarn - prepare is added and postinstall is removed', function(t) { - const expectedResults = _.cloneDeep(fixture); + const expectedResults = cloneDeep(fixture); process.chdir(dir); spy.resetHistory(); return wizard diff --git a/test/wizard-prepublish.test.js b/test/wizard-prepublish.test.js index f0c6849a43..37cbac9bb2 100644 --- a/test/wizard-prepublish.test.js +++ b/test/wizard-prepublish.test.js @@ -5,7 +5,7 @@ const spy = sinon.spy(); const fixture = require(__dirname + '/fixtures/protect-via-snyk/package.json'); var wizard = proxyquire('../src/cli/commands/protect/wizard', { - inquirer: { + '@snyk/inquirer': { prompt: function(q, cb) { cb(q); },