From 7a264eeeecb6557ae1507710760071f3525c2b33 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 7 Feb 2024 11:20:37 -0500 Subject: [PATCH 01/28] @W-14989109@: Restore plugin linkability by fixing a few imports --- package.json | 2 +- src/lib/DefaultRuleManager.ts | 2 +- src/lib/output/TableOutputFormatter.ts | 6 ++++-- yarn.lock | 7 ++++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 66ce561e6..ad4a79ad9 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@salesforce/eslint-config-lwc": "^3.2.1", "@salesforce/eslint-plugin-lightning": "^1.0.0", "@salesforce/sf-plugins-core": "^5.0.4", + "@types/wordwrap": "^1.0.3", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "cross-spawn": "^7.0.3", @@ -40,7 +41,6 @@ "typescript": "~5.1.0", "untildify": "^4.0.0", "uuid": "^9.0.0", - "word-wrap": "^1.2.3", "xml-js": "^1.6.11" }, "resolutions": { diff --git a/src/lib/DefaultRuleManager.ts b/src/lib/DefaultRuleManager.ts index 62e4ec78f..7b46e4bda 100644 --- a/src/lib/DefaultRuleManager.ts +++ b/src/lib/DefaultRuleManager.ts @@ -251,7 +251,7 @@ export class DefaultRuleManager implements RuleManager { const ruleTargets: RuleTarget[] = []; // Ask engines for their desired target patterns. const engineTargets = await engine.getTargetPatterns(); - assert(engineTargets); + assert.ok(engineTargets); // We also need to do a bit of processing on the patterns we were given. const positivePatterns: string[] = []; const negativePatterns: string[] = []; diff --git a/src/lib/output/TableOutputFormatter.ts b/src/lib/output/TableOutputFormatter.ts index b294db70b..a84103380 100644 --- a/src/lib/output/TableOutputFormatter.ts +++ b/src/lib/output/TableOutputFormatter.ts @@ -1,10 +1,12 @@ import {OutputFormatter, Results} from "./Results"; import {FormattedOutput, ResultTableRow, RuleResult} from "../../types"; import * as path from "path"; -import * as wrap from "word-wrap"; +import * as wordwrap from "wordwrap"; import {isPathlessViolation} from "../util/Utils"; import {Ux} from "@salesforce/sf-plugins-core"; +const WORDWRAP_LIMIT = 50; + const BASE_COLUMNS: Ux.Table.Columns = { description: {}, category: {}, @@ -47,7 +49,7 @@ export class TableOutputFormatter implements OutputFormatter { const relativeFile = path.relative(process.cwd(), fileName); // Instantiate our Row object. const baseRow: ResultTableRow = { - description: wrap(message), + description: wordwrap.hard(WORDWRAP_LIMIT)(message), category: violation.category, url: violation.url }; diff --git a/yarn.lock b/yarn.lock index 3c9dfa8a6..08e2405d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1311,6 +1311,11 @@ "@types/expect" "^1.20.4" "@types/node" "*" +"@types/wordwrap@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@types/wordwrap/-/wordwrap-1.0.3.tgz#1faf6e6002e8d63534bd9ad329a32bc772d4983e" + integrity sha512-jx39cOYWJxZxVOZeNHvLVoDLRUFcYtIJaurC6C0qzCovIB3GPDbMDbYvoWi9D1B2PtIE16rElQOFR4Y+8QbUgw== + "@typescript-eslint/eslint-plugin@^5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" @@ -7492,7 +7497,7 @@ winreg@~1.2.2: resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.5.tgz#b650383e89278952494b5d113ba049a5a4fa96d8" integrity sha512-uf7tHf+tw0B1y+x+mKTLHkykBgK2KMs3g+KlzmyMbLvICSHQyB/xOFjTT8qZ3oeTFyU7Bbj4FzXitGG6jvKhYw== -word-wrap@^1.2.3, word-wrap@~1.2.3: +word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== From 4466c60164bfb99131c7c252e8f2f27a4dea6dec Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Tue, 6 Feb 2024 16:02:26 -0500 Subject: [PATCH 02/28] @W-14980216@: [PMD7-Preview](Part 1) Refactor pmd and cpd engines to make it easy to swap PMD versions --- src/Constants.ts | 4 +- src/Controller.ts | 17 +++++++++ src/lib/cpd/CpdWrapper.ts | 12 ++---- src/lib/output/SarifOutputFormatter.ts | 6 +-- src/lib/pmd/PmdCommandInfo.ts | 45 +++++++++++++++++++++++ src/lib/pmd/PmdEngine.ts | 16 ++++++-- src/lib/pmd/PmdWrapper.ts | 19 +++------- test/lib/output/ResultsFormatting.test.ts | 4 +- test/lib/pmd/PmdEngine.test.ts | 4 +- 9 files changed, 94 insertions(+), 33 deletions(-) create mode 100644 src/lib/pmd/PmdCommandInfo.ts diff --git a/src/Constants.ts b/src/Constants.ts index 0e2c2eca3..f239b9e8e 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -1,7 +1,7 @@ import os = require('os'); import path = require('path'); -export const PMD_VERSION = '6.55.0'; +export const PMD6_VERSION = '6.55.0'; export const PMD_APPEXCHANGE_RULES_VERSION = '0.12'; export const SFGE_VERSION = '1.0.1-pilot'; export const DEFAULT_SCANNER_PATH = path.join(os.homedir(), '.sfdx-scanner'); @@ -132,7 +132,7 @@ export enum Severity { } // Here, current dir __dirname = /sfdx-scanner/src -export const PMD_LIB = path.join(__dirname, '..', 'dist', 'pmd', 'lib'); +export const PMD6_LIB = path.join(__dirname, '..', 'dist', 'pmd', 'lib'); // Here, current dir __dirname = /sfdx-scanner/src export const APPEXCHANGE_PMD_LIB = path.join(__dirname, '..', 'pmd-appexchange', 'lib'); diff --git a/src/Controller.ts b/src/Controller.ts index 3e69aef1d..de0637a0f 100644 --- a/src/Controller.ts +++ b/src/Controller.ts @@ -9,6 +9,7 @@ import {RuleEngine} from './lib/services/RuleEngine'; import {RulePathManager} from './lib/RulePathManager'; import {RuleCatalog} from './lib/services/RuleCatalog'; import {BundleName, getMessage} from "./MessageCatalog"; +import {Pmd6CommandInfo, PmdCommandInfo} from "./lib/pmd/PmdCommandInfo"; /** * Converts an array of RuleEngines to a sorted, comma delimited * string of their names. @@ -23,6 +24,14 @@ function enginesToString(engines: RuleEngine[]): string { // See https://stackoverflow.com/questions/137975/what-are-drawbacks-or-disadvantages-of-singleton-pattern +// We all should hate global state. But our team agreed that we have a bit of refactoring to do before we can more +// easily swap out the pmd version. So this is meant to be a temporary solution until we do that refactoring. +declare global { + // eslint-disable-next-line no-var + var _activePmdCommandInfo: PmdCommandInfo; +} +globalThis._activePmdCommandInfo = new Pmd6CommandInfo(); + // This is probably more appropriately called a ProviderFactory (Salesforce Core folks know this code smell all too well) export const Controller = { container, @@ -92,5 +101,13 @@ export const Controller = { } return engines; + }, + + setActivePmdCommandInfo(pmdCommandInfo: PmdCommandInfo): void { + globalThis._activePmdCommandInfo = pmdCommandInfo; + }, + + getActivePmdCommandInfo: (): PmdCommandInfo => { + return globalThis._activePmdCommandInfo; } }; diff --git a/src/lib/cpd/CpdWrapper.ts b/src/lib/cpd/CpdWrapper.ts index 0b40b5473..dba960a30 100644 --- a/src/lib/cpd/CpdWrapper.ts +++ b/src/lib/cpd/CpdWrapper.ts @@ -2,11 +2,9 @@ import {Logger} from '@salesforce/core'; import {FileHandler} from '../util/FileHandler'; import * as JreSetupManager from './../JreSetupManager'; import path = require('path'); -import { PMD_LIB } from '../../Constants'; import { CommandLineSupport} from '../services/CommandLineSupport'; - -const MAIN_CLASS = 'net.sourceforge.pmd.cpd.CPD'; -const HEAP_SIZE = '-Xmx1024m'; +import {Controller} from "../../Controller"; +import {PmdCommandInfo} from "../pmd/PmdCommandInfo"; interface CpdWrapperOptions { path: string; @@ -36,14 +34,12 @@ export default class CpdWrapper extends CommandLineSupport { const javaHome = await JreSetupManager.verifyJreSetup(); const command = path.join(javaHome, 'bin', 'java'); - const classpath = [`${PMD_LIB}/*`]; - const fileHandler = new FileHandler(); const tmpPath = await fileHandler.tmpFileWithCleanup(); await fileHandler.writeFile(tmpPath, this.path); - const args = ['-cp', classpath.join(path.delimiter), HEAP_SIZE, MAIN_CLASS, '--filelist', tmpPath, - '--format', 'xml', '--minimum-tokens', String(this.minimumTokens), '--language', this.language]; + const pmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo(); + const args: string[] = pmdCommandInfo.constructJavaCommandArgsForCpd(tmpPath, this.minimumTokens, this.language) this.logger.trace(`Preparing to execute CPD with command: "${command}", args: "${JSON.stringify(args)}"`); return [command, args]; diff --git a/src/lib/output/SarifOutputFormatter.ts b/src/lib/output/SarifOutputFormatter.ts index 7c8ba0908..ebbadb087 100644 --- a/src/lib/output/SarifOutputFormatter.ts +++ b/src/lib/output/SarifOutputFormatter.ts @@ -5,7 +5,7 @@ import {deepCopy, isPathlessViolation} from "../util/Utils"; import * as url from "url"; import {RuleCatalog} from "../services/RuleCatalog"; import {ESLint} from "eslint"; -import {ENGINE, PMD_VERSION, SFGE_VERSION} from "../../Constants"; +import {ENGINE, SFGE_VERSION} from "../../Constants"; import {Controller} from "../../Controller"; import * as retire from 'retire'; @@ -256,7 +256,7 @@ class PMDSarifFormatter extends SarifFormatter { tool: { driver: { name: ENGINE.PMD, - version: PMD_VERSION, + version: Controller.getActivePmdCommandInfo().getVersion(), informationUri: 'https://pmd.github.io/pmd', rules: [] } @@ -278,7 +278,7 @@ class CPDSarifFormatter extends SarifFormatter { tool: { driver: { name: ENGINE.CPD, - version: PMD_VERSION, /*CPD would use the same PMD version*/ + version: Controller.getActivePmdCommandInfo().getVersion(), /*CPD would use the same PMD version*/ informationUri: 'https://pmd.github.io/latest/pmd_userdocs_cpd.html', rules: [] } diff --git a/src/lib/pmd/PmdCommandInfo.ts b/src/lib/pmd/PmdCommandInfo.ts new file mode 100644 index 000000000..5a3017343 --- /dev/null +++ b/src/lib/pmd/PmdCommandInfo.ts @@ -0,0 +1,45 @@ +import {PMD6_LIB, PMD6_VERSION} from "../../Constants"; +import * as path from 'path'; + +const PMD6_MAIN_CLASS = 'net.sourceforge.pmd.PMD'; +const CPD6_MAIN_CLASS = 'net.sourceforge.pmd.cpd.CPD'; +const HEAP_SIZE = '-Xmx1024m'; + +export interface PmdCommandInfo { + getVersion(): string + + getJarPathForLanguage(lang: string): string + + constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string): string[] + + constructJavaCommandArgsForCpd(fileList: string, minimumTokens: number, language: string): string[] +} + +export class Pmd6CommandInfo implements PmdCommandInfo { + getVersion(): string { + return PMD6_VERSION; + } + + getJarPathForLanguage(language: string): string { + return path.join(PMD6_LIB, `pmd-${language}-${this.getVersion()}.jar`); + } + + constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string): string[] { + // The classpath needs PMD's lib folder. There may be redundancy with the shared classpath, but having the + // same JAR in the classpath twice is fine. Also note that the classpath is not wrapped in quotes like how it + // would be if we invoked directly through the CLI, because child_process.spawn() hates that. + const classpath = classPathsForExternalRules.concat([`${PMD6_LIB}/*`]).join(path.delimiter); + const args = ['-cp', classpath, HEAP_SIZE, PMD6_MAIN_CLASS, '-filelist', fileList, + '-format', 'xml']; + if (rulesets.length > 0) { + args.push('-rulesets', rulesets); + } + return args; + } + + constructJavaCommandArgsForCpd(fileList: string, minimumTokens: number, language: string): string[] { + const classpath = `${PMD6_LIB}/*`; + return ['-cp', classpath, HEAP_SIZE, CPD6_MAIN_CLASS, '--filelist', fileList, + '--format', 'xml', '--minimum-tokens', String(minimumTokens), '--language', language]; + } +} diff --git a/src/lib/pmd/PmdEngine.ts b/src/lib/pmd/PmdEngine.ts index 7f46fc588..2622a84ab 100644 --- a/src/lib/pmd/PmdEngine.ts +++ b/src/lib/pmd/PmdEngine.ts @@ -1,10 +1,18 @@ import {Logger, SfError} from '@salesforce/core'; import {Element, xml2js} from 'xml-js'; import {Controller} from '../../Controller'; -import {Catalog, Rule, RuleGroup, RuleResult, RuleTarget, RuleViolation, TargetPattern} from '../../types'; +import { + Catalog, + Rule, + RuleGroup, + RuleResult, + RuleTarget, + RuleViolation, + TargetPattern +} from '../../types'; import {AbstractRuleEngine} from '../services/RuleEngine'; import {Config} from '../util/Config'; -import {APPEXCHANGE_PMD_LIB, PMD_APPEXCHANGE_RULES_VERSION, CUSTOM_CONFIG, ENGINE, EngineBase, HARDCODED_RULES, PMD_LIB, PMD_VERSION, Severity} from '../../Constants'; +import {APPEXCHANGE_PMD_LIB, PMD_APPEXCHANGE_RULES_VERSION, CUSTOM_CONFIG, ENGINE, EngineBase, HARDCODED_RULES, Severity} from '../../Constants'; import {PmdCatalogWrapper} from './PmdCatalogWrapper'; import PmdWrapper from './PmdWrapper'; import {EVENTS, uxEvents} from "../ScannerEvents"; @@ -628,10 +636,12 @@ export class _PmdRuleMapper extends AsyncCreatable { const rulePathsByLanguage = new Map>(); // Add the default PMD jar for each activated language. (await PmdLanguageManager.getSupportedLanguages()).forEach(language => { - const pmdJarPath = path.join(PMD_LIB, `pmd-${language}-${PMD_VERSION}.jar`); const rulePaths = rulePathsByLanguage.get(language) || new Set(); + + const pmdJarPath = Controller.getActivePmdCommandInfo().getJarPathForLanguage(language); rulePaths.add(pmdJarPath); this.logger.trace(`Adding JAR ${pmdJarPath}, the default PMD JAR for language ${language}`); + rulePathsByLanguage.set(language, rulePaths); }); diff --git a/src/lib/pmd/PmdWrapper.ts b/src/lib/pmd/PmdWrapper.ts index dc59c528e..d0dba5625 100644 --- a/src/lib/pmd/PmdWrapper.ts +++ b/src/lib/pmd/PmdWrapper.ts @@ -1,12 +1,10 @@ import {Logger} from '@salesforce/core'; -import {PMD_LIB} from '../../Constants'; import {PmdSupport, PmdSupportOptions} from './PmdSupport'; import * as JreSetupManager from './../JreSetupManager'; import path = require('path'); import {FileHandler} from '../util/FileHandler'; - -const MAIN_CLASS = 'net.sourceforge.pmd.PMD'; -const HEAP_SIZE = '-Xmx1024m'; +import {Controller} from "../../Controller"; +import {PmdCommandInfo} from "./PmdCommandInfo"; type PmdWrapperOptions = PmdSupportOptions & { targets: string[]; @@ -49,21 +47,16 @@ export default class PmdWrapper extends PmdSupport { const javaHome = await JreSetupManager.verifyJreSetup(); const command = path.join(javaHome, 'bin', 'java'); - // The classpath needs PMD's lib folder. There may be redundancy with the shared classpath, but having the - // same JAR in the classpath twice is fine. Also note that the classpath is not wrapped in quotes like how it - // would be if we invoked directly through the CLI, because child_process.spawn() hates that. - const classpath = [...this.supplementalClasspath, `${PMD_LIB}/*`, ...this.buildSharedClasspath()].join(path.delimiter); // Operating systems impose limits on the maximum length of a command line invocation. This can be problematic // when scanning a large number of files. Store the list of files to scan in a temp file. Pass the location // of the temp file to PMD. The temp file is cleaned up when the process exits. const fileHandler = new FileHandler(); const tmpPath = await fileHandler.tmpFileWithCleanup(); await fileHandler.writeFile(tmpPath, this.targets.join(',')); - const args = ['-cp', classpath, HEAP_SIZE, MAIN_CLASS, '-filelist', tmpPath, - '-format', 'xml']; - if (this.rules.length > 0) { - args.push('-rulesets', this.rules); - } + + const pmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo(); + const classPathsForExternalRules: string[] = this.buildSharedClasspath().concat(this.supplementalClasspath); + const args: string[] = pmdCommandInfo.constructJavaCommandArgsForPmd(tmpPath, classPathsForExternalRules, this.rules); this.logger.trace(`Preparing to execute PMD with command: "${command}", args: "${JSON.stringify(args)}"`); return [command, args]; diff --git a/test/lib/output/ResultsFormatting.test.ts b/test/lib/output/ResultsFormatting.test.ts index 9c3265a6e..0a5763b71 100644 --- a/test/lib/output/ResultsFormatting.test.ts +++ b/test/lib/output/ResultsFormatting.test.ts @@ -6,7 +6,7 @@ import path = require('path'); import * as csvParse from 'csv-parse'; import {parseString} from 'xml2js'; import * as TestOverrides from '../../test-related-lib/TestOverrides'; -import { PathlessEngineFilters, ENGINE, PMD_VERSION, SFGE_VERSION } from '../../../src/Constants'; +import { PathlessEngineFilters, ENGINE, PMD6_VERSION, SFGE_VERSION } from '../../../src/Constants'; import { fail } from 'assert'; import {Results, RunResults} from "../../../src/lib/output/Results"; import { OutputFormat } from '../../../src/lib/output/OutputFormat'; @@ -517,7 +517,7 @@ describe('Results Formatting', () => { function validatePMDSarif(run: unknown, normalizeSeverity: boolean): void { const driver = run['tool']['driver']; expect(driver.name).to.equal('pmd'); - expect(driver.version).to.equal(PMD_VERSION); + expect(driver.version).to.equal(PMD6_VERSION); expect(driver.informationUri).to.equal('https://pmd.github.io/pmd'); // tool.driver.rules diff --git a/test/lib/pmd/PmdEngine.test.ts b/test/lib/pmd/PmdEngine.test.ts index c7a0398fb..8ce58784f 100644 --- a/test/lib/pmd/PmdEngine.test.ts +++ b/test/lib/pmd/PmdEngine.test.ts @@ -7,7 +7,7 @@ import Sinon = require('sinon'); import {PmdEngine, _PmdRuleMapper} from '../../../src/lib/pmd/PmdEngine' import {uxEvents, EVENTS} from '../../../src/lib/ScannerEvents'; import * as TestOverrides from '../../test-related-lib/TestOverrides'; -import {CUSTOM_CONFIG, ENGINE, LANGUAGE, PMD_VERSION} from '../../../src/Constants'; +import {CUSTOM_CONFIG, ENGINE, LANGUAGE, PMD6_VERSION} from '../../../src/Constants'; import * as DataGenerator from '../eslint/EslintTestDataGenerator'; import {BundleName, getMessage} from "../../../src/MessageCatalog"; import {Config} from "../../../src/lib/util/Config"; @@ -412,7 +412,7 @@ describe('_PmdRuleMapper', () => { const validJar = 'jar-that-exists.jar'; const missingJar = 'jar-that-is-missing.jar'; // This jar is automatically included by the PmdCatalogWrapper - const pmdJar = path.resolve(path.join('dist', 'pmd', 'lib', `pmd-java-${PMD_VERSION}.jar`)); + const pmdJar = path.resolve(path.join('dist', 'pmd', 'lib', `pmd-java-${PMD6_VERSION}.jar`)); let uxSpy = null; before(() => { From 4d7991c79f8eaeb3f15f560678bfb596aa57bae6 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 7 Feb 2024 10:26:33 -0500 Subject: [PATCH 03/28] @W-14980258@: Add pmd7 download, install, and cleanup tasks to our gradle build --- pmd-cataloger/build.gradle.kts | 147 ++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 46 deletions(-) diff --git a/pmd-cataloger/build.gradle.kts b/pmd-cataloger/build.gradle.kts index 66f2d6bd7..1495a4a96 100644 --- a/pmd-cataloger/build.gradle.kts +++ b/pmd-cataloger/build.gradle.kts @@ -10,51 +10,11 @@ plugins { group = "sfdx" version = "1.0" -val distDir = "$buildDir/../../dist" -val pmdVersion = "6.55.0" -val pmdFile = "pmd-bin-$pmdVersion.zip" -val pmdUrl = "https://github.com/pmd/pmd/releases/download/pmd_releases%2F${pmdVersion}/${pmdFile}" -val skippableJarRegexes = setOf("""^common_[\d\.-]*\.jar""".toRegex(), - """^fastparse.*\.jar""".toRegex(), - """^groovy.*\.jar""".toRegex(), - """^lenses.*\.jar""".toRegex(), - """^parsers.*\.jar""".toRegex(), - """^pmd-(cpp|cs|dart|fortran|go|groovy|jsp|kotlin|lua|matlab|modelica|objectivec|perl|php|plsql|python|ruby|scala|swift|ui)[-_\d\.]*\.jar""".toRegex(), - """^protobuf-java-[\d\.]*\.jar""".toRegex(), - """^scala.*\.jar""".toRegex(), - """^sourcecode_[\d\.-]*\.jar""".toRegex(), - """^trees_[\d\.-]*\.jar""".toRegex() -) - repositories { mavenCentral() google() } -jacoco { - toolVersion = "0.8.7" -} - -tasks.register("downloadPmd") { - src(pmdUrl) - dest(buildDir) - overwrite(false) -} - -tasks.register("installPmd") { - dependsOn("downloadPmd") - from(zipTree("$buildDir/$pmdFile")) - exclude { details: FileTreeElement -> - skippableJarRegexes.any {it.containsMatchIn(details.file.name)} - } - into("$distDir/pmd") - // TODO include("just the *.jars etc. we care about") - includeEmptyDirs = false - eachFile { - relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) - } -} - dependencies { implementation(project(":cli-messaging")) implementation ("com.googlecode.json-simple:json-simple:1.1.1") { @@ -73,25 +33,120 @@ dependencies { testImplementation(files("$buildDir/../../test/test-jars/apex/testjar-categories-and-rulesets-1.jar")) } + +// ======== MODIFY PLUGIN PROPERTIES =================================================================================== java.sourceCompatibility = JavaVersion.VERSION_1_8 application { mainClass.set("sfdc.sfdx.scanner.pmd.Main"); } -// Running the cli locally needs the dist exploded, so just do that -// automatically with build for ease of use. +jacoco { + toolVersion = "0.8.7" +} + +val distDir = "$buildDir/../../dist" + + +// ======== DEFINE/UPDATE PMD-CATALOGER DIST RELATED TASKS ============================================================= +val pmdCatalogerDistDir = "$distDir/pmd-cataloger" + tasks.named("installDist") { - into("$distDir/pmd-cataloger") + // The installDist task comes with the distribution plugin which comes with the applciation plugin. We modify it here: + into(pmdCatalogerDistDir) +} + +tasks.register("deletePmdCatalogerDist") { + delete(pmdCatalogerDistDir) +} + +// ======== DEFINE/UPDATE PMD6 DIST RELATED TASKS ===================================================================== +val pmd6DistDir = "$distDir/pmd" +val pmd6Version = "6.55.0" +val pmd6File = "pmd-bin-$pmd6Version.zip" + +tasks.register("downloadPmd6") { + src("https://github.com/pmd/pmd/releases/download/pmd_releases%2F${pmd6Version}/${pmd6File}") + dest(buildDir) + overwrite(false) +} + +tasks.register("installPmd6") { + dependsOn("downloadPmd6") + from(zipTree("$buildDir/$pmd6File")) + + val skippablePmd6JarRegexes = setOf("""^common_[\d\.-]*\.jar""".toRegex(), + """^fastparse.*\.jar""".toRegex(), + """^groovy.*\.jar""".toRegex(), + """^lenses.*\.jar""".toRegex(), + """^parsers.*\.jar""".toRegex(), + """^pmd-(cpp|cs|dart|fortran|go|groovy|jsp|kotlin|lua|matlab|modelica|objectivec|perl|php|plsql|python|ruby|scala|swift|ui)[-_\d\.]*\.jar""".toRegex(), + """^protobuf-java-[\d\.]*\.jar""".toRegex(), + """^scala.*\.jar""".toRegex(), + """^sourcecode_[\d\.-]*\.jar""".toRegex(), + """^trees_[\d\.-]*\.jar""".toRegex() + ) + exclude { details: FileTreeElement -> + skippablePmd6JarRegexes.any {it.containsMatchIn(details.file.name)} + } + + into(pmd6DistDir) + // TODO include("just the *.jars etc. we care about") + includeEmptyDirs = false + eachFile { + // We drop the parent "pmd-bin-6.55.0" folder and put files directly into our "pmd" folder + relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) + } +} + +tasks.register("deletePmd6Dist") { + delete(pmd6DistDir) +} + + +// ======== DEFINE/UPDATE PMD7 DIST RELATED TASKS ===================================================================== +val pmd7DistDir = "$distDir/pmd7" +val pmd7Version = "7.0.0-rc4" +val pmd7File = "pmd-dist-$pmd7Version-bin.zip" + +tasks.register("downloadPmd7") { + src("https://github.com/pmd/pmd/releases/download/pmd_releases%2F${pmd7Version}/${pmd7File}") + dest(buildDir) + overwrite(false) +} + +tasks.register("installPmd7") { + dependsOn("downloadPmd7") + from(zipTree("$buildDir/$pmd7File")) + // TODO: We will soon optimize this with W-14980337 by reducing the dist down to only the jars we care about. + into(pmd7DistDir) + includeEmptyDirs = false + eachFile { + // We drop the parent "pmd-bin-7.0.0-rc4" folder and put files directly into our "pmd7" folder + relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) + } +} + +tasks.register("deletePmd7Dist") { + delete(pmd7DistDir) } -tasks.named("assemble") { - // TODO: These currently do not get cleaned with ./gradlew clean which can cause a lot of confusion. +// ======== ATTACH TASKS TO ASSEMBLE AND CLEAN ======================================================================== +tasks.assemble { dependsOn("installDist") - dependsOn("installPmd") + dependsOn("installPmd6") + dependsOn("installPmd7") +} + +tasks.clean { + dependsOn("deletePmdCatalogerDist") + dependsOn("deletePmd6Dist") + dependsOn("deletePmd7Dist") } + +// ======== TEST RELATED TASKS ========================================================================================= tasks.test { // Use JUnit 5 useJUnitPlatform() From 3fa79c1d18bd2cb95e0f8df732ca87436b5d98fc Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Thu, 8 Feb 2024 17:19:44 -0500 Subject: [PATCH 04/28] @W-14980290@: Implement Pmd7CommandInfo to allow us to call pmd7 jars --- src/Constants.ts | 2 + src/lib/Display.ts | 14 ++- src/lib/actions/RuleDescribeAction.ts | 24 ++-- src/lib/cpd/CpdEngine.ts | 8 +- src/lib/pmd/PmdCommandInfo.ts | 32 ++++- src/types.d.ts | 1 + test/commands/scanner/rule/describe.test.ts | 2 +- test/lib/FakeDisplay.ts | 11 ++ test/lib/actions/RuleDescribeAction.test.ts | 69 +++++++++++ test/lib/actions/RuleListAction.test.ts | 72 ++++++++++++ test/lib/actions/RunAction.test.ts | 124 ++++++++++++++++++++ test/lib/actions/fakes.ts | 41 +++++++ test/lib/output/ResultsFormatting.test.ts | 51 +++++--- test/lib/pmd/PmdEngine.test.ts | 24 +++- 14 files changed, 442 insertions(+), 33 deletions(-) create mode 100644 test/lib/actions/RuleDescribeAction.test.ts create mode 100644 test/lib/actions/RuleListAction.test.ts create mode 100644 test/lib/actions/RunAction.test.ts create mode 100644 test/lib/actions/fakes.ts diff --git a/src/Constants.ts b/src/Constants.ts index f239b9e8e..d0f86b934 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -2,6 +2,7 @@ import os = require('os'); import path = require('path'); export const PMD6_VERSION = '6.55.0'; +export const PMD7_VERSION = '7.0.0-rc4'; export const PMD_APPEXCHANGE_RULES_VERSION = '0.12'; export const SFGE_VERSION = '1.0.1-pilot'; export const DEFAULT_SCANNER_PATH = path.join(os.homedir(), '.sfdx-scanner'); @@ -133,6 +134,7 @@ export enum Severity { // Here, current dir __dirname = /sfdx-scanner/src export const PMD6_LIB = path.join(__dirname, '..', 'dist', 'pmd', 'lib'); +export const PMD7_LIB = path.join(__dirname, '..', 'dist', 'pmd7', 'lib'); // Here, current dir __dirname = /sfdx-scanner/src export const APPEXCHANGE_PMD_LIB = path.join(__dirname, '..', 'pmd-appexchange', 'lib'); diff --git a/src/lib/Display.ts b/src/lib/Display.ts index b42ed9ed2..e12fe449f 100644 --- a/src/lib/Display.ts +++ b/src/lib/Display.ts @@ -1,5 +1,6 @@ import {Spinner} from "@salesforce/sf-plugins-core"; import {Ux} from "@salesforce/sf-plugins-core/lib/ux"; +import {AnyJson} from "@salesforce/ts-types"; export interface Display { /** @@ -27,6 +28,11 @@ export interface Display { */ displayTable(data: R[], columns: Ux.Table.Columns): void; + /** + * Output object to stdout only if the "--json" flag is not present. + */ + displayStyledObject(obj: AnyJson): void; + /** * Display a message as a warning. */ @@ -91,6 +97,10 @@ export class UxDisplay implements Display { this.displayable.table(data, columns); } + public displayStyledObject(obj: AnyJson): void { + this.displayable.styledObject(obj); + } + public displayWarning(msg: string): void { this.displayable.warn(msg); } @@ -126,13 +136,15 @@ export interface Displayable { // Display an error or message as a warning. [Implemented by Command] warn(input: string): void; - // Simplified prompt for single-question confirmation. Times out and throws after 10s. [Implemented by SfCommand] confirm(message: string): Promise; // Output stylized header to stdout only when "--json" flag is not present. [Implemented by SfCommand] styledHeader(headerText: string): void; + // Output stylized object to stdout only when "--json" flag is not present. [Implemented by SfCommand] + styledObject(obj: AnyJson): void; + // Output table to stdout only when "--json" flag is not present. [Implemented by SfCommand] table(data: R[], columns: Ux.Table.Columns, options?: Ux.Table.Options): void; } diff --git a/src/lib/actions/RuleDescribeAction.ts b/src/lib/actions/RuleDescribeAction.ts index e8f87cff0..6221e9727 100644 --- a/src/lib/actions/RuleDescribeAction.ts +++ b/src/lib/actions/RuleDescribeAction.ts @@ -7,7 +7,6 @@ import {BundleName, getMessage} from "../../MessageCatalog"; import {deepCopy} from "../util/Utils"; import Dfa from "../../commands/scanner/run/dfa"; import Run from "../../commands/scanner/run"; -import {Ux} from "@salesforce/sf-plugins-core"; import {Display} from "../Display"; import {RuleFilterFactory} from "../RuleFilterFactory"; @@ -34,8 +33,6 @@ export class RuleDescribeAction implements Action { } public async run(inputs: Inputs): Promise { - const jsonEnabled: boolean = inputs.json as boolean; - const ruleFilters: RuleFilter[] = this.ruleFilterFactory.createRuleFilters(inputs); // TODO: Inject RuleManager as a dependency to improve testability by removing coupling to runtime implementation @@ -52,11 +49,11 @@ export class RuleDescribeAction implements Action { this.display.displayWarning(msg); rules.forEach((rule, idx) => { this.display.displayStyledHeader(`Rule #${idx + 1}`); - this.displayStyledRule(rule, jsonEnabled); + this.displayStyledRule(rule); }); } else { // If there's exactly one rule, we don't need to do anything special, and can just log the rule. - this.displayStyledRule(rules[0], jsonEnabled); + this.displayStyledRule(rules[0]); } // We need to return something for when the --json flag is used, so we'll just return the list of rules. return deepCopy(rules); @@ -87,9 +84,18 @@ export class RuleDescribeAction implements Action { }); } - private displayStyledRule(rule: DescribeStyledRule, jsonEnabled: boolean): void { - // TODO: We should remove this instantiation of new Ux in favor of possibly a new method on Display - new Ux({jsonEnabled: jsonEnabled}) - .styledObject(rule, ['name', 'engine', 'runWith', 'isPilot', 'enabled', 'categories', 'rulesets', 'languages', 'description', 'message']); + private displayStyledRule(rule: DescribeStyledRule): void { + this.display.displayStyledObject({ + name: rule.name, + engine: rule.engine, + runWith: rule.runWith, + isPilot: rule.isPilot, + enabled: rule.enabled, + categories: rule.categories, + rulesets: rule.rulesets, + languages: rule.languages, + description: rule.description, + message: rule.message + }) } } diff --git a/src/lib/cpd/CpdEngine.ts b/src/lib/cpd/CpdEngine.ts index 327c5019d..8688e35aa 100644 --- a/src/lib/cpd/CpdEngine.ts +++ b/src/lib/cpd/CpdEngine.ts @@ -216,10 +216,10 @@ export class CpdEngine extends AbstractRuleEngine { for (const occ of occurences) { // create a violation for each occurence of the code fragment const violation: RuleViolation = { - line: occ.attributes.line as number, - column: occ.attributes.column as number, - endLine: occ.attributes.endline as number, - endColumn: occ.attributes.endcolumn as number, + line: Number(occ.attributes.line), + column: Number(occ.attributes.column), + endLine: Number(occ.attributes.endline), + endColumn: Number(occ.attributes.endcolumn), ruleName: CpdRuleName, severity: CpdViolationSeverity, message: getMessage(BundleName.CpdEngine, "CpdViolationMessage", [codeFragmentID, occCount, occurences.length, duplication.attributes.lines, duplication.attributes.tokens]), diff --git a/src/lib/pmd/PmdCommandInfo.ts b/src/lib/pmd/PmdCommandInfo.ts index 5a3017343..a5aaa0610 100644 --- a/src/lib/pmd/PmdCommandInfo.ts +++ b/src/lib/pmd/PmdCommandInfo.ts @@ -1,8 +1,9 @@ -import {PMD6_LIB, PMD6_VERSION} from "../../Constants"; +import {PMD6_LIB, PMD6_VERSION, PMD7_LIB, PMD7_VERSION} from "../../Constants"; import * as path from 'path'; const PMD6_MAIN_CLASS = 'net.sourceforge.pmd.PMD'; const CPD6_MAIN_CLASS = 'net.sourceforge.pmd.cpd.CPD'; +const PMD7_CLI_CLASS = 'net.sourceforge.pmd.cli.PmdCli'; const HEAP_SIZE = '-Xmx1024m'; export interface PmdCommandInfo { @@ -40,6 +41,33 @@ export class Pmd6CommandInfo implements PmdCommandInfo { constructJavaCommandArgsForCpd(fileList: string, minimumTokens: number, language: string): string[] { const classpath = `${PMD6_LIB}/*`; return ['-cp', classpath, HEAP_SIZE, CPD6_MAIN_CLASS, '--filelist', fileList, - '--format', 'xml', '--minimum-tokens', String(minimumTokens), '--language', language]; + '--format', 'xml', '--minimum-tokens', minimumTokens.toString(), '--language', language]; + } +} + +export class Pmd7CommandInfo implements PmdCommandInfo { + getVersion(): string { + return PMD7_VERSION; + } + + getJarPathForLanguage(language: string): string { + return path.join(PMD7_LIB, `pmd-${language}-${this.getVersion()}.jar`); + } + + constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string): string[] { + const classpath = classPathsForExternalRules.concat([`${PMD7_LIB}/*`]).join(path.delimiter); + const args = ['-cp', classpath, HEAP_SIZE, PMD7_CLI_CLASS, 'check', '--file-list', fileList, + '--format', 'xml']; + if (rulesets.length > 0) { + args.push('--rulesets', rulesets); + } + return args; + } + + constructJavaCommandArgsForCpd(fileList: string, minimumTokens: number, language: string): string[] { + const classpath = `${PMD7_LIB}/*`; + const resolvedLanguage = language === 'visualforce' ? 'vf' : language; + return ['-cp', classpath, HEAP_SIZE, PMD7_CLI_CLASS, 'cpd', '--file-list', fileList, '--format', 'xml', + '--minimum-tokens', minimumTokens.toString(), '--language', resolvedLanguage, '--skip-lexical-errors']; } } diff --git a/src/types.d.ts b/src/types.d.ts index fa9a51219..21d9da770 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -18,6 +18,7 @@ export type Rule = { // be OR'd together in this property. defaultConfig?: ESRuleConfigValue; url?: string; + message?: string; } export type TelemetryData = { diff --git a/test/commands/scanner/rule/describe.test.ts b/test/commands/scanner/rule/describe.test.ts index 15cd92d0d..cdb914abe 100644 --- a/test/commands/scanner/rule/describe.test.ts +++ b/test/commands/scanner/rule/describe.test.ts @@ -60,7 +60,7 @@ describe('scanner rule describe', () => { expect(ctx.stderr.toLowerCase()).to.contain(`WARNING: ${formattedWarning}`.toLowerCase(), 'Warning message should be formatted correctly'); // Next, verify that there are rule descriptions that are distinctly identified. - const regex = /=== Rule #1\n\nname:\s+constructor-super(.*\n)*=== Rule #2\n\nname:\s+constructor-super(.*\n)*=== Rule #3\n\nname:\s+constructor-super/g; + const regex = /=== Rule #1\n(.*\n)*name:\s+constructor-super(.*\n)*=== Rule #2\n(.*\n)*name:\s+constructor-super(.*\n)*=== Rule #3\n(.*\n)*name:\s+constructor-super/g; expect(ctx.stdout).to.match(regex, 'Output should contain three rules named constructor-super for each eslint based engine'); }); diff --git a/test/lib/FakeDisplay.ts b/test/lib/FakeDisplay.ts index 3de33c141..b9ab12444 100644 --- a/test/lib/FakeDisplay.ts +++ b/test/lib/FakeDisplay.ts @@ -1,11 +1,13 @@ import {Display} from "../../src/lib/Display"; import {Ux} from "@salesforce/sf-plugins-core"; +import {AnyJson} from "@salesforce/ts-types"; export class FakeDisplay implements Display { private outputs: string[] = []; private confirmationPromptResponse: boolean = true; private lastTableColumns: Ux.Table.Columns; private lastTableData: Ux.Table.Data[]; + private lastStyledObject: AnyJson; public getOutputArray(): string[] { return this.outputs; @@ -27,6 +29,10 @@ export class FakeDisplay implements Display { return this.lastTableData; } + public getLastStyledObject(): AnyJson { + return this.lastStyledObject; + } + displayConfirmationPrompt(msg: string): Promise { this.outputs.push(msg); @@ -59,6 +65,11 @@ export class FakeDisplay implements Display { this.outputs.push("[Table][" + JSON.stringify(columns) + "]: " + JSON.stringify(data)); } + displayStyledObject(obj: AnyJson): void { + this.lastStyledObject = obj; + this.outputs.push(JSON.stringify(obj)) + } + spinnerStart(msg: string, status?: string): void { const statusText = status ? "[" + status + "]" : ""; this.outputs.push("[SpinnerStart]" + statusText + ": " + msg) diff --git a/test/lib/actions/RuleDescribeAction.test.ts b/test/lib/actions/RuleDescribeAction.test.ts new file mode 100644 index 000000000..23f5b508d --- /dev/null +++ b/test/lib/actions/RuleDescribeAction.test.ts @@ -0,0 +1,69 @@ +import {FakeDisplay} from "../FakeDisplay"; +import {initContainer} from "../../../src/ioc.config"; +import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; +import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; +import {after} from "mocha"; +import {Inputs} from "../../../src/types"; +import {expect} from "chai"; +import {RuleDescribeAction} from "../../../src/lib/actions/RuleDescribeAction"; +import {AnyJson} from "@salesforce/ts-types"; + +describe("Tests for RuleDescribeAction", () => { + let display: FakeDisplay; + let ruleDescribeAction: RuleDescribeAction; + before(() => { + initContainer(); + }); + beforeEach(() => { + display = new FakeDisplay(); + ruleDescribeAction = new RuleDescribeAction(display, new RuleFilterFactoryImpl()); + }); + + describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7 with pmd engine", () => { + + // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead + const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() + before(() => { + Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); + }); + after(() => { + Controller.setActivePmdCommandInfo(originalPmdCommandInfo); + }); + + it("When using PMD7, the rule description for a pmd rule should give correct info from PMD 7", async () => { + const inputs: Inputs = { + rulename: 'ApexCRUDViolation' + } + await ruleDescribeAction.run(inputs); + + const rule: AnyJson = display.getLastStyledObject(); + expect(rule['name']).to.equal('ApexCRUDViolation'); + expect(rule['engine']).to.equal('pmd'); + expect(rule['isPilot']).to.equal(false); + expect(rule['enabled']).to.equal(true); + expect(rule['categories']).to.deep.equal(['Security']); + expect(rule['rulesets']).to.contain('quickstart'); + expect(rule['languages']).to.deep.equal(['apex']); + expect(rule['description']).to.have.length.greaterThan(0); + expect(rule['message']).to.have.length.greaterThan(0); + }) + + it("When using PMD7, the rule description for a cpd rule should give back correct info from PMD 7", async () => { + const inputs: Inputs = { + rulename: 'copy-paste-detected' + } + await ruleDescribeAction.run(inputs); + + const rule: AnyJson = display.getLastStyledObject(); + expect(rule['name']).to.equal('copy-paste-detected'); + expect(rule['engine']).to.equal('cpd'); + expect(rule['isPilot']).to.equal(false); + expect(rule['enabled']).to.equal(false); + expect(rule['categories']).to.deep.equal(['Copy/Paste Detected']); + expect(rule['rulesets']).to.deep.equal([]); + expect(rule['languages']).to.deep.equal(['apex', 'java', 'visualforce', 'xml']); + expect(rule['description']).to.have.length.greaterThan(0); + }); + }); +}); diff --git a/test/lib/actions/RuleListAction.test.ts b/test/lib/actions/RuleListAction.test.ts new file mode 100644 index 000000000..c25849761 --- /dev/null +++ b/test/lib/actions/RuleListAction.test.ts @@ -0,0 +1,72 @@ +import {FakeDisplay} from "../FakeDisplay"; +import {initContainer} from "../../../src/ioc.config"; +import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; +import {RuleListAction} from "../../../src/lib/actions/RuleListAction"; +import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; +import {after} from "mocha"; +import {Inputs} from "../../../src/types"; +import {expect} from "chai"; +import {Ux} from "@salesforce/sf-plugins-core"; +import {PMD7_LIB} from "../../../src/Constants"; + +describe("Tests for RuleListAction", () => { + let display: FakeDisplay; + let ruleListAction: RuleListAction; + before(() => { + initContainer(); + }); + beforeEach(() => { + display = new FakeDisplay(); + ruleListAction = new RuleListAction(display, new RuleFilterFactoryImpl()); + }); + + describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7", () => { + + // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead + const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() + before(() => { + Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); + }); + after(() => { + Controller.setActivePmdCommandInfo(originalPmdCommandInfo); + }); + + it("When using PMD7, the rule list for the pmd engine should give back rules for PMD 7", async () => { + const inputs: Inputs = { + engine: ['pmd'] + } + await ruleListAction.run(inputs); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + expect(tableData).to.have.length(67); + for (const rowData of tableData) { + expect(rowData.engine).to.equal("pmd"); + expect(rowData.sourcepackage).to.contain(PMD7_LIB); + expect(rowData.name).to.have.length.greaterThan(0); + expect(rowData.categories).to.have.length.greaterThan(0); + expect(rowData.isDfa).to.equal(false); + expect(rowData.isPilot).to.equal(false); + expect(rowData.languages).to.have.length.greaterThan(0); + } + }) + + it("When using PMD7, the rule list for the cpd engine should give back the copy-paste-detected rule", async () => { + const inputs: Inputs = { + engine: ['cpd'] + } + await ruleListAction.run(inputs); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + expect(tableData).to.have.length(1); + expect(tableData[0].engine).to.equal("cpd"); + expect(tableData[0].sourcepackage).to.equal("cpd"); + expect(tableData[0].name).to.equal("copy-paste-detected"); + expect(tableData[0].categories).to.deep.equal(["Copy/Paste Detected"]); + expect(tableData[0].rulesets).to.deep.equal([]); + expect(tableData[0].isDfa).to.equal(false); + expect(tableData[0].isPilot).to.equal(false); + expect(tableData[0].languages).to.deep.equal(['apex', 'java', 'visualforce', 'xml']); + }); + }); +}); diff --git a/test/lib/actions/RunAction.test.ts b/test/lib/actions/RunAction.test.ts new file mode 100644 index 000000000..4fca40f42 --- /dev/null +++ b/test/lib/actions/RunAction.test.ts @@ -0,0 +1,124 @@ +import {InputProcessor, InputProcessorImpl} from "../../../src/lib/InputProcessor"; +import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; +import {RunEngineOptionsFactory} from "../../../src/lib/EngineOptionsFactory"; +import {RunAction} from "../../../src/lib/actions/RunAction"; +import {FakeDisplay} from "../FakeDisplay"; +import {Logger} from "@salesforce/core"; +import {Inputs, PathlessRuleViolation, RuleResult} from "../../../src/types"; +import * as path from "path"; +import {initContainer} from '../../../src/ioc.config'; +import {expect} from "chai"; +import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; +import {after} from "mocha"; +import {Results} from "../../../src/lib/output/Results"; +import {PMD6_VERSION, PMD7_VERSION} from "../../../src/Constants"; +import {FakeResultsProcessorFactory, RawResultsProcessor} from "./fakes"; + +const codeFixturesDir = path.join(__dirname, '..', '..', 'code-fixtures'); +const pathToSomeTestClass = path.join(codeFixturesDir, 'apex', 'SomeTestClass.cls'); +const pathToCodeForCpd = path.join(codeFixturesDir, 'cpd'); + + +describe("Tests for RunAction", () => { + let display: FakeDisplay; + let resultsProcessor: RawResultsProcessor; + let runAction: RunAction; + before(() => { + initContainer(); + }); + beforeEach(() => { + display = new FakeDisplay(); + resultsProcessor = new RawResultsProcessor(); + + const inputProcessor: InputProcessor = new InputProcessorImpl("2.11.8", display); + runAction = new RunAction( + Logger.childFromRoot("forTesting"), + display, + inputProcessor, + new RuleFilterFactoryImpl(), + new RunEngineOptionsFactory(inputProcessor), + new FakeResultsProcessorFactory(resultsProcessor)); + }); + + describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7", () => { + + // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead + const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() + before(() => { + Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); + }); + after(() => { + Controller.setActivePmdCommandInfo(originalPmdCommandInfo); + }); + + it("When using PMD7, the pmd engine actually uses PMD7 instead of PMD6", async () => { + const inputs: Inputs = { + target: [pathToSomeTestClass], + engine: ['pmd'], + 'normalize-severity': true + } + await runAction.run(inputs); + + const results: Results = resultsProcessor.getResults(); + expect(results.getExecutedEngines().size).to.equal(1); + expect(results.getExecutedEngines()).to.contain('pmd'); + const ruleResults: RuleResult[] = results.getRuleResults(); + expect(ruleResults).to.have.length(1); + expect(ruleResults[0].violations).to.have.length(8); + for (let violation of ruleResults[0].violations) { + violation = violation as PathlessRuleViolation; + + // Unfortunately, there isn't an easy way to detect that we are using PMD 7 binaries other than checking + // that the violation urls contain version 7 information instead of version 6. + expect(violation.url).to.contain(PMD7_VERSION); + expect(violation.url).not.to.contain(PMD6_VERSION); + + // Other sanity checks to make the fields are filled in + expect(violation.ruleName).to.have.length.greaterThan(0); + expect(violation.category).to.have.length.greaterThan(0); + expect(violation.line).to.be.greaterThan(0); + expect(violation.column).to.be.greaterThan(0); + expect(violation.message).to.have.length.greaterThan(0); + expect(violation.severity).to.be.greaterThanOrEqual(3); + expect(violation.normalizedSeverity).to.equal(3); + } + }); + + it("When using PMD7, the cpd engine actually uses PMD7 instead of PMD6", async () => { + const inputs: Inputs = { + target: [pathToCodeForCpd], + engine: ['cpd'], + 'normalize-severity': true + } + await runAction.run(inputs); + + const results: Results = resultsProcessor.getResults(); + expect(results.getExecutedEngines().size).to.equal(1); + expect(results.getExecutedEngines()).to.contain('cpd'); + const ruleResults: RuleResult[] = results.getRuleResults(); + expect(ruleResults).to.have.length(2); + expect(ruleResults[0].violations).to.have.length(1); + expect(ruleResults[1].violations).to.have.length(1); + const violation1: PathlessRuleViolation = ruleResults[0].violations[0] as PathlessRuleViolation; + const violation2: PathlessRuleViolation = ruleResults[1].violations[0] as PathlessRuleViolation; + + for (let violation of [violation1, violation2]) { + + // Unfortunately, there isn't an easy way to detect that we are using PMD 7 binaries. + // The best we can do is check for 'latest' in the url. + expect(violation.url).to.contain('latest'); + expect(violation.url).not.to.contain(PMD6_VERSION); + + // Other sanity checks to make the fields are filled in + expect(violation.ruleName).to.have.length.greaterThan(0); + expect(violation.category).to.have.length.greaterThan(0); + expect(violation.line).to.be.greaterThan(0); + expect(violation.column).to.be.greaterThan(0); + expect(violation.message).to.have.length.greaterThan(0); + expect(violation.severity).to.be.greaterThanOrEqual(3); + expect(violation.normalizedSeverity).to.equal(3); + } + }); + }); +}); diff --git a/test/lib/actions/fakes.ts b/test/lib/actions/fakes.ts new file mode 100644 index 000000000..e198733b5 --- /dev/null +++ b/test/lib/actions/fakes.ts @@ -0,0 +1,41 @@ +import {ResultsProcessorFactory} from "../../../src/lib/output/ResultsProcessorFactory"; +import {ResultsProcessor} from "../../../src/lib/output/ResultsProcessor"; +import {Display} from "../../../src/lib/Display"; +import {RunOutputOptions} from "../../../src/lib/output/RunResultsProcessor"; +import {JsonReturnValueHolder} from "../../../src/lib/output/JsonReturnValueHolder"; +import {Results} from "../../../src/lib/output/Results"; + + + +/** + * This fake does zero processing, but instead gives you the ability to access the raw results that were to be processed + */ +export class RawResultsProcessor implements ResultsProcessor { + private results: Results; + + processResults(results: Results): Promise { + this.results = results; + return Promise.resolve(); + } + + getResults(): Results { + return this.results; + } +} + + + +/** + * This fake just passes back whatever results processor you pass in. + */ +export class FakeResultsProcessorFactory implements ResultsProcessorFactory { + private readonly resultsProcessor: ResultsProcessor; + + constructor(resultsProcessor: ResultsProcessor) { + this.resultsProcessor = resultsProcessor + } + + createResultsProcessor(_d: Display, _r: RunOutputOptions, _j: JsonReturnValueHolder): ResultsProcessor { + return this.resultsProcessor + } +} diff --git a/test/lib/output/ResultsFormatting.test.ts b/test/lib/output/ResultsFormatting.test.ts index 0a5763b71..e828093b7 100644 --- a/test/lib/output/ResultsFormatting.test.ts +++ b/test/lib/output/ResultsFormatting.test.ts @@ -10,6 +10,9 @@ import { PathlessEngineFilters, ENGINE, PMD6_VERSION, SFGE_VERSION } from '../.. import { fail } from 'assert'; import {Results, RunResults} from "../../../src/lib/output/Results"; import { OutputFormat } from '../../../src/lib/output/OutputFormat'; +import {Controller} from "../../../lib/Controller"; +import {Pmd7CommandInfo, PmdCommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; +import {PMD7_VERSION} from "../../../lib/Constants"; const sampleFile1 = path.join('Users', 'SomeUser', 'samples', 'sample-file1.js'); const sampleFile2 = path.join('Users', 'SomeUser', 'samples', 'sample-file2.js'); @@ -303,6 +306,22 @@ const retireJsVerboseViolations: RuleResult[] = [ } ]; +function createSampleRuleResultsForEngine(engine: string): RuleResult[] { + return [{ + engine: engine, + fileName: sampleFile1, + violations: [{ + "line": 2, + "column": 11, + "severity": 2, + "message": "A generic message", + "ruleName": "rule-name", + "category": "category-name", + "url": "https://some/url.org" + }] + }]; +} + function isString(x: string | {columns; rows}): x is string { return typeof x === 'string'; } @@ -610,7 +629,6 @@ describe('Results Formatting', () => { } it ('Happy Path - pathless rules', async () => { - const results: Results = new RunResults(allFakePathlessRuleResults, new Set(['eslint', 'pmd'])); const formattedOutput: FormattedOutput = await results.toFormattedOutput(OutputFormat.SARIF, false); const minSev: number = results.getMinSev(); @@ -744,20 +762,7 @@ describe('Results Formatting', () => { it('Handles all pathless engines', async () => { const allEngines = PathlessEngineFilters.map(engine => engine.valueOf()); for (const engine of allEngines) { - const ruleResults: RuleResult[] = [{ - engine: engine, - fileName: sampleFile1, - violations: [{ - "line": 2, - "column": 11, - "severity": 2, - "message": "A generic message", - "ruleName": "rule-name", - "category": "category-name", - "url": "https://some/url.org" - }] - }]; - const results: Results = new RunResults(ruleResults, new Set([engine])); + const results: Results = new RunResults(createSampleRuleResultsForEngine(engine), new Set([engine])); await results.toFormattedOutput(OutputFormat.SARIF, false); // should throw an error if the engine was not handled } @@ -785,6 +790,22 @@ describe('Results Formatting', () => { } } }); + + it ('Switching to PMD7 is reflected in sarif output for pmd and cpd engines', async () => { + const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() + try { + Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); + for (const engine of ['pmd', 'cpd']) { + const results: Results = new RunResults(createSampleRuleResultsForEngine(engine), new Set([engine])); + const formattedOutput: FormattedOutput = await results.toFormattedOutput(OutputFormat.SARIF, false); + const sarifResults: unknown[] = JSON.parse(formattedOutput as string); + expect(sarifResults['runs']).to.have.lengthOf(1); + expect(sarifResults['runs'][0]['tool']['driver']['version']).to.equal(PMD7_VERSION); + } + } finally { + Controller.setActivePmdCommandInfo(originalPmdCommandInfo); + } + }) }); describe('Output Format: JSON', () => { diff --git a/test/lib/pmd/PmdEngine.test.ts b/test/lib/pmd/PmdEngine.test.ts index 8ce58784f..f9e03a81b 100644 --- a/test/lib/pmd/PmdEngine.test.ts +++ b/test/lib/pmd/PmdEngine.test.ts @@ -7,12 +7,14 @@ import Sinon = require('sinon'); import {PmdEngine, _PmdRuleMapper} from '../../../src/lib/pmd/PmdEngine' import {uxEvents, EVENTS} from '../../../src/lib/ScannerEvents'; import * as TestOverrides from '../../test-related-lib/TestOverrides'; -import {CUSTOM_CONFIG, ENGINE, LANGUAGE, PMD6_VERSION} from '../../../src/Constants'; +import {CUSTOM_CONFIG, ENGINE, LANGUAGE, PMD6_VERSION, PMD7_LIB, PMD7_VERSION} from '../../../src/Constants'; import * as DataGenerator from '../eslint/EslintTestDataGenerator'; import {BundleName, getMessage} from "../../../src/MessageCatalog"; import {Config} from "../../../src/lib/util/Config"; import {CustomRulePathManager} from "../../../src/lib/CustomRulePathManager"; import {after} from "mocha"; +import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; TestOverrides.initializeTestSetup(); @@ -450,4 +452,24 @@ describe('_PmdRuleMapper', () => { Sinon.assert.calledWith(uxSpy, EVENTS.WARNING_ALWAYS, `Custom rule file path [${missingJar}] for language [${LANGUAGE.JAVA}] was not found.`); }); }); + + describe('Using PMD7', async () => { + const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() + before(() => { + Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); + }); + after(() => { + Controller.setActivePmdCommandInfo(originalPmdCommandInfo); + }) + + it('PMD7 lib jar files are found correctly', async () => { + const mapper = await _PmdRuleMapper.create({}); + const ruleMap = await mapper.createStandardRuleMap(); + expect(ruleMap.size).to.greaterThan(0); + ruleMap.forEach((jars: Set, language: string) => { + expect(jars.size).to.equal(1); + expect(jars).to.contain(path.join(PMD7_LIB, `pmd-${language}-${PMD7_VERSION}.jar`)); + }) + }) + }); }); From b47bd2695e358d1be9119a1dace967f6f821ded6 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Mon, 12 Feb 2024 17:17:00 -0500 Subject: [PATCH 05/28] @W-14980337@: Optimize the pmd6 and pmd7 binary distributions --- pmd-cataloger/build.gradle.kts | 66 +++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/pmd-cataloger/build.gradle.kts b/pmd-cataloger/build.gradle.kts index 1495a4a96..28a07e36c 100644 --- a/pmd-cataloger/build.gradle.kts +++ b/pmd-cataloger/build.gradle.kts @@ -57,7 +57,7 @@ tasks.named("installDist") { } tasks.register("deletePmdCatalogerDist") { - delete(pmdCatalogerDistDir) + delete(pmdCatalogerDistDir) } // ======== DEFINE/UPDATE PMD6 DIST RELATED TASKS ===================================================================== @@ -75,23 +75,29 @@ tasks.register("installPmd6") { dependsOn("downloadPmd6") from(zipTree("$buildDir/$pmd6File")) - val skippablePmd6JarRegexes = setOf("""^common_[\d\.-]*\.jar""".toRegex(), - """^fastparse.*\.jar""".toRegex(), - """^groovy.*\.jar""".toRegex(), - """^lenses.*\.jar""".toRegex(), - """^parsers.*\.jar""".toRegex(), - """^pmd-(cpp|cs|dart|fortran|go|groovy|jsp|kotlin|lua|matlab|modelica|objectivec|perl|php|plsql|python|ruby|scala|swift|ui)[-_\d\.]*\.jar""".toRegex(), - """^protobuf-java-[\d\.]*\.jar""".toRegex(), - """^scala.*\.jar""".toRegex(), - """^sourcecode_[\d\.-]*\.jar""".toRegex(), - """^trees_[\d\.-]*\.jar""".toRegex() + // I went to https://github.com/pmd/pmd/tree/pmd_releases/6.55.0 and for each of the languages that we support + // (apex, java, visualforce, xml), I took a look at its pom file (like pmd-apex/src/pom.xml for example). + // That pom said what other modules it depends on and I listed these dependencies (besides test-scoped and optional + // modules). I did this recursively for any dependent pmd-* modules and put it all here. + // For completeness, I listed the modules and all their dependencies. Duplicates don't matter since we use setOf. + val pmd6ModulesToInclude = setOf( + // LANGUAGE MODULE DEPENDENCIES + "pmd-apex", "pmd-core", "antlr-runtime", "pmd-apex-jorje", "commons-lang3", + "pmd-java", "pmd-core", "saxon", "asm", "commons-lang3", + "pmd-visualforce", "pmd-core", "pmd-apex", + "pmd-xml", "pmd-core", "antlr4-runtime", "saxon", + // DEPENDENT MODULE DEPENDENCIES + "pmd-core", "antlr4-runtime", "jcommander", "saxon", "commons-lang3", "asm", "gson", + "pmd-apex-jorje", "cglib", "logback-classic", "logback-core", "jsr305", "gson", "error_prone_annotations", "guava", "j2objc-annotations", "antlr-runtime", "stringtemplate", "common-lang3", "animal-sniffer-annotations", "jol-core", "slf4j-api", "snakeyaml", "aopalliance", "javax.inject", "asm" ) - exclude { details: FileTreeElement -> - skippablePmd6JarRegexes.any {it.containsMatchIn(details.file.name)} + + val pmd6JarsToIncludeRegexes = mutableSetOf("""^LICENSE""".toRegex()) + pmd6ModulesToInclude.forEach { + pmd6JarsToIncludeRegexes.add("""^$it-.*\.jar""".toRegex()) } + include { details: FileTreeElement -> pmd6JarsToIncludeRegexes.any { it.containsMatchIn(details.file.name) } } into(pmd6DistDir) - // TODO include("just the *.jars etc. we care about") includeEmptyDirs = false eachFile { // We drop the parent "pmd-bin-6.55.0" folder and put files directly into our "pmd" folder @@ -118,7 +124,35 @@ tasks.register("downloadPmd7") { tasks.register("installPmd7") { dependsOn("downloadPmd7") from(zipTree("$buildDir/$pmd7File")) - // TODO: We will soon optimize this with W-14980337 by reducing the dist down to only the jars we care about. + + // I went to https://github.com/pmd/pmd/tree/pmd_releases/7.0.0-rc4 and for each of the languages that we support + // (apex, java, visualforce, xml), I took a look at its pom file (like pmd-apex/src/pom.xml for example). + // That pom said what other modules it depends on and I took these dependencies (besides test-scoped and optional + // modules). I did this recursively for any dependent pmd-* modules and put it all here. + // For completeness, I listed the modules and all their dependencies except for pmd-ui (since it isn't needed) and + // the dependencies of pmd-languages-deps (since it contains all language modules). I also had to add in pmd-cli. + // Note that "pkgforce_2.13" was missing from pmd-apex, so I added it in and that unfortunately required me to pull + // in all of its dependencies listed at https://central.sonatype.com/artifact/com.github.nawforce/pkgforce_2.13/dependencies. + // Duplicates don't matter since we use setOf. + val pmd7ModulesToInclude = setOf( + // LANGUAGE MODULE DEPENDENCIES + "pmd-apex", "pmd-core", "antlr-runtime", "pmd-apex-jorje", "apex-link", "commons-lang3", "guava", "pkgforce_2.13", + "pmd-java", "pmd-core", "asm", "commons-lang3", "checker-qual", "Saxon-HE", "pcollections", + "pmd-visualforce", "pmd-core", "pmd-apex", + "pmd-xml", "pmd-core", "antlr4-runtime", + // MAIN CLI MODULE DEPENDENCIES + "pmd-cli", "pmd-languages-deps", "slf4j-api", "slf4j-simple", "picocli", "progressbar", "checker-qual", + // DEPENDENT MODULE DEPENDENCIES + "pmd-core", "slf4j-api", "jul-to-slf4j", "antlr4-runtime", "Saxon-HE", "commons-lang3", "asm", "gson", "checker-qual", "pcollections", "nice-xml-messages", + "pmd-apex-jorje", "cglib", "jsr305", "gson", "error_prone_annotations", "guava", "j2objc-annotations", "antlr-runtime", "stringtemplate", "commons-lang3", "animal-sniffer-annotations", "slf4j-api", "aopalliance", "javax.inject", "asm", + "pkgforce_2.13", "scala-json-rpc-upickle-json-serializer_2.13", "scala-json-rpc_2.13", "geny_2.13", "ujson_2.13", "upack_2.13", "upickle-core_2.13", "upickle-implicits_2.13", "upickle_2.13", "apex-parser", "antlr4-runtime", "scala-collection-compat_2.13", "scala-xml_2.13", "scala-library", "scala-reflect" + ) + val pmd7JarsToIncludeRegexes = mutableSetOf("""^LICENSE""".toRegex()) + pmd7ModulesToInclude.forEach { + pmd7JarsToIncludeRegexes.add("""^$it-.*\.jar""".toRegex()) + } + + include { details: FileTreeElement -> pmd7JarsToIncludeRegexes.any { it.containsMatchIn(details.file.name) } } into(pmd7DistDir) includeEmptyDirs = false eachFile { @@ -140,7 +174,7 @@ tasks.assemble { } tasks.clean { - dependsOn("deletePmdCatalogerDist") + dependsOn("deletePmdCatalogerDist") dependsOn("deletePmd6Dist") dependsOn("deletePmd7Dist") } From 2904d2c1fe1e9ad1e7aa154fc4cb0d4b06ce0f30 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 14 Feb 2024 13:19:19 -0500 Subject: [PATCH 06/28] @W-15041815@: Force the global --json flag to show up in our help text --- src/lib/ScannerCommand.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/ScannerCommand.ts b/src/lib/ScannerCommand.ts index 5b7a4e39e..e37acca0e 100644 --- a/src/lib/ScannerCommand.ts +++ b/src/lib/ScannerCommand.ts @@ -24,6 +24,10 @@ import {Logger} from "@salesforce/core"; * runtime dependency injection points to their corresponding Action classes. */ export abstract class ScannerCommand extends SfCommand implements Displayable { + + // It appears we need to explicitly set this in order for the global --json flag to show up in the generated help text + public static readonly enableJsonFlag = true; + protected async init(): Promise { await super.init(); initContainer(); From e40c03dc9f3332b918bae50bd014f95d7281eb59 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Fri, 9 Feb 2024 12:21:42 -0500 Subject: [PATCH 07/28] @W-14980315@: Add --preview-pmd7 to run, rule describe, and rule list --- messages/describe.md | 8 +++++++ messages/list.md | 8 +++++++ messages/run-pathless.md | 8 +++++++ src/commands/scanner/rule/describe.ts | 7 +++++- src/commands/scanner/rule/list.ts | 8 +++++-- src/commands/scanner/run.ts | 7 +++++- src/lib/actions/AbstractRunAction.ts | 2 ++ src/lib/actions/RuleDescribeAction.ts | 2 ++ src/lib/actions/RuleListAction.ts | 2 ++ test/lib/actions/RuleDescribeAction.test.ts | 21 +++++++---------- test/lib/actions/RuleListAction.test.ts | 24 +++++++++----------- test/lib/actions/RunAction.test.ts | 25 +++++++++------------ 12 files changed, 76 insertions(+), 46 deletions(-) diff --git a/messages/describe.md b/messages/describe.md index 5226678da..40b57f11e 100644 --- a/messages/describe.md +++ b/messages/describe.md @@ -14,6 +14,14 @@ the name of the rule The name of the rule. +# flags.previewPmd7Summary + +use PMD version %s to describe PMD and CPD rules + +# flags.previewPmd7Description + +Uses PMD version %s instead of %s to describe PMD and CPD rules. + # output.noMatchingRules No rules were found with the name '%s'. diff --git a/messages/list.md b/messages/list.md index 7fa8f2d50..723146886 100644 --- a/messages/list.md +++ b/messages/list.md @@ -38,6 +38,14 @@ select rules by engine Selects rules by engine. Enter multiple engines as a comma-separated list. +# flags.previewPmd7Summary + +use PMD version %s to list PMD and CPD rules + +# flags.previewPmd7Description + +Uses PMD version %s instead of %s to list PMD and CPD rules. + # rulesetDeprecation The 'ruleset' command parameter is deprecated. Use 'category' instead diff --git a/messages/run-pathless.md b/messages/run-pathless.md index 8f313161d..7d001585c 100644 --- a/messages/run-pathless.md +++ b/messages/run-pathless.md @@ -66,6 +66,14 @@ specify location of PMD rule reference XML file to customize rule selection Specifies the location of PMD rule reference XML file to customize rule selection. +# flags.previewPmd7Summary + +use PMD version %s when running PMD and CPD + +# flags.previewPmd7Description + +Uses PMD version %s instead of %s when running PMD and CPD engines. + # flags.verboseViolationsSummary return retire-js violation message details diff --git a/src/commands/scanner/rule/describe.ts b/src/commands/scanner/rule/describe.ts index bcbde2744..e04553576 100644 --- a/src/commands/scanner/rule/describe.ts +++ b/src/commands/scanner/rule/describe.ts @@ -5,6 +5,7 @@ import {BundleName, getMessage} from "../../../MessageCatalog"; import {Logger} from "@salesforce/core"; import {Display} from "../../../lib/Display"; import {RuleDescribeAction} from "../../../lib/actions/RuleDescribeAction"; +import {PMD6_VERSION, PMD7_VERSION} from "../../../Constants"; /** * Defines the "rule describe" command for the "scanner" cli. @@ -28,7 +29,11 @@ export default class Describe extends ScannerCommand { }), verbose: Flags.boolean({ summary: getMessage(BundleName.Common, 'flags.verboseSummary') - }) + }), + "preview-pmd7": Flags.boolean({ + summary: getMessage(BundleName.Describe, 'flags.previewPmd7Summary', [PMD7_VERSION]), + description: getMessage(BundleName.Describe, 'flags.previewPmd7Description', [PMD7_VERSION, PMD6_VERSION]) + }), }; protected createAction(_logger: Logger, display: Display): Action { diff --git a/src/commands/scanner/rule/list.ts b/src/commands/scanner/rule/list.ts index ca3774949..c94908458 100644 --- a/src/commands/scanner/rule/list.ts +++ b/src/commands/scanner/rule/list.ts @@ -1,6 +1,6 @@ import {Flags} from '@salesforce/sf-plugins-core'; import {Action, ScannerCommand} from '../../../lib/ScannerCommand'; -import {AllowedEngineFilters} from '../../../Constants'; +import {AllowedEngineFilters, PMD6_VERSION, PMD7_VERSION} from '../../../Constants'; import {BundleName, getMessage} from "../../../MessageCatalog"; import {Logger} from "@salesforce/core"; import {Display} from "../../../lib/Display"; @@ -56,7 +56,11 @@ export default class List extends ScannerCommand { options: [...AllowedEngineFilters], delimiter: ',', multiple: true - })() + })(), + "preview-pmd7": Flags.boolean({ + summary: getMessage(BundleName.List, 'flags.previewPmd7Summary', [PMD7_VERSION]), + description: getMessage(BundleName.List, 'flags.previewPmd7Description', [PMD7_VERSION, PMD6_VERSION]) + }), }; protected createAction(_logger: Logger, display: Display): Action { diff --git a/src/commands/scanner/run.ts b/src/commands/scanner/run.ts index ce67dad98..78cbcd19d 100644 --- a/src/commands/scanner/run.ts +++ b/src/commands/scanner/run.ts @@ -1,5 +1,5 @@ import {Flags} from '@salesforce/sf-plugins-core'; -import {PathlessEngineFilters} from '../../Constants'; +import {PathlessEngineFilters, PMD6_VERSION, PMD7_VERSION} from '../../Constants'; import {ScannerRunCommand} from '../../lib/ScannerRunCommand'; import {EngineOptionsFactory, RunEngineOptionsFactory} from "../../lib/EngineOptionsFactory"; import {InputProcessor, InputProcessorImpl} from "../../lib/InputProcessor"; @@ -69,6 +69,11 @@ export default class Run extends ScannerRunCommand { summary: getMessage(BundleName.Run, 'flags.pmdConfigSummary'), description: getMessage(BundleName.Run, 'flags.pmdConfigDescription') }), + "preview-pmd7": Flags.boolean({ + summary: getMessage(BundleName.Run, 'flags.previewPmd7Summary', [PMD7_VERSION]), + description: getMessage(BundleName.Run, 'flags.previewPmd7Description', [PMD7_VERSION, PMD6_VERSION]) + }), + // TODO: This flag was implemented for W-7791882, and it's suboptimal. It leaks the abstraction and pollutes the command. // It should be replaced during the 3.0 release cycle. env: Flags.string({ diff --git a/src/lib/actions/AbstractRunAction.ts b/src/lib/actions/AbstractRunAction.ts index a840368ce..d015a3a68 100644 --- a/src/lib/actions/AbstractRunAction.ts +++ b/src/lib/actions/AbstractRunAction.ts @@ -21,6 +21,7 @@ import {ResultsProcessorFactory} from "../output/ResultsProcessorFactory"; import {JsonReturnValueHolder} from "../output/JsonReturnValueHolder"; import untildify = require('untildify'); import normalize = require('normalize-path'); +import {Pmd6CommandInfo, Pmd7CommandInfo} from "../pmd/PmdCommandInfo"; /** * Abstract Action to share a common implementation behind the "run" and "run dfa" commands @@ -80,6 +81,7 @@ export abstract class AbstractRunAction implements Action { } async run(inputs: Inputs): Promise { + Controller.setActivePmdCommandInfo(inputs['preview-pmd7'] ? new Pmd7CommandInfo() : new Pmd6CommandInfo()); const filters: RuleFilter[] = this.ruleFilterFactory.createRuleFilters(inputs); const targetPaths: string[] = this.inputProcessor.resolveTargetPaths(inputs); const runOptions: RunOptions = this.inputProcessor.createRunOptions(inputs, this.isDfa()); diff --git a/src/lib/actions/RuleDescribeAction.ts b/src/lib/actions/RuleDescribeAction.ts index 6221e9727..4df308eb1 100644 --- a/src/lib/actions/RuleDescribeAction.ts +++ b/src/lib/actions/RuleDescribeAction.ts @@ -9,6 +9,7 @@ import Dfa from "../../commands/scanner/run/dfa"; import Run from "../../commands/scanner/run"; import {Display} from "../Display"; import {RuleFilterFactory} from "../RuleFilterFactory"; +import {Pmd6CommandInfo, Pmd7CommandInfo} from "../pmd/PmdCommandInfo"; type DescribeStyledRule = Rule & { runWith: string; @@ -33,6 +34,7 @@ export class RuleDescribeAction implements Action { } public async run(inputs: Inputs): Promise { + Controller.setActivePmdCommandInfo(inputs['preview-pmd7'] ? new Pmd7CommandInfo() : new Pmd6CommandInfo()); const ruleFilters: RuleFilter[] = this.ruleFilterFactory.createRuleFilters(inputs); // TODO: Inject RuleManager as a dependency to improve testability by removing coupling to runtime implementation diff --git a/src/lib/actions/RuleListAction.ts b/src/lib/actions/RuleListAction.ts index 22663d54d..f0c5f2521 100644 --- a/src/lib/actions/RuleListAction.ts +++ b/src/lib/actions/RuleListAction.ts @@ -7,6 +7,7 @@ import {RuleFilter} from "../RuleFilter"; import {Controller} from "../../Controller"; import {Display} from "../Display"; import {RuleFilterFactory} from "../RuleFilterFactory"; +import {Pmd6CommandInfo, Pmd7CommandInfo} from "../pmd/PmdCommandInfo"; const MSG_YES: string = getMessage(BundleName.List, 'yes'); const MSG_NO: string = getMessage(BundleName.List, 'no'); @@ -59,6 +60,7 @@ export class RuleListAction implements Action { } public async run(inputs: Inputs): Promise { + Controller.setActivePmdCommandInfo(inputs['preview-pmd7'] ? new Pmd7CommandInfo() : new Pmd6CommandInfo()); const ruleFilters: RuleFilter[] = this.ruleFilterFactory.createRuleFilters(inputs); // TODO: Inject RuleManager as a dependency to improve testability by removing coupling to runtime implementation diff --git a/test/lib/actions/RuleDescribeAction.test.ts b/test/lib/actions/RuleDescribeAction.test.ts index 23f5b508d..0f376edac 100644 --- a/test/lib/actions/RuleDescribeAction.test.ts +++ b/test/lib/actions/RuleDescribeAction.test.ts @@ -1,13 +1,12 @@ import {FakeDisplay} from "../FakeDisplay"; import {initContainer} from "../../../src/ioc.config"; import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; -import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; -import {Controller} from "../../../src/Controller"; -import {after} from "mocha"; import {Inputs} from "../../../src/types"; import {expect} from "chai"; import {RuleDescribeAction} from "../../../src/lib/actions/RuleDescribeAction"; import {AnyJson} from "@salesforce/ts-types"; +import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../lib/Controller"; describe("Tests for RuleDescribeAction", () => { let display: FakeDisplay; @@ -21,19 +20,15 @@ describe("Tests for RuleDescribeAction", () => { }); describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7 with pmd engine", () => { - - // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead - const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() - before(() => { - Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); - }); - after(() => { - Controller.setActivePmdCommandInfo(originalPmdCommandInfo); - }); + afterEach(() => { + // Until we remove global state, we should cleanup after ourselves to prevent other tests from being impacted + Controller.setActivePmdCommandInfo(new Pmd6CommandInfo()) + }) it("When using PMD7, the rule description for a pmd rule should give correct info from PMD 7", async () => { const inputs: Inputs = { - rulename: 'ApexCRUDViolation' + rulename: 'ApexCRUDViolation', + "preview-pmd7": true } await ruleDescribeAction.run(inputs); diff --git a/test/lib/actions/RuleListAction.test.ts b/test/lib/actions/RuleListAction.test.ts index c25849761..9be671a71 100644 --- a/test/lib/actions/RuleListAction.test.ts +++ b/test/lib/actions/RuleListAction.test.ts @@ -2,13 +2,12 @@ import {FakeDisplay} from "../FakeDisplay"; import {initContainer} from "../../../src/ioc.config"; import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; import {RuleListAction} from "../../../src/lib/actions/RuleListAction"; -import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; -import {Controller} from "../../../src/Controller"; -import {after} from "mocha"; import {Inputs} from "../../../src/types"; import {expect} from "chai"; import {Ux} from "@salesforce/sf-plugins-core"; import {PMD7_LIB} from "../../../src/Constants"; +import {Controller} from "../../../lib/Controller"; +import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; describe("Tests for RuleListAction", () => { let display: FakeDisplay; @@ -22,19 +21,15 @@ describe("Tests for RuleListAction", () => { }); describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7", () => { - - // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead - const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() - before(() => { - Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); - }); - after(() => { - Controller.setActivePmdCommandInfo(originalPmdCommandInfo); - }); + afterEach(() => { + // Until we remove global state, we should cleanup after ourselves to prevent other tests from being impacted + Controller.setActivePmdCommandInfo(new Pmd6CommandInfo()) + }) it("When using PMD7, the rule list for the pmd engine should give back rules for PMD 7", async () => { const inputs: Inputs = { - engine: ['pmd'] + engine: ['pmd'], + "preview-pmd7": true } await ruleListAction.run(inputs); @@ -53,7 +48,8 @@ describe("Tests for RuleListAction", () => { it("When using PMD7, the rule list for the cpd engine should give back the copy-paste-detected rule", async () => { const inputs: Inputs = { - engine: ['cpd'] + engine: ['cpd'], + "preview-pmd7": true } await ruleListAction.run(inputs); diff --git a/test/lib/actions/RunAction.test.ts b/test/lib/actions/RunAction.test.ts index 4fca40f42..1af2e9102 100644 --- a/test/lib/actions/RunAction.test.ts +++ b/test/lib/actions/RunAction.test.ts @@ -8,18 +8,16 @@ import {Inputs, PathlessRuleViolation, RuleResult} from "../../../src/types"; import * as path from "path"; import {initContainer} from '../../../src/ioc.config'; import {expect} from "chai"; -import {Pmd7CommandInfo, PmdCommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; -import {Controller} from "../../../src/Controller"; -import {after} from "mocha"; import {Results} from "../../../src/lib/output/Results"; import {PMD6_VERSION, PMD7_VERSION} from "../../../src/Constants"; import {FakeResultsProcessorFactory, RawResultsProcessor} from "./fakes"; +import {Controller} from "../../../lib/Controller"; +import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; const codeFixturesDir = path.join(__dirname, '..', '..', 'code-fixtures'); const pathToSomeTestClass = path.join(codeFixturesDir, 'apex', 'SomeTestClass.cls'); const pathToCodeForCpd = path.join(codeFixturesDir, 'cpd'); - describe("Tests for RunAction", () => { let display: FakeDisplay; let resultsProcessor: RawResultsProcessor; @@ -42,21 +40,17 @@ describe("Tests for RunAction", () => { }); describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7", () => { - - // TODO: Soon we will have an input flag to control this. Once we do, we can update this to use that instead - const originalPmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo() - before(() => { - Controller.setActivePmdCommandInfo(new Pmd7CommandInfo()); - }); - after(() => { - Controller.setActivePmdCommandInfo(originalPmdCommandInfo); - }); + afterEach(() => { + // Until we remove global state, we should cleanup after ourselves to prevent other tests from being impacted + Controller.setActivePmdCommandInfo(new Pmd6CommandInfo()) + }) it("When using PMD7, the pmd engine actually uses PMD7 instead of PMD6", async () => { const inputs: Inputs = { target: [pathToSomeTestClass], engine: ['pmd'], - 'normalize-severity': true + 'normalize-severity': true, + "preview-pmd7": true } await runAction.run(inputs); @@ -89,7 +83,8 @@ describe("Tests for RunAction", () => { const inputs: Inputs = { target: [pathToCodeForCpd], engine: ['cpd'], - 'normalize-severity': true + 'normalize-severity': true, + "preview-pmd7": true } await runAction.run(inputs); From 96acf31b17f60b00f0aae25983e44debb2e47139 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 14 Feb 2024 13:19:19 -0500 Subject: [PATCH 08/28] @W-15041815@: Force the global --json flag to show up in our help text --- pmd-cataloger/build.gradle.kts | 51 ++++++++++++++-------------------- src/lib/ScannerCommand.ts | 4 +++ 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/pmd-cataloger/build.gradle.kts b/pmd-cataloger/build.gradle.kts index 28a07e36c..a2361247d 100644 --- a/pmd-cataloger/build.gradle.kts +++ b/pmd-cataloger/build.gradle.kts @@ -76,19 +76,17 @@ tasks.register("installPmd6") { from(zipTree("$buildDir/$pmd6File")) // I went to https://github.com/pmd/pmd/tree/pmd_releases/6.55.0 and for each of the languages that we support - // (apex, java, visualforce, xml), I took a look at its pom file (like pmd-apex/src/pom.xml for example). - // That pom said what other modules it depends on and I listed these dependencies (besides test-scoped and optional - // modules). I did this recursively for any dependent pmd-* modules and put it all here. - // For completeness, I listed the modules and all their dependencies. Duplicates don't matter since we use setOf. + // (apex, java, visualforce, xml), I took a look at its direct and indirect dependencies at + // https://central.sonatype.com/artifact/net.sourceforge.pmd/pmd-apex/dependencies + // by selecting the 6.55.0 dropdown and clicking on "Dependencies" and selecting "All Dependencies". + // For completeness, I listed the modules and all their compile time dependencies (direct and indirect). + // Duplicates don't matter since we use setOf. val pmd6ModulesToInclude = setOf( - // LANGUAGE MODULE DEPENDENCIES - "pmd-apex", "pmd-core", "antlr-runtime", "pmd-apex-jorje", "commons-lang3", - "pmd-java", "pmd-core", "saxon", "asm", "commons-lang3", - "pmd-visualforce", "pmd-core", "pmd-apex", - "pmd-xml", "pmd-core", "antlr4-runtime", "saxon", - // DEPENDENT MODULE DEPENDENCIES - "pmd-core", "antlr4-runtime", "jcommander", "saxon", "commons-lang3", "asm", "gson", - "pmd-apex-jorje", "cglib", "logback-classic", "logback-core", "jsr305", "gson", "error_prone_annotations", "guava", "j2objc-annotations", "antlr-runtime", "stringtemplate", "common-lang3", "animal-sniffer-annotations", "jol-core", "slf4j-api", "snakeyaml", "aopalliance", "javax.inject", "asm" + // LANGUAGE MODULE DEPENDENCIES (direct and indirect) + "pmd-apex", "animal-sniffer-annotations", "antlr", "antlr-runtime", "antlr4-runtime", "aopalliance", "asm", "cglib", "commons-lang3", "error_prone_annotations", "gson", "j2objc-annotations", "javax.inject", "jcommander", "jol-core", "jsr305", "logback-classic", "logback-core", "pmd-apex-jorje", "pmd-core", "saxon", "slf4j-api", "stringtemplate", + "pmd-java", "antlr4-runtime", "asm", "commons-lang3", "gson", "jcommander", "pmd-core", "saxon", + "pmd-visualforce", "animal-sniffer-annotations", "antlr", "antlr-runtime", "antlr4-runtime", "aopalliance", "asm", "cglib", "commons-lang3", "error_prone_annotations", "gson", "j2objc-annotations", "javax.inject", "jcommander", "jol-core", "jsr305", "logback-classic", "logback-core", "pmd-apex", "pmd-apex-jorje", "pmd-core", "saxon", "slf4j-api", "stringtemplate", + "pmd-xml", "antr4-runtime", "asm", "commons-lang3", "gson", "jcommander", "pmd-core", "saxon" ) val pmd6JarsToIncludeRegexes = mutableSetOf("""^LICENSE""".toRegex()) @@ -126,26 +124,19 @@ tasks.register("installPmd7") { from(zipTree("$buildDir/$pmd7File")) // I went to https://github.com/pmd/pmd/tree/pmd_releases/7.0.0-rc4 and for each of the languages that we support - // (apex, java, visualforce, xml), I took a look at its pom file (like pmd-apex/src/pom.xml for example). - // That pom said what other modules it depends on and I took these dependencies (besides test-scoped and optional - // modules). I did this recursively for any dependent pmd-* modules and put it all here. - // For completeness, I listed the modules and all their dependencies except for pmd-ui (since it isn't needed) and - // the dependencies of pmd-languages-deps (since it contains all language modules). I also had to add in pmd-cli. - // Note that "pkgforce_2.13" was missing from pmd-apex, so I added it in and that unfortunately required me to pull - // in all of its dependencies listed at https://central.sonatype.com/artifact/com.github.nawforce/pkgforce_2.13/dependencies. + // (apex, java, visualforce, xml), I took a look at its direct and indirect dependencies at + // https://central.sonatype.com/artifact/net.sourceforge.pmd/pmd-apex/dependencies + // by selecting the 7.0.0-rc4 dropdown and clicking on "Dependencies" and selecting "All Dependencies". + // For completeness, I listed the modules and all their compile time dependencies (direct and indirect). // Duplicates don't matter since we use setOf. val pmd7ModulesToInclude = setOf( - // LANGUAGE MODULE DEPENDENCIES - "pmd-apex", "pmd-core", "antlr-runtime", "pmd-apex-jorje", "apex-link", "commons-lang3", "guava", "pkgforce_2.13", - "pmd-java", "pmd-core", "asm", "commons-lang3", "checker-qual", "Saxon-HE", "pcollections", - "pmd-visualforce", "pmd-core", "pmd-apex", - "pmd-xml", "pmd-core", "antlr4-runtime", - // MAIN CLI MODULE DEPENDENCIES - "pmd-cli", "pmd-languages-deps", "slf4j-api", "slf4j-simple", "picocli", "progressbar", "checker-qual", - // DEPENDENT MODULE DEPENDENCIES - "pmd-core", "slf4j-api", "jul-to-slf4j", "antlr4-runtime", "Saxon-HE", "commons-lang3", "asm", "gson", "checker-qual", "pcollections", "nice-xml-messages", - "pmd-apex-jorje", "cglib", "jsr305", "gson", "error_prone_annotations", "guava", "j2objc-annotations", "antlr-runtime", "stringtemplate", "commons-lang3", "animal-sniffer-annotations", "slf4j-api", "aopalliance", "javax.inject", "asm", - "pkgforce_2.13", "scala-json-rpc-upickle-json-serializer_2.13", "scala-json-rpc_2.13", "geny_2.13", "ujson_2.13", "upack_2.13", "upickle-core_2.13", "upickle-implicits_2.13", "upickle_2.13", "apex-parser", "antlr4-runtime", "scala-collection-compat_2.13", "scala-xml_2.13", "scala-library", "scala-reflect" + // LANGUAGE MODULE DEPENDENCIES (direct and indirect) + "pmd-apex", "Saxon-HE", "animal-sniffer-annotations", "antlr", "antlr-runtime", "antlr4-runtime", "aopalliance", "apex-parser", "apexlink", "asm", "cglib", "checker-qual", "commons-lang3", "error_prone_annotations", "failureaccess", "geny_2.13", "gson", "guava", "j2objc-annotations", "javax.inject", "jsr305", "jul-to-slf4j", "listenablefuture", "nice-xml-messages", "pcollections", "pkgforce_2.13", "pmd-apex-jorje", "pmd-core", "runforce", "scala-collection-compat_2.13", "scala-json-rpc-upickle-json-serializer_2.13", "scala-json-rpc_2.13", "scala-library", "scala-parallel-collections_2.13", "scala-reflect", "scala-xml_2.13", "slf4j-api", "stringtemplate", "ujson_2.13", "upack_2.13", "upickle-core_2.13", "upickle-implicits_2.13", "upickle_2.13", + "pmd-java", "Saxon-HE", "antlr4-runtime", "asm", "checker-qual", "commons-lang3", "gson", "jul-to-slf4j", "nice-xml-messages", "pcollections", "pmd-core", "slf4j-api", + "pmd-visualforce", "Saxon-HE", "animal-sniffer-annotations", "antlr", "antlr-runtime", "antlr4-runtime", "aopalliance", "apex-parser", "apexlink", "asm", "cglib", "checker-qual", "commons-lang3", "error_prone_annotations", "failureaccess", "geny_2.13", "gson", "guava", "j2objc-annotations", "javax.inject", "jsr305", "jul-to-slf4j", "listenablefuture", "nice-xml-messages", "pcollections", "pkgforce_2.13", "pmd-apex", "pmd-apex-jorje", "pmd-core", "runforce", "scala-collection-compat_2.13", "scala-json-rpc-upickle-json-serializer_2.13", "scala-json-rpc_2.13", "scala-library", "scala-parallel-collections_2.13", "scala-reflect", "scala-xml_2.13", "slf4j-api", "stringtemplate", "ujson_2.13", "upack_2.13", "upickle-core_2.13", "upickle-implicits_2.13", "upickle_2.13", + "pmd-xml", "Saxon-HE", "antlr4-runtime", "asm", "checker-qual", "commons-lang3", "gson", "jul-to-slf4j", "nice-xml-messages", "pcollections", "pmd-core", "slf4j-api", + // MAIN CLI MODULE DEPENDENCIES (direct and indirect) + "pmd-cli", "Saxon-HE", "antlr4-runtime", "asm", "checker-qual", "commons-lang3", "gson", "jline", "jul-to-slf4j", "nice-xml-messages", "pcollections", "picocli", "pmd-core", "pmd-ui", "progressbar", "slf4j-api", "slf4j-simple", ) val pmd7JarsToIncludeRegexes = mutableSetOf("""^LICENSE""".toRegex()) pmd7ModulesToInclude.forEach { diff --git a/src/lib/ScannerCommand.ts b/src/lib/ScannerCommand.ts index 5b7a4e39e..e37acca0e 100644 --- a/src/lib/ScannerCommand.ts +++ b/src/lib/ScannerCommand.ts @@ -24,6 +24,10 @@ import {Logger} from "@salesforce/core"; * runtime dependency injection points to their corresponding Action classes. */ export abstract class ScannerCommand extends SfCommand implements Displayable { + + // It appears we need to explicitly set this in order for the global --json flag to show up in the generated help text + public static readonly enableJsonFlag = true; + protected async init(): Promise { await super.init(); initContainer(); From 43fd85cc72128e51aa48fcc4eca601cf8e8ccec1 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 16 Feb 2024 14:28:10 -0600 Subject: [PATCH 09/28] @W-15059732@: scanner rule describe now includes runWith column. --- src/commands/scanner/run.ts | 1 + src/commands/scanner/run/dfa.ts | 1 + src/lib/actions/RuleDescribeAction.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/scanner/run.ts b/src/commands/scanner/run.ts index 78cbcd19d..1a0c64ebf 100644 --- a/src/commands/scanner/run.ts +++ b/src/commands/scanner/run.ts @@ -21,6 +21,7 @@ export default class Run extends ScannerRunCommand { public static examples = [ getMessage(BundleName.Run, 'examples') ]; + public static readonly invocation = 'scanner run'; // This defines the flags accepted by this command. The key is the longname, the char property is the shortname, // and summary and description is what's printed when the -h/--help flag is supplied. diff --git a/src/commands/scanner/run/dfa.ts b/src/commands/scanner/run/dfa.ts index 2c24f2c3d..07bb927bf 100644 --- a/src/commands/scanner/run/dfa.ts +++ b/src/commands/scanner/run/dfa.ts @@ -20,6 +20,7 @@ export default class Dfa extends ScannerRunCommand { public static examples = [ getMessage(BundleName.RunDfa, 'examples') ]; + public static readonly invocation = 'scanner run dfa'; // This defines the flags accepted by this command. // NOTE: Unlike the other classes that extend ScannerCommand, this class has no flags for specifying rules. This is diff --git a/src/lib/actions/RuleDescribeAction.ts b/src/lib/actions/RuleDescribeAction.ts index 4df308eb1..5f9e7388d 100644 --- a/src/lib/actions/RuleDescribeAction.ts +++ b/src/lib/actions/RuleDescribeAction.ts @@ -76,7 +76,7 @@ export class RuleDescribeAction implements Action { return rules.map(r => { const styledRule: DescribeStyledRule = { ...r, - runWith: r.isDfa ? Dfa.id : Run.id, + runWith: r.isDfa ? Dfa.invocation : Run.invocation, isPilot: r.isPilot, enabled: enabledEngineNames.has(r.engine) }; From 8283360a85700e13e3ead341d5436d1b079debc5 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Thu, 15 Feb 2024 12:00:20 -0600 Subject: [PATCH 10/28] @W-14945179@: Added deprecation warning for Java v1.8. --- messages/jreSetupManager.md | 6 +++++- src/lib/Display.ts | 14 ++++++++++++++ src/lib/JreSetupManager.ts | 4 +++- src/lib/ScannerCommand.ts | 1 + src/lib/ScannerEvents.ts | 1 + test/lib/FakeDisplay.ts | 4 ++++ test/lib/JreSetupManager.test.ts | 23 ++++++++++++++++++++++- 7 files changed, 50 insertions(+), 3 deletions(-) diff --git a/messages/jreSetupManager.md b/messages/jreSetupManager.md index d0dd7a1b5..c7c9a6cfb 100644 --- a/messages/jreSetupManager.md +++ b/messages/jreSetupManager.md @@ -18,4 +18,8 @@ If the problem persists, please manually add a 'javaHome' property to your Confi # InvalidVersion -Java version %s isn't supported. Install Java 1.8 or later. \ No newline at end of file +Java version %s isn't supported. Install Java 1.8 or later. + +# warning.JavaV8Deprecated + +We deprecated support for Java v8. Update to Java v11 and update the `javaHome` property in your `%s` file. diff --git a/src/lib/Display.ts b/src/lib/Display.ts index e12fe449f..27504d205 100644 --- a/src/lib/Display.ts +++ b/src/lib/Display.ts @@ -43,6 +43,11 @@ export interface Display { */ displayVerboseWarning(msg: string): void; + /** + * Display a message as a warning, unless it's been displayed using this method before. + */ + displayUniqueWarning(msg: string): void; + /** * Adds a spinner to the display. */ @@ -68,11 +73,13 @@ export class UxDisplay implements Display { private readonly displayable: Displayable; private readonly spinner: Spinner; private readonly isVerboseSet: boolean; + private uniqueMessageSet: Set; public constructor(displayable: Displayable, spinner: Spinner, isVerboseSet: boolean) { this.displayable = displayable; this.spinner = spinner; this.isVerboseSet = isVerboseSet; + this.uniqueMessageSet = new Set(); } public displayInfo(msg: string): void { @@ -111,6 +118,13 @@ export class UxDisplay implements Display { } } + public displayUniqueWarning(msg: string): void { + if (!this.uniqueMessageSet.has(msg)) { + this.uniqueMessageSet.add(msg); + this.displayWarning(msg); + } + } + public spinnerStart(msg: string, status?: string): void { this.spinner.start(msg, status); } diff --git a/src/lib/JreSetupManager.ts b/src/lib/JreSetupManager.ts index 378eb4980..eeae5279b 100644 --- a/src/lib/JreSetupManager.ts +++ b/src/lib/JreSetupManager.ts @@ -9,6 +9,7 @@ import path = require('path'); import {FileHandler} from './util/FileHandler'; import {Config} from './util/Config'; import {BundleName, getMessage} from "../MessageCatalog"; +import {uxEvents, EVENTS} from './ScannerEvents'; const JAVA_HOME_SYSTEM_VARIABLES = ['JAVA_HOME', 'JRE_HOME', 'JDK_HOME']; @@ -142,6 +143,7 @@ class JreSetupManager extends AsyncCreatable { } else if (majorVersion === 1 && minorVersion === 8) { // Accommodating 1.8 version = `${majorVersion}.${minorVersion}`; + uxEvents.emit(EVENTS.WARNING_ALWAYS_UNIQUE, getMessage(BundleName.JreSetupManager, 'warning.JavaV8Deprecated', [path.join(Controller.getSfdxScannerPath(), "Config.json")])); } else { // Not matching what we are looking for const errName = 'InvalidVersion'; @@ -157,7 +159,7 @@ class JreSetupManager extends AsyncCreatable { private async fetchJavaVersion(javaHome: string): Promise { const javaWithFullPath = path.join(javaHome, 'bin', 'java'); // Run java -version and examine stderr for version - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { childProcess.execFile(javaWithFullPath, ['-version'], {}, (error, _stdout, stderr) => { if (error) { diff --git a/src/lib/ScannerCommand.ts b/src/lib/ScannerCommand.ts index e37acca0e..d1fc7b892 100644 --- a/src/lib/ScannerCommand.ts +++ b/src/lib/ScannerCommand.ts @@ -54,6 +54,7 @@ export abstract class ScannerCommand extends SfCommand implements Displ uxEvents.on(EVENTS.INFO_VERBOSE, (msg: string) => display.displayVerboseInfo(msg)); uxEvents.on(EVENTS.WARNING_ALWAYS, (msg: string) => display.displayWarning(msg)); uxEvents.on(EVENTS.WARNING_VERBOSE, (msg: string) => display.displayVerboseWarning(msg)); + uxEvents.on(EVENTS.WARNING_ALWAYS_UNIQUE, (msg: string) => display.displayUniqueWarning(msg)); uxEvents.on(EVENTS.START_SPINNER, (msg: string, status: string) => display.spinnerStart(msg, status)); uxEvents.on(EVENTS.UPDATE_SPINNER, (msg: string) => display.spinnerUpdate(msg)); uxEvents.on(EVENTS.WAIT_ON_SPINNER, (_msg: string) => display.spinnerWait()); // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/src/lib/ScannerEvents.ts b/src/lib/ScannerEvents.ts index 00226d8f5..ccd4e00cb 100644 --- a/src/lib/ScannerEvents.ts +++ b/src/lib/ScannerEvents.ts @@ -9,6 +9,7 @@ export enum EVENTS { INFO_VERBOSE = 'info-verbose', WARNING_ALWAYS = 'warning-always', WARNING_VERBOSE = 'warning-verbose', + WARNING_ALWAYS_UNIQUE = 'warning-always-unique', // NOTE: If, for some reason, we eventually need verbose-only spinners, we'll need to split START_SPINNER into // always/verbose variants, but the other two can be left alone. This is because they correspond to `ux.setSpinnerStatus()` // and `ux.stopSpinner()`, which are both no-ops if there's not an active spinner. diff --git a/test/lib/FakeDisplay.ts b/test/lib/FakeDisplay.ts index b9ab12444..6f91b685f 100644 --- a/test/lib/FakeDisplay.ts +++ b/test/lib/FakeDisplay.ts @@ -55,6 +55,10 @@ export class FakeDisplay implements Display { this.outputs.push("[VerboseWarning]: " + msg); } + displayUniqueWarning(msg: string): void { + this.outputs.push("[UniqueWarning]: " + msg); + } + displayStyledHeader(headerText: string): void { this.outputs.push("[StyledHeader]: " + headerText); } diff --git a/test/lib/JreSetupManager.test.ts b/test/lib/JreSetupManager.test.ts index 1bf09f536..1c0998b9f 100644 --- a/test/lib/JreSetupManager.test.ts +++ b/test/lib/JreSetupManager.test.ts @@ -1,10 +1,11 @@ -import {expect} from 'chai'; +import {assert, expect} from 'chai'; import {FileHandler} from '../../src/lib/util/FileHandler'; import {Config} from '../../src/lib/util/Config'; import Sinon = require('sinon'); import {verifyJreSetup, JreSetupManagerDependencies} from '../../src/lib/JreSetupManager'; import childProcess = require('child_process'); import * as TestOverrides from '../test-related-lib/TestOverrides'; +import {uxEvents, EVENTS} from '../../src/lib/ScannerEvents'; TestOverrides.initializeTestSetup(); @@ -18,6 +19,14 @@ describe('JreSetupManager #verifyJreSetup', () => { const validVersion8 = 'openjdk version "1.8.0_172"\nOpenJDK Runtime Environment (Zulu 8.30.0.2-macosx) (build 1.8.0_172-b01)\nOpenJDK 64-Bit Server VM (Zulu 8.30.0.2-macosx) (build 25.172-b01, mixed mode)\n'; const validVersion14Win = 'openjdk 14 2020-03-17\r\nOpenJDK Runtime Environment (build 14+36-1461)\r\nOpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)\r\n'; const invalidVersion = 'openjdk version "1.5.0_188"\nOpenJDK Runtime Environment'; + let uniqueWarningCounter = 0; + uxEvents.on(EVENTS.WARNING_ALWAYS_UNIQUE, (_msg) => { + uniqueWarningCounter += 1; + }); + + beforeEach(() => { + uniqueWarningCounter = 0; + }); describe('With valid javaHome path in Config and an accepted Java version', () => { @@ -48,6 +57,7 @@ describe('JreSetupManager #verifyJreSetup', () => { expect(javaHomeValue).equals(javaHomeValidPath); expect(setJavaHomeStub.calledOnce).to.be.true; expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(1); }); }); @@ -83,6 +93,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(1); }); it('should check JRE_HOME for path', async () => { @@ -93,6 +104,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(1); }); it('should check JDK_HOME for path', async () => { @@ -103,6 +115,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(1); }); }); @@ -140,6 +153,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(findJavaHomeStub.calledOnce).to.be.true; expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(1); findJavaHomeStub.restore(); @@ -156,6 +170,7 @@ describe('JreSetupManager #verifyJreSetup', () => { } expect(findJavaHomeStub.calledOnce).to.be.true; + expect(uniqueWarningCounter).to.equal(0); findJavaHomeStub.restore(); @@ -183,8 +198,10 @@ describe('JreSetupManager #verifyJreSetup', () => { // Execute and verify try { await verifyJreSetup(); + assert.fail('Should have failed'); } catch (err) { expect(err.name).equals('InvalidJavaHome'); + expect(uniqueWarningCounter).to.equal(0); } configGetJavaHomeStub.restore(); @@ -201,8 +218,10 @@ describe('JreSetupManager #verifyJreSetup', () => { // Execute and verify try { await verifyJreSetup(); + assert.fail('Should have failed'); } catch (err) { expect(err.name).equals('InvalidVersion'); + expect(uniqueWarningCounter).to.equal(0); } configGetJavaHomeStub.restore(); @@ -221,6 +240,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(0); configGetJavaHomeStub.restore(); statStub.restore(); @@ -238,6 +258,7 @@ describe('JreSetupManager #verifyJreSetup', () => { // Verify expect(javaHome).equals(javaHomeValidPath); + expect(uniqueWarningCounter).to.equal(0); configGetJavaHomeStub.restore(); statStub.restore(); From 4b5dec27f667bbba9f84d056f0501bb0064f6824 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Mon, 19 Feb 2024 13:23:38 -0600 Subject: [PATCH 11/28] @W-14945179@: Switched to approved message. --- messages/jreSetupManager.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messages/jreSetupManager.md b/messages/jreSetupManager.md index c7c9a6cfb..772d503ea 100644 --- a/messages/jreSetupManager.md +++ b/messages/jreSetupManager.md @@ -22,4 +22,4 @@ Java version %s isn't supported. Install Java 1.8 or later. # warning.JavaV8Deprecated -We deprecated support for Java v8. Update to Java v11 and update the `javaHome` property in your `%s` file. +Code Analyzer requires Java v11 or later. Update to Java v11 and update the `javaHome` property in your `%s` file. From 55ac4ff90249f417655584e26eedbcc627a1a6d8 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Mon, 19 Feb 2024 13:55:07 -0600 Subject: [PATCH 12/28] @W-14945179@: Implemented feedback from review. --- src/lib/JreSetupManager.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/JreSetupManager.ts b/src/lib/JreSetupManager.ts index eeae5279b..f07eeacb0 100644 --- a/src/lib/JreSetupManager.ts +++ b/src/lib/JreSetupManager.ts @@ -8,6 +8,7 @@ import childProcess = require('child_process'); import path = require('path'); import {FileHandler} from './util/FileHandler'; import {Config} from './util/Config'; +import {CONFIG_FILE} from '../Constants'; import {BundleName, getMessage} from "../MessageCatalog"; import {uxEvents, EVENTS} from './ScannerEvents'; @@ -143,7 +144,7 @@ class JreSetupManager extends AsyncCreatable { } else if (majorVersion === 1 && minorVersion === 8) { // Accommodating 1.8 version = `${majorVersion}.${minorVersion}`; - uxEvents.emit(EVENTS.WARNING_ALWAYS_UNIQUE, getMessage(BundleName.JreSetupManager, 'warning.JavaV8Deprecated', [path.join(Controller.getSfdxScannerPath(), "Config.json")])); + uxEvents.emit(EVENTS.WARNING_ALWAYS_UNIQUE, getMessage(BundleName.JreSetupManager, 'warning.JavaV8Deprecated', [path.join(Controller.getSfdxScannerPath(), CONFIG_FILE)])); } else { // Not matching what we are looking for const errName = 'InvalidVersion'; From 6e21ddc17087aa2b93af63d9e97ac8ed6a3b71d8 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Tue, 20 Feb 2024 11:57:22 -0600 Subject: [PATCH 13/28] FIX (CodeAnalyzer): @W-14901310@: Restored error-always event. --- src/lib/Display.ts | 12 ++++++++++++ src/lib/ScannerCommand.ts | 1 + src/lib/ScannerEvents.ts | 1 + test/lib/FakeDisplay.ts | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/src/lib/Display.ts b/src/lib/Display.ts index 27504d205..4ed113e57 100644 --- a/src/lib/Display.ts +++ b/src/lib/Display.ts @@ -33,6 +33,11 @@ export interface Display { */ displayStyledObject(obj: AnyJson): void; + /** + * Display a message as an error. + */ + displayError(msg: string): void; + /** * Display a message as a warning. */ @@ -108,6 +113,10 @@ export class UxDisplay implements Display { this.displayable.styledObject(obj); } + public displayError(msg: string): void { + this.displayable.error(msg); + } + public displayWarning(msg: string): void { this.displayable.warn(msg); } @@ -150,6 +159,9 @@ export interface Displayable { // Display an error or message as a warning. [Implemented by Command] warn(input: string): void; + // Display an error or message as an error. [Implemented by Command] + error(message: string): void; + // Simplified prompt for single-question confirmation. Times out and throws after 10s. [Implemented by SfCommand] confirm(message: string): Promise; diff --git a/src/lib/ScannerCommand.ts b/src/lib/ScannerCommand.ts index d1fc7b892..8b5cd140d 100644 --- a/src/lib/ScannerCommand.ts +++ b/src/lib/ScannerCommand.ts @@ -55,6 +55,7 @@ export abstract class ScannerCommand extends SfCommand implements Displ uxEvents.on(EVENTS.WARNING_ALWAYS, (msg: string) => display.displayWarning(msg)); uxEvents.on(EVENTS.WARNING_VERBOSE, (msg: string) => display.displayVerboseWarning(msg)); uxEvents.on(EVENTS.WARNING_ALWAYS_UNIQUE, (msg: string) => display.displayUniqueWarning(msg)); + uxEvents.on(EVENTS.ERROR_ALWAYS, (msg: string) => display.displayError(msg)); uxEvents.on(EVENTS.START_SPINNER, (msg: string, status: string) => display.spinnerStart(msg, status)); uxEvents.on(EVENTS.UPDATE_SPINNER, (msg: string) => display.spinnerUpdate(msg)); uxEvents.on(EVENTS.WAIT_ON_SPINNER, (_msg: string) => display.spinnerWait()); // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/src/lib/ScannerEvents.ts b/src/lib/ScannerEvents.ts index ccd4e00cb..eef80684d 100644 --- a/src/lib/ScannerEvents.ts +++ b/src/lib/ScannerEvents.ts @@ -10,6 +10,7 @@ export enum EVENTS { WARNING_ALWAYS = 'warning-always', WARNING_VERBOSE = 'warning-verbose', WARNING_ALWAYS_UNIQUE = 'warning-always-unique', + ERROR_ALWAYS = 'error-always', // NOTE: If, for some reason, we eventually need verbose-only spinners, we'll need to split START_SPINNER into // always/verbose variants, but the other two can be left alone. This is because they correspond to `ux.setSpinnerStatus()` // and `ux.stopSpinner()`, which are both no-ops if there's not an active spinner. diff --git a/test/lib/FakeDisplay.ts b/test/lib/FakeDisplay.ts index 6f91b685f..026ac5f20 100644 --- a/test/lib/FakeDisplay.ts +++ b/test/lib/FakeDisplay.ts @@ -59,6 +59,10 @@ export class FakeDisplay implements Display { this.outputs.push("[UniqueWarning]: " + msg); } + displayError(msg: string): void { + this.outputs.push("[Error]: " + msg); + } + displayStyledHeader(headerText: string): void { this.outputs.push("[StyledHeader]: " + headerText); } From 63dde9e1e839db3e93aea9e83a5a6cbd65692ff6 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Wed, 21 Feb 2024 10:32:20 -0600 Subject: [PATCH 14/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored test coverage for command. --- messages/add.md | 8 + package.json | 3 +- src/lib/actions/RuleAddAction.ts | 8 +- test/commands/scanner/rule/add.test.ts | 150 -- test/lib/actions/RuleAddAction.test.ts | 186 ++ yarn.lock | 2307 ++++++++++++++++++------ 6 files changed, 1911 insertions(+), 751 deletions(-) delete mode 100644 test/commands/scanner/rule/add.test.ts create mode 100644 test/lib/actions/RuleAddAction.test.ts diff --git a/messages/add.md b/messages/add.md index 4ce224067..a11b10e1c 100644 --- a/messages/add.md +++ b/messages/add.md @@ -30,6 +30,14 @@ Specify a language Specify a path +# output.successfullyAddedRules + +Successfully added rules for %s. + +# output.resultSummary + +%s Path(s) added: %s + # examples Bundle custom PMD rules in JAR files. Follow PMD conventions, such as defining the custom rules in XML files under a `/category/` directory. diff --git a/package.json b/package.json index ad4a79ad9..b74ade706 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@types/picomatch": "^2.3.0", "@types/sarif": "^2.1.4", "@types/semver": "^7.3.9", + "@types/sinon": "^17.0.3", "@types/tmp": "^0.2.3", "@types/uuid": "^8.3.4", "chai": "^4", @@ -78,7 +79,7 @@ "mocha-junit-reporter": "^2.0.0", "nyc": "^15.0.0", "oclif": "^4.0.3", - "sinon": "^13", + "sinon": "^17", "tildify": "^2.0.0", "ts-mockito": "^2.6.1" }, diff --git a/src/lib/actions/RuleAddAction.ts b/src/lib/actions/RuleAddAction.ts index c59dcb8a6..8d9cdaad5 100644 --- a/src/lib/actions/RuleAddAction.ts +++ b/src/lib/actions/RuleAddAction.ts @@ -23,12 +23,12 @@ export class RuleAddAction implements Action { } public validateInputs(inputs: Inputs): Promise { - if ((inputs.language as string).length === 0) { + if (!inputs.language || (inputs.language as string).length === 0) { throw new SfError(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); } // --path '' results in different values depending on the OS. On Windows it is [], on *nix it is [""] - if (inputs.path && stringArrayTypeGuard(inputs.path) && (!inputs.path.length || inputs.path.includes(''))) { + if (!inputs.path || inputs.path && stringArrayTypeGuard(inputs.path) && (!inputs.path.length || inputs.path.includes(''))) { throw new SfError(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); } @@ -46,8 +46,8 @@ export class RuleAddAction implements Action { const manager = await Controller.createRulePathManager(); const classpathEntries = await manager.addPathsForLanguage(language, paths); - this.display.displayInfo(`Successfully added rules for ${language}.`); - this.display.displayInfo(`${classpathEntries.length} Path(s) added: ${classpathEntries.toString()}`); + this.display.displayInfo(getMessage(BundleName.Add, 'output.successfullyAddedRules', [language])); + this.display.displayInfo(getMessage(BundleName.Add, 'output.resultSummary', [classpathEntries.length, classpathEntries.toString()])); return {success: true, language, path: classpathEntries}; } } diff --git a/test/commands/scanner/rule/add.test.ts b/test/commands/scanner/rule/add.test.ts deleted file mode 100644 index a3cd28e1d..000000000 --- a/test/commands/scanner/rule/add.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -import {expect} from 'chai'; -// @ts-ignore -import {runCommand} from '../../../TestUtils'; -import * as os from 'os'; -import fs = require('fs'); -import path = require('path'); -import {BundleName, getMessage } from '../../../../src/MessageCatalog'; - - -describe('scanner rule add', () => { - describe('E2E', () => { - const myLanguage = 'apex'; - describe('Test Case: Adding individual JARs', () => { - // Create four temporary directories, each having a single JAR. - const tmpDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar1 = path.join(tmpDir1, 'bar1.jar'); - fs.writeFileSync(tmpJar1, 'In the Age of Ancients, the world was unformed and shrouded by fog.'); - const tmpDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar2 = path.join(tmpDir2, 'bar2.jar'); - fs.writeFileSync(tmpJar2, 'A land of grey crags, arch trees, and everlasting dragons.'); - const tmpDir3 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar3 = path.join(tmpDir3, 'bar3.jar'); - fs.writeFileSync(tmpJar3, 'Then there was Fire, and with Fire came disparity.'); - const tmpDir4 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar4 = path.join(tmpDir4, 'bar4.jar'); - fs.writeFileSync(tmpJar4, 'Heat and cold, life and death, and of course, light and dark.'); - - it('Individual JARs can be added with their absolute path', () => { - // For the first test, we'll add two of the JARs with their absolute paths. - const absolutePaths = [tmpJar1, tmpJar2]; - const output = runCommand(`scanner rule add --language ${myLanguage} --path ${absolutePaths.join(',')} --json`); - // The expectation is that the paths will just be used as-is. - const expectedPaths = absolutePaths; - const outputJson = output.jsonOutput; - const result = outputJson.result; - expect(result).to.have.property('success') - .and.equals(true); - - expect(result).to.have.property('language') - .and.equals(myLanguage); - - expect(result).to.have.property('path') - .and.have.lengthOf(expectedPaths.length) - .and.deep.equals(expectedPaths); - }); - - it('Individual JARs can be added with their relative paths', () => { - // For the second test, we'll add the other two JARs with relative paths. - const relativePaths = [path.relative('.', tmpJar3), path.relative('.', tmpJar4)]; - const output = runCommand(`scanner rule add --language ${myLanguage} --path ${relativePaths.join(',')} --json`); - // The expectation is that the paths will be converted to absolute paths. - const expectedPaths = [tmpJar3, tmpJar4]; - const outputJson = output.jsonOutput; - const result = outputJson.result; - expect(result).to.have.property('success') - .and.equals(true); - - expect(result).to.have.property('language') - .and.equals(myLanguage); - - expect(result).to.have.property('path') - .and.have.lengthOf(expectedPaths.length) - .and.deep.equals(expectedPaths); - }); - }); - - - describe('Test Case: Adding all JARs in a folder', () => { - // Create two temporary directories, each containing three JARs. - const tmpDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar1 = path.join(tmpDir1, 'bar1.jar'); - const tmpJar2 = path.join(tmpDir1, 'bar2.jar'); - const tmpJar3 = path.join(tmpDir1, 'bar3.jar'); - fs.writeFileSync(tmpJar1, 'Then from the dark They came, and found the Souls of Lords within the flame.'); - fs.writeFileSync(tmpJar2, 'Gravelord Nito, the First of the Dead.'); - fs.writeFileSync(tmpJar3, 'The Witch of Izaleth, and her Daughters of Chaos.'); - const tmpDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'foo-')); - const tmpJar4 = path.join(tmpDir2, 'bar4.jar'); - const tmpJar5 = path.join(tmpDir2, 'bar5.jar'); - const tmpJar6 = path.join(tmpDir2, 'bar6.jar'); - fs.writeFileSync(tmpJar4, 'Gwynn, Lord of Sunlight, and his faithful knights.'); - fs.writeFileSync(tmpJar5, 'And the Furtive Pygmy, so easily forgotten.'); - fs.writeFileSync(tmpJar6, 'With the strength of Lords, they challenged the Dragons.'); - - // For the first test, we'll add one of the folders by its absolute path. - it('Folders can be added with their absolute paths', () => { - const output = runCommand(`scanner rule add --language ${myLanguage} --path ${tmpDir1} --json`); - // The expectation is that all three JARs in the folder will have been added. - const expectedPaths = [tmpJar1, tmpJar2, tmpJar3]; - const result = output.jsonOutput.result; - expect(result).to.have.property('success') - .and.equals(true); - - expect(result).to.have.property('language') - .and.equals(myLanguage); - - expect(result).to.have.property('path') - .and.have.lengthOf(expectedPaths.length) - .and.deep.equals(expectedPaths); - }); - - // For the second test, we'll add the other folder by its relative path. - it('Folders can be added by their relative paths', () => { - const output = runCommand(`scanner rule add --language ${myLanguage} --path ${path.relative('.', tmpDir2)} --json`); - // The expectation is that all three JARs in the folder will have been added. - const expectedPaths = [tmpJar4, tmpJar5, tmpJar6]; - const result = output.jsonOutput.result; - expect(result).to.have.property('success') - .and.equals(true); - - expect(result).to.have.property('language') - .and.equals(myLanguage); - - expect(result).to.have.property('path') - .and.have.lengthOf(expectedPaths.length) - .and.deep.equals(expectedPaths); - }); - }); - }); - - describe('Validations', () => { - describe('Language validations', () => { - // Test for failure scenario doesn't need to do any special setup or cleanup. - it('should complain about missing --language flag', () => { - const output = runCommand(`scanner rule add --path /some/local/path`); - expect(output.shellOutput.stderr).to.contain('Missing required flag language'); - }); - - // Test for failure scenario doesn't need to do any special setup or cleanup. - it('should complain about empty language entry', () => { - const output = runCommand(`scanner rule add --language "" --path /some/local/path`); - expect(output.shellOutput.stderr).to.contain(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty')); - }); - }); - - describe('Path validations', () => { - // Test for failure scenario doesn't need to do any special setup or cleanup. - it('should complain about missing --path flag', () => { - const output = runCommand(`scanner rule add --language apex`); - expect(output.shellOutput.stderr).to.contain('Missing required flag path'); - }); - - // Test for failure scenario doesn't need to do any special setup or cleanup. - it('should complain about empty path', () => { - const output = runCommand(`scanner rule add --language apex --path ''`); - expect(output.shellOutput.stderr).to.contain(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty')); - }); - }); - }); -}); diff --git a/test/lib/actions/RuleAddAction.test.ts b/test/lib/actions/RuleAddAction.test.ts new file mode 100644 index 000000000..4ec5ab228 --- /dev/null +++ b/test/lib/actions/RuleAddAction.test.ts @@ -0,0 +1,186 @@ +import {Logger} from '@salesforce/core'; +import {assert, expect} from 'chai'; +import sinon = require('sinon'); +import path = require('path'); +import untildify = require('untildify'); + +import {Inputs} from '../../../src/types'; +import {InputProcessor, InputProcessorImpl} from '../../../src/lib/InputProcessor'; +import {RuleAddAction} from '../../../src/lib/actions/RuleAddAction'; +import {BundleName, getMessage} from '../../../src/MessageCatalog'; +import {RulePathManager} from '../../../src/lib/RulePathManager'; +import {Controller} from '../../../src/Controller'; + +import {FakeDisplay} from '../FakeDisplay'; + +class FakeRulePathManager implements RulePathManager { + public language: string; + public paths: string[]; + + public init(): Promise { + return Promise.resolve(); + } + + /** + * For now, only this method needs a non-empty implementation. + * It just tracks what arguments it's fed. + */ + public addPathsForLanguage(language: string, paths: string[]): Promise { + this.language = language; + this.paths = paths; + return Promise.resolve(paths); + } + + public getAllPaths(): string[] { + return []; + } + + public getMatchingPaths(paths: string[]): Promise { + return Promise.resolve([]); + } + + public removePaths(paths: string[]): Promise { + return Promise.resolve([]); + } + + public getRulePathEntries(engine: string): Map> { + return new Map(); + } +} + +describe('RuleAddAction', () => { + let testLogger: Logger; + let testDisplay: FakeDisplay; + let testInputProcessor: InputProcessor; + let testAction: RuleAddAction; + + beforeEach(async () => { + testLogger = await Logger.child('RuleAddAction.test.ts'); + testDisplay = new FakeDisplay(); + testInputProcessor = new InputProcessorImpl('test', testDisplay); + testAction = new RuleAddAction(testLogger, testDisplay, testInputProcessor); + }); + + describe('#validateInputs', () => { + + it('Rejects missing `.language` property', async () => { + const inputs: Inputs = { + path: ['this/does/not/matter'] + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); + } + }); + + it('Rejects empty `.language` property', async () => { + const inputs: Inputs = { + language: '', + path: ['this/does/not/matter'] + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); + } + }); + + it('Rejects missing `.path` property', async () => { + const inputs: Inputs = { + language: 'apex' + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + } + }); + + it('Rejects empty `.path` property', async () => { + const inputs: Inputs = { + language: 'apex', + path: [] + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + } + }); + + it('Rejects `.path` containing empty string', async () => { + const inputs: Inputs = { + language: 'apex', + path: [""] + } + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + } + }); + }); + + describe('#run', () => { + let fakeRulePathManager: FakeRulePathManager; + let controllerStub; + const language = 'apex'; + const inputPaths = [ + '~/this/path/is/tildified', + '/This/Path/Is/Absolute', + './This/Path/Is/Relative' + ]; + const expectedOutputPaths = [ + untildify(inputPaths[0]), + inputPaths[1], + path.resolve(inputPaths[2]) + ]; + const inputs: Inputs = { + language, + path: inputPaths + }; + + beforeEach(() => { + fakeRulePathManager = new FakeRulePathManager(); + controllerStub = sinon.stub(Controller, 'createRulePathManager'); + controllerStub.resolves(fakeRulePathManager); + + }); + + afterEach(() => { + sinon.restore(); + }); + + it('Passes un-tildified paths into CustomRulePathManager', async () => { + // ==== TESTED METHOD INVOCATION ==== + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + expect(fakeRulePathManager.language).to.equal(language); + expect(fakeRulePathManager.paths).to.have.lengthOf(3); + expect(fakeRulePathManager.paths[0]).to.equal(expectedOutputPaths[0], 'Should receive untildified tilde path'); + expect(fakeRulePathManager.paths[1]).to.equal(expectedOutputPaths[1], 'Should receive unchanged absolute path'); + expect(fakeRulePathManager.paths[2]).to.equal(expectedOutputPaths[2], 'Should absolutized relative path'); + }); + + it('Displays information about added paths', async () => { + // ==== TESTED METHOD INVOCATION ==== + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + expect(testDisplay.getOutputArray()).to.contain(`[Info]: ${getMessage(BundleName.Add, 'output.successfullyAddedRules', [language])}`); + expect(testDisplay.getOutputArray()).to.contain(`[Info]: ${getMessage(BundleName.Add, 'output.resultSummary', [3, expectedOutputPaths.toString()])}`); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 08e2405d9..9c6923511 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,6 +15,664 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/crc32c@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz#016c92da559ef638a84a245eecb75c3e97cb664f" + integrity sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/ie11-detection@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" + integrity sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/sha1-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz#f9083c00782b24714f528b1a1fef2174002266a3" + integrity sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" + integrity sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/sha256-js" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" + integrity sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/supports-web-crypto@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" + integrity sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/util@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" + integrity sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/client-cloudfront@^3.511.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudfront/-/client-cloudfront-3.515.0.tgz#34324ed503c411b1e89a30fcb00779092f50d575" + integrity sha512-aDiTeB2QEX6M9I3yqchCce4z78wRuDOh3oZq2eiBueJqk3R3RGm8zDdsiJ+U9N6NVSmcm7Xs55Ws8NUJZGwizw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.515.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/credential-provider-node" "3.515.0" + "@aws-sdk/middleware-host-header" "3.515.0" + "@aws-sdk/middleware-logger" "3.515.0" + "@aws-sdk/middleware-recursion-detection" "3.515.0" + "@aws-sdk/middleware-user-agent" "3.515.0" + "@aws-sdk/region-config-resolver" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@aws-sdk/util-user-agent-browser" "3.515.0" + "@aws-sdk/util-user-agent-node" "3.515.0" + "@aws-sdk/xml-builder" "3.496.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.2" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-stream" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + "@smithy/util-waiter" "^2.1.1" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/client-s3@^3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.515.0.tgz#f14aa19c55292cee36f07b314655e435e52b3bc6" + integrity sha512-K527n83hrMUdosxOYTzL63wtlJtmN5SUJZnGY1sUR6UyOrnOr9lS6t3AB6BgHqLFRFZJqSqmhflv2cOD7P1UPg== + dependencies: + "@aws-crypto/sha1-browser" "3.0.0" + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.515.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/credential-provider-node" "3.515.0" + "@aws-sdk/middleware-bucket-endpoint" "3.515.0" + "@aws-sdk/middleware-expect-continue" "3.515.0" + "@aws-sdk/middleware-flexible-checksums" "3.515.0" + "@aws-sdk/middleware-host-header" "3.515.0" + "@aws-sdk/middleware-location-constraint" "3.515.0" + "@aws-sdk/middleware-logger" "3.515.0" + "@aws-sdk/middleware-recursion-detection" "3.515.0" + "@aws-sdk/middleware-sdk-s3" "3.515.0" + "@aws-sdk/middleware-signing" "3.515.0" + "@aws-sdk/middleware-ssec" "3.515.0" + "@aws-sdk/middleware-user-agent" "3.515.0" + "@aws-sdk/region-config-resolver" "3.515.0" + "@aws-sdk/signature-v4-multi-region" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@aws-sdk/util-user-agent-browser" "3.515.0" + "@aws-sdk/util-user-agent-node" "3.515.0" + "@aws-sdk/xml-builder" "3.496.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.2" + "@smithy/eventstream-serde-browser" "^2.1.1" + "@smithy/eventstream-serde-config-resolver" "^2.1.1" + "@smithy/eventstream-serde-node" "^2.1.1" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-blob-browser" "^2.1.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/hash-stream-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/md5-js" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-stream" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + "@smithy/util-waiter" "^2.1.1" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/client-sso-oidc@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.515.0.tgz#7864bbcc1cca2441c726b1db5ef74be6142ec270" + integrity sha512-zACa8LNlPUdlNUBqQRf5a3MfouLNtcBfm84v2c8M976DwJrMGONPe1QjyLLsD38uESQiXiVQRruj/b000iMXNw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.515.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.515.0" + "@aws-sdk/middleware-logger" "3.515.0" + "@aws-sdk/middleware-recursion-detection" "3.515.0" + "@aws-sdk/middleware-user-agent" "3.515.0" + "@aws-sdk/region-config-resolver" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@aws-sdk/util-user-agent-browser" "3.515.0" + "@aws-sdk/util-user-agent-node" "3.515.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.2" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.515.0.tgz#858d3ebd187e54e70ebd7ac948fb889f70a7deee" + integrity sha512-4oGBLW476zmkdN98lAns3bObRNO+DLOfg4MDUSR6l6GYBV/zGAtoy2O/FhwYKgA2L5h2ZtElGopLlk/1Q0ePLw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.515.0" + "@aws-sdk/middleware-logger" "3.515.0" + "@aws-sdk/middleware-recursion-detection" "3.515.0" + "@aws-sdk/middleware-user-agent" "3.515.0" + "@aws-sdk/region-config-resolver" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@aws-sdk/util-user-agent-browser" "3.515.0" + "@aws-sdk/util-user-agent-node" "3.515.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.2" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.515.0.tgz#a645696bbc160e46c4c9e60aa66b79fd212d1230" + integrity sha512-ScYuvaIDgip3atOJIA1FU2n0gJkEdveu1KrrCPathoUCV5zpK8qQmO/n+Fj/7hKFxeKdFbB+4W4CsJWYH94nlg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.513.0" + "@aws-sdk/middleware-host-header" "3.515.0" + "@aws-sdk/middleware-logger" "3.515.0" + "@aws-sdk/middleware-recursion-detection" "3.515.0" + "@aws-sdk/middleware-user-agent" "3.515.0" + "@aws-sdk/region-config-resolver" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@aws-sdk/util-user-agent-browser" "3.515.0" + "@aws-sdk/util-user-agent-node" "3.515.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.2" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.2.0" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/core@3.513.0": + version "3.513.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.513.0.tgz#9fce86d472f7b38724cb1156d06a854124a51aaa" + integrity sha512-L+9DL4apWuqNKVOMJ8siAuWoRM9rZf9w1iPv8S2o83WO2jVK7E/m+rNW1dFo9HsA5V1ccDl2H2qLXx24HiHmOw== + dependencies: + "@smithy/core" "^1.3.2" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.515.0.tgz#8a96e51bb50a70596ec8d6fc38a78c2aca3b5b6f" + integrity sha512-45vxdyqhTAaUMERYVWOziG3K8L2TV9G4ryQS/KZ84o7NAybE9GMdoZRVmGHAO7mJJ1wQiYCM/E+i5b3NW9JfNA== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-http@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.515.0.tgz#780b31ebb0d2c3fb1da31d163a2f39edb7d7d7c5" + integrity sha512-Ba6FXK77vU4WyheiamNjEuTFmir0eAXuJGPO27lBaA8g+V/seXGHScsbOG14aQGDOr2P02OPwKGZrWWA7BFpfQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-stream" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.515.0.tgz#f669afd30aeac6088db0d7d485730c633836872b" + integrity sha512-ouDlNZdv2TKeVEA/YZk2+XklTXyAAGdbWnl4IgN9ItaodWI+lZjdIoNC8BAooVH+atIV/cZgoGTGQL7j2TxJ9A== + dependencies: + "@aws-sdk/client-sts" "3.515.0" + "@aws-sdk/credential-provider-env" "3.515.0" + "@aws-sdk/credential-provider-process" "3.515.0" + "@aws-sdk/credential-provider-sso" "3.515.0" + "@aws-sdk/credential-provider-web-identity" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.515.0.tgz#57e2105208fb8b2edc857f48533cb0a1e28a9412" + integrity sha512-Y4kHSpbxksiCZZNcvsiKUd8Fb2XlyUuONEwqWFNL82ZH6TCCjBGS31wJQCSxBHqYcOL3tiORUEJkoO7uS30uQA== + dependencies: + "@aws-sdk/credential-provider-env" "3.515.0" + "@aws-sdk/credential-provider-http" "3.515.0" + "@aws-sdk/credential-provider-ini" "3.515.0" + "@aws-sdk/credential-provider-process" "3.515.0" + "@aws-sdk/credential-provider-sso" "3.515.0" + "@aws-sdk/credential-provider-web-identity" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.515.0.tgz#71e1e624669ef5918b477b48ec8aff1bd686e787" + integrity sha512-pSjiOA2FM63LHRKNDvEpBRp80FVGT0Mw/gzgbqFXP+sewk0WVonYbEcMDTJptH3VsLPGzqH/DQ1YL/aEIBuXFQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.515.0.tgz#b8efce2c885adf529c4f70db76bcc188afef299b" + integrity sha512-j7vUkiSmuhpBvZYoPTRTI4ePnQbiZMFl6TNhg9b9DprC1zHkucsZnhRhqjOVlrw/H6J4jmcPGcHHTZ5WQNI5xQ== + dependencies: + "@aws-sdk/client-sso" "3.515.0" + "@aws-sdk/token-providers" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.515.0.tgz#848f113ca92dd7a6ebbb436872688a78a28d309b" + integrity sha512-66+2g4z3fWwdoGReY8aUHvm6JrKZMTRxjuizljVmMyOBttKPeBYXvUTop/g3ZGUx1f8j+C5qsGK52viYBvtjuQ== + dependencies: + "@aws-sdk/client-sts" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-bucket-endpoint@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.515.0.tgz#59dc2a3443f458cc503f70490618814ad0c2cbd9" + integrity sha512-Vm423j3udFrhKPaKiXtie+6aF05efjX8lhAu5VOruIvbam7olvdWNdkH7sGWlz1ko3CVa7PwOYjGHiOOhxpEOA== + dependencies: + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-arn-parser" "3.495.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-expect-continue@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.515.0.tgz#4a9056cbc0acf2dd89b29220fbd9ae5da56b8256" + integrity sha512-TWCXulivab4reOMx/vxa/IwnPX78fLwI9NUoAxjsqB6W9qjmSnPD43BSVeGvbbl/YNmgk7XfMbZb6IgxW7RyzA== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-flexible-checksums@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.515.0.tgz#88302e23931bb936f12048953a825cfe8fa5c3c3" + integrity sha512-ydGjnqNeYlJaAkmQeQnS4pZRAAvzefdm8c234Qh0Fg55xRwHTNLp7uYsdfkTjrdAlj6YIO3Zr6vK6VJ6MGCwug== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@aws-crypto/crc32c" "3.0.0" + "@aws-sdk/types" "3.515.0" + "@smithy/is-array-buffer" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.515.0.tgz#835a1865d4e35ad8fd2f7e579b191d58f52e450c" + integrity sha512-I1MwWPzdRKM1luvdDdjdGsDjNVPhj9zaIytEchjTY40NcKOg+p2evLD2y69ozzg8pyXK63r8DdvDGOo9QPuh0A== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-location-constraint@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.515.0.tgz#848a90fb284ba7fc7258faada73808425aeb7b76" + integrity sha512-ORFC5oijjTJsHhUXy9o52/vl5Irf6e83bE/8tBp+sVVx81+E8zTTWZbysoa41c0B5Ycd0H3wCWutvjdXT16ydQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.515.0.tgz#430fc40d6897fdc25ad82075865d00d5d707b6ad" + integrity sha512-qXomJzg2m/5seQOxHi/yOXOKfSjwrrJSmEmfwJKJyQgdMbBcjz3Cz0H/1LyC6c5hHm6a/SZgSTzDAbAoUmyL+Q== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.515.0.tgz#7f44705d6d93adbcc743a5adf3bfa2c09670637c" + integrity sha512-dokHLbTV3IHRIBrw9mGoxcNTnQsjlm7TpkJhPdGT9T4Mq399EyQo51u6IsVMm07RXLl2Zw7u+u9p+qWBFzmFRA== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-s3@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.515.0.tgz#5d3e355d474c22c6748a4a6e48788eca3e81b713" + integrity sha512-vB8JwiTEAqm1UT9xfugnCgl0H0dtBLUQQK99JwQEWjHPZmQ3HQuVkykmJRY3X0hzKMEgqXodz0hZOvf3Hq1mvQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-arn-parser" "3.495.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.515.0.tgz#1fe447d8fdc403367a7ba4af53d2dcc647c24190" + integrity sha512-SdjCyQCL702I07KhCiBFcoh6+NYtnruHJQIzWwMpBteuYHnCHW1k9uZ6pqacsS+Y6qpAKfTVNpQx2zP2s6QoHA== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-ssec@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.515.0.tgz#395a16a27b99246bb88e8344ec8c0da507cdf1a6" + integrity sha512-0qLjKiorosVBzzaV/o7MEyS9xqLLu02qGbP564Z/FZY74JUQEpBNedgveMUbb6lqr85RnOuwZ0GZ0cBRfH2brQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.515.0.tgz#93daacea920fad11481559e5a399cf786e5e6c0c" + integrity sha512-nOqZjGA/GkjuJ5fUshec9Fv6HFd7ovOTxMJbw3MfAhqXuVZ6dKF41lpVJ4imNsgyFt3shUg9WDY8zGFjlYMB3g== + dependencies: + "@aws-sdk/types" "3.515.0" + "@aws-sdk/util-endpoints" "3.515.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/region-config-resolver@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.515.0.tgz#c0973acc32256c3688265512cf6d0469baa3af21" + integrity sha512-RIRx9loxMgEAc/r1wPfnfShOuzn4RBi8pPPv6/jhhITEeMnJe6enAh2k5y9DdiVDDgCWZgVFSv0YkAIfzAFsnQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/signature-v4-multi-region@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.515.0.tgz#93d10569869ccc506a7cb6603566c9e0638a436e" + integrity sha512-5lrCn4DSE0zL41k0L6moqcdExZhWdAnV0/oMEagrISzQYoia+aNTEeyVD3xqJhRbEW4gCj3Uoyis6c8muf7b9g== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.515.0.tgz#c4e549a28d287b2861a2d331eae2be98c4236bd1" + integrity sha512-MQuf04rIcTXqwDzmyHSpFPF1fKEzRl64oXtCRUF3ddxTdK6wxXkePfK6wNCuL+GEbEcJAoCtIGIRpzGPJvQjHA== + dependencies: + "@aws-sdk/client-sso-oidc" "3.515.0" + "@aws-sdk/types" "3.515.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/types@3.515.0", "@aws-sdk/types@^3.222.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.515.0.tgz#ee97c887293211f1891bc1d8f0aaf354072b6002" + integrity sha512-B3gUpiMlpT6ERaLvZZ61D0RyrQPsFYDkCncLPVkZOKkCOoFU46zi1o6T5JcYiz8vkx1q9RGloQ5exh79s5pU/w== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/util-arn-parser@3.495.0": + version "3.495.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.495.0.tgz#539f2d6dfef343a80324348f1f9a1b7eed2390f3" + integrity sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-endpoints@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.515.0.tgz#6d8bcc62617261a4c1de5d7507060ab361694923" + integrity sha512-UJi+jdwcGFV/F7d3+e2aQn5yZOVpDiAgfgNhPnEtgV0WozJ5/ZUeZBgWvSc/K415N4A4D/9cbBc7+I+35qzcDQ== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/types" "^2.9.1" + "@smithy/util-endpoints" "^1.1.1" + tslib "^2.5.0" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.495.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz#9034fd8db77991b28ed20e067acdd53e8b8f824b" + integrity sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-browser@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.515.0.tgz#f3c7027cfbfaf1786ae32176dd5ac8b0753ad0a1" + integrity sha512-pTWQb0JCafTmLHLDv3Qqs/nAAJghcPdGQIBpsCStb0YEzg3At/dOi2AIQ683yYnXmeOxLXJDzmlsovfVObJScw== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/types" "^2.9.1" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.515.0": + version "3.515.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.515.0.tgz#a76182778964e9e9098f5607b379c0efb12ffaa4" + integrity sha512-A/KJ+/HTohHyVXLH+t/bO0Z2mPrQgELbQO8tX+B2nElo8uklj70r5cT7F8ETsI9oOy+HDVpiL5/v45ZgpUOiPg== + dependencies: + "@aws-sdk/types" "3.515.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + +"@aws-sdk/xml-builder@3.496.0": + version "3.496.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.496.0.tgz#7d0ef487a8088ef84a5a9aad228e6173ca85341d" + integrity sha512-GvEjh537IIeOw1ZkZuB37sV12u+ipS5Z1dwjEC/HAvhl5ac23ULtTr1/n+U1gLNN+BAKSWjKiQ2ksj8DiUzeyw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" @@ -29,20 +687,20 @@ integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@^7.11.0", "@babel/core@^7.7.5": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" - integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" + integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.23.5" "@babel/generator" "^7.23.6" "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.7" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" + "@babel/helpers" "^7.23.9" + "@babel/parser" "^7.23.9" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -71,9 +729,9 @@ semver "^6.3.1" "@babel/eslint-parser@^7": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.3.tgz#7bf0db1c53b54da0c8a12627373554a0828479ca" - integrity sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw== + version "7.23.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz#2d4164842d6db798873b40e0c4238827084667a2" + integrity sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" @@ -176,14 +834,14 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== -"@babel/helpers@^7.22.15", "@babel/helpers@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.7.tgz#eb543c36f81da2873e47b76ee032343ac83bba60" - integrity sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ== +"@babel/helpers@^7.22.15", "@babel/helpers@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" + integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" "@babel/highlight@^7.23.4": version "7.23.4" @@ -194,39 +852,39 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== +"@babel/parser@^7.22.16", "@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== "@babel/runtime-corejs3@^7.12.5": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.7.tgz#2c3d323d21569f2950c9126780bfa400632360bd" - integrity sha512-ER55qzLREVA5YxeyQ3Qu48tgsF2ZrFjFjUS6V6wF0cikSw+goBJgB9PBRM1T6+Ah4iiM+sxmfS/Sy/jdzFfhiQ== + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.9.tgz#1b43062a13ecb60158aecdd81bc3fab4108b7cbc" + integrity sha512-oeOFTrYWdWXCvXGB5orvMTJ6gCZ9I6FBjR+M38iKNXCsPxr4xT0RTdg5uz1H7QP8pp74IzPtwritEr+JscqHXQ== dependencies: core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" "@babel/runtime@^7.12.5": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193" - integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA== + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== +"@babel/template@^7.22.15", "@babel/template@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" -"@babel/traverse@^7.22.20", "@babel/traverse@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== +"@babel/traverse@^7.22.20", "@babel/traverse@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== dependencies: "@babel/code-frame" "^7.23.5" "@babel/generator" "^7.23.6" @@ -234,15 +892,15 @@ "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== +"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== dependencies: "@babel/helper-string-parser" "^7.23.4" "@babel/helper-validator-identifier" "^7.22.20" @@ -293,12 +951,12 @@ integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@humanwhocodes/config-array@^0.11.13": - version "0.11.13" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" - integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^2.0.1" - debug "^4.1.1" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": @@ -306,10 +964,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" - integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -361,9 +1019,9 @@ "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/set-array@^1.0.1": version "1.1.2" @@ -384,9 +1042,9 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + version "0.3.22" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" + integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -659,11 +1317,12 @@ wordwrap "^1.0.0" wrap-ansi "^7.0.0" -"@oclif/core@^3.15.0", "@oclif/core@^3.15.1", "@oclif/core@^3.16.0", "@oclif/core@^3.3.2": - version "3.16.0" - resolved "https://registry.yarnpkg.com/@oclif/core/-/core-3.16.0.tgz#682657cb5e4a3262a47e26e0c8a7bf0343acaf76" - integrity sha512-/PIz+udzb59XE8O/bQvqlCtXy6RByEHH0KsrAJNa/ZrqtdsLmeDNJcHdgygFHx+nz+PYMoUzsyzJMau++EDNoQ== +"@oclif/core@^3.15.1", "@oclif/core@^3.19.2", "@oclif/core@^3.19.3", "@oclif/core@^3.3.2": + version "3.19.3" + resolved "https://registry.yarnpkg.com/@oclif/core/-/core-3.19.3.tgz#8ae8c2bd3a95145ce911346855f304a29d6afbac" + integrity sha512-pILSMpQ1ltAe51dgGxVsjfEVaZrRSEE3pKBGh/GtUkmVCJCP2MiS4AFg1qiLGrwjks0WrzSii3QdM4jDLyMAAA== dependencies: + "@types/cli-progress" "^3.11.5" ansi-escapes "^4.3.2" ansi-styles "^4.3.0" cardinal "^2.1.1" @@ -687,7 +1346,6 @@ strip-ansi "^6.0.1" supports-color "^8.1.1" supports-hyperlinks "^2.2.0" - tsconfck "^3.0.0" widest-line "^3.1.0" wordwrap "^1.0.0" wrap-ansi "^7.0.0" @@ -699,28 +1357,28 @@ dependencies: "@oclif/core" "^2.15.0" -"@oclif/plugin-help@^6.0.9": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-6.0.9.tgz#87bbf624372b9afe5dc183a13f52c929d6b022cf" - integrity sha512-O9zHzjsj8G3DWV+Ju4prrBwHUmwT1pcq7AJNxguedMk8jGZhwKWrcQHdZX6kjC+7QbupSzgjcvXvXpYVR1y3ow== +"@oclif/plugin-help@^6.0.12": + version "6.0.13" + resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-6.0.13.tgz#36e3eaeb5552b375d44630ef6abfb8a6b9ab7ba4" + integrity sha512-D/hiHmg+c6eOny95VfbhBcdgGxbi4AU2I3s1nFit0wpV2YziZnjmD7NQvYUCUJB052RcVmni6NiegttLgM4y5g== dependencies: - "@oclif/core" "^3.15.0" + "@oclif/core" "^3.19.2" -"@oclif/plugin-not-found@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@oclif/plugin-not-found/-/plugin-not-found-3.0.7.tgz#7dcdd1406d464f74eb37e9cde73918d5e1139d8d" - integrity sha512-AofTUzKVvuU9uQBKMhX3i62aPeoijqtNsRM4rHShS4FyUd1MEhjbI2SmxcNTWjwedRL5F+b9EpjWuswc86fUMg== +"@oclif/plugin-not-found@^3.0.10": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@oclif/plugin-not-found/-/plugin-not-found-3.0.11.tgz#222515ff74f52d354e9cd49ae5bf0984823c2ae8" + integrity sha512-bmZHh5INkqnouz8E/8QiZ2q+hXeela4s8cnxdtcCNEc2vb5JIYYa0JAPR/LVmE2q19LyKStIOOpDy/eVdonpPg== dependencies: - "@oclif/core" "^3.15.1" + "@oclif/core" "^3.19.3" chalk "^5.3.0" fast-levenshtein "^3.0.0" -"@oclif/plugin-warn-if-update-available@^3.0.8": - version "3.0.8" - resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.0.8.tgz#715c7f8896a318805cae08f2994115b8d5e39c20" - integrity sha512-CNusBwZHzWdj4E6xVBbR9+DtxjeQZoK2LDYk3CFwBfLd5L8TJ/6IJNer0ZacDRvnCeABeVqMN33Vk7UlmJ7ngQ== +"@oclif/plugin-warn-if-update-available@^3.0.10": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.0.11.tgz#c5915dcce656d2bb66ffff090d86ad5d91bf11b1" + integrity sha512-L3WqhpkSAry0V/OAmScgvQol4lQedhNUg6vx3CkOVKdu2K54lRcQ/v74SLLSTC//0+Kg03JNKflnuYlcbR2RJQ== dependencies: - "@oclif/core" "^3.15.1" + "@oclif/core" "^3.19.2" chalk "^5.3.0" debug "^4.1.0" http-call "^5.2.2" @@ -833,11 +1491,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@salesforce/cli-plugins-testkit@^5.0.4": - version "5.1.3" - resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-5.1.3.tgz#5e7a7afebaa9a2c02eadbf533273d496335929d6" - integrity sha512-wmaiVR2Hr6AGUBdDF4M5xCEm4iczNdkm3lVlz8dU/8nISEAyNHOUkt2sB07Yx5oXoDMNNuuxM2DthxxMxxwzzA== + version "5.1.9" + resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-5.1.9.tgz#c21b0d282c0d309141ca5e2fe47835530a24621d" + integrity sha512-8a9dwYdo2tXhVMrDe4ex8tjMYGuIwT9wlltB4+h3gt/IuowazjQGy5VWam08gsm3UT/FhhjZBdN0aKJPbD4wXA== dependencies: - "@salesforce/core" "^6.4.2" + "@salesforce/core" "^6.5.3" "@salesforce/kit" "^3.0.15" "@salesforce/ts-types" "^2.0.9" "@types/shelljs" "^0.8.15" @@ -845,7 +1503,7 @@ jszip "^3.10.1" shelljs "^0.8.4" strip-ansi "6.0.1" - ts-retry-promise "^0.7.1" + ts-retry-promise "^0.8.0" "@salesforce/core@^5": version "5.3.20" @@ -871,15 +1529,15 @@ semver "^7.5.4" ts-retry-promise "^0.7.1" -"@salesforce/core@^6.4.0", "@salesforce/core@^6.4.1", "@salesforce/core@^6.4.2": - version "6.4.3" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-6.4.3.tgz#77edcf00c4b6e0b43a0620eb7d1cd97ad0bf17e4" - integrity sha512-MEHd9W2PM+Ytosirry7vInBrtU4RZK+v7ubNozbR4kCWr4yMe+1vzAkGqB2NoL5vAVbOmF7wyy8+tMGYCyLyww== +"@salesforce/core@^6.4.1", "@salesforce/core@^6.5.1", "@salesforce/core@^6.5.3": + version "6.5.5" + resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-6.5.5.tgz#ddfab1f6a51808ed1cadc98be3b7235d25ea436f" + integrity sha512-2zWTwc9m+LGJNSKXk6I01dzWEjWKkHyYZbROksIPzfWJ5lGfErzpvsTcGAAskBrJD9EpQ4/BtMSLhPSwskI7Fw== dependencies: "@salesforce/kit" "^3.0.15" "@salesforce/schemas" "^1.6.1" "@salesforce/ts-types" "^2.0.9" - "@types/semver" "^7.5.6" + "@types/semver" "^7.5.7" ajv "^8.12.0" change-case "^4.1.2" faye "^1.4.0" @@ -888,11 +1546,11 @@ jsforce "^2.0.0-beta.29" jsonwebtoken "9.0.2" jszip "3.10.1" - pino "^8.16.2" + pino "^8.19.0" pino-abstract-transport "^1.1.0" pino-pretty "^10.3.1" proper-lockfile "^4.1.2" - semver "^7.5.4" + semver "^7.6.0" ts-retry-promise "^0.7.1" "@salesforce/dev-config@^4.1.0": @@ -901,9 +1559,9 @@ integrity sha512-2iDDepiIwjXHS5IVY7pwv8jMo4xWosJ7p/UTj+lllpB/gnJiYLhjJPE4Z3FCGFKyvfg5jGaimCd8Ca6bLGsCQA== "@salesforce/eslint-config-lwc@^3.2.1": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@salesforce/eslint-config-lwc/-/eslint-config-lwc-3.5.2.tgz#45ae1596a35395cfec7c49736b9c52f8b9aa2b82" - integrity sha512-TqD5pF/OwjNNrms5nn9f6bf630T7WzXuH0RYF1ybsFOYsGQ2vFxD/F5fUNAjdQgLTR0hXK303j8yIw2fwTiOIQ== + version "3.5.3" + resolved "https://registry.yarnpkg.com/@salesforce/eslint-config-lwc/-/eslint-config-lwc-3.5.3.tgz#dcbc06e05e2d42fd01ac469d5648dd7b1cf056c5" + integrity sha512-bQ3EdqDQadG18a19Aw7VD6iS5YPuQXNPjfvR/bOFzu1DZoctW5lq28gSMueRLoYjBW+dDa2V8gUWQNmj+b0JUQ== dependencies: "@babel/core" "~7.22.8" "@babel/eslint-parser" "~7.22.7" @@ -991,7 +1649,7 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== -"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3": +"@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.7.0": version "1.8.6" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== @@ -1006,63 +1664,520 @@ type-detect "4.0.8" "@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== +"@sinonjs/fake-timers@^11.2.2": + version "11.2.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" + integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== dependencies: "@sinonjs/commons" "^3.0.0" -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== - dependencies: - "@sinonjs/commons" "^1.7.0" - "@sinonjs/formatio@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" integrity sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg== dependencies: - samsam "1.3.0" + samsam "1.3.0" + +"@sinonjs/formatio@^3.2.1": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c" + integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ== + dependencies: + "@sinonjs/commons" "^1" + "@sinonjs/samsam" "^3.1.0" + +"@sinonjs/samsam@^3.1.0": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a" + integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ== + dependencies: + "@sinonjs/commons" "^1.3.0" + array-from "^2.1.1" + lodash "^4.17.15" + +"@sinonjs/samsam@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" + integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== + dependencies: + "@sinonjs/commons" "^2.0.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.1", "@sinonjs/text-encoding@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + +"@smithy/abort-controller@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.1.1.tgz#bb68596a7c8213c2ef259bc7fb0f0c118c67ea9d" + integrity sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/chunked-blob-reader-native@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.1.1.tgz#6b98479c8f6ea94832dd6a6e5ca78969a44eafe1" + integrity sha512-zNW+43dltfNMUrBEYLMWgI8lQr0uhtTcUyxkgC9EP4j17WREzgSFMPUFVrVV6Rc2+QtWERYjb4tzZnQGa7R9fQ== + dependencies: + "@smithy/util-base64" "^2.1.1" + tslib "^2.5.0" + +"@smithy/chunked-blob-reader@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.1.1.tgz#997faba8e197e0cb9824dad30ae581466e386e57" + integrity sha512-NjNFCKxC4jVvn+lUr3Yo4/PmUJj3tbyqH6GNHueyTGS5Q27vlEJ1MkNhUDV8QGxJI7Bodnc2pD18lU2zRfhHlQ== + dependencies: + tslib "^2.5.0" + +"@smithy/config-resolver@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.1.1.tgz#fc6b036084b98fd26a8ff01a5d7eb676e41749c7" + integrity sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/core@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-1.3.2.tgz#e11f3860b69ec0bdbd31e6afaa54963c02dc7f8e" + integrity sha512-tYDmTp0f2TZVE18jAOH1PnmkngLQ+dOGUlMd1u67s87ieueNeyqhja6z/Z4MxhybEiXKOWFOmGjfTZWFxljwJw== + dependencies: + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/credential-provider-imds@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz#4805bf5e104718b959cf8699113fa9de6ddeeafa" + integrity sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + tslib "^2.5.0" + +"@smithy/eventstream-codec@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz#4405ab0f9c77d439c575560c4886e59ee17d6d38" + integrity sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@smithy/types" "^2.9.1" + "@smithy/util-hex-encoding" "^2.1.1" + tslib "^2.5.0" + +"@smithy/eventstream-serde-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.1.tgz#743a374639e9e2dd858b6fda1fd814eb6c604946" + integrity sha512-JvEdCmGlZUay5VtlT8/kdR6FlvqTDUiJecMjXsBb0+k1H/qc9ME5n2XKPo8q/MZwEIA1GmGgYMokKGjVvMiDow== + dependencies: + "@smithy/eventstream-serde-universal" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/eventstream-serde-config-resolver@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.1.tgz#0b84d6f8be0836af7b92455c69f7427e4f01e7a2" + integrity sha512-EqNqXYp3+dk//NmW3NAgQr9bEQ7fsu/CcxQmTiq07JlaIcne/CBWpMZETyXm9w5LXkhduBsdXdlMscfDUDn2fA== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/eventstream-serde-node@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.1.tgz#2e1afa27f9c7eb524c1c53621049c5e4e3cea6a5" + integrity sha512-LF882q/aFidFNDX7uROAGxq3H0B7rjyPkV6QDn6/KDQ+CG7AFkRccjxRf1xqajq/Pe4bMGGr+VKAaoF6lELIQw== + dependencies: + "@smithy/eventstream-serde-universal" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/eventstream-serde-universal@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.1.tgz#0f5eec9ad033017973a67bafb5549782499488d2" + integrity sha512-LR0mMT+XIYTxk4k2fIxEA1BPtW3685QlqufUEUAX1AJcfFfxNDKEvuCRZbO8ntJb10DrIFVJR9vb0MhDCi0sAQ== + dependencies: + "@smithy/eventstream-codec" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/fetch-http-handler@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz#b4d73bbc1449f61234077d58c705b843a8587bf0" + integrity sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg== + dependencies: + "@smithy/protocol-http" "^3.1.1" + "@smithy/querystring-builder" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-base64" "^2.1.1" + tslib "^2.5.0" + +"@smithy/hash-blob-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.1.tgz#f4571d4e2fbc2cc1869c443850e5409bf541ba25" + integrity sha512-jizu1+2PAUjiGIfRtlPEU8Yo6zn+d78ti/ZHDesdf1SUn2BuZW433JlPoCOLH3dBoEEvTgLvQ8tUGSoTTALA+A== + dependencies: + "@smithy/chunked-blob-reader" "^2.1.1" + "@smithy/chunked-blob-reader-native" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/hash-node@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.1.1.tgz#0f8a22d97565ca948724f72267e4d3a2f33740a8" + integrity sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-buffer-from" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/hash-stream-node@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-2.1.1.tgz#d1885a3bf159872cbb8c9d9f1aefc596ea6cf5db" + integrity sha512-VgDaKcfCy0iHcmtAZgZ3Yw9g37Gkn2JsQiMtFQXUh8Wmo3GfNgDwLOtdhJ272pOT7DStzpe9cNr+eV5Au8KfQA== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/invalid-dependency@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz#bd69fa24dd35e9bc65a160bd86becdf1399e4463" + integrity sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/is-array-buffer@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz#07b4c77ae67ed58a84400c76edd482271f9f957b" + integrity sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ== + dependencies: + tslib "^2.5.0" + +"@smithy/md5-js@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-2.1.1.tgz#f414982bc6ab275b80ec517d2e44a779c374ff9c" + integrity sha512-L3MbIYBIdLlT+MWTYrdVSv/dow1+6iZ1Ad7xS0OHxTTs17d753ZcpOV4Ro7M7tRAVWML/sg2IAp/zzCb6aAttg== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/middleware-content-length@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz#df767de12d594bc5622009fb0fc8343522697d8c" + integrity sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g== + dependencies: + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/middleware-endpoint@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz#9e500df4d944741808e92018ccd2e948b598a49f" + integrity sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q== + dependencies: + "@smithy/middleware-serde" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/middleware-retry@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz#ddc749dd927f136714f76ca5a52dcfb0993ee162" + integrity sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/service-error-classification" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + tslib "^2.5.0" + uuid "^8.3.2" + +"@smithy/middleware-serde@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz#2c5750f76e276a5249720f6c3c24fac29abbee16" + integrity sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/middleware-stack@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz#67f992dc36e8a6861f881f80a81c1c30956a0396" + integrity sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/node-config-provider@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz#c440c7948d58d72f0e212aa1967aa12f0729defd" + integrity sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg== + dependencies: + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/node-http-handler@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz#77d23279ff0a12cbe7cde93c5e7c0e86ad56dd20" + integrity sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA== + dependencies: + "@smithy/abort-controller" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/querystring-builder" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/property-provider@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.1.1.tgz#0f7ffc5e43829eaca5b2b5aae8554807a52b30f3" + integrity sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/protocol-http@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-3.1.1.tgz#eee522d0ed964a72b735d64925e07bcfb7a7806f" + integrity sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/querystring-builder@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz#b9693448ad3f8e0767d84cf5cae29f35514591fb" + integrity sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-uri-escape" "^2.1.1" + tslib "^2.5.0" + +"@smithy/querystring-parser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz#a4282a66cc56844317dbff824e573f469bbfc032" + integrity sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/service-error-classification@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz#dd24e1ec529ae9ec8e87d8b15f0fc8f7e17f3d02" + integrity sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw== + dependencies: + "@smithy/types" "^2.9.1" + +"@smithy/shared-ini-file-loader@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz#a2e28b4d85f8a8262a84403fa2b74a086b3a7703" + integrity sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/signature-v4@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.1.1.tgz#6080171e3d694f40d3f553bbc236c5c433efd4d2" + integrity sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg== + dependencies: + "@smithy/eventstream-codec" "^2.1.1" + "@smithy/is-array-buffer" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-hex-encoding" "^2.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-uri-escape" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/smithy-client@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.3.1.tgz#0c3a4a0d3935c7ad2240cc23181f276705212b1f" + integrity sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA== + dependencies: + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-stream" "^2.1.1" + tslib "^2.5.0" + +"@smithy/types@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.9.1.tgz#ed04d4144eed3b8bd26d20fc85aae8d6e357ebb9" + integrity sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw== + dependencies: + tslib "^2.5.0" + +"@smithy/url-parser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.1.1.tgz#a30de227b6734650d740b6dff74d488b874e85e3" + integrity sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q== + dependencies: + "@smithy/querystring-parser" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-base64@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.1.1.tgz#af729085cc9d92ebd54a5d2c5d0aa5a0c31f83bf" + integrity sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g== + dependencies: + "@smithy/util-buffer-from" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-body-length-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz#1fc77072768013ae646415eedb9833cd252d055d" + integrity sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag== + dependencies: + tslib "^2.5.0" + +"@smithy/util-body-length-node@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz#a6f5c9911f1c3e23efb340d5ce7a590b62f2056e" + integrity sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-buffer-from@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz#f9346bf8b23c5ba6f6bdb61dd9db779441ba8d08" + integrity sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg== + dependencies: + "@smithy/is-array-buffer" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-config-provider@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz#aea0a80236d6cedaee60473802899cff4a8cc0ba" + integrity sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw== + dependencies: + tslib "^2.5.0" + +"@smithy/util-defaults-mode-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz#be9ac82acee6ec4821b610e7187b0e147f0ba8ff" + integrity sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA== + dependencies: + "@smithy/property-provider" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + bowser "^2.11.0" + tslib "^2.5.0" + +"@smithy/util-defaults-mode-node@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.2.0.tgz#72fd6f945c265f1ef9be647fe829d55df5101390" + integrity sha512-iFJp/N4EtkanFpBUtSrrIbtOIBf69KNuve03ic1afhJ9/korDxdM0c6cCH4Ehj/smI9pDCfVv+bqT3xZjF2WaA== + dependencies: + "@smithy/config-resolver" "^2.1.1" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-endpoints@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz#45426dba6fb42282a0ad955600b2b3ba050d118f" + integrity sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-hex-encoding@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz#978252b9fb242e0a59bae4ead491210688e0d15f" + integrity sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-middleware@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.1.1.tgz#903ba19bb17704f4b476fb9ade9bf9eb0174bc3d" + integrity sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" -"@sinonjs/formatio@^3.2.1": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c" - integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ== +"@smithy/util-retry@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.1.1.tgz#f2d3566b6e5b841028c7240c852007d4037e49b2" + integrity sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA== dependencies: - "@sinonjs/commons" "^1" - "@sinonjs/samsam" "^3.1.0" + "@smithy/service-error-classification" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" -"@sinonjs/samsam@^3.1.0": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a" - integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ== +"@smithy/util-stream@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.1.1.tgz#3ae0e88c3a1a45899e29c1655d2e5a3865b6c0a6" + integrity sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ== + dependencies: + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-buffer-from" "^2.1.1" + "@smithy/util-hex-encoding" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-uri-escape@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz#7eedc93b73ecda68f12fb9cf92e9fa0fbbed4d83" + integrity sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw== dependencies: - "@sinonjs/commons" "^1.3.0" - array-from "^2.1.1" - lodash "^4.17.15" + tslib "^2.5.0" -"@sinonjs/samsam@^6.1.1": - version "6.1.3" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.1.3.tgz#4e30bcd4700336363302a7d72cbec9b9ab87b104" - integrity sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ== +"@smithy/util-utf8@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.1.1.tgz#690018dd28f47f014114497735e51417ea5900a6" + integrity sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A== dependencies: - "@sinonjs/commons" "^1.6.0" - lodash.get "^4.4.2" - type-detect "^4.0.8" + "@smithy/util-buffer-from" "^2.1.1" + tslib "^2.5.0" -"@sinonjs/text-encoding@^0.7.1": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" - integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== +"@smithy/util-waiter@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-2.1.1.tgz#292d4d09cda7df38aba6ea2abd7d948e3f11bf2d" + integrity sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA== + dependencies: + "@smithy/abort-controller" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" "@szmarczak/http-timer@^4.0.5": version "4.0.6" @@ -1129,7 +2244,7 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.11.tgz#e95050bf79a932cb7305dd130254ccdf9bde671c" integrity sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ== -"@types/cli-progress@^3.11.0": +"@types/cli-progress@^3.11.0", "@types/cli-progress@^3.11.5": version "3.11.5" resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.11.5.tgz#9518c745e78557efda057e3f96a5990c717268c3" integrity sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g== @@ -1144,9 +2259,9 @@ "@types/node" "*" "@types/eslint@^8.4.1": - version "8.56.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.1.tgz#988cabb39c973e9200f35fdbb29d17992965bb08" - integrity sha512-18PLWRzhy9glDQp3+wOgfLYRWlhgX0azxgJ63rdpoUHyrC9z0f5CkFburjQx4uD7ZCruw85ZtMt6K+L+R8fLJQ== + version "8.56.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.2.tgz#1c72a9b794aa26a8b94ad26d5b9aa51c8a6384bb" + integrity sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -1225,9 +2340,9 @@ integrity sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA== "@types/node@*": - version "20.10.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.6.tgz#a3ec84c22965802bf763da55b2394424f22bfbb5" - integrity sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw== + version "20.11.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.19.tgz#b466de054e9cb5b3831bee38938de64ac7f81195" + integrity sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ== dependencies: undici-types "~5.26.4" @@ -1273,10 +2388,10 @@ resolved "https://registry.yarnpkg.com/@types/sarif/-/sarif-2.1.7.tgz#dab4d16ba7568e9846c454a8764f33c5d98e5524" integrity sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ== -"@types/semver@^7.3.12", "@types/semver@^7.3.9", "@types/semver@^7.5.0", "@types/semver@^7.5.4", "@types/semver@^7.5.6": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== +"@types/semver@^7.3.12", "@types/semver@^7.3.9", "@types/semver@^7.5.0", "@types/semver@^7.5.4", "@types/semver@^7.5.7": + version "7.5.7" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.7.tgz#326f5fdda70d13580777bcaa1bc6fa772a5aef0e" + integrity sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg== "@types/shelljs@^0.8.15": version "0.8.15" @@ -1286,6 +2401,18 @@ "@types/glob" "~7.2.0" "@types/node" "*" +"@types/sinon@^17.0.3": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa" + integrity sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.5" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2" + integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== + "@types/through@*": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56" @@ -1350,13 +2477,13 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz#70e6c1334d0d76562dfa61aed9009c140a7601b4" - integrity sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA== +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" "@typescript-eslint/type-utils@5.62.0": version "5.62.0" @@ -1373,10 +2500,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.17.0.tgz#844a92eb7c527110bf9a7d177e3f22bd5a2f40cb" - integrity sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A== +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -1391,13 +2518,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz#b913d19886c52d8dc3db856903a36c6c64fd62aa" - integrity sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg== +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1419,17 +2546,17 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@^6.13.0", "@typescript-eslint/utils@^6.13.2": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.17.0.tgz#f2b16d4c9984474656c420438cdede7eccd4079e" - integrity sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ== +"@typescript-eslint/utils@^6.17.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.17.0" - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/typescript-estree" "6.17.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" semver "^7.5.4" "@typescript-eslint/visitor-keys@5.62.0": @@ -1440,12 +2567,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz#3ed043709c39b43ec1e58694f329e0b0430c26b6" - integrity sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg== +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== dependencies: - "@typescript-eslint/types" "6.17.0" + "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" "@ungap/promise-all-settled@1.1.2": @@ -1476,9 +2603,9 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1, acorn-walk@^8.2.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.1.tgz#2f10f5b69329d90ae18c58bf1fa8fccd8b959a43" - integrity sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw== + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== acorn@^8.4.1, acorn@^8.7.0, acorn@^8.9.0: version "8.11.3" @@ -1626,13 +2753,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" + call-bind "^1.0.5" + is-array-buffer "^3.0.4" array-differ@^3.0.0: version "3.0.0" @@ -1660,16 +2787,27 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.findlastindex@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" - integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== +array.prototype.filter@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" + integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +array.prototype.findlastindex@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" + integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" array.prototype.flat@^1.3.2: version "1.3.2" @@ -1691,17 +2829,18 @@ array.prototype.flatmap@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -arraybuffer.prototype.slice@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" - integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-array-buffer "^3.0.2" + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" arrify@^2.0.1: @@ -1753,33 +2892,19 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-sdk@^2.1231.0: - version "2.1529.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1529.0.tgz#18cfc7249b31621cf475663413903ccdf1f98a05" - integrity sha512-Y+DkK5iD0KAiJAprCCUgIEKTBd+i+hp2uDbTOsyBeOKgojPtIY218X37gYDx395L8Vab2QwIscEOOChYUdpIJQ== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.5.0" +available-typed-arrays@^1.0.6, available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2, base64-js@^1.3.1: +base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -1825,6 +2950,11 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1853,12 +2983,12 @@ browser-stdout@1.3.1: integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" node-releases "^2.0.14" update-browserslist-db "^1.0.13" @@ -1867,15 +2997,6 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -2003,14 +3124,16 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" @@ -2035,10 +3158,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001565: - version "1.0.30001572" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz#1ccf7dc92d2ee2f92ed3a54e11b7b4a3041acfa0" - integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw== +caniuse-lite@^1.0.30001587: + version "1.0.30001588" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz#07f16b65a7f95dba82377096923947fb25bce6e3" + integrity sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ== capital-case@^1.0.4: version "1.0.4" @@ -2058,9 +3181,9 @@ cardinal@^2.1.1: redeyed "~2.1.0" chai@^4: - version "4.3.10" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" - integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== + version "4.4.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== dependencies: assertion-error "^1.1.0" check-error "^1.0.3" @@ -2373,14 +3496,14 @@ convert-source-map@^2.0.0: integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== core-js-pure@^3.30.2: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.35.0.tgz#4660033304a050215ae82e476bd2513a419fbb34" - integrity sha512-f+eRYmkou59uh7BPcyJ8MC76DiGhspj1KMxVIcF24tzP8NA9HVa1uC7BTW2tgx7E1QVCzDzsgp7kArrzhlz8Ew== + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.36.0.tgz#ffb34330b14e594d6a9835cf5843b4123f1d95db" + integrity sha512-cN28qmhRNgbMZZMc/RFu5w8pK9VJzpb2rJVR/lHuZJKwmXnoWOpXmMkxqBB514igkp1Hu8WGROsiOAzUcKdHOQ== core-js@^3.6.4: - version "3.35.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.0.tgz#58e651688484f83c34196ca13f099574ee53d6b4" - integrity sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg== + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.36.0.tgz#e752fa0b0b462a0787d56e9d73f80b0f7c0dde68" + integrity sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw== core-util-is@~1.0.0: version "1.0.3" @@ -2529,14 +3652,14 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== +define-data-property@^1.0.1, define-data-property@^1.1.2, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: - get-intrinsic "^1.2.1" + es-define-property "^1.0.0" + es-errors "^1.3.0" gopd "^1.0.1" - has-property-descriptors "^1.0.0" define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" @@ -2600,10 +3723,10 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== +diff@^5.0.0, diff@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== dir-glob@^3.0.1: version "3.0.1" @@ -2653,10 +3776,10 @@ ejs@^3.1.8, ejs@^3.1.9: dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.601: - version "1.4.618" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.618.tgz#98899b3c78495157cc2fe4944316f686939a435d" - integrity sha512-mTM2HieHLxs1RbD/R/ZoQLMsGI8lWIkP17G7cx32mJRBJt9wlNPkXwE3sYg/OnNb5GBkus98lXatSthoL8Y5Ag== +electron-to-chromium@^1.4.668: + version "1.4.677" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.677.tgz#49ee77713516740bdde32ac2d1443c444f0dafe7" + integrity sha512-erDa3CaDzwJOpyvfKhOiJjBVNnMM0qxHq47RheVVwsSQrgBA9ZSGV9kdaOfZDPXcHzhG7lBxhj6A7KvfLJBd6Q== emoji-regex@^8.0.0: version "8.0.0" @@ -2704,61 +3827,80 @@ error@^10.4.0: resolved "https://registry.yarnpkg.com/error/-/error-10.4.0.tgz#6fcf0fd64bceb1e750f8ed9a3dd880f00e46a487" integrity sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw== -es-abstract@^1.22.1: - version "1.22.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" - integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== - dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.2" - available-typed-arrays "^1.0.5" - call-bind "^1.0.5" - es-set-tostringtag "^2.0.1" +es-abstract@^1.22.1, es-abstract@^1.22.3: + version "1.22.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.4.tgz#26eb2e7538c3271141f5754d31aabfdb215f27bf" + integrity sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.6" + call-bind "^1.0.7" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.2" es-to-primitive "^1.2.1" function.prototype.name "^1.1.6" - get-intrinsic "^1.2.2" - get-symbol-description "^1.0.0" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" globalthis "^1.0.3" gopd "^1.0.1" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.2" has-proto "^1.0.1" has-symbols "^1.0.3" - hasown "^2.0.0" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" + hasown "^2.0.1" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" - is-typed-array "^1.1.12" + is-typed-array "^1.1.13" is-weakref "^1.0.2" object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.1" - safe-array-concat "^1.0.1" - safe-regex-test "^1.0.0" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.0" + safe-regex-test "^1.0.3" string.prototype.trim "^1.2.8" string.prototype.trimend "^1.0.7" string.prototype.trimstart "^1.0.7" - typed-array-buffer "^1.0.0" + typed-array-buffer "^1.0.1" typed-array-byte-length "^1.0.0" typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" - which-typed-array "^1.1.13" + which-typed-array "^1.1.14" -es-set-tostringtag@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" - integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: - get-intrinsic "^1.2.2" - has-tostringtag "^1.0.0" - hasown "^2.0.0" + get-intrinsic "^1.2.4" + +es-errors@^1.0.0, es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-set-tostringtag@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" -es-shim-unscopables@^1.0.0: +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== @@ -2780,9 +3922,9 @@ es6-error@^4.0.1: integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" @@ -2852,22 +3994,13 @@ eslint-plugin-jest@^26.1.1: dependencies: "@typescript-eslint/utils" "^5.10.0" -eslint-plugin-perfectionist@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-2.5.0.tgz#f7f83733e18d1b26694c4aab1b986eac836773a7" - integrity sha512-F6XXcq4mKKUe/SREoMGQqzgw6cgCgf3pFzkFfQVIGtqD1yXVpQjnhTepzhBeZfxZwgMzR9HO4yH4CUhIQ2WBcQ== - dependencies: - "@typescript-eslint/utils" "^6.13.0" - minimatch "^9.0.3" - natural-compare-lite "^1.4.0" - eslint-plugin-sf-plugin@^1.16.15: - version "1.17.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-sf-plugin/-/eslint-plugin-sf-plugin-1.17.0.tgz#9a7e81cb63bc6f36aae7c7797f95e2179def7fd3" - integrity sha512-grW7leP0FJbKQZgDjBZanLSTYrus0itKaEmoflEuqTZSyqH4feP53rHby5ysbOnw9OvgZfuq9NSc0a/CzcIbtQ== + version "1.17.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-sf-plugin/-/eslint-plugin-sf-plugin-1.17.3.tgz#3adda2e9955bf8f09859f935468c99ca15b58cc3" + integrity sha512-IFbKJYHbb0LBkdr/ftcz/awuEiktIhouJrHeZ0oQ2BOYKK4YOFdgfpVGqENNW2RvIS077bnjf8yzdgn2pLhcdg== dependencies: - "@salesforce/core" "^6.4.0" - "@typescript-eslint/utils" "^6.13.2" + "@salesforce/core" "^6.5.1" + "@typescript-eslint/utils" "^6.17.0" eslint-restricted-globals@~0.2.0: version "0.2.0" @@ -2997,11 +4130,6 @@ eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== - events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -3084,15 +4212,22 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.7: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" @@ -3218,9 +4353,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + version "3.3.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.0.tgz#5fdca2b5e671cd38d1537427a10e02a2caa8257e" + integrity sha512-noqGuLw158+DuD9UPRKHpJ2hGxpFyDlYYrfM0mWt4XhT4n0lwzTLh70Tkdyy4kyTmyTT9Bv7bWAJqw7cgkEXDg== for-each@^0.3.3: version "0.3.3" @@ -3364,11 +4499,12 @@ get-func-name@^2.0.1, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: + es-errors "^1.3.0" function-bind "^1.1.2" has-proto "^1.0.1" has-symbols "^1.0.3" @@ -3391,13 +4527,14 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" get-uri@3: version "3.0.2" @@ -3566,29 +4703,29 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.2.2" + es-define-property "^1.0.0" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.1, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - has-symbols "^1.0.2" + has-symbols "^1.0.3" has-unicode@^2.0.1: version "2.0.1" @@ -3603,10 +4740,10 @@ hasha@^5.0.0: is-stream "^2.0.0" type-fest "^0.8.0" -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== +hasown@^2.0.0, hasown@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" + integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== dependencies: function-bind "^1.1.2" @@ -3743,12 +4880,7 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -3768,9 +4900,9 @@ ignore-walk@^6.0.0: minimatch "^9.0.0" ignore@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== immediate@~3.0.5: version "3.0.6" @@ -3853,12 +4985,12 @@ inquirer@^8.0.0, inquirer@^8.2.5: through "^2.3.6" wrap-ansi "^6.0.1" -internal-slot@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" - integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== +internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: - get-intrinsic "^1.2.2" + es-errors "^1.3.0" hasown "^2.0.0" side-channel "^1.0.4" @@ -3867,32 +4999,26 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -ip@^1.1.5: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" - integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== - -ip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + jsbn "1.1.0" + sprintf-js "^1.1.3" -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== +ip@^1.1.5: + version "1.1.9" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" + integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== + +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" + get-intrinsic "^1.2.1" is-arrayish@^0.2.1: version "0.2.1" @@ -3965,13 +5091,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -3990,9 +5109,9 @@ is-lambda@^1.0.1: integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: version "1.0.7" @@ -4067,12 +5186,12 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== +is-typed-array@^1.1.10, is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: - which-typed-array "^1.1.11" + which-typed-array "^1.1.14" is-typedarray@^1.0.0: version "1.0.0" @@ -4118,25 +5237,25 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isbinaryfile@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== isbinaryfile@^5, isbinaryfile@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-5.0.0.tgz#034b7e54989dab8986598cbcea41f66663c65234" - integrity sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg== + version "5.0.2" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-5.0.2.tgz#fe6e4dfe2e34e947ffa240c113444876ba393ae0" + integrity sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg== isexe@^2.0.0: version "2.0.0" @@ -4196,9 +5315,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" - integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -4222,11 +5341,6 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - joycon@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" @@ -4259,6 +5373,11 @@ js2xmlparser@^4.0.1: dependencies: xmlcreate "^2.0.4" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4390,6 +5509,11 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== + jwa@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -4600,9 +5724,9 @@ lru-cache@^7.4.4, lru-cache@^7.7.1: integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== "lru-cache@^9.1.1 || ^10.0.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" @@ -5042,16 +6166,16 @@ nise@^1.3.3: lolex "^5.0.1" path-to-regexp "^1.7.0" -nise@^5.1.1: - version "5.1.5" - resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.5.tgz#f2aef9536280b6c18940e32ba1fbdc770b8964ee" - integrity sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw== +nise@^5.1.5: + version "5.1.9" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" + integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== dependencies: - "@sinonjs/commons" "^2.0.0" - "@sinonjs/fake-timers" "^10.0.2" - "@sinonjs/text-encoding" "^0.7.1" - just-extend "^4.0.2" - path-to-regexp "^1.7.0" + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/text-encoding" "^0.7.2" + just-extend "^6.2.0" + path-to-regexp "^6.2.1" no-case@^3.0.4: version "3.0.4" @@ -5361,7 +6485,7 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.13.1, object-inspect@^1.9.0: +object-inspect@^1.13.1: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== @@ -5376,7 +6500,7 @@ object-treeify@^1.1.33: resolved "https://registry.yarnpkg.com/object-treeify/-/object-treeify-1.1.33.tgz#f06fece986830a3cba78ddd32d4c11d1f76cdf40" integrity sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A== -object.assign@^4.1.4: +object.assign@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== @@ -5396,14 +6520,15 @@ object.fromentries@^2.0.7: es-abstract "^1.22.1" object.groupby@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" - integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + version "1.0.2" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" + integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" + array.prototype.filter "^1.0.3" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.0.0" object.values@^1.1.7: version "1.1.7" @@ -5415,26 +6540,26 @@ object.values@^1.1.7: es-abstract "^1.22.1" oclif@^4.0.3: - version "4.1.2" - resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.1.2.tgz#abf267372b86e020ad5b955114cc08522a4e0d5b" - integrity sha512-vMdk1IRvbENXjmr31LVvxOqKMqsxE4yboqi9YRLIwKj3YzdszfWanQEg4IcyIHRS2MbcNM86Slv9xiKVPCFXoA== - dependencies: - "@oclif/core" "^3.16.0" - "@oclif/plugin-help" "^6.0.9" - "@oclif/plugin-not-found" "^3.0.7" - "@oclif/plugin-warn-if-update-available" "^3.0.8" + version "4.4.16" + resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.4.16.tgz#30384a03e20b7294a048a5f36ed7a755e988c0fd" + integrity sha512-4qNgN8ZhLZV2k92HXBiIvFGDM2HKgXrB8auVe9EpNQPlZr/PXeW7CTYpkEm3VYrmtohe2p3ma5jIR/Nyuu/v6g== + dependencies: + "@aws-sdk/client-cloudfront" "^3.511.0" + "@aws-sdk/client-s3" "^3.515.0" + "@oclif/core" "^3.19.2" + "@oclif/plugin-help" "^6.0.12" + "@oclif/plugin-not-found" "^3.0.10" + "@oclif/plugin-warn-if-update-available" "^3.0.10" async-retry "^1.3.3" - aws-sdk "^2.1231.0" change-case "^4" debug "^4.3.3" - eslint-plugin-perfectionist "^2.1.0" find-yarn-workspace-root "^2.0.0" fs-extra "^8.1" github-slugger "^1.5.0" got "^11" lodash.template "^4.5.0" normalize-package-data "^3.0.3" - semver "^7.3.8" + semver "^7.6.0" yeoman-environment "^3.15.1" yeoman-generator "^5.8.0" @@ -5778,6 +6903,11 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" +path-to-regexp@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -5841,10 +6971,10 @@ pino-std-serializers@^6.0.0: resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz#d9a9b5f2b9a402486a5fc4db0a737570a860aab3" integrity sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA== -pino@^8.16.0, pino@^8.16.2: - version "8.17.2" - resolved "https://registry.yarnpkg.com/pino/-/pino-8.17.2.tgz#0ed20175623a69d31664a1e8a5f85476272224be" - integrity sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ== +pino@^8.16.0, pino@^8.19.0: + version "8.19.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-8.19.0.tgz#ccc15ef736f103ec02cfbead0912bc436dc92ce4" + integrity sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA== dependencies: atomic-sleep "^1.0.0" fast-redact "^3.1.1" @@ -5865,6 +6995,11 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + preferred-pm@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/preferred-pm/-/preferred-pm-3.1.2.tgz#aedb70550734a574dffcbf2ce82642bd1753bdd6" @@ -5986,21 +7121,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -6206,14 +7331,15 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexp.prototype.flags@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" - integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== +regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - set-function-name "^2.0.0" + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" release-zalgo@^1.0.0: version "1.0.0" @@ -6346,13 +7472,13 @@ rxjs@^7.2.0, rxjs@^7.5.5: dependencies: tslib "^2.1.0" -safe-array-concat@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" - integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== +safe-array-concat@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" + integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" + call-bind "^1.0.5" + get-intrinsic "^1.2.2" has-symbols "^1.0.3" isarray "^2.0.5" @@ -6366,13 +7492,13 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" + call-bind "^1.0.6" + es-errors "^1.3.0" is-regex "^1.1.4" safe-stable-stringify@^2.3.1: @@ -6390,11 +7516,6 @@ samsam@1.3.0: resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" integrity sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg== -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== - sax@>=0.6.0, sax@^1.2.4: version "1.3.0" resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" @@ -6420,10 +7541,10 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== +semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== dependencies: lru-cache "^6.0.0" @@ -6453,24 +7574,27 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-function-length@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== +set-function-length@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" + integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== dependencies: - define-data-property "^1.1.1" - get-intrinsic "^1.2.1" + define-data-property "^1.1.2" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.3" gopd "^1.0.1" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.1" -set-function-name@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" - integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== +set-function-name@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== dependencies: - define-data-property "^1.0.1" + define-data-property "^1.1.4" + es-errors "^1.3.0" functions-have-names "^1.2.3" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.2" setimmediate@^1.0.5: version "1.0.5" @@ -6504,13 +7628,14 @@ shelljs@^0.8.4, shelljs@^0.8.5: rechoir "^0.6.2" side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + version "1.0.5" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" + integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.6" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -6540,16 +7665,16 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sinon@^13: - version "13.0.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-13.0.2.tgz#c6a8ddd655dc1415bbdc5ebf0e5b287806850c3a" - integrity sha512-KvOrztAVqzSJWMDoxM4vM+GPys1df2VBoXm+YciyB/OLMamfS3VXh3oGh5WtrAGSzrgczNWFFY22oKb7Fi5eeA== +sinon@^17: + version "17.0.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.1.tgz#26b8ef719261bf8df43f925924cccc96748e407a" + integrity sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g== dependencies: - "@sinonjs/commons" "^1.8.3" - "@sinonjs/fake-timers" "^9.1.2" - "@sinonjs/samsam" "^6.1.1" - diff "^5.0.0" - nise "^5.1.1" + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/samsam" "^8.0.0" + diff "^5.1.0" + nise "^5.1.5" supports-color "^7.2.0" sinon@^5.1.1: @@ -6625,17 +7750,17 @@ socks-proxy-agent@^7.0.0: socks "^2.6.2" socks@^2.3.3, socks@^2.6.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" - integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + version "2.7.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.3.tgz#7d8a75d7ce845c0a96f710917174dba0d543a785" + integrity sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw== dependencies: - ip "^2.0.0" + ip-address "^9.0.5" smart-buffer "^4.2.0" sonic-boom@^3.0.0, sonic-boom@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.7.0.tgz#b4b7b8049a912986f4a92c51d4660b721b11f2f2" - integrity sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg== + version "3.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66" + integrity sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA== dependencies: atomic-sleep "^1.0.0" @@ -6672,9 +7797,9 @@ spdx-correct@^3.0.0: spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -6685,15 +7810,20 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.16" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" - integrity sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw== + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== split2@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -6845,6 +7975,11 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + supports-color@8.1.1, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -6979,9 +8114,9 @@ treeverse@^1.0.4: integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g== ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" + integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== ts-mockito@^2.6.1: version "2.6.1" @@ -7014,10 +8149,10 @@ ts-retry-promise@^0.7.1: resolved "https://registry.yarnpkg.com/ts-retry-promise/-/ts-retry-promise-0.7.1.tgz#176d6eee6415f07b6c7c286d3657355e284a6906" integrity sha512-NhHOCZ2AQORvH42hOPO5UZxShlcuiRtm7P2jIq2L2RY3PBxw2mLnUsEdHrIslVBFya1v5aZmrR55lWkzo13LrQ== -tsconfck@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.0.1.tgz#803ca0ed8f2f2075639e4061238f04b99ba85e85" - integrity sha512-7ppiBlF3UEddCLeI1JRx5m2Ryq+xk4JrZuq4EuYXykipebaq1dV0Fhgr1hb7CkmHt32QSgOZlcqVLEtHBG4/mg== +ts-retry-promise@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/ts-retry-promise/-/ts-retry-promise-0.8.0.tgz#0a0c57b510827d5630da4b0c47f36b55b83a49e3" + integrity sha512-elI/GkojPANBikPaMWQnk4T/bOJ6tq/hqXyQRmhfC9PAD6MoHmXIXK7KilJrlpx47VAKCGcmBrTeK5dHk6YAYg== tsconfig-paths@^3.15.0: version "3.15.0" @@ -7029,12 +8164,12 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.5.0, tslib@^2.6.1, tslib@^2.6.2: +tslib@^2, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0, tslib@^2.6.1, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -7108,14 +8243,14 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typed-array-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" - integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== +typed-array-buffer@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - is-typed-array "^1.1.10" + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" typed-array-byte-length@^1.0.0: version "1.0.0" @@ -7128,24 +8263,28 @@ typed-array-byte-length@^1.0.0: is-typed-array "^1.1.10" typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + version "1.0.5" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.5.tgz#57d44da160296d8663fd63180a1802ebf25905d5" + integrity sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" for-each "^0.3.3" - is-typed-array "^1.1.9" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" typedarray-to-buffer@^3.1.5: version "3.1.5" @@ -7278,14 +8417,6 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7296,22 +8427,6 @@ util-extend@^1.0.1: resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" integrity sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA== -util@^0.12.4: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -7448,16 +8563,16 @@ which-pm@2.0.0: load-yaml-file "^0.2.0" path-exists "^4.0.0" -which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.2: - version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== +which-typed-array@^1.1.14: + version "1.1.14" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.14.tgz#1f78a111aee1e131ca66164d8bdc3ab062c95a06" + integrity sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" + available-typed-arrays "^1.0.6" + call-bind "^1.0.5" for-each "^0.3.3" gopd "^1.0.1" - has-tostringtag "^1.0.0" + has-tostringtag "^1.0.1" which@2.0.2, which@^2.0.1, which@^2.0.2: version "2.0.2" @@ -7569,7 +8684,7 @@ xml-js@^1.6.11: dependencies: sax "^1.2.4" -xml2js@0.5.0, xml2js@^0.5.0: +xml2js@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== From 44b9ddf8b47a8a53303c69d6fafcc4d418fd26c1 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 23 Feb 2024 11:44:39 -0600 Subject: [PATCH 15/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored tests for scanner rule describe command. --- test/commands/scanner/rule/describe.test.ts | 87 ---------- test/lib/actions/RuleDescribeAction.test.ts | 177 ++++++++++++++------ 2 files changed, 128 insertions(+), 136 deletions(-) delete mode 100644 test/commands/scanner/rule/describe.test.ts diff --git a/test/commands/scanner/rule/describe.test.ts b/test/commands/scanner/rule/describe.test.ts deleted file mode 100644 index cdb914abe..000000000 --- a/test/commands/scanner/rule/describe.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import {expect} from 'chai'; -// @ts-ignore -import {runCommand} from '../../../TestUtils'; -import {getMessage, BundleName} from '../../../../src/MessageCatalog'; - -describe('scanner rule describe', () => { - describe('E2E', () => { - describe('Test Case: No matching rules', () => { - const formattedWarning = getMessage(BundleName.Describe, 'output.noMatchingRules', ['DefinitelyFakeRule']); - it('Correct warning is displayed', () => { - const output = runCommand(`scanner rule describe --rulename DefinitelyFakeRule`); - expect(output.shellOutput.stderr.toLowerCase()).to.contain(`WARNING: ${formattedWarning}`.toLowerCase(), 'Warning message should match'); - }); - - it('--json flag yields correct results', () => { - const output = runCommand(`scanner rule describe --rulename DefinitelyFakeRule --json`); - const ctxJson = output.jsonOutput; - expect((ctxJson.result as any[]).length).to.equal(0, 'Should be no results'); - expect(ctxJson.warnings.length).to.equal(2, 'Incorrect warning count'); - expect(ctxJson.warnings[1]).to.equal(formattedWarning, 'Warning message should match'); - }); - }); - - describe('Test Case: One matching rule', () => { - it('Displayed output matches expectations', () => { - const output = runCommand(`scanner rule describe --rulename TooManyFields`); - // Rather than compare every attribute, we'll just compare a few, so we can be reasonably confident we got the right - // rule. - const ctx = output.shellOutput; - expect(ctx.stdout).to.match(/name:\s+TooManyFields/, 'Name should be \'TooManyFields\''); - expect(ctx.stdout).to.match(/engine:\s+pmd/, 'Engine should be PMD'); - expect(ctx.stdout).to.match(/enabled:\s+true/, 'Rule is enabled'); - expect(ctx.stdout).to.match(/categories:\s+Design/, 'Category should be \'Design\''); - expect(ctx.stdout).to.match(/languages:\s+apex/, 'Language should be \'apex\''); - expect(ctx.stdout).to.match(/message:\s+Too many fields/, 'Message should match'); - }); - - it('--json flag yields correct results', () => { - const output = runCommand(`scanner rule describe --rulename TooManyFields --json`); - const resultList = output.jsonOutput.result as any[]; - expect(resultList.length).to.equal(1, 'Should be one matching rule'); - const ruleJson = resultList[0]; - // Rather than compare every attribute, we'll just compare a few so we can be reasonably confident we got the right - // rule. - expect(ruleJson.name).to.equal('TooManyFields'); - expect(ruleJson.languages.length).to.equal(1, 'Should be one language applied to rule'); - expect(ruleJson.languages[0]).to.equal('apex', 'Rule language should be apex'); - expect(ruleJson.message).to.equal('Too many fields', 'Rule message should match'); - }); - }); - - describe('Test Case: Multiple matching rules', () => { - // Both tests will test for the presence of this warning string in the output, so we might as well format it up here. - const formattedWarning = getMessage(BundleName.Describe, 'output.multipleMatchingRules', ['3', 'constructor-super']); - - it('Displayed output matches expectations', () => { - const output = runCommand(`scanner rule describe --rulename constructor-super`); - const ctx = output.shellOutput; - // First, verify that the warning was printed at the start like it should have been. - expect(ctx.stderr.toLowerCase()).to.contain(`WARNING: ${formattedWarning}`.toLowerCase(), 'Warning message should be formatted correctly'); - - // Next, verify that there are rule descriptions that are distinctly identified. - const regex = /=== Rule #1\n(.*\n)*name:\s+constructor-super(.*\n)*=== Rule #2\n(.*\n)*name:\s+constructor-super(.*\n)*=== Rule #3\n(.*\n)*name:\s+constructor-super/g; - expect(ctx.stdout).to.match(regex, 'Output should contain three rules named constructor-super for each eslint based engine'); - }); - - it('--json flag yields correct results', () => { - const output = runCommand(`scanner rule describe --rulename constructor-super --json`); - const ctxJson = output.jsonOutput; - - // Verify we got the right number of rules. - expect(ctxJson.result).to.have.lengthOf(3, 'Should be three included rules'); - // There are two warnings, but only the second is relevant. - expect(ctxJson.warnings).to.have.lengthOf(2, 'Should be two warnings'); - expect(ctxJson.warnings[1]).to.equal(formattedWarning, 'Warning should match'); - }); - }); - - describe('Error handling', () => { - it('Must input a rule name', () => { - const output = runCommand(`scanner rule describe`); - expect(output.shellOutput.stderr).to.contain(`The following error occurred: - Missing required flag rulename`); - }); - }); - }); -}); diff --git a/test/lib/actions/RuleDescribeAction.test.ts b/test/lib/actions/RuleDescribeAction.test.ts index 0f376edac..d36576ef1 100644 --- a/test/lib/actions/RuleDescribeAction.test.ts +++ b/test/lib/actions/RuleDescribeAction.test.ts @@ -1,64 +1,143 @@ +import {AnyJson} from "@salesforce/ts-types"; +import {expect} from "chai"; + import {FakeDisplay} from "../FakeDisplay"; -import {initContainer} from "../../../src/ioc.config"; +import {initializeTestSetup} from "../../test-related-lib/TestOverrides"; + import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; import {Inputs} from "../../../src/types"; -import {expect} from "chai"; import {RuleDescribeAction} from "../../../src/lib/actions/RuleDescribeAction"; -import {AnyJson} from "@salesforce/ts-types"; -import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; -import {Controller} from "../../../lib/Controller"; +import {Pmd6CommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; +import {getMessage, BundleName} from '../../../src/MessageCatalog'; -describe("Tests for RuleDescribeAction", () => { +describe("RuleDescribeAction", () => { let display: FakeDisplay; let ruleDescribeAction: RuleDescribeAction; - before(() => { - initContainer(); - }); beforeEach(() => { + // TODO: Add some functional tests for RuleManager.getRulesMatchingOnlyExplicitCriteria(), + // then switch this from initializing the controller to using mock-ups, so we're only + // testing the actual code here and not the underlying implementation. + initializeTestSetup(); display = new FakeDisplay(); ruleDescribeAction = new RuleDescribeAction(display, new RuleFilterFactoryImpl()); }); - describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7 with pmd engine", () => { - afterEach(() => { - // Until we remove global state, we should cleanup after ourselves to prevent other tests from being impacted - Controller.setActivePmdCommandInfo(new Pmd6CommandInfo()) - }) - - it("When using PMD7, the rule description for a pmd rule should give correct info from PMD 7", async () => { - const inputs: Inputs = { - rulename: 'ApexCRUDViolation', - "preview-pmd7": true - } - await ruleDescribeAction.run(inputs); - - const rule: AnyJson = display.getLastStyledObject(); - expect(rule['name']).to.equal('ApexCRUDViolation'); - expect(rule['engine']).to.equal('pmd'); - expect(rule['isPilot']).to.equal(false); - expect(rule['enabled']).to.equal(true); - expect(rule['categories']).to.deep.equal(['Security']); - expect(rule['rulesets']).to.contain('quickstart'); - expect(rule['languages']).to.deep.equal(['apex']); - expect(rule['description']).to.have.length.greaterThan(0); - expect(rule['message']).to.have.length.greaterThan(0); - }) - - it("When using PMD7, the rule description for a cpd rule should give back correct info from PMD 7", async () => { - const inputs: Inputs = { - rulename: 'copy-paste-detected' - } - await ruleDescribeAction.run(inputs); - - const rule: AnyJson = display.getLastStyledObject(); - expect(rule['name']).to.equal('copy-paste-detected'); - expect(rule['engine']).to.equal('cpd'); - expect(rule['isPilot']).to.equal(false); - expect(rule['enabled']).to.equal(false); - expect(rule['categories']).to.deep.equal(['Copy/Paste Detected']); - expect(rule['rulesets']).to.deep.equal([]); - expect(rule['languages']).to.deep.equal(['apex', 'java', 'visualforce', 'xml']); - expect(rule['description']).to.have.length.greaterThan(0); + describe('#run', () => { + describe('When no rules match...', () => { + it('Shows warning and returns nothing', async () => { + const inputs: Inputs = { + rulename: 'definitely-fake-rule' + }; + + const output = await ruleDescribeAction.run(inputs); + + expect(display.getOutputArray()).to.contain(`[Warning]: ${getMessage(BundleName.Describe, 'output.noMatchingRules', [inputs.rulename])}`); + expect(output).to.deep.equal([]); + }); + }); + + describe('When one rule matches...', () => { + it('Rule is displayed and returned', async () => { + const inputs: Inputs = { + rulename: 'TooManyFields' + }; + + const output = await ruleDescribeAction.run(inputs); + + // Test the returned value (used by --json flag) + expect(output).to.have.lengthOf(1, 'Wrong number of rules returned'); + expect(output[0]['name']).to.equal(inputs.rulename, 'Wrong name in returned output'); + expect(output[0]['engine']).to.equal('pmd', 'Wrong engine in returned output'); + expect(output[0]['enabled']).to.equal(true, 'Wrong enablement status in returned output'); + expect(output[0]['categories']).to.deep.equal(['Design'], 'Wrong categories in returned output'); + expect(output[0]['languages']).to.deep.equal(['apex'], 'Wrong language in returned output'); + expect(output[0]['message']).to.equal('Too many fields', 'Wrong message in returned output'); + + // Test the displayed value + const displayedRule: AnyJson = display.getLastStyledObject(); + expect(displayedRule['name']).to.equal(inputs.rulename, 'Wrong name in displayed output'); + expect(displayedRule['engine']).to.equal('pmd', 'Wrong engine in displayed output'); + expect(displayedRule['enabled']).to.equal(true, 'Wrong enablement status in displayed output'); + expect(displayedRule['categories']).to.deep.equal(['Design'], 'Wrong categories in displayed output'); + expect(displayedRule['languages']).to.deep.equal(['apex'], 'Wrong language in displayed output'); + expect(displayedRule['message']).to.equal('Too many fields', 'Wrong message in displayed output'); + + }); + }); + + describe('When multiple rules match...', () => { + it('Shows warning; displays and returns rules', async () => { + const inputs: Inputs = { + rulename: 'constructor-super' + }; + + const output = await ruleDescribeAction.run(inputs); + + expect(display.getOutputArray()).to.contain(`[Warning]: ${getMessage(BundleName.Describe,'output.multipleMatchingRules', [3, inputs.rulename])}`) + + // Multiple rules should have been returned + expect(output).to.have.lengthOf(3, 'Wrong number of rules returned'); + // Check some properties on each rule + for (let i = 0; i < 3; i++) { + expect(output[i]['name']).to.equal(inputs.rulename, `Wrong name in returned output for rule #${i + 1}`); + expect(output[i]['engine']).to.contain('eslint', `Wrong engine in returned output for rule #${i + 1}`); + expect(output[i]['categories']).to.deep.equal(['problem'], `Wrong categories in returned output for rule #${i + 1}`); + expect(output[i]['description']).to.equal('Require `super()` calls in constructors', `Wrong description in returned output for rule #${i + 1}`); + } + + // Just check the last displayed rule, it should be fine. + const displayedRule = display.getLastStyledObject(); + expect(displayedRule['name']).to.equal(inputs.rulename, 'Wrong name in displayed output'); + expect(displayedRule['engine']).to.equal('eslint-typescript', 'Wrong engine in displayed output'); + expect(displayedRule['categories']).to.deep.equal(['problem'], 'Wrong categories in displayed output'); + expect(displayedRule['languages']).to.deep.equal(['typescript'], 'Wrong language in displayed output'); + expect(displayedRule['description']).to.equal('Require `super()` calls in constructors', 'Wrong description in displayed output'); + }); + }); + + describe('When PMD7 binary is invoked...', () => { + afterEach(() => { + // Until we remove global state, we should clean up after ourselves to prevent other tests from being impacted + Controller.setActivePmdCommandInfo(new Pmd6CommandInfo()); + }) + + it('PMD7 pmd rule is returned', async () => { + const inputs: Inputs = { + rulename: 'ApexCRUDViolation', + "preview-pmd7": true + } + await ruleDescribeAction.run(inputs); + + const rule: AnyJson = display.getLastStyledObject(); + expect(rule['name']).to.equal('ApexCRUDViolation'); + expect(rule['engine']).to.equal('pmd'); + expect(rule['isPilot']).to.equal(false); + expect(rule['enabled']).to.equal(true); + expect(rule['categories']).to.deep.equal(['Security']); + expect(rule['rulesets']).to.contain('quickstart'); + expect(rule['languages']).to.deep.equal(['apex']); + expect(rule['description']).to.have.length.greaterThan(0); + expect(rule['message']).to.have.length.greaterThan(0); + }); + + it('PMD7 cpd rule is returned', async () => { + const inputs: Inputs = { + rulename: 'copy-paste-detected', + "preview-pmd7": true + }; + await ruleDescribeAction.run(inputs); + + const rule: AnyJson = display.getLastStyledObject(); + expect(rule['name']).to.equal('copy-paste-detected'); + expect(rule['engine']).to.equal('cpd'); + expect(rule['isPilot']).to.equal(false); + expect(rule['enabled']).to.equal(false); + expect(rule['categories']).to.deep.equal(['Copy/Paste Detected']); + expect(rule['rulesets']).to.deep.equal([]); + expect(rule['languages']).to.deep.equal(['apex', 'java', 'visualforce', 'xml']); + expect(rule['description']).to.have.length.greaterThan(0); + }); }); }); }); From f49e12757b384be2f1974450ed7dc0a376f3dfee Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 23 Feb 2024 11:45:06 -0600 Subject: [PATCH 16/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored tests for scanner rule list command. --- test/commands/scanner/rule/list.test.ts | 287 ------------------------ test/lib/RuleManager.test.ts | 72 +++++- test/lib/actions/RuleListAction.test.ts | 68 +++++- 3 files changed, 130 insertions(+), 297 deletions(-) diff --git a/test/commands/scanner/rule/list.test.ts b/test/commands/scanner/rule/list.test.ts index 19092aa3b..f32841c22 100644 --- a/test/commands/scanner/rule/list.test.ts +++ b/test/commands/scanner/rule/list.test.ts @@ -1,141 +1,10 @@ import {expect} from 'chai'; -// @ts-ignore import {runCommand} from '../../../TestUtils'; -import {Rule} from '../../../../src/types'; -import {CATALOG_FILE, ENGINE} from '../../../../src/Constants'; -import fs = require('fs'); -import path = require('path'); -import { Controller } from '../../../../src/Controller'; import {BundleName, getMessage} from "../../../../src/MessageCatalog"; -function getCatalogJson(): { rules: Rule[] } { - const sfdxScannerPath = Controller.getSfdxScannerPath(); - const catalogPath = path.join(sfdxScannerPath, CATALOG_FILE); - expect(fs.existsSync(catalogPath), catalogPath).to.equal(true, 'Catalog file should exist'); - return JSON.parse(fs.readFileSync(catalogPath).toString()); -} - -function listContentsOverlap(list1: T[], list2: T[]): boolean { - return list1.some(x => list2.includes(x)); -} - -/** - * Rather than painstakingly check all of the rules, we'll just make sure that we got the right number of rules, - * compared to the number of rules in the catalog. This method filters the catalogs rules. - * - * @param includeDefaultDisabled - if true, include rule when Rule.defaultEnabled is false. if false, include rule when Rule.defaultEnabled is true - * @param includedCategories - include rule if any of its categories overlaps with this array - * @param excludeCategories- exclude rule if any of its categories overlaps with this array - * - * @return the number of rules returned - */ -async function getRulesFilteredByCategoryCount(includeDefaultDisabled: boolean, includedCategories: string[]=undefined, excludeCategories: string[]=undefined): Promise { - const catalog = getCatalogJson(); - const enabledEngineNames = (await Controller.getEnabledEngines()).map(e => e.getName()); - let rules: Rule[] = catalog.rules.filter(r => (includeDefaultDisabled || r.defaultEnabled) && enabledEngineNames.includes(r.engine)); - if (includedCategories?.length > 0) { - rules = rules.filter((r: Rule) => includedCategories.some(c => r.categories.includes(c))); - } - if (excludeCategories?.length > 0) { - rules = rules.filter((r: Rule) => !excludeCategories.some(c => r.categories.includes(c))); - } - expect(rules.length).to.be.above(0, 'Expected rule count cannot be zero. Test invalid'); - return rules.length; -} - describe('scanner rule list', () => { describe('E2E', () => { - describe('Test Case: No filters applied', () => { - it('All rules for enabled engines are returned', async () => { - const output = runCommand(`scanner rule list`); - const totalRuleCount = await getRulesFilteredByCategoryCount(false); - - // Split the output table by newline and throw out the first two rows, since they just contain header information. That - // should leave us with the actual data. - const rows = output.shellOutput.stdout.trim().split('\n'); - rows.shift(); - rows.shift(); - expect(rows).to.have.lengthOf(totalRuleCount, 'All rules should have been returned'); - }); - - it('--json flag yields expected JSON', async () => { - const output = runCommand(`scanner rule list --json`); - const totalRuleCount = await getRulesFilteredByCategoryCount(false); - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(totalRuleCount, 'All rules should have been returned'); - }); - }); - - describe('Test Case: Filtering by category only', () => { - const positiveCategories = ['Best Practices', 'Design']; - // Add a preceding '!' to each category - const negatedCategories = positiveCategories.map(c => `!${c}`); - - it('Filtering by one category returns only the rules in that category for enabled engines', async () => { - const output = runCommand(`scanner rule list --category "${positiveCategories[0]}" --json`); - const targetRuleCount = await getRulesFilteredByCategoryCount(true, [positiveCategories[0]]); - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in the specified category should have been returned'); - - // Make sure that each rule overlaps with the expected categories - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule.categories).to.contain(positiveCategories[0], `Rule ${rule.name} was included despite being in the wrong category`); - }); - }) - - it('Filtering by multiple categories returns any rule in either category', async () => { - const output = runCommand(`scanner rule list --category "${positiveCategories.join(',')}" --json`); - const targetRuleCount = await getRulesFilteredByCategoryCount(true, positiveCategories); - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in either category should be returned'); - - // Make sure that each rule overlaps with the expected categories - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule).to.satisfy((rule) => { - return listContentsOverlap(rule.categories, positiveCategories) - }, - `Rule ${rule.name} was included despite being in the wrong category` - ); - }); - }); - - it('Excluding by one category excludes all rules from that category', async () => { - const output = runCommand(`scanner rule list --category "${negatedCategories[0]}" --json`); - const targetRuleCount = await getRulesFilteredByCategoryCount(false, [], [positiveCategories[0]]); - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in the specified category should have been returned'); - - // Ensure that all of the returned rules have excluded the single category - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule.categories).to.not.contain(positiveCategories[0], `Rule ${rule.name} with categories ${rule.categories} was included despite being in the wrong category`); - }); - }); - - it('Excluding by multiple categories excludes all rules from those categories', async () => { - const output = runCommand(`scanner rule list --category "${negatedCategories.join(',')}" --json`); - const targetRuleCount = await getRulesFilteredByCategoryCount(false, [], positiveCategories); - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in the specified category should have been returned'); - - // Ensure that all of the returned rules have excluded both categories - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule).to.satisfy((rule) => { return !positiveCategories.some(c => rule.categories.includes(c)) }, - `Rule ${rule.name} with categories ${rule.categories} was included despite being in the wrong category` - ); - }); - }); - }); describe('Test Case: Filtering by ruleset only', () => { @@ -143,162 +12,6 @@ describe('scanner rule list', () => { const output = runCommand(`scanner rule list --ruleset Braces`); expect(output.shellOutput.stderr).contains(getMessage(BundleName.List, 'rulesetDeprecation')); }); - - it('Filtering by a single ruleset returns only the rules in that ruleset', () => { - const output = runCommand(`scanner rule list --ruleset Braces --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.rulesets.includes('Braces')).length; - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in the desired ruleset should be returned'); - - // Make sure that only rules in the right ruleset were returned. - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule.rulesets).to.contain('Braces', 'Only rules in the desired ruleset should have been returned'); - }); - }); - - it('Filtering by multiple rulesets returns any rule in either ruleset', () => { - const output = runCommand(`scanner rule list --ruleset ApexUnit,Braces --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.rulesets.includes('Braces') || rule.rulesets.includes('ApexUnit')).length; - - // Parse the output back into a JSON, and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules in both sets should have been returned'); - // Make sure that only rules in the desired sets were returned. - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule).to.satisfy((rule) => { - return rule.rulesets.includes('Braces') || rule.rulesets.includes('ApexUnit') - }, - `Rule ${rule.name} was included despite being in the wrong ruleset` - ); - }); - }); - }); - - describe('Test Case: Filtering by language only', () => { - const filteredLanguages = ['apex', 'javascript']; - - it('Filtering by a single language returns only rules applied to that language', () => { - const output = runCommand(`scanner rule list --language ${filteredLanguages[0]} --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.languages.includes(filteredLanguages[0])).length; - expect(targetRuleCount).to.be.above(0, 'Expected rule count cannot be zero. Test invalid'); - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule) => { - expect(rule.languages).to.contain(filteredLanguages[0], `Rule ${rule.name} was included despite targeting the wrong language`) - }); - }); - - it('Filtering by multiple languages returns any rule for either language', async () => { - const output = runCommand(`scanner rule list --language ${filteredLanguages.join(',')} --json`); - // Count how many rules in the catalog fit the criteria. - const enabledEngines = (await Controller.getEnabledEngines()).map(e => e.getName()); - const filterFunction: (Rule) => boolean = - (r: Rule) => listContentsOverlap(r.languages, filteredLanguages) && enabledEngines.includes(r.engine); - const targetRuleCount = getCatalogJson().rules.filter(filterFunction).length; - expect(targetRuleCount).to.be.above(0, 'Expected rule count cannot be zero. Test invalid'); - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules of the desired languages should be returned'); - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule).to.satisfy((rule) => { - return listContentsOverlap(rule.languages, filteredLanguages) - }, - `Rule ${rule.name} was included despite targeting neither desired language` - ); - }); - }); - }); - - describe('Test Case: Filtering by engine only', () => { - it('Filtering by a single engine returns only rules applied to that engine', () => { - const output = runCommand(`scanner rule list --engine ${ENGINE.PMD} --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.engine === (ENGINE.PMD)).length; - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules of the desired engine should be returned'); - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule) => { - expect(rule.engine).to.equal(ENGINE.PMD, `Rule ${rule.name} was included despite targeting the wrong engine`) - }); - }); - - it('Filtering by a disabled engine returns rules', () => { - const output = runCommand(`scanner rule list --engine ${ENGINE.ESLINT_LWC} --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.engine.includes(ENGINE.ESLINT_LWC)).length; - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules of the desired engine should be returned'); - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule) => { - expect(rule.engine).to.equal(ENGINE.ESLINT_LWC, `Rule ${rule.name} was included despite targeting the wrong engine`) - }); - }); - - it('Filtering by multiple engines returns any rule for either engine', () => { - const engines: string[] = [ENGINE.PMD, ENGINE.ESLINT_LWC]; - const output = runCommand(`scanner rule list --engine ${engines.join(',')} --json`); - // Count how many rules in the catalog fit the criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => (engines.indexOf(rule.engine) >= 0)).length; - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules of the desired engines should be returned'); - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule).to.satisfy((rule) => { - return (engines.indexOf(rule.engine) >= 0) - }, - `Rule ${rule.name} was included despite targeting neither desired engine` - ); - }); - }); - }); - - describe('Test Case: Applying multiple filter types', () => { - it('Filtering on multiple columns only returns rows that satisfy BOTH filters', () => { - const output = runCommand(`scanner rule list --category "Best Practices" --language apex --json`); - // Count how many rules in the catalog fit all criteria. - const targetRuleCount = getCatalogJson().rules.filter(rule => rule.categories.includes('Best Practices') && rule.languages.includes('apex')).length; - - // Parse the output back into a JSON and make sure it has the right number of rules. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(targetRuleCount, 'All rules matching criteria should have been returned'); - - // Make sure that only the right rules were returned. - (outputJson.result as any[]).forEach((rule: Rule) => { - expect(rule.languages).to.contain('apex', `Rule ${rule.name} was included despite targeting the wrong language`); - expect(rule.categories).to.contain('Best Practices', `Rule ${rule.name} was included despite being in the wrong category`); - }); - }); - }); - - describe('Edge Case: No rules match criteria', () => { - it('Without --json flag, an empty table is printed', () => { - const output = runCommand(`scanner rule list --category Beebleborp`); - // Split the result by newline, and make sure there are two rows. - const rows = output.shellOutput.stdout.trim().split('\n'); - expect(rows).to.have.lengthOf(2, 'Only the header rows should have been printed'); - }) - - it('With the --json flag, the results are empty', () => { - const output = runCommand(`scanner rule list --category Beebleborp --json`); - // Parse the results back into a JSON and make sure it has an empty list. - const outputJson = output.jsonOutput; - expect(outputJson.result).to.have.lengthOf(0, 'No results should be included'); - }); }); }); }); diff --git a/test/lib/RuleManager.test.ts b/test/lib/RuleManager.test.ts index a99a75037..5e6467b89 100644 --- a/test/lib/RuleManager.test.ts +++ b/test/lib/RuleManager.test.ts @@ -96,6 +96,39 @@ describe('RuleManager', () => { } } }); + + it('Excluding one category excludes all rules from that category', async () => { + // Set up our filter array. + const categories = ['!Best Practices']; + const filters = [new CategoryFilter(categories)]; + + // Pass the filter array into the manager. + const matchingRules = await ruleManager.getRulesMatchingCriteria(filters); + + // Expect the right number of rules to be returned. + expect(matchingRules).to.have.lengthOf(9, 'Wrong number of rules returned'); + for (const rule of matchingRules) { + expect(rule.categories).to.not.contain('Best Practices', 'Excluded category should not be present'); + } + }); + + it('Excluding by multiple categories excludes all rules from those categories', async () => { + // Set up our filter array. + const positiveCategories = ['Best Practices', 'Design']; + const categories = ['!Best Practices', '!Design']; + const filters = [new CategoryFilter(categories)]; + + // Pass the filter array into the manager. + const matchingRules = await ruleManager.getRulesMatchingCriteria(filters); + + // Expect the right number of rules to be returned. + expect(matchingRules).to.have.lengthOf(7, 'Wrong number of rules returned'); + for (const rule of matchingRules) { + expect(rule).to.satisfy(rule => { + return !positiveCategories.some(c => rule.categories.includes(c)); + }, `Rule ${rule.name} with categories ${rule.categories} was wrongly included`); + } + }); }); describe('Test Case: Filtering by ruleset only', () => { @@ -107,7 +140,10 @@ describe('RuleManager', () => { const matchingRules = await ruleManager.getRulesMatchingCriteria(filters); // Expect the right number of rules to be returned. - expect(matchingRules).to.have.lengthOf(3, 'Exactly 8 rules are in the "Braces" ruleset'); + expect(matchingRules).to.have.lengthOf(3, 'Wrong number of rules returned'); + for (const rule of matchingRules) { + expect(rule.rulesets).to.contain('Braces', `Rule ${rule.name} wrongly included`); + } }); it('Filtering by multiple rulesets returns any rule in either ruleset', async () => { @@ -132,6 +168,9 @@ describe('RuleManager', () => { // Expect the right number of rules to be returned. expect(matchingRules).to.have.lengthOf(2, 'There are 2 rules that target Apex'); + for (const rule of matchingRules) { + expect(rule.languages).to.contain('apex', `Rule ${rule.name} wrongly included`); + } }); it('Filtering by multiple languages returns any rule targeting either language', async () => { @@ -146,6 +185,37 @@ describe('RuleManager', () => { }); }); + describe('Test Case: Filtering by engine only', () => { + it('Filtering by a single engine returns only rules applied to that engine', async () => { + // Set up our filter array. + const filters = [new EngineFilter(['pmd'])]; + + // Pass the filter array into the manager. + const matchingRules = await ruleManager.getRulesMatchingCriteria(filters); + + // Expect the right number of rules to be returned. + expect(matchingRules).to.have.lengthOf(7, 'Wrong number of rules returned'); + for (const rule of matchingRules) { + expect(rule.engine).to.equal('pmd', `Rule ${rule.name} wrongly included`); + } + }); + + it('Filtering by multiple engines returns any rule for either engine', async () => { + // Set up our filter array. + const engines = ['pmd', 'eslint'] + const filters = [new EngineFilter(engines)]; + + // Pass the filter array into the manager. + const matchingRules = await ruleManager.getRulesMatchingCriteria(filters); + + // Expect the right number of rules to be returned. + expect(matchingRules).to.have.lengthOf(11, 'Wrong number of rules returned'); + for (const rule of matchingRules) { + expect(engines).to.contain(rule.engine, `Rule ${rule.name} wrongly included`); + } + }); + }); + describe('Test Case: Mixing filter types', () => { it('Filtering on multiple columns at once returns only rules that satisfy ALL filters', async () => { // Set up our filter array. diff --git a/test/lib/actions/RuleListAction.test.ts b/test/lib/actions/RuleListAction.test.ts index 9be671a71..ef25c6d64 100644 --- a/test/lib/actions/RuleListAction.test.ts +++ b/test/lib/actions/RuleListAction.test.ts @@ -1,25 +1,75 @@ +import {expect} from "chai"; +import {Ux} from "@salesforce/sf-plugins-core"; +import sinon = require('sinon'); + import {FakeDisplay} from "../FakeDisplay"; -import {initContainer} from "../../../src/ioc.config"; +import {initializeTestSetup} from "../../test-related-lib/TestOverrides"; + import {RuleFilterFactoryImpl} from "../../../src/lib/RuleFilterFactory"; import {RuleListAction} from "../../../src/lib/actions/RuleListAction"; import {Inputs} from "../../../src/types"; -import {expect} from "chai"; -import {Ux} from "@salesforce/sf-plugins-core"; -import {PMD7_LIB} from "../../../src/Constants"; -import {Controller} from "../../../lib/Controller"; -import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; +import {ENGINE, PMD7_LIB} from "../../../src/Constants"; +import {Controller} from "../../../src/Controller"; +import {Pmd6CommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; +import {Config} from '../../../src/lib/util/Config'; describe("Tests for RuleListAction", () => { let display: FakeDisplay; let ruleListAction: RuleListAction; - before(() => { - initContainer(); - }); + beforeEach(() => { + initializeTestSetup() display = new FakeDisplay(); ruleListAction = new RuleListAction(display, new RuleFilterFactoryImpl()); }); + describe('Filtering logic', () => { + + beforeEach(() => { + sinon.stub(Config.prototype, 'isEngineEnabled').callThrough().withArgs(ENGINE.ESLINT_LWC).resolves(false); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('Test Case: Without filters, all rules for enabled engines are returned', async () => { + await ruleListAction.run([]); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + + for (const rowData of tableData) { + expect(rowData.engine).to.not.equal('eslint-lwc', 'Should not return rules for disabled engine'); + } + }); + + it('Test Case: Filtering explicitly for disabled engine will return its rules', async () => { + const inputs: Inputs = { + engine: ['eslint-lwc'] + }; + + await ruleListAction.run(inputs); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + expect(tableData).to.have.length(222); + + for (const rowData of tableData) { + expect(rowData.engine).to.equal('eslint-lwc'); + } + }); + + it('Edge Case: No matching rules causes empty table', async () => { + const inputs: Inputs = { + category: ['beebleborp'] + }; + + await ruleListAction.run(inputs); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + expect(tableData).to.have.length(0, 'No rules should have been logged'); + }); + }); + describe("Tests to confirm that PMD7 binary files are invoked when choosing PMD7", () => { afterEach(() => { // Until we remove global state, we should cleanup after ourselves to prevent other tests from being impacted From f92b45acc1950565894724eb49a72e1efe08c396 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 23 Feb 2024 15:34:27 -0600 Subject: [PATCH 17/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored tests for scanner rule remove command. --- test/commands/scanner/rule/remove.test.ts | 146 ------------ test/lib/actions/RuleRemoveAction.test.ts | 259 ++++++++++++++++++++++ test/lib/actions/RunAction.test.ts | 10 +- 3 files changed, 263 insertions(+), 152 deletions(-) delete mode 100644 test/commands/scanner/rule/remove.test.ts create mode 100644 test/lib/actions/RuleRemoveAction.test.ts diff --git a/test/commands/scanner/rule/remove.test.ts b/test/commands/scanner/rule/remove.test.ts deleted file mode 100644 index 0005d4b31..000000000 --- a/test/commands/scanner/rule/remove.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -import {expect} from 'chai'; -import {Interaction} from '@salesforce/cli-plugins-testkit'; -// @ts-ignore -import {runCommand, runInteractiveCommand} from '../../../TestUtils'; -import {Controller} from '../../../../src/Controller'; -import { CUSTOM_PATHS_FILE } from '../../../../src/Constants'; -import * as TestOverrides from './../../../test-related-lib/TestOverrides'; -import fs = require('fs'); -import path = require('path'); -import {BundleName, getMessage} from "../../../../src/MessageCatalog"; - -function getSfdxScannerPath(): string { - return Controller.getSfdxScannerPath(); -} - -// NOTE: The relative paths are relative to the root of the project instead of to the location of this file, -// because the root is the working directory during test evaluation. -const parentFolderForJars = path.resolve('test', 'test-jars', 'apex'); -const pathToApexJar1 = path.resolve('test', 'test-jars', 'apex', 'testjar1.jar'); -const pathToApexJar2 = path.resolve('test', 'test-jars', 'apex', 'testjar2.jar'); -const pathToApexJar3 = path.resolve('test', 'test-jars', 'apex', 'testjar3.jar'); -const pathToApexJar4 = path.resolve('test', 'test-jars', 'apex', 'testjar4.jar'); -// For our tests, we'll include three Apex JARs. -const customPathDescriptor = { - 'pmd': { - 'apex': [pathToApexJar1, pathToApexJar2, pathToApexJar3] - } -}; - -describe('scanner rule remove', () => { - beforeEach(() => { - TestOverrides.initializeTestSetup(); - writePopulatedCustomPathFile(); - }); - - afterEach(() => { - // Clean up after ourselves. - writeEmptyCustomPathFile(); - }); - - describe('E2E', () => { - describe('Interactivity', () => { - it('Omitting --path outputs list of removeable paths', () => { - const output = runCommand(`scanner rule remove`); - const expectedRuleSummary = [pathToApexJar1, pathToApexJar2, pathToApexJar3] - .map(p => getMessage(BundleName.Remove, 'output.dryRunRuleTemplate', [p])) - .join('\n'); - expect(output.shellOutput.stdout).to.contain(getMessage(BundleName.Remove, 'output.dryRunOutput', [3, expectedRuleSummary]), 'All paths should be logged'); - }); - - it('By default, rule removal must be confirmed', async () => { - const output = await runInteractiveCommand(`scanner rule remove --path ${pathToApexJar1}`, { - 'These rules will be unregistered': Interaction.Yes - }); - expect(output.stdout).to.contain( - getMessage(BundleName.Remove, 'output.resultSummary', [pathToApexJar1]), - 'Console should report deletion.' - ); - const updatedCustomPathJson = getCustomPathFileContent(); - expect(updatedCustomPathJson).to.deep.equal({ - 'pmd': { - 'apex': [pathToApexJar2, pathToApexJar3] - } - }, `Deletion should have been persisted ${JSON.stringify(updatedCustomPathJson)}`); - }); - - it('Rule removal can be safely aborted', async () => { - const output = await runInteractiveCommand(`scanner rule remove --path ${pathToApexJar1}`, { - 'These rules will be unregistered': Interaction.No - }); - expect(output.stdout).to.contain(getMessage(BundleName.Remove, 'output.aborted'), 'Transaction should have been aborted'); - const updatedCustomPathJson = getCustomPathFileContent(); - expect(updatedCustomPathJson).to.deep.equal(customPathDescriptor, 'Custom paths should not have changed'); - }); - }); - - describe('Functionality', () => { - it('Successfully removes a single JAR', () => { - const output = runCommand(`scanner rule remove --path ${pathToApexJar1} --force`); - expect(output.shellOutput.stdout).to.contain( - getMessage(BundleName.Remove, 'output.resultSummary', [pathToApexJar1]), - 'Console should report deletion.' - ); - const updatedCustomPathJson = getCustomPathFileContent(); - expect(updatedCustomPathJson).to.deep.equal({ - 'pmd': { - 'apex': [pathToApexJar2, pathToApexJar3] - } - }, `Deletion should have been persisted ${JSON.stringify(updatedCustomPathJson)}`); - }); - - it('Successfully removes multiple JARs at once', () => { - const output = runCommand(`scanner rule remove --path ${pathToApexJar1},${pathToApexJar2} --force`); - expect(output.shellOutput.stdout).to.contain( - getMessage(BundleName.Remove, 'output.resultSummary', [[pathToApexJar1, pathToApexJar2].join(', ')]), - 'Console should report deletion' - ); - const updatedCustomPathJson = getCustomPathFileContent(); - expect(updatedCustomPathJson).to.deep.equal({ - 'pmd': { - 'apex': [pathToApexJar3] - } - }, 'Deletion should have been persisted'); - }); - - it('Successfully removes a whole folder', () => { - const output = runCommand(`scanner rule remove --path ${parentFolderForJars} --force`); - expect(output.shellOutput.stdout).to.contain( - getMessage(BundleName.Remove, 'output.resultSummary', [[pathToApexJar1, pathToApexJar2, pathToApexJar3].join(', ')]), - 'Console should report deletion' - ); - const updatedCustomPathJson = getCustomPathFileContent(); - expect(updatedCustomPathJson).to.deep.equal({ - 'pmd': { - 'apex': [] - } - }, 'Deletion should have been persisted'); - }); - - it('Throws error when requested path is not already registered', () => { - const output = runCommand(`scanner rule remove --path ${pathToApexJar4}`); - expect(output.shellOutput.stderr).to.contain(getMessage(BundleName.Remove, 'errors.noMatchingPaths'), 'Should throw expected error'); - }); - }); - - describe('Validations', () => { - it('Complains about empty --path', () => { - const output = runCommand(`scanner rule remove --path ''`); - expect(output.shellOutput.stderr).to.contain(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty')); - }); - }); - }); -}); - -function writeEmptyCustomPathFile() { - fs.writeFileSync(path.join(getSfdxScannerPath(), CUSTOM_PATHS_FILE), "{}"); -} - -function writePopulatedCustomPathFile() { - fs.writeFileSync(path.join(getSfdxScannerPath(), CUSTOM_PATHS_FILE), JSON.stringify(customPathDescriptor)); -} - -function getCustomPathFileContent(): string { - return JSON.parse(fs.readFileSync(path.join(getSfdxScannerPath(), CUSTOM_PATHS_FILE)).toString()); -} - diff --git a/test/lib/actions/RuleRemoveAction.test.ts b/test/lib/actions/RuleRemoveAction.test.ts new file mode 100644 index 000000000..24a2131b0 --- /dev/null +++ b/test/lib/actions/RuleRemoveAction.test.ts @@ -0,0 +1,259 @@ +import {Logger} from '@salesforce/core'; +import {assert, expect} from 'chai'; +import {FileHandler} from '../../../src/lib/util/FileHandler'; +import sinon = require('sinon'); +import path = require('path'); + +import {FakeDisplay} from '../FakeDisplay'; +import {initializeTestSetup} from '../../test-related-lib/TestOverrides'; + +import {Controller} from '../../../src/Controller'; +import {Inputs} from '../../../src/types'; +import {CUSTOM_PATHS_FILE} from '../../../src/Constants'; +import {BundleName, getMessage} from '../../../src/MessageCatalog'; +import {InputProcessor, InputProcessorImpl} from '../../../src/lib/InputProcessor'; +import {RuleRemoveAction} from '../../../src/lib/actions/RuleRemoveAction'; + +describe('RuleRemoveAction', () => { + let testLogger: Logger; + let testDisplay: FakeDisplay; + let testInputProcessor: InputProcessor; + let testAction: RuleRemoveAction; + + beforeEach(async () => { + initializeTestSetup(); + testLogger = await Logger.child('RuleRemoveAction.test.ts'); + testDisplay = new FakeDisplay(); + testInputProcessor = new InputProcessorImpl('test', testDisplay); + testAction = new RuleRemoveAction(testLogger, testDisplay, testInputProcessor); + }); + + describe('#validateInputs()' ,() => { + it('Rejects empty `.path` property', async () => { + const inputs: Inputs = { + path: [] + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); + } + }); + + it('rejects `.path` containing empty string', async () => { + const inputs: Inputs = { + path: [''] + }; + + try { + await testAction.validateInputs(inputs); + assert.fail('Exception should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); + } + }); + }); + + describe('#run', () => { + const FAKE_PARENT_FOLDER = path.resolve('test', 'test-jars', 'apex'); + const FAKE_PATH_1 = path.resolve('test', 'test-jars', 'apex', 'testjar1.jar'); + const FAKE_PATH_2 = path.resolve('test', 'test-jars', 'apex', 'testjar2.jar'); + const FAKE_PATH_3 = path.resolve('test', 'test-jars', 'apex', 'testjar3.jar'); + const FAKE_PATH_4 = path.resolve('test', 'test-jars', 'apex', 'testjar4.jar'); + const FAKE_CUSTOM_RULE_DESCRIPTOR = { + pmd: { + apex: [FAKE_PATH_1, FAKE_PATH_2, FAKE_PATH_3] + } + }; + + afterEach(() => { + sinon.restore(); + }); + + describe('When there ARE NOT registered rule paths...', () => { + + beforeEach(() => { + // Stub out the file handler, so it thinks the custom rule file has our desired contents. + const fullRulePath = path.join(Controller.getSfdxScannerPath(), CUSTOM_PATHS_FILE); + sinon.stub(FileHandler.prototype, 'readFile').callThrough() + .withArgs(fullRulePath).resolves('{}'); + }); + + it('Omitting --path causes dry-run with appropriate message', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Run the dry run. + const inputs: Inputs = {}; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + const expectedDryRunOutput = getMessage(BundleName.Remove, 'output.dryRunReturnedNoRules', []); + expect(testDisplay.getOutputArray()).to.contain(`[Info]: ${expectedDryRunOutput}`); + }); + + it('Using --path causes Match Failure error, since there no paths to match', async () => { + // ==== EXECUTE TESTED METHOD ==== + const inputs: Inputs = { + path: [FAKE_PATH_1] + }; + try { + await testAction.run(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + // ==== ASSERTIONS ==== + expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths')); + } + }); + }); + + describe('When there ARE registered rule paths...', () => { + let writtenFile: string; + + beforeEach(() => { + writtenFile = ''; + // Stub out the file handler, so it thinks the custom rule file has our desired contents. + const fullRulePath = path.join(Controller.getSfdxScannerPath(), CUSTOM_PATHS_FILE); + sinon.stub(FileHandler.prototype, 'readFile').callThrough() + .withArgs(fullRulePath).resolves(JSON.stringify(FAKE_CUSTOM_RULE_DESCRIPTOR)); + sinon.stub(FileHandler.prototype, 'writeFile').callThrough() + .withArgs(fullRulePath).callsFake(async (file, content) => { + writtenFile = content; + }); + }); + + it('Omitting --path causes dry-run and logs all paths', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Run the dry run. + const inputs: Inputs = {}; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + const expectedDryRunOutput = getMessage(BundleName.Remove, 'output.dryRunOutput', + [3, FAKE_CUSTOM_RULE_DESCRIPTOR.pmd.apex.join('\n')]); + expect(testDisplay.getOutputArray()).to.contain(`[Info]: ${expectedDryRunOutput}`); + }); + + describe('Using --path allows removal with confirmation prompt', () => { + it('Test Case: Can remove a single JAR', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Remove just one JAR. + const inputs = { + path: [FAKE_PATH_1] + }; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + // The JAR we removed should be gone. + expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + // The other JARs should still be there. + expect(writtenFile).to.contain(FAKE_PATH_2, 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + }); + + it('Test Case: Can remove a list of JARs', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Remove two JARs. + const inputs = { + path: [FAKE_PATH_1, FAKE_PATH_2] + }; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + // The JARs we removed should be gone. + expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(FAKE_PATH_2, 'JAR should have been removed'); + // The other JAR should still be there. + expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + }); + + it('Test Case: Can remove a folder', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Remove the folder containing all the JARs. + const inputs = { + path: [FAKE_PARENT_FOLDER] + }; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + // All JARs should be gone. + expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(FAKE_PATH_2, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(FAKE_PATH_3, 'JAR should have been removed'); + }); + + it('Test Case: Throws error for unregistered path', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Attempt to remove a JAR that isn't already registered. + const inputs = { + path: [FAKE_PATH_4] + }; + try { + await testAction.run(inputs); + assert.fail('Error should have thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); + } + }); + + it('Test Case: Action can be aborted during confirmation prompt', async () => { + // ==== SETUP ==== + // Configure the display so that aborts instead of confirming. + testDisplay.setConfirmationPromptResponse(false); + + // ==== EXECUTE TESTED METHOD ==== + // Attempt to remove a JAR. + const inputs = { + path: [FAKE_PATH_1] + }; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + // Action should have aborted and persisted no changes. + expect(testDisplay.getOutputArray()).to.contain(`[Info]: ${getMessage(BundleName.Remove, 'output.aborted', [])}`); + expect(writtenFile).to.equal('', 'Nothing should have been persisted'); + }); + }); + + describe('Using --force bypasses the confirmation prompt', () => { + it('Test Case: Removing a single JAR', async () => { + // ==== SETUP ==== + // Configure the display such that the confirmation prompt will reject if it's encountered. + // This is guaranteeing that the confirmation prompt was never given, meaning that --force + // bypassed it. + testDisplay.setConfirmationPromptResponse(false); + + // ==== EXECUTE TESTED METHOD ==== + // Remove just one JAR. + const inputs = { + path: [FAKE_PATH_1], + force: true + }; + await testAction.run(inputs); + + // ==== ASSERTIONS ==== + // The JAR we removed should be gone. + expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + // The other JARs should still be there. + expect(writtenFile).to.contain(FAKE_PATH_2, 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + }); + + it('Test Case: Throws error for unregistered path', async () => { + // ==== EXECUTE TESTED METHOD ==== + // Attempt to remove a JAR that isn't already registered. + const inputs = { + path: [FAKE_PATH_4], + force: true + }; + try { + await testAction.run(inputs); + assert.fail('Error should have thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); + } + }); + }); + }); + }); +}); diff --git a/test/lib/actions/RunAction.test.ts b/test/lib/actions/RunAction.test.ts index 1af2e9102..880afad88 100644 --- a/test/lib/actions/RunAction.test.ts +++ b/test/lib/actions/RunAction.test.ts @@ -6,13 +6,13 @@ import {FakeDisplay} from "../FakeDisplay"; import {Logger} from "@salesforce/core"; import {Inputs, PathlessRuleViolation, RuleResult} from "../../../src/types"; import * as path from "path"; -import {initContainer} from '../../../src/ioc.config'; +import {initializeTestSetup} from "../../test-related-lib/TestOverrides"; import {expect} from "chai"; import {Results} from "../../../src/lib/output/Results"; import {PMD6_VERSION, PMD7_VERSION} from "../../../src/Constants"; import {FakeResultsProcessorFactory, RawResultsProcessor} from "./fakes"; -import {Controller} from "../../../lib/Controller"; -import {Pmd6CommandInfo} from "../../../lib/lib/pmd/PmdCommandInfo"; +import {Controller} from "../../../src/Controller"; +import {Pmd6CommandInfo} from "../../../src/lib/pmd/PmdCommandInfo"; const codeFixturesDir = path.join(__dirname, '..', '..', 'code-fixtures'); const pathToSomeTestClass = path.join(codeFixturesDir, 'apex', 'SomeTestClass.cls'); @@ -22,10 +22,8 @@ describe("Tests for RunAction", () => { let display: FakeDisplay; let resultsProcessor: RawResultsProcessor; let runAction: RunAction; - before(() => { - initContainer(); - }); beforeEach(() => { + initializeTestSetup(); display = new FakeDisplay(); resultsProcessor = new RawResultsProcessor(); From a546060281f8eba2839564a48c4f07b28933e45d Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Mon, 26 Feb 2024 13:35:00 -0700 Subject: [PATCH 18/28] fix: publish npm-shrinkwrap.json --- .gitignore | 2 ++ package.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fc6cda164..ef7fe04da 100644 --- a/.gitignore +++ b/.gitignore @@ -157,3 +157,5 @@ oclif.lock pmd-cataloger/bin sfge*.log.gz + +npm-shrinkwrap.json diff --git a/package.json b/package.json index ad4a79ad9..5c8045de9 100644 --- a/package.json +++ b/package.json @@ -136,8 +136,8 @@ "repository": "forcedotcom/sfdx-scanner", "scripts": { "build": "./gradlew build -x test", - "prepack": "rm -rf lib && tsc -b && oclif manifest && oclif readme && oclif lock", - "postpack": "rm -f oclif.manifest.json", + "prepack": "rm -rf lib && tsc -b && oclif manifest && oclif readme && oclif lock && npm-shrinkwrap", + "postpack": "rm -f oclif.manifest.json oclif.lock npm-shrinkwrap.json", "lint-typescript": "eslint ./src --ext .ts --max-warnings 0", "test": "./gradlew test jacocoTestCoverageVerification && nyc mocha --timeout 10000 --retries 5 \"./test/**/*.test.ts\"", "test-quiet": "cross-env SFGE_LOGGING=false ./gradlew test jacocoTestCoverageVerification && nyc mocha --timeout 10000 --retries 5 \"./test/**/*.test.ts\"", From e63c32fd200574a34103662ff01723a19d72c3a5 Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Mon, 26 Feb 2024 13:46:51 -0700 Subject: [PATCH 19/28] fix: typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5c8045de9..892f08a3d 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "repository": "forcedotcom/sfdx-scanner", "scripts": { "build": "./gradlew build -x test", - "prepack": "rm -rf lib && tsc -b && oclif manifest && oclif readme && oclif lock && npm-shrinkwrap", + "prepack": "rm -rf lib && tsc -b && oclif manifest && oclif readme && oclif lock && npm shrinkwrap", "postpack": "rm -f oclif.manifest.json oclif.lock npm-shrinkwrap.json", "lint-typescript": "eslint ./src --ext .ts --max-warnings 0", "test": "./gradlew test jacocoTestCoverageVerification && nyc mocha --timeout 10000 --retries 5 \"./test/**/*.test.ts\"", From 33dc6b292af35e1627db341b3fb961e3dbbb1b72 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Mon, 26 Feb 2024 14:50:56 -0600 Subject: [PATCH 20/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored test coverage for scanner run dfa command. --- test/commands/scanner/run.dfa.test.ts | 107 -------------- test/lib/actions/RunDfaAction.test.ts | 197 ++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 107 deletions(-) delete mode 100644 test/commands/scanner/run.dfa.test.ts create mode 100644 test/lib/actions/RunDfaAction.test.ts diff --git a/test/commands/scanner/run.dfa.test.ts b/test/commands/scanner/run.dfa.test.ts deleted file mode 100644 index 7a6120a81..000000000 --- a/test/commands/scanner/run.dfa.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import {expect} from 'chai'; -// @ts-ignore -import {runCommand} from '../../TestUtils'; -import * as path from 'path'; -import * as sinon from 'sinon'; -import {UxDisplay} from "../../../src/lib/Display"; -import {BundleName, getMessage} from "../../../src/MessageCatalog"; - - -const dfaTarget = path.join('test', 'code-fixtures', 'projects', 'sfge-smoke-app', 'src'); -const projectdir = path.join('test', 'code-fixtures', 'projects', 'sfge-smoke-app', 'src'); - -const apexControllerStr = 'UnsafeVfController'; -const customSettingsStr = 'none found'; -const fileCount = '7'; -const entryPointCount = '5'; -const pathCount = '6'; -const violationCount = '2'; - -const customSettingsMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeMetaInfoCollected', ['Custom Settings', customSettingsStr]); -const apexControllerMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeMetaInfoCollected', ['Apex Controllers', apexControllerStr]); -const compiledMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeFinishedCompilingFiles', [fileCount]); -const startGraphBuildMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeStartedBuildingGraph'); -const endGraphBuildMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeFinishedBuildingGraph'); -const identifiedEntryMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgePathEntryPointsIdentified', [entryPointCount]); -const completedAnalysisMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeCompletedPathAnalysis', [pathCount, entryPointCount, violationCount]); -const experimentalRuleName = "RemoveUnusedMethod"; - -function isSubstr(output: string, substring: string): boolean { - const updatedSubstr = substring.replace('[', '\\['); - const regex = new RegExp(`${updatedSubstr}`, 'gm'); - const regexMatch = output.match(regex); - return regexMatch != null && regexMatch.length >= 1; -} - -function verifyContains(output: string, substring: string): void { - expect(isSubstr(output, substring), `Output "${output}" should contain substring "${substring}"`).is.true; -} - -function verifyNotContains(output: string, substring: string): void { - expect(isSubstr(output, substring), `Output "${output}" should not contain substring "${substring}"`).is.false; -} - -describe('scanner run dfa', function () { - this.timeout(20000); // TODO why do we get timeouts at the default of 5000? What is so expensive here? - - describe('End to end', () => { - describe('Without special flags', () => { - let sandbox; - let spy: sinon.SinonSpy; - - before(() => { - sandbox = sinon.createSandbox(); - spy = sandbox.spy(UxDisplay.prototype, "spinnerUpdate"); - }) - - after(() => { - spy.restore(); - sinon.restore(); - }); - - const output = runCommand(`scanner run dfa --target ${dfaTarget} --projectdir ${projectdir} --format json`); - - - it('Output is parsable JSON', () => { - try { - JSON.parse(output.shellOutput.stdout); - } catch (error) { - expect.fail(`Invalid JSON output from --format json: ${output.shellOutput.stdout}; error = ${error}`); - } - }); - - it('Pilot rules are not executed', () => { - // Verify that there's NOT a violation somewhere for an experimental rule. - verifyNotContains(output.shellOutput.stdout, experimentalRuleName); - }); - - it('Contains no verbose-only information', () => { - // The messages about loading various types of thing should only be logged when --verbose is used. - const stdout = output.shellOutput.stdout; - verifyNotContains(stdout, customSettingsMessage); - verifyNotContains(stdout, apexControllerMessage); - expect(spy.calledWith(compiledMessage, startGraphBuildMessage, endGraphBuildMessage, identifiedEntryMessage, completedAnalysisMessage)); - }); - }); - - describe('Using --with-pilot flag', () => { - const output = runCommand(`scanner run dfa --target ${dfaTarget} --projectdir ${projectdir} --format json --with-pilot`); - - it('Executes experimental rules', () => { - // Verify that there's a violation somewhere in there for an experimental rule. - verifyContains(output.shellOutput.stdout, experimentalRuleName); - }); - }); - - describe('Using --verbose flag', () => { - const output = runCommand(`scanner run dfa --target ${dfaTarget} --projectdir ${projectdir} --format json --verbose`); - - it('Verbose information is logged', () => { - // The messages about loading various types of thing should only be logged when --verbose is used. - const stdout = output.shellOutput.stdout; - verifyContains(stdout, customSettingsMessage); - verifyContains(stdout, apexControllerMessage); - }); - }); - }); -}); diff --git a/test/lib/actions/RunDfaAction.test.ts b/test/lib/actions/RunDfaAction.test.ts new file mode 100644 index 000000000..caa2ae08c --- /dev/null +++ b/test/lib/actions/RunDfaAction.test.ts @@ -0,0 +1,197 @@ +import {Logger} from '@salesforce/core'; +import {assert, expect} from 'chai'; +import path = require('path'); + +import {FakeDisplay} from '../FakeDisplay'; +import {initializeTestSetup} from '../../test-related-lib/TestOverrides'; + +import {OutputFormat} from '../../../src/lib/output/OutputFormat'; +import {getMessage, BundleName} from '../../../src/MessageCatalog'; +import {Inputs} from '../../../src/types'; +import {RunDfaAction} from '../../../src/lib/actions/RunDfaAction'; +import {InputProcessor, InputProcessorImpl} from '../../../src/lib/InputProcessor'; +import {RuleFilterFactory, RuleFilterFactoryImpl} from '../../../src/lib/RuleFilterFactory'; +import {EngineOptionsFactory, RunDfaEngineOptionsFactory} from '../../../src/lib/EngineOptionsFactory'; +import {ResultsProcessorFactory, ResultsProcessorFactoryImpl} from '../../../src/lib/output/ResultsProcessorFactory'; + +describe('RunDfaAction', () => { + let display: FakeDisplay; + let logger: Logger; + let inputProcessor: InputProcessor; + let ruleFilterFactory: RuleFilterFactory; + let engineOptionsFactory: EngineOptionsFactory; + let resultsProcessorFactory: ResultsProcessorFactory; + + let runDfaAction: RunDfaAction; + + beforeEach(async () => { + initializeTestSetup(); + display = new FakeDisplay(); + logger = await Logger.child('RunDfaAction.test.ts'); + inputProcessor = new InputProcessorImpl('test', display); + ruleFilterFactory = new RuleFilterFactoryImpl(); + engineOptionsFactory = new RunDfaEngineOptionsFactory(inputProcessor); + resultsProcessorFactory = new ResultsProcessorFactoryImpl(); + runDfaAction = new RunDfaAction(logger, display, inputProcessor, + ruleFilterFactory, engineOptionsFactory, resultsProcessorFactory); + }); + + describe('#validateInputs()', () => { + it('--projectdir cannot be a glob', async () => { + const inputs: Inputs = { + 'projectdir': ['./**/*.cls'] + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirCannotBeGlob')); + } + }); + + it('--projectdir must be real', async () => { + const inputs: Inputs = { + 'projectdir': ['./not/a/real/file.txt'] + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustExist')); + } + }); + + it('--projectdir must be directory', async () => { + const inputs: Inputs = { + // The path is relative to the root directory of the project, not this specific file. + 'projectdir': [path.resolve('./src/Controller.ts')] + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustBeDir')); + } + }); + + it('--outfile cannot be used if --format is "table"', async () => { + const inputs: Inputs = { + 'outfile': 'beep.csv', + 'format': 'table' + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.cannotWriteTableToFile')); + } + }); + + it('If --outfile and --format conflict, message is logged', async () => { + const inputs: Inputs = { + 'outfile': 'beep.csv', + 'format': OutputFormat.XML + }; + + await runDfaAction.validateInputs(inputs); + expect(display.getOutputArray()).to.contain(`[Info]: ${getMessage(BundleName.CommonRun, 'validations.outfileFormatMismatch', ['xml', 'csv'])}`); + }); + + it('Method-level --target values cannot be globs', async () => { + const inputs: Inputs = { + 'target': ['./**/*.cls#beep'] + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetCannotBeGlob')); + } + }); + + it('Method-level --target values must be a real file', async () => { + const file = './not/a/real/file.cls'; + const inputs: Inputs = { + 'target': [`${file}#beep`] + }; + + try { + await runDfaAction.validateInputs(inputs); + assert.fail('Error should have been thrown'); + } catch (e) { + expect(e.message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetMustBeRealFile', [file])); + } + }); + }); + + describe('#run()', () => { + const apexControllerStr = 'UnsafeVfController'; + const customSettingsStr = 'none found'; + const customSettingsMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeMetaInfoCollected', ['Custom Settings', customSettingsStr]); + const apexControllerMessage = getMessage(BundleName.EventKeyTemplates, 'info.sfgeMetaInfoCollected', ['Apex Controllers', apexControllerStr]); + const dfaTarget = path.join('test', 'code-fixtures', 'projects', 'sfge-smoke-app', 'src'); + const projectdir = path.join('test', 'code-fixtures', 'projects', 'sfge-smoke-app', 'src'); + + describe('With no special flags', () => { + it('Pilot rules are not executed', async () => { + const inputs: Inputs = { + target: [dfaTarget], + projectdir: [projectdir], + format: 'json' + }; + + await runDfaAction.run(inputs); + + expect(display.getOutputText()).to.not.contain('RemoveUnusedMethod', 'Experimental rules should not be executed'); + }); + + it('Verbose-only information is not logged', async () => { + const inputs: Inputs = { + target: [dfaTarget], + projectdir: [projectdir], + format: 'json' + }; + + await runDfaAction.run(inputs); + + expect(display.getOutputText()).to.not.contain(customSettingsMessage, 'Custom Settings verbose message should not have been logged'); + expect(display.getOutputText()).to.not.contain(apexControllerMessage, 'Apex Controller verbose message should not have been logged'); + }); + }); + + it('Using --with-pilot runs experimental rules', async () => { + const inputs: Inputs = { + target: [dfaTarget], + projectdir: [projectdir], + format: 'json', + 'with-pilot': true + }; + + await runDfaAction.run(inputs); + expect(display.getOutputText()).to.contain('RemoveUnusedMethod', 'Expected violation for experimental rule'); + }); + + // TODO: This test fails because the event handler for the messages is assigned in + // ScannerCommand.ts, which is no longer invoked in this style of test. + // When we move away from the event passing model, it should allow us to enable + // this test (hopefully). + xit('Using --verbose flag logs more detailed information', async () => { + const inputs: Inputs = { + target: [dfaTarget], + projectdir: [projectdir], + format: 'json', + verbose: true + }; + + await runDfaAction.run(inputs); + expect(display.getOutputText()).to.contain(customSettingsMessage, 'Expected Custom Settings verbose message'); + expect(display.getOutputText()).to.contain(apexControllerMessage, 'Expected Apex Controller verbose message'); + }); + }); + +}); From 2b6983b9cea2cb017afa2b56d174f098db857017 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Tue, 27 Feb 2024 12:11:21 -0600 Subject: [PATCH 21/28] CHANGE (CodeAnalyzer): @W-14645433@: Fixing broken windows tests. --- test/lib/actions/RuleAddAction.test.ts | 6 +++--- test/lib/actions/RuleRemoveAction.test.ts | 24 +++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/lib/actions/RuleAddAction.test.ts b/test/lib/actions/RuleAddAction.test.ts index 4ec5ab228..451f20ea2 100644 --- a/test/lib/actions/RuleAddAction.test.ts +++ b/test/lib/actions/RuleAddAction.test.ts @@ -137,9 +137,9 @@ describe('RuleAddAction', () => { let controllerStub; const language = 'apex'; const inputPaths = [ - '~/this/path/is/tildified', - '/This/Path/Is/Absolute', - './This/Path/Is/Relative' + path.join('~', 'this', 'path', 'is', 'tildified'), + path.resolve('.', 'this', 'path', 'is', 'absolute'), + path.join('.', 'this', 'path', 'is', 'relative') ]; const expectedOutputPaths = [ untildify(inputPaths[0]), diff --git a/test/lib/actions/RuleRemoveAction.test.ts b/test/lib/actions/RuleRemoveAction.test.ts index 24a2131b0..19d03d5d4 100644 --- a/test/lib/actions/RuleRemoveAction.test.ts +++ b/test/lib/actions/RuleRemoveAction.test.ts @@ -145,10 +145,10 @@ describe('RuleRemoveAction', () => { // ==== ASSERTIONS ==== // The JAR we removed should be gone. - expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_1), 'JAR should have been removed'); // The other JARs should still be there. - expect(writtenFile).to.contain(FAKE_PATH_2, 'JAR should NOT have been removed'); - expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(JSON.stringify(FAKE_PATH_2), 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(JSON.stringify(FAKE_PATH_3), 'JAR should NOT have been removed'); }); it('Test Case: Can remove a list of JARs', async () => { @@ -161,10 +161,10 @@ describe('RuleRemoveAction', () => { // ==== ASSERTIONS ==== // The JARs we removed should be gone. - expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); - expect(writtenFile).to.not.contain(FAKE_PATH_2, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_1), 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_2), 'JAR should have been removed'); // The other JAR should still be there. - expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(JSON.stringify(FAKE_PATH_3), 'JAR should NOT have been removed'); }); it('Test Case: Can remove a folder', async () => { @@ -177,9 +177,9 @@ describe('RuleRemoveAction', () => { // ==== ASSERTIONS ==== // All JARs should be gone. - expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); - expect(writtenFile).to.not.contain(FAKE_PATH_2, 'JAR should have been removed'); - expect(writtenFile).to.not.contain(FAKE_PATH_3, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_1), 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_2), 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_3), 'JAR should have been removed'); }); it('Test Case: Throws error for unregistered path', async () => { @@ -233,10 +233,10 @@ describe('RuleRemoveAction', () => { // ==== ASSERTIONS ==== // The JAR we removed should be gone. - expect(writtenFile).to.not.contain(FAKE_PATH_1, 'JAR should have been removed'); + expect(writtenFile).to.not.contain(JSON.stringify(FAKE_PATH_1), 'JAR should have been removed'); // The other JARs should still be there. - expect(writtenFile).to.contain(FAKE_PATH_2, 'JAR should NOT have been removed'); - expect(writtenFile).to.contain(FAKE_PATH_3, 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(JSON.stringify(FAKE_PATH_2), 'JAR should NOT have been removed'); + expect(writtenFile).to.contain(JSON.stringify(FAKE_PATH_3), 'JAR should NOT have been removed'); }); it('Test Case: Throws error for unregistered path', async () => { From f4e23a70d0e4276a273a1e36c55165de55d1fca8 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 1 Mar 2024 13:55:25 -0600 Subject: [PATCH 22/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored CPD-related list tests. --- test/TestUtils.ts | 2 +- .../DefaultCatalogFixture.json | 23 +++++++++++ test/commands/scanner/e2e.cpd.test.ts | 32 +-------------- test/lib/actions/RuleListAction.test.ts | 33 ++++++++++++++- test/lib/services/LocalCatalog.test.ts | 41 ++++++++++++++----- 5 files changed, 86 insertions(+), 45 deletions(-) diff --git a/test/TestUtils.ts b/test/TestUtils.ts index 678ec2356..a2192de8b 100644 --- a/test/TestUtils.ts +++ b/test/TestUtils.ts @@ -14,7 +14,7 @@ import LocalCatalog from '../src/lib/services/LocalCatalog'; const CATALOG_FIXTURE_PATH = path.join('test', 'catalog-fixtures', 'DefaultCatalogFixture.json'); -export const CATALOG_FIXTURE_RULE_COUNT = 15; +export const CATALOG_FIXTURE_RULE_COUNT = 16; export const CATALOG_FIXTURE_DEFAULT_ENABLED_RULE_COUNT = 11; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/test/catalog-fixtures/DefaultCatalogFixture.json b/test/catalog-fixtures/DefaultCatalogFixture.json index dea489e9e..39b262bbe 100644 --- a/test/catalog-fixtures/DefaultCatalogFixture.json +++ b/test/catalog-fixtures/DefaultCatalogFixture.json @@ -53,6 +53,11 @@ "paths": [ "https://eslint.org/docs/rules/no-inner-declarations" ] + }, + { + "name": "Copy/Paste Detected", + "engine": "cpd", + "paths": [] } ], "rulesets": [ @@ -332,6 +337,24 @@ ], "message": "Avoid using if statements without curly braces", "engine": "pmd" + }, + { + "rulesets": [], + "defaultEnabled": true, + "sourcepackage": "cpd", + "languages": [ + "apex", + "java", + "visualforce", + "xml" + ], + "name": "copy-paste-detected", + "description": "Identify duplicate code blocks.", + "categories": [ + "Copy/Paste Detected" + ], + "message": "", + "engine": "cpd" } ] } diff --git a/test/commands/scanner/e2e.cpd.test.ts b/test/commands/scanner/e2e.cpd.test.ts index 2fef5f599..eb5418295 100644 --- a/test/commands/scanner/e2e.cpd.test.ts +++ b/test/commands/scanner/e2e.cpd.test.ts @@ -1,10 +1,9 @@ import { expect } from "chai"; -// @ts-ignore import { runCommand } from "../../TestUtils"; import path = require("path"); import { ENGINE } from "../../../src/Constants"; import { RuleResult } from "../../../src/types"; -import { CpdLanguagesSupported, CpdRuleCategory, CpdRuleDescription, CpdRuleName, CpdViolationSeverity } from "../../../src/lib/cpd/CpdEngine"; +import {CpdRuleCategory, CpdRuleName, CpdViolationSeverity } from "../../../src/lib/cpd/CpdEngine"; const Cpd_Test_Code_Path = path.join("test", "code-fixtures", "cpd"); const Vf_File1 = path.join(Cpd_Test_Code_Path, "myVfPage1.page"); @@ -112,35 +111,6 @@ describe("End to end tests for CPD engine", () => { }); }); }); - - describe("Integration with `scanner rule list` command", () => { - describe("Invoking CPD engine", () => { - it("CPD engine rules should not be displayed by default", () => { - const output = runCommand(`scanner rule list --json`); - const results = output.jsonOutput.result as any[]; - expect(results.length).to.be.greaterThan(0); - - const cpdCatalogs = results.filter(row => row.engine === ENGINE.CPD); - expect(cpdCatalogs).to.have.lengthOf(0); - }); - - it("CPD engine rules should be displayed when using `--engine cpd`", () => { - const output = runCommand(`scanner rule list --engine cpd --json`); - const results = output.jsonOutput.result as any[]; - expect(results.length).equals(1); - - // Verify properties of rule. - const rule = results[0]; - expect(rule.engine).equals(ENGINE.CPD); - expect(rule.sourcepackage).equals(ENGINE.CPD); - expect(rule.name).equals(CpdRuleName); - expect(rule.description).equals(CpdRuleDescription); - expect(rule.categories).contains(CpdRuleCategory); - expect(rule.languages).has.same.members(CpdLanguagesSupported); - expect(rule.defaultEnabled).equals(true); - }); - }); - }); }); function verifyEnvVarIsUsedForMinimumTokens(ctx) { const Minimum_Tokens_50 = [Apex_File1, Apex_File2, Vf_File1, Vf_File2].sort(); diff --git a/test/lib/actions/RuleListAction.test.ts b/test/lib/actions/RuleListAction.test.ts index ef25c6d64..99f4238fb 100644 --- a/test/lib/actions/RuleListAction.test.ts +++ b/test/lib/actions/RuleListAction.test.ts @@ -26,20 +26,29 @@ describe("Tests for RuleListAction", () => { describe('Filtering logic', () => { beforeEach(() => { - sinon.stub(Config.prototype, 'isEngineEnabled').callThrough().withArgs(ENGINE.ESLINT_LWC).resolves(false); + sinon.stub(Config.prototype, 'isEngineEnabled') + .callThrough() + .withArgs(ENGINE.ESLINT_LWC).resolves(false) + .withArgs(ENGINE.CPD).resolves(true); }); afterEach(() => { sinon.restore(); }); - it('Test Case: Without filters, all rules for enabled engines are returned', async () => { + it('Test Case: Without filters, all rules for enabled and default-runnable engines are returned', async () => { await ruleListAction.run([]); let tableData: Ux.Table.Data[] = display.getLastTableData(); for (const rowData of tableData) { expect(rowData.engine).to.not.equal('eslint-lwc', 'Should not return rules for disabled engine'); + // NOTE: Currently, CPD has the unique behavior of only running/listing rules when it's explicitly + // requested via the --engine parameter, even if it's listed as enabled. So since it wasn't + // explicitly requested, it shouldn't be included. + // This behavior is something of an anomaly, and should not be taken as ironclad. If it becomes + // advantageous or convenient to change it, we should take the opportunity to do so. + expect(rowData.engine).to.not.equal('cpd', 'Should not return rule for unrequested CPD engine'); } }); @@ -58,6 +67,26 @@ describe("Tests for RuleListAction", () => { } }); + // NOTE: Currently, CPD has the unique behavior of only running/listing rules when it's explicitly requested via + // the --engine parameter, even if it's listed as enabled. So since it's explicitly requested here, it should + // be included. + // This behavior is something of an anomaly, and should not be taken as ironclad. If it becomes + // advantageous or convenient to change it, we should take the opportunity to do so. + it('Test Case: Filtering explicitly for a default non-runnable engine will return its rules', async () => { + const inputs: Inputs = { + engine: ['cpd'] + }; + + await ruleListAction.run(inputs); + + let tableData: Ux.Table.Data[] = display.getLastTableData(); + expect(tableData).to.have.length(1); + + for (const rowData of tableData) { + expect(rowData.engine).to.equal('cpd'); + } + }); + it('Edge Case: No matching rules causes empty table', async () => { const inputs: Inputs = { category: ['beebleborp'] diff --git a/test/lib/services/LocalCatalog.test.ts b/test/lib/services/LocalCatalog.test.ts index 74d897825..3392105dd 100644 --- a/test/lib/services/LocalCatalog.test.ts +++ b/test/lib/services/LocalCatalog.test.ts @@ -1,12 +1,12 @@ import Sinon = require('sinon'); import * as TestOverrides from '../../test-related-lib/TestOverrides'; import * as TestUtils from '../../TestUtils'; -import { RuleCatalog } from '../../../src/lib/services/RuleCatalog'; -import { CategoryFilter, EngineFilter, LanguageFilter, RuleFilter, RulesetFilter } from '../../../src/lib/RuleFilter'; -import { ENGINE, LANGUAGE } from '../../../src/Constants'; -import { Rule, RuleGroup } from '../../../src/types'; +import {RuleCatalog} from '../../../src/lib/services/RuleCatalog'; +import {CategoryFilter, EngineFilter, LanguageFilter, RuleFilter, RulesetFilter} from '../../../src/lib/RuleFilter'; +import {ENGINE, LANGUAGE} from '../../../src/Constants'; +import {Rule, RuleGroup} from '../../../src/types'; import LocalCatalog from '../../../src/lib/services/LocalCatalog'; -import { expect } from 'chai'; +import {expect} from 'chai'; import {Controller} from '../../../src/Controller'; TestOverrides.initializeTestSetup(); @@ -63,6 +63,14 @@ describe('LocalCatalog', () => { validatePmdRuleGroup(mappedRuleGroups, name, languages, 'category'); }; + const validateCpdCategory = (mappedRuleGroups: Map, name: string, languages: string[]): void => { + const ruleGroup = mappedRuleGroups.get(`${ENGINE.CPD}:${name}`); + expect(ruleGroup).to.not.be.undefined; + expect(ruleGroup.name).to.equal(name); + expect(ruleGroup.engine).to.equal(ENGINE.CPD); + expect(ruleGroup.paths, TestUtils.prettyPrint(ruleGroup.paths)).to.be.lengthOf(0); + } + const validateEslintBestPractices = (mappedRuleGroups: Map): void => { for (const engine of [ENGINE.ESLINT, ENGINE.ESLINT_TYPESCRIPT]) { const ruleGroup = mappedRuleGroups.get(`${engine}:Best Practices`); @@ -174,12 +182,13 @@ describe('LocalCatalog', () => { // ASSERTIONS // ESLint and ESLint-typescript should both have one category, and PMD should have two. - expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(4); + expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(5); const mappedRuleGroups = mapRuleGroups(ruleGroups); validateEslintPossibleErrors(mappedRuleGroups); validatePmdCategory(mappedRuleGroups, 'Design', [LANGUAGE.APEX, LANGUAGE_ECMASCRIPT]); validatePmdCategory(mappedRuleGroups, 'Error Prone', [LANGUAGE.APEX, LANGUAGE_ECMASCRIPT]); + validateCpdCategory(mappedRuleGroups, 'Copy/Paste Detected', [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); }); it('Correctly filters by multiple values', async () => { @@ -193,11 +202,12 @@ describe('LocalCatalog', () => { // ASSERTIONS // ESLint, ESLint-Typescript, and PMD should each have one category. - expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(3); + expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(4); const mappedRuleGroups = mapRuleGroups(ruleGroups); validateEslintPossibleErrors(mappedRuleGroups); validatePmdCategory(mappedRuleGroups, 'Error Prone', [LANGUAGE.APEX, LANGUAGE_ECMASCRIPT]); + validateCpdCategory(mappedRuleGroups, 'Copy/Paste Detected', [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); }); }); }); @@ -226,7 +236,7 @@ describe('LocalCatalog', () => { describe('Edge Cases', () => { const validateRuleGroups = (ruleGroups: RuleGroup[]) => { - expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(7); + expect(ruleGroups, TestUtils.prettyPrint(ruleGroups)).to.be.lengthOf(8); const mappedRuleGroups = mapRuleGroups(ruleGroups); validateEslintBestPractices(mappedRuleGroups); @@ -234,6 +244,7 @@ describe('LocalCatalog', () => { validatePmdCategory(mappedRuleGroups, 'Best Practices', [LANGUAGE_ECMASCRIPT, LANGUAGE.APEX]); validatePmdCategory(mappedRuleGroups, 'Design', [LANGUAGE_ECMASCRIPT, LANGUAGE.APEX]); validatePmdCategory(mappedRuleGroups, 'Error Prone', [LANGUAGE_ECMASCRIPT, LANGUAGE.APEX]); + validateCpdCategory(mappedRuleGroups, 'Copy/Paste Detected', [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); } it('Returns all categories for eligible engines when given no filters', async () => { @@ -293,6 +304,11 @@ describe('LocalCatalog', () => { validateRule(mappedRules, names, categories, languages, [ENGINE.PMD]); }; + const validateCpdRule = (mappedRules: Map, names: string[], categories: string[], languages: string[]): void => { + validateRule(mappedRules, names, categories, languages, [ENGINE.CPD]); + } + + const validateEslintRule = (mappedRules: Map, names: string[], categories: string[], engines=[ENGINE.ESLINT, ENGINE.ESLINT_TYPESCRIPT]): void => { for (const engine of engines) { const languages = engine === ENGINE.ESLINT ? [LANGUAGE.JAVASCRIPT] : [LANGUAGE.TYPESCRIPT]; @@ -330,22 +346,24 @@ describe('LocalCatalog', () => { it ('Single Value', async () => { const filter: RuleFilter = new CategoryFilter(['!Possible Errors']); const rules: Rule[] = catalog.getRulesMatchingFilters([filter]); - expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(7); + expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(8); const mappedRules = mapRules(rules); validatePmdRule(mappedRules, ['AvoidDeeplyNestedIfStmts', 'ExcessiveClassLength'], ['Design'], [LANGUAGE.APEX]); validatePmdRule(mappedRules, ['AvoidWithStatement', 'ConsistentReturn'], ['Best Practices'], [LANGUAGE.JAVASCRIPT]); validatePmdRule(mappedRules, ['ForLoopsMustUseBraces', 'IfElseStmtsMustUseBraces', 'IfStmtsMustUseBraces'], ['Code Style'], [LANGUAGE.JAVASCRIPT]); + validateCpdRule(mappedRules, ['copy-paste-detected'], ['Copy/Paste Detected'], [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); }); it ('Multiple Values', async () => { const filter: RuleFilter = new CategoryFilter(['!Possible Errors', '!Code Style']); const rules: Rule[] = catalog.getRulesMatchingFilters([filter]); - expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(4); + expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(5); const mappedRules = mapRules(rules); validatePmdRule(mappedRules, ['AvoidDeeplyNestedIfStmts', 'ExcessiveClassLength'], ['Design'], [LANGUAGE.APEX]); validatePmdRule(mappedRules, ['AvoidWithStatement', 'ConsistentReturn'], ['Best Practices'], [LANGUAGE.JAVASCRIPT]); + validateCpdRule(mappedRules, ['copy-paste-detected'], ['Copy/Paste Detected'], [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); }); }); }); @@ -434,10 +452,11 @@ describe('LocalCatalog', () => { const categoryFilter: RuleFilter = new CategoryFilter(['!Possible Errors', '!Code Style']); const languageFilter: RuleFilter = new LanguageFilter([LANGUAGE.APEX]); const rules: Rule[] = catalog.getRulesMatchingFilters([categoryFilter, languageFilter]); - expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(2); + expect(rules, TestUtils.prettyPrint(rules)).to.be.lengthOf(3); const mappedRules = mapRules(rules); validatePmdRule(mappedRules, ['AvoidDeeplyNestedIfStmts', 'ExcessiveClassLength'], ['Design'], [LANGUAGE.APEX]); + validateCpdRule(mappedRules, ['copy-paste-detected'], ['Copy/Paste Detected'], [LANGUAGE.APEX, LANGUAGE.JAVA, LANGUAGE.VISUALFORCE, LANGUAGE.XML]); }); }); }); From 18ef5bcf56332a9aba5075a3483b675868af04d7 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Fri, 1 Mar 2024 16:17:38 -0600 Subject: [PATCH 23/28] CHANGE (CodeAnalyzer): @W-14645433@: Refactored some scanner run tests. --- test/commands/scanner/run.test.ts | 89 --------- ...nAction.test.ts => RunAction.pmd7.test.ts} | 0 test/lib/actions/RunAction.target.test.ts | 169 ++++++++++++++++++ 3 files changed, 169 insertions(+), 89 deletions(-) rename test/lib/actions/{RunAction.test.ts => RunAction.pmd7.test.ts} (100%) create mode 100644 test/lib/actions/RunAction.target.test.ts diff --git a/test/commands/scanner/run.test.ts b/test/commands/scanner/run.test.ts index 23f3b1715..8a006a58c 100644 --- a/test/commands/scanner/run.test.ts +++ b/test/commands/scanner/run.test.ts @@ -6,11 +6,8 @@ import {ENV_VAR_NAMES} from "../../../src/Constants"; import fs = require('fs'); import path = require('path'); import process = require('process'); -import tildify = require('tildify'); -const pathToApexFolder = path.join('test', 'code-fixtures', 'apex'); const pathToSomeTestClass = path.join('test', 'code-fixtures', 'apex', 'SomeTestClass.cls'); -const pathToSomeOtherTestClass = path.join('test', 'code-fixtures', 'apex', 'SomeOtherTestClass.cls'); const pathToAnotherTestClass = path.join('test', 'code-fixtures', 'apex', 'AnotherTestClass.cls'); const pathToYetAnotherTestClass = path.join('test', 'code-fixtures', 'apex', 'YetAnotherTestClass.cls'); @@ -30,78 +27,12 @@ describe('scanner run', function () { validateXmlOutput(output.shellOutput.stdout); }); - it('Target path may be relative or absolute', () => { - const output = runCommand(`scanner run --target ${path.join('.', pathToSomeTestClass)} --ruleset ApexUnit --format xml`); - validateXmlOutput(output.shellOutput.stdout); - }); - it('When the file contains no violations, a message is logged to the console', () => { const output = runCommand(`scanner run --target ${pathToYetAnotherTestClass} --ruleset ApexUnit --format xml`); expect(output.shellOutput.stdout).to.contain(getMessage(BundleName.RunOutputProcessor, 'output.noViolationsDetected', ['pmd, retire-js'])); }); }); - describe('Test Case: Running rules against multiple specified files', () => { - it('Both files are evaluated, and any violations are logged', () => { - const output = runCommand(`scanner run --target "${pathToSomeTestClass},${pathToSomeOtherTestClass}" --ruleset ApexUnit --format xml`); - // We'll split the output by the tag first, so we can get each file that violated rules. - const results = output.shellOutput.stdout.split(' tag so we can inspect individual violations. - const firstFileViolations = results[0].split(' { - it('Any violations in the folder are logged as an XML', () => { - const output = runCommand(`scanner run --target ${pathToApexFolder} --ruleset ApexUnit --format xml`); - // We'll split the output by the tag first, so we can get each file that violated rules. - const results = output.shellOutput.stdout.split(' tag so we can inspect individual violations. - const firstFileViolations = results[0].split(' { it('Violations from each rule are logged as an XML', () => { const output = runCommand(`scanner run --target ${pathToAnotherTestClass} --ruleset ApexUnit,Style --format xml`); @@ -425,26 +356,6 @@ describe('scanner run', function () { }) }); - describe('Dynamic Input', () => { - - describe('Test Case: Using ~/ shorthand in target', () => { - const pathWithTilde = tildify(path.join(process.cwd(), 'test', 'code-fixtures', 'apex', 'SomeTestClass.cls')); - - it('Tilde is expanded to full directory', () => { - const output = runCommand(`scanner run --target ${pathWithTilde} --ruleset ApexUnit --format xml`); - // We'll split the output by the tag, so we can get individual violations. - const violations = output.shellOutput.stdout.split(' { describe('Test case: No output specified', () => { it('When no format is specified, we default to a TABLE', () => { diff --git a/test/lib/actions/RunAction.test.ts b/test/lib/actions/RunAction.pmd7.test.ts similarity index 100% rename from test/lib/actions/RunAction.test.ts rename to test/lib/actions/RunAction.pmd7.test.ts diff --git a/test/lib/actions/RunAction.target.test.ts b/test/lib/actions/RunAction.target.test.ts new file mode 100644 index 000000000..5031326b1 --- /dev/null +++ b/test/lib/actions/RunAction.target.test.ts @@ -0,0 +1,169 @@ +import path = require('path'); +import {Logger} from '@salesforce/core'; +import {expect} from 'chai'; +import tildify = require('tildify'); + +import {Results} from '../../../src/lib/output/Results'; +import {Inputs, RuleResult} from '../../../src/types'; +import {RunAction} from '../../../src/lib/actions/RunAction'; +import {InputProcessorImpl} from '../../../src/lib/InputProcessor'; +import {RuleFilterFactoryImpl} from '../../../src/lib/RuleFilterFactory'; +import {RunEngineOptionsFactory} from '../../../src/lib/EngineOptionsFactory'; + +import {initializeTestSetup} from '../../test-related-lib/TestOverrides'; +import {FakeDisplay} from '../FakeDisplay'; +import {FakeResultsProcessorFactory, RawResultsProcessor} from './fakes'; + + +describe('scanner run, targeting capabilities', () => { + const PATH_TO_TEST_FOLDER = path.join('.', 'test', 'code-fixtures', 'apex'); + const PATH_TO_SOME_TEST_CLASS = path.join('.', 'test', 'code-fixtures', 'apex', 'SomeTestClass.cls'); + const PATH_TO_SOME_OTHER_TEST_CLASS = path.join('.', 'test', 'code-fixtures', 'apex', 'SomeOtherTestClass.cls'); + const PATH_TO_SOQL_IN_LOOP = path.join('.', 'test', 'code-fixtures', 'apex', 'SoqlInLoop.cls'); + + let logger: Logger; + let display: FakeDisplay; + let inputProcessor: InputProcessorImpl; + let resultsProcessor: RawResultsProcessor; + let runAction: RunAction; + + beforeEach(async () => { + initializeTestSetup(); + logger = await Logger.child('RunAction.target.test.ts'); + display = new FakeDisplay(); + inputProcessor = new InputProcessorImpl('testing', display); + resultsProcessor = new RawResultsProcessor(); + runAction = new RunAction( + logger, + display, + inputProcessor, + new RuleFilterFactoryImpl(), + new RunEngineOptionsFactory(inputProcessor), + new FakeResultsProcessorFactory(resultsProcessor) + ); + }); + + describe('Test Case: Can target a single file...', () => { + it('...with a relative path', async () => { + // Prepare Input + const target = [PATH_TO_SOME_TEST_CLASS]; + const inputs: Inputs = { + target, + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, target.map(p => path.resolve(p))); + }); + + it('... with an absolute path', async () => { + // Prepare Input + const target = [path.resolve(PATH_TO_SOME_TEST_CLASS)]; + const inputs: Inputs = { + target, + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, target); + }); + + it('With a tilde-style path', async () => { + // Prepare Input + const target = [tildify(path.resolve(PATH_TO_SOME_TEST_CLASS))]; + const inputs: Inputs = { + target, + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, [path.resolve(PATH_TO_SOME_TEST_CLASS)]); + }); + }); + + it('Test Case: Can target a list of files', async () => { + // Prepare Input + const target = [PATH_TO_SOME_TEST_CLASS, PATH_TO_SOME_OTHER_TEST_CLASS]; + const inputs: Inputs = { + target, + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, target.map(p => path.resolve(p))); + }); + + it('Test Case: Can target a whole folder', async () => { + // Prepare Input + const inputs: Inputs = { + target: [PATH_TO_TEST_FOLDER], + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const expectedTargets = [PATH_TO_SOME_TEST_CLASS, PATH_TO_SOME_OTHER_TEST_CLASS, PATH_TO_SOQL_IN_LOOP].map(p => path.resolve(p)); + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, expectedTargets); + }); + + it('Test Case: Can target a glob', async () => { + // Prepare Input + const inputs: Inputs = { + target: [path.join(PATH_TO_TEST_FOLDER, 'Some*.cls')], + engine: ['pmd'], + category: ['Performance'], + format: 'xml' + }; + + // Invoke tested method + await runAction.run(inputs); + + // Assert against results + const expectedTargets = [PATH_TO_SOME_TEST_CLASS, PATH_TO_SOME_OTHER_TEST_CLASS].map(p => path.resolve(p)); + const results: Results = resultsProcessor.getResults(); + assertPerformanceViolations(results, expectedTargets); + }); + + function assertPerformanceViolations(results: Results, fileList: string[]): void { + expect(results.getExecutedEngines().size).to.equal(1, 'Wrong executedEngines count'); + expect(results.getExecutedEngines()).to.contain('pmd', 'Wrong engines executed'); + const ruleResults: RuleResult[] = results.getRuleResults(); + expect(ruleResults).to.have.length(fileList.length, 'Wrong number of results'); + for (const ruleResult of ruleResults) { + const fullFileName = path.resolve(ruleResult.fileName); + expect(fileList).to.contain(fullFileName, `Violations in unexpected file ${fullFileName}`); + for (const violation of ruleResult.violations) { + expect(violation.category).to.equal('Performance', `Wrong category of violation found in ${ruleResult.fileName}`); + } + } + } +}); From 8039a4ae8e9555bfd0ffd48194ee143382999e3f Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Fri, 1 Mar 2024 17:24:56 -0500 Subject: [PATCH 24/28] @W-15142453@: Update help text to match latest command reference changes --- messages/add.md | 2 +- messages/common.md | 4 ++++ messages/list.md | 4 ++-- messages/run-common.md | 2 +- messages/run-dfa.md | 6 +++--- messages/run-pathless.md | 18 +++++++++--------- src/commands/scanner/rule/describe.ts | 3 ++- src/commands/scanner/rule/list.ts | 3 ++- src/commands/scanner/rule/remove.ts | 3 ++- src/lib/ScannerRunCommand.ts | 3 ++- 10 files changed, 28 insertions(+), 20 deletions(-) diff --git a/messages/add.md b/messages/add.md index a11b10e1c..56c783904 100644 --- a/messages/add.md +++ b/messages/add.md @@ -20,7 +20,7 @@ one or more paths (such as a directory or JAR file) to custom rule definitions # flags.pathDescription -One or more paths (such as a directory or JAR file) to custom rule definitions. Specify multiple values as a comma-separated list. +One or more paths (such as a directory or JAR file) to custom rule definitions. Specify multiple values as a comma-separated list. # validations.languageCannotBeEmpty diff --git a/messages/common.md b/messages/common.md index 1e028d00a..b2fde775e 100644 --- a/messages/common.md +++ b/messages/common.md @@ -2,6 +2,10 @@ emit additional command output to stdout +# flags.verboseDescription + +Emit additional command output to stdout. + # surveyRequestMessage We're continually improving Salesforce Code Analyzer. Tell us what you think! Give feedback at https://research.net/r/SalesforceCA \ No newline at end of file diff --git a/messages/list.md b/messages/list.md index 723146886..6efab1a29 100644 --- a/messages/list.md +++ b/messages/list.md @@ -24,11 +24,11 @@ Selects rules by category. Enter multiple values as a comma-separated list. # flags.rulesetSummary -[deprecated] select rules by ruleset +[Deprecated] select rules by ruleset # flags.rulesetDescription -[deprecated] Selects rules by ruleset. Enter multiple values as a comma-separated list. +Deprecated. Use category instead. Selects rules by ruleset. Enter multiple values as a comma-separated list. # flags.engineSummary diff --git a/messages/run-common.md b/messages/run-common.md index 74ba6bc44..a915f5e89 100644 --- a/messages/run-common.md +++ b/messages/run-common.md @@ -12,7 +12,7 @@ specify results output format # flags.formatDescription -Specifies results output format written directly to the console. +Specifies the output format for results written directly to the console. # flags.normalizesevSummary diff --git a/messages/run-dfa.md b/messages/run-dfa.md index 1912e57c6..dcc581b1d 100644 --- a/messages/run-dfa.md +++ b/messages/run-dfa.md @@ -13,7 +13,7 @@ specify a path expansion upper boundary to limit the complexity of code that Gr # flags.pathexplimitDescription -Specifies a path expansion upper boundary to limit the complexity of code Graph Engine analyzes before failing fast. Set the value to -1 to remove any upper boundary. --pathexplimit inherits value from SFGE_PATH_EXPANSION_LIMIT env-var, if set. Its default value is derived from JVM heap space allocation. +Specifies a path expansion upper boundary to limit the complexity of code Graph Engine analyzes before failing fast. Set the value to -1 to remove any upper boundary. --pathexplimit inherits value from SFGE_PATH_EXPANSION_LIMIT env-var, if set. Its default value is derived from JVM heap space allocation. # flags.ruledisablewarningviolationSummary @@ -29,7 +29,7 @@ specify number of threads that evaluate DFA rules. Alternatively, set value usin # flags.rulethreadcountDescription -Specifies number of rule evaluation threads, or how many entrypoints can be evaluated concurrently. Inherits value from SFGE_RULE_THREAD_COUNT env-var, if set. Default is 4. +Specifies the number of rule-evaluation threads or how many entry points can be evaluated concurrently. Inherits its value from the SFGE_RULE_THREAD_COUNT environment variable, if set. The default is 4. # flags.rulethreadtimeoutSummary @@ -37,7 +37,7 @@ specify timeout for individual rule threads in milliseconds. Alternatively, set # flags.rulethreadtimeoutDescription -Specifies time limit for evaluating a single entrypoint in milliseconds. Inherits value from SFGE_RULE_THREAD_TIMEOUT env-var if set. Default is 900,000 ms, or 15 minutes. +Specifies the time limit for evaluating a single entry point in milliseconds. Inherits its value from the SFGE_RULE_THREAD_TIMEOUT environment variable, if set. The default is 900,000 ms or 15 minutes. # flags.sfgejvmargsSummary diff --git a/messages/run-pathless.md b/messages/run-pathless.md index 7d001585c..ce2da5bfc 100644 --- a/messages/run-pathless.md +++ b/messages/run-pathless.md @@ -8,11 +8,11 @@ Scans a codebase with a selection of rules. You can scan the codebase with all t # flags.rulesetSummary -[deprecated] rulesets to run +[Deprecated] rulesets to run # flags.rulesetDescription -[deprecated] One or more rulesets to run. Specify multiple values as a comma-separated list. +Deprecated. Use category instead. One or more rulesets to run. Specify multiple values as a comma-separated list. # flags.targetSummary @@ -20,15 +20,15 @@ source code location # flags.targetDescription -Specifies the source code location. May use glob patterns. Specify multiple values as a comma-separated list. Default is ".". +Specifies the source code location. Can use glob patterns. Specify multiple values as a comma-separated list. Default is ".". # flags.envSummary -[deprecated] override ESLint's default environment variables, in JSON-formatted string +[Deprecated] override ESLint's default environment variables, in JSON-formatted string # flags.envDescription -[deprecated] Overrides ESLint's default environmental variables, in JSON-formatted string. +Deprecated. Overrides ESLint's default environmental variables, in JSON-formatted string. # flags.envParamDeprecationWarning @@ -40,7 +40,7 @@ location of tsconfig.json file # flags.tsconfigDescription -Location of tsconfig.json file used by eslint-typescript engine. +The location of the tsconfig.json file used by the eslint-typescript engine. The --tsconfig flag can’t be used with --eslintconfig flag. # flags.engineSummary @@ -56,7 +56,7 @@ specify the location of eslintrc config to customize eslint engine # flags.eslintConfigDescription -Specifies the location of eslintrc config to customize eslint engine. +Specifies the location of eslintrc config to customize ESLint engine. The --tsconfig flag can’t be used with --eslintconfig flag. # flags.pmdConfigSummary @@ -64,7 +64,7 @@ specify location of PMD rule reference XML file to customize rule selection # flags.pmdConfigDescription -Specifies the location of PMD rule reference XML file to customize rule selection. +Specifies the location of the PMD rule reference XML file to customize rule selection. # flags.previewPmd7Summary @@ -80,7 +80,7 @@ return retire-js violation message details # flags.verboseViolationsDescription -Returns retire-js violation messages details about each vulnerability, including summary, Common Vulnerabilities and Exposures (CVE), and URLs. +Returns retire-js violation-message details about each vulnerability, including summary, common vulnerabilities and exposures (CVE), and URLs. # validations.methodLevelTargetingDisallowed diff --git a/src/commands/scanner/rule/describe.ts b/src/commands/scanner/rule/describe.ts index e04553576..199753242 100644 --- a/src/commands/scanner/rule/describe.ts +++ b/src/commands/scanner/rule/describe.ts @@ -28,7 +28,8 @@ export default class Describe extends ScannerCommand { required: true }), verbose: Flags.boolean({ - summary: getMessage(BundleName.Common, 'flags.verboseSummary') + summary: getMessage(BundleName.Common, 'flags.verboseSummary'), + description: getMessage(BundleName.Common, 'flags.verboseDescription') }), "preview-pmd7": Flags.boolean({ summary: getMessage(BundleName.Describe, 'flags.previewPmd7Summary', [PMD7_VERSION]), diff --git a/src/commands/scanner/rule/list.ts b/src/commands/scanner/rule/list.ts index c94908458..1537f6eff 100644 --- a/src/commands/scanner/rule/list.ts +++ b/src/commands/scanner/rule/list.ts @@ -23,7 +23,8 @@ export default class List extends ScannerCommand { // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { verbose: Flags.boolean({ - summary: getMessage(BundleName.Common, 'flags.verboseSummary') + summary: getMessage(BundleName.Common, 'flags.verboseSummary'), + description: getMessage(BundleName.Common, 'flags.verboseDescription') }), category: Flags.custom({ char: 'c', diff --git a/src/commands/scanner/rule/remove.ts b/src/commands/scanner/rule/remove.ts index 2e2f3b59b..429181aec 100644 --- a/src/commands/scanner/rule/remove.ts +++ b/src/commands/scanner/rule/remove.ts @@ -22,7 +22,8 @@ export default class Remove extends ScannerCommand { // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { verbose: Flags.boolean({ - summary: getMessage(BundleName.Common, 'flags.verboseSummary') + summary: getMessage(BundleName.Common, 'flags.verboseSummary'), + description: getMessage(BundleName.Common, 'flags.verboseDescription') }), force: Flags.boolean({ char: 'f', diff --git a/src/lib/ScannerRunCommand.ts b/src/lib/ScannerRunCommand.ts index ae304a181..e2d1deeb8 100644 --- a/src/lib/ScannerRunCommand.ts +++ b/src/lib/ScannerRunCommand.ts @@ -10,7 +10,8 @@ export abstract class ScannerRunCommand extends ScannerCommand { */ public static readonly flags = { verbose: Flags.boolean({ - summary: getMessage(BundleName.Common, 'flags.verboseSummary') + summary: getMessage(BundleName.Common, 'flags.verboseSummary'), + description: getMessage(BundleName.Common, 'flags.verboseDescription') }), // BEGIN: Filter-related flags. category: Flags.custom({ From 11e40b1d12c3497b5b96d301f759e43c0f27df86 Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Thu, 7 Mar 2024 16:53:34 -0600 Subject: [PATCH 25/28] CHANGE (CodeAnalyzer): @W-14645433@: Fixed some broken tests. (#1381) --- test/lib/InputProcessor.test.ts | 20 ++++++-- test/lib/JreSetupManager.test.ts | 26 +++++++--- test/lib/actions/RuleAddAction.test.ts | 47 +++++++++++++----- test/lib/actions/RuleRemoveAction.test.ts | 50 ++++++++++++++----- test/lib/actions/RunDfaAction.test.ts | 56 +++++++++++++++++----- test/lib/eslint/CustomEslintEngine.test.ts | 24 ++++++---- test/lib/sfge/SfgeDfaEngine.test.ts | 9 ++-- 7 files changed, 172 insertions(+), 60 deletions(-) diff --git a/test/lib/InputProcessor.test.ts b/test/lib/InputProcessor.test.ts index 2ee587ea5..a1e9715e4 100644 --- a/test/lib/InputProcessor.test.ts +++ b/test/lib/InputProcessor.test.ts @@ -1,5 +1,5 @@ import {InputProcessor, InputProcessorImpl} from "../../src/lib/InputProcessor"; -import {assert, expect} from "chai"; +import {expect} from "chai"; import * as path from "path"; import {Inputs} from "../../src/types"; import {BundleName, getMessage} from "../../src/MessageCatalog"; @@ -129,24 +129,34 @@ describe("InputProcessorImpl Tests", async () => { const inputs: Inputs = { target: ['thisFileDoesNotExist.xml', 'thisFileAlsoDoesNotExist.json'] }; + let errorThrown: boolean; + let message: string; try { inputProcessor.resolveProjectDirPaths(inputs); - assert.fail("Expected error to be thrown") + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); }) it("Unspecified projectdir with glob target that resolves to no files", async () => { const inputs: Inputs = { target: ['**.filesOfThisTypeShouldNotExist'] }; + let errorThrown: boolean; + let message: string; try { inputProcessor.resolveProjectDirPaths(inputs); - assert.fail("Expected error to be thrown") + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); }) }) }) diff --git a/test/lib/JreSetupManager.test.ts b/test/lib/JreSetupManager.test.ts index 1c0998b9f..1fa106d84 100644 --- a/test/lib/JreSetupManager.test.ts +++ b/test/lib/JreSetupManager.test.ts @@ -1,4 +1,4 @@ -import {assert, expect} from 'chai'; +import {expect} from 'chai'; import {FileHandler} from '../../src/lib/util/FileHandler'; import {Config} from '../../src/lib/util/Config'; import Sinon = require('sinon'); @@ -196,13 +196,19 @@ describe('JreSetupManager #verifyJreSetup', () => { const statStub = Sinon.stub(FileHandler.prototype, 'stats').throws(error); // Execute and verify + let errorThrown: boolean; + let errName: string; try { await verifyJreSetup(); - assert.fail('Should have failed'); + errorThrown = false; } catch (err) { - expect(err.name).equals('InvalidJavaHome'); - expect(uniqueWarningCounter).to.equal(0); + errorThrown = true; + errName = err.name; } + expect(errorThrown).to.equal(true, 'Should have failed'); + expect(errName).equals('InvalidJavaHome'); + expect(uniqueWarningCounter).to.equal(0); + configGetJavaHomeStub.restore(); statStub.restore(); @@ -216,13 +222,19 @@ describe('JreSetupManager #verifyJreSetup', () => { const execStub = Sinon.stub(childProcess, 'execFile').yields(noError, emptyStdout, invalidVersion); // Execute and verify + let errorThrown: boolean; + let errName: string; try { await verifyJreSetup(); - assert.fail('Should have failed'); + errorThrown = false; } catch (err) { - expect(err.name).equals('InvalidVersion'); - expect(uniqueWarningCounter).to.equal(0); + errorThrown = true; + errName = err.name; } + expect(errorThrown).to.equal(true, 'Should have failed'); + expect(errName).equals('InvalidVersion'); + expect(uniqueWarningCounter).to.equal(0); + configGetJavaHomeStub.restore(); statStub.restore(); diff --git a/test/lib/actions/RuleAddAction.test.ts b/test/lib/actions/RuleAddAction.test.ts index 451f20ea2..9c3ef8bb5 100644 --- a/test/lib/actions/RuleAddAction.test.ts +++ b/test/lib/actions/RuleAddAction.test.ts @@ -1,5 +1,5 @@ import {Logger} from '@salesforce/core'; -import {assert, expect} from 'chai'; +import {expect} from 'chai'; import sinon = require('sinon'); import path = require('path'); import untildify = require('untildify'); @@ -68,12 +68,17 @@ describe('RuleAddAction', () => { path: ['this/does/not/matter'] }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); }); it('Rejects empty `.language` property', async () => { @@ -82,12 +87,17 @@ describe('RuleAddAction', () => { path: ['this/does/not/matter'] }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.Add, 'validations.languageCannotBeEmpty', [])); }); it('Rejects missing `.path` property', async () => { @@ -95,12 +105,17 @@ describe('RuleAddAction', () => { language: 'apex' }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); }); it('Rejects empty `.path` property', async () => { @@ -109,12 +124,17 @@ describe('RuleAddAction', () => { path: [] }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); }); it('Rejects `.path` containing empty string', async () => { @@ -123,12 +143,17 @@ describe('RuleAddAction', () => { path: [""] } + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.Add, 'validations.pathCannotBeEmpty', [])); }); }); diff --git a/test/lib/actions/RuleRemoveAction.test.ts b/test/lib/actions/RuleRemoveAction.test.ts index 19d03d5d4..b598e6040 100644 --- a/test/lib/actions/RuleRemoveAction.test.ts +++ b/test/lib/actions/RuleRemoveAction.test.ts @@ -1,5 +1,5 @@ import {Logger} from '@salesforce/core'; -import {assert, expect} from 'chai'; +import {expect} from 'chai'; import {FileHandler} from '../../../src/lib/util/FileHandler'; import sinon = require('sinon'); import path = require('path'); @@ -34,12 +34,17 @@ describe('RuleRemoveAction', () => { path: [] }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); }); it('rejects `.path` containing empty string', async () => { @@ -47,12 +52,17 @@ describe('RuleRemoveAction', () => { path: [''] }; + let errorThrown: boolean; + let message: string; try { await testAction.validateInputs(inputs); - assert.fail('Exception should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.Remove, 'validations.pathCannotBeEmpty', [])); }); }); @@ -97,13 +107,19 @@ describe('RuleRemoveAction', () => { const inputs: Inputs = { path: [FAKE_PATH_1] }; + let errorThrown: boolean; + let message: string; try { await testAction.run(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - // ==== ASSERTIONS ==== - expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths')); + errorThrown = true; + message = e.message; } + + // ==== ASSERTIONS ==== + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths')); }); }); @@ -188,12 +204,17 @@ describe('RuleRemoveAction', () => { const inputs = { path: [FAKE_PATH_4] }; + let errorThrown: boolean; + let message: string; try { await testAction.run(inputs); - assert.fail('Error should have thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); }); it('Test Case: Action can be aborted during confirmation prompt', async () => { @@ -246,12 +267,17 @@ describe('RuleRemoveAction', () => { path: [FAKE_PATH_4], force: true }; + let errorThrown: boolean; + let message: string; try { await testAction.run(inputs); - assert.fail('Error should have thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.Remove, 'errors.noMatchingPaths', [])); }); }); }); diff --git a/test/lib/actions/RunDfaAction.test.ts b/test/lib/actions/RunDfaAction.test.ts index caa2ae08c..06c46a692 100644 --- a/test/lib/actions/RunDfaAction.test.ts +++ b/test/lib/actions/RunDfaAction.test.ts @@ -1,5 +1,5 @@ import {Logger} from '@salesforce/core'; -import {assert, expect} from 'chai'; +import {expect} from 'chai'; import path = require('path'); import {FakeDisplay} from '../FakeDisplay'; @@ -42,12 +42,17 @@ describe('RunDfaAction', () => { 'projectdir': ['./**/*.cls'] }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirCannotBeGlob')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirCannotBeGlob')); }); it('--projectdir must be real', async () => { @@ -55,12 +60,17 @@ describe('RunDfaAction', () => { 'projectdir': ['./not/a/real/file.txt'] }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustExist')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustExist')); }); it('--projectdir must be directory', async () => { @@ -69,12 +79,17 @@ describe('RunDfaAction', () => { 'projectdir': [path.resolve('./src/Controller.ts')] }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustBeDir')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.projectdirMustBeDir')); }); it('--outfile cannot be used if --format is "table"', async () => { @@ -83,12 +98,17 @@ describe('RunDfaAction', () => { 'format': 'table' }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.CommonRun, 'validations.cannotWriteTableToFile')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.cannotWriteTableToFile')); }); it('If --outfile and --format conflict, message is logged', async () => { @@ -106,12 +126,17 @@ describe('RunDfaAction', () => { 'target': ['./**/*.cls#beep'] }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetCannotBeGlob')); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetCannotBeGlob')); }); it('Method-level --target values must be a real file', async () => { @@ -120,12 +145,17 @@ describe('RunDfaAction', () => { 'target': [`${file}#beep`] }; + let errorThrown: boolean; + let message: string; try { await runDfaAction.validateInputs(inputs); - assert.fail('Error should have been thrown'); + errorThrown = false; } catch (e) { - expect(e.message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetMustBeRealFile', [file])); + errorThrown = true; + message = e.message; } + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).to.equal(getMessage(BundleName.RunDfa, 'validations.methodLevelTargetMustBeRealFile', [file])); }); }); diff --git a/test/lib/eslint/CustomEslintEngine.test.ts b/test/lib/eslint/CustomEslintEngine.test.ts index 238980d2d..aada1f726 100644 --- a/test/lib/eslint/CustomEslintEngine.test.ts +++ b/test/lib/eslint/CustomEslintEngine.test.ts @@ -1,4 +1,4 @@ -import { assert, expect } from 'chai'; +import { expect } from 'chai'; import { CustomEslintEngine } from '../../../src/lib/eslint/CustomEslintEngine'; import * as DataGenerator from './EslintTestDataGenerator'; import { CUSTOM_CONFIG, HARDCODED_RULES } from '../../../src/Constants'; @@ -152,18 +152,21 @@ describe("Tests for CustomEslintEngine", () => { const customEslintEngine = await getCustomEslintEngine(fileHandlerMock); + let errorThrown: boolean; + let message: string; try { await customEslintEngine.run( [], [], [DataGenerator.getDummyTarget()], engineOptionsWithEslintCustom); - - assert.fail('Expected exception'); + errorThrown = false; } catch (err) { - expect(err.message).to.equal(getMessage(BundleName.CustomEslintEngine, 'ConfigFileDoesNotExist', [configFilePath])); + errorThrown = true; + message = err.message; } - + expect(errorThrown).to.equal(true, 'Error should be thrown'); + expect(message).to.equal(getMessage(BundleName.CustomEslintEngine, 'ConfigFileDoesNotExist', [configFilePath])); }); it('Throws error when JSON in config file cannot be parsed', async () => { @@ -172,6 +175,8 @@ describe("Tests for CustomEslintEngine", () => { const fileHandlerMock = mockFileHandlerToReturnContentForFile(configFilePath, invalidJsonContent); const customEslintEngine = await getCustomEslintEngine(fileHandlerMock); + let errorThrown: boolean; + let message: string; try { await customEslintEngine.run( @@ -179,12 +184,13 @@ describe("Tests for CustomEslintEngine", () => { [], [target], engineOptionsWithEslintCustom); - - assert.fail('Expected exception'); + errorThrown = false; } catch (err) { - expect(err.message).contains(`Something in the ESLint config JSON is invalid. Check ESLint's JSON specifications: ${configFilePath}`); + errorThrown = true; + message = err.message; } - + expect(errorThrown).to.equal(true, 'Error should have been thrown'); + expect(message).contains(`Something in the ESLint config JSON is invalid. Check ESLint's JSON specifications: ${configFilePath}`); }); it('Invokes Eslint when config can be fetched', async () => { diff --git a/test/lib/sfge/SfgeDfaEngine.test.ts b/test/lib/sfge/SfgeDfaEngine.test.ts index a4dbe7851..dacad117a 100644 --- a/test/lib/sfge/SfgeDfaEngine.test.ts +++ b/test/lib/sfge/SfgeDfaEngine.test.ts @@ -4,7 +4,7 @@ import * as TestOverrides from '../../test-related-lib/TestOverrides'; import Sinon = require('sinon'); import path = require('path'); import fs = require('fs'); -import {assert, expect} from 'chai'; +import {expect} from 'chai'; import {RuleResult} from '../../../src/types'; import {SfgeDfaEngine} from '../../../src/lib/sfge/SfgeDfaEngine'; @@ -118,15 +118,18 @@ describe('SfgeDfaEngine', () => { const expectedError = spoofedOutput.split('\n').slice(21).join('\n').trimStart(); // ==== TESTED METHOD ==== + let errorThrown: boolean; let err: string = null; try { - const results = await testEngine.processExecutionFailure(spoofedOutput); - assert.fail(`Expected error, received ${JSON.stringify(results)}`); + await testEngine.processExecutionFailure(spoofedOutput); + errorThrown = false; } catch (e) { + errorThrown = true; err = e instanceof Error ? e.message : e as string; } // ==== ASSERTIONS ==== + expect(errorThrown).to.equal(true, 'Error should have been thrown'); expect(err).to.equal(expectedError, 'Wrong error returned'); Sinon.assert.callCount(uxSpy, 0); }); From 088702f22e140db2daa15e0d6d31e7d93fe2287b Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Mon, 11 Mar 2024 12:39:13 -0500 Subject: [PATCH 26/28] CHANGE (CodeAnalyzer): @W-14645433@: Increased enforced code coverage lower bound. (#1382) --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8b482dc92..a342d6f9a 100644 --- a/package.json +++ b/package.json @@ -129,10 +129,10 @@ "flexibleTaxonomy": true }, "nyc": { - "branches": "60", - "lines": "75", - "functions": "75", - "statements": "75" + "branches": "75", + "lines": "85", + "functions": "85", + "statements": "85" }, "repository": "forcedotcom/sfdx-scanner", "scripts": { From 3df553bf062b9edb66f0a89fc2021b5d14cfe737 Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Mon, 11 Mar 2024 14:23:09 -0500 Subject: [PATCH 27/28] CHANGE (CodeAnalyzer): @W-15214308@: Updating package version for 3.22.0 release. (#1390) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a342d6f9a..211568ec5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@salesforce/sfdx-scanner", "description": "Static code scanner that applies quality and security rules to Apex code, and provides feedback.", - "version": "3.21.0", + "version": "3.22.0", "author": "ISV SWAT", "bugs": "https://github.com/forcedotcom/sfdx-scanner/issues", "dependencies": { From 3935a5bf2e73d85b36b030708b115196eb64647e Mon Sep 17 00:00:00 2001 From: Stephen Carter <123964848+stephen-carter-at-sf@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:10:07 -0400 Subject: [PATCH 28/28] CHANGE (CodeAnalyzer): @W-15214308@: Update retire js vuln (#1391) --- retire-js/RetireJsVulns.json | 107 ++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 8 deletions(-) diff --git a/retire-js/RetireJsVulns.json b/retire-js/RetireJsVulns.json index d5aa2f530..7ef6b0816 100644 --- a/retire-js/RetireJsVulns.json +++ b/retire-js/RetireJsVulns.json @@ -233,7 +233,8 @@ "atOrAbove": "3.0.0-rc.1", "below": "3.0.0", "cwe": [ - "CWE-400" + "CWE-400", + "CWE-674" ], "severity": "high", "identifiers": { @@ -319,12 +320,14 @@ "/\\*!? jQuery v(§§version§§)", "\\* jQuery JavaScript Library v(§§version§§)", "\\* jQuery (§§version§§) - New Wave Javascript", + "/\\*![\\s]+\\* jQuery JavaScript Library v(§§version§§)", "// \\$Id: jquery.js,v (§§version§§)", "/\\*! jQuery v(§§version§§)", "[^a-z]f=\"(§§version§§)\",.*[^a-z]jquery:f,", "[^a-z]m=\"(§§version§§)\",.*[^a-z]jquery:m,", "[^a-z.]jquery:[ ]?\"(§§version§§)\"", - "\\$\\.documentElement,Q=e.jQuery,Z=e\\.\\$,ee=\\{\\},te=\\[\\],ne=\"(§§version§§)\"" + "\\$\\.documentElement,Q=e.jQuery,Z=e\\.\\$,ee=\\{\\},te=\\[\\],ne=\"(§§version§§)\"", + "=\"(§§version§§)\",.{50,300}(.)\\.fn=(\\2)\\.prototype=\\{jquery:" ], "filecontentreplace": [ "/var [a-z]=[a-z]\\.document,([a-z])=\"(§§version§§)\",([a-z])=.{130,160};\\3\\.fn=\\3\\.prototype=\\{jquery:\\1/$2/" @@ -2336,6 +2339,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2361,6 +2365,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2385,6 +2390,7 @@ "CWE-79" ], "identifiers": { + "summary": "Affected versions of dojo are susceptible to a cross-site scripting vulnerability in the dijit.Editor and textarea components, which execute their contents as Javascript, even when sanitized.", "CVE": [ "CVE-2008-6681" ], @@ -2402,6 +2408,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2427,6 +2434,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2452,6 +2460,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2476,6 +2485,7 @@ "CWE-79" ], "identifiers": { + "summary": "Cross-site scripting (XSS) vulnerability in dijit/tests/_testCommon.js in Dojo Toolkit SDK before 1.4.2 allows remote attackers to inject arbitrary web script or HTML via the theme parameter, as demonstrated by an attack against dijit/tests/form/test_Button.html", "CVE": [ "CVE-2010-2275" ] @@ -2492,6 +2502,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2516,6 +2527,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.2.0 are vulnerable to Cross-Site Scripting (XSS). The package fails to sanitize HTML code in user-controlled input, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "CVE": [ "CVE-2015-5654" ], @@ -2533,6 +2545,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2558,6 +2571,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2584,6 +2598,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2602,6 +2617,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2629,6 +2645,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2647,6 +2664,7 @@ "CWE-79" ], "identifiers": { + "summary": "Versions of dojo prior to 1.4.2 are vulnerable to DOM-based Cross-Site Scripting (XSS). The package does not sanitize URL parameters in the _testCommon.js and runner.html test files, allowing attackers to execute arbitrary JavaScript in the victim's browser.", "PR": "307", "CVE": [ "CVE-2010-2273" @@ -2674,6 +2692,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2691,9 +2710,11 @@ "CWE-79" ], "identifiers": { + "summary": "In Dojo Toolkit before 1.14.0, there is unescaped string injection in dojox/Grid/DataGrid.", "CVE": [ "CVE-2018-15494" - ] + ], + "githubID": "GHSA-84cm-x2q5-8225" }, "info": [ "https://dojotoolkit.org/blog/dojo-1-14-released" @@ -2709,6 +2730,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2729,6 +2751,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2749,6 +2772,7 @@ "CWE-94" ], "identifiers": { + "summary": "Prototype pollution in dojo", "CVE": [ "CVE-2020-5258" ], @@ -2779,13 +2803,14 @@ ], "extractors": { "uri": [ - "/(?:dojo-)?(§§version§§)/dojo(\\.min)?\\.js" + "/(?:dojo-)?(§§version§§)(?:/dojo)?/dojo(\\.min)?\\.js" ], "filename": [ "dojo-(§§version§§)(\\.min)?\\.js" ], "filecontentreplace": [ - "/dojo.version=\\{major:([0-9]+),minor:([0-9]+),patch:([0-9]+)/$1.$2.$3/" + "/dojo.version=\\{major:([0-9]+),minor:([0-9]+),patch:([0-9]+)/$1.$2.$3/", + "/\"dojox\"[\\s\\S]{1,350}\\.version=\\{major:([0-9]+),minor:([0-9]+),patch:([0-9]+)/$1.$2.$3/" ], "hashes": { "73cdd262799aab850abbe694cd3bfb709ea23627": "1.4.1", @@ -2989,7 +3014,7 @@ "CWE-1104" ], "identifiers": { - "summary": "End-of-Life: Long term support for AngularJS has been discontinued", + "summary": "End-of-Life: Long term support for AngularJS has been discontinued as of December 31, 2021", "retid": "54" }, "info": [ @@ -3064,6 +3089,30 @@ "https://github.com/advisories/GHSA-qwqh-hm9m-p5hr" ] }, + { + "atOrAbove": "1.3.0", + "below": "999", + "cwe": [ + "CWE-1333" + ], + "severity": "high", + "identifiers": { + "summary": "angular vulnerable to super-linear runtime due to backtracking", + "CVE": [ + "CVE-2024-21490" + ], + "githubID": "GHSA-4w4v-5hc9-xrr2" + }, + "info": [ + "https://github.com/advisories/GHSA-4w4v-5hc9-xrr2", + "https://nvd.nist.gov/vuln/detail/CVE-2024-21490", + "https://github.com/angular/angular.js", + "https://security.snyk.io/vuln/SNYK-JAVA-ORGWEBJARSBOWER-6241746", + "https://security.snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-6241747", + "https://security.snyk.io/vuln/SNYK-JS-ANGULAR-6091113", + "https://stackblitz.com/edit/angularjs-vulnerability-ng-srcset-redos" + ] + }, { "atOrAbove": "1.7.0", "below": "999", @@ -3660,7 +3709,8 @@ "this.Handlebars=\\{\\};[\n\r \t]+\\(function\\([a-z]\\)\\{[a-z].VERSION=(?:'|\")(§§version§§)(?:'|\")", "exports.HandlebarsEnvironment=[\\s\\S]{70,120}exports.VERSION=(?:'|\")(§§version§§)(?:'|\")", "/\\*+![\\s]+(?:@license)?[\\s]+handlebars v+(§§version§§)", - "window\\.Handlebars=.,.\\.VERSION=\"(§§version§§)\"" + "window\\.Handlebars=.,.\\.VERSION=\"(§§version§§)\"", + ".\\.HandlebarsEnvironment=.;var .=.\\(.\\),.=.\\(.\\),.=\"(§§version§§)\";.\\.VERSION=" ], "hashes": {} } @@ -4285,7 +4335,7 @@ "filecontent": [ "/\\*\\*\n +\\* React \\(with addons\\) ?v(§§version§§)", "/\\*\\*\n +\\* React v(§§version§§)", - "/\\*\\* @license React v(§§version§§)[\\s]*\\* react\\.", + "/\\*\\* @license React v(§§version§§)[\\s]*\\* react(-jsx-runtime)?\\.", "\"\\./ReactReconciler\":[0-9]+,\"\\./Transaction\":[0-9]+,\"fbjs/lib/invariant\":[0-9]+\\}\\],[0-9]+:\\[function\\(require,module,exports\\)\\{\"use strict\";module\\.exports=\"(§§version§§)\"\\}", "ReactVersion\\.js[\\*! \\\\/\n\r]{0,100}function\\(e,t\\)\\{\"use strict\";e\\.exports=\"(§§version§§)\"", "expected a ReactNode.[\\s\\S]{0,1800}?function\\(e,t\\)\\{\"use strict\";e\\.exports=\"(§§version§§)\"" @@ -4405,6 +4455,22 @@ ] } }, + "react-is": { + "vulnerabilities": [], + "extractors": { + "filecontent": [ + "/\\*\\* @license React v(§§version§§)[\\s]*\\* react-is\\." + ] + } + }, + "scheduler": { + "vulnerabilities": [], + "extractors": { + "filecontent": [ + "/\\*\\* @license React v(§§version§§)[\\s]*\\* scheduler\\." + ] + } + }, "flowplayer": { "vulnerabilities": [ { @@ -5541,6 +5607,31 @@ }, { "atOrAbove": "0.8.1", + "below": "0.28.0", + "cwe": [ + "CWE-352" + ], + "severity": "medium", + "identifiers": { + "summary": "Axios Cross-Site Request Forgery Vulnerability", + "CVE": [ + "CVE-2023-45857" + ], + "githubID": "GHSA-wf5p-g6vw-rhxx" + }, + "info": [ + "https://github.com/advisories/GHSA-wf5p-g6vw-rhxx", + "https://nvd.nist.gov/vuln/detail/CVE-2023-45857", + "https://github.com/axios/axios/issues/6006", + "https://github.com/axios/axios/issues/6022", + "https://github.com/axios/axios/pull/6028", + "https://github.com/axios/axios/commit/96ee232bd3ee4de2e657333d4d2191cd389e14d0", + "https://github.com/axios/axios/releases/tag/v1.6.0", + "https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459" + ] + }, + { + "atOrAbove": "1.0.0", "below": "1.6.0", "cwe": [ "CWE-352"