diff --git a/.circleci/config.yml b/.circleci/config.yml index 97524098..ae81598b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ _refs: defaults: &defaults working_directory: ~/cli docker: - - image: node:12 + - image: node:14 ssh-config: &ssh-config fingerprints: - 'b1:50:d4:d9:01:2c:7c:8b:a0:e3:3c:c1:f8:a4:41:f0' @@ -63,7 +63,7 @@ commands: git commit -m "chore: updated version $RELEASE_TAG [ci skip]" - run: *build - run: - name: Generate plugin manifest + name: Generate plugin manifest command: yarn manifest:generate - run: yarn package release-management-commands: @@ -101,7 +101,7 @@ commands: git tag -a $PKG_TAG -m "Releasing ${PKG_TAG}" git push origin $PKG_TAG build-artifact: - steps: + steps: - run: name: Archiving tarball command: | @@ -132,10 +132,10 @@ jobs: - run: *build - run: *test - build-artifact - node-12: + node-16: <<: *node-test docker: - - image: node:12 + - image: node:16 node-14: <<: *node-test docker: @@ -193,7 +193,7 @@ jobs: working_directory: ~/cli/packages/apex-node steps: - attach_workspace: - at: ~/cli + at: ~/cli - npm-release-management/publish: use_tarfile: true - slack/notify: @@ -224,7 +224,7 @@ jobs: workflows: version: 2.1 - + commit-workflow: jobs: - slack/approval-notification: @@ -236,7 +236,7 @@ workflows: branches: only: main - node-latest - - node-12 + - node-16 - node-14 - cache: filters: @@ -244,7 +244,7 @@ workflows: only: /^v.*/ branches: ignore: - - main + - main - /.*/ - run-win-tests - hold: # Requires manual approval in Circle Ci @@ -267,7 +267,7 @@ workflows: requires: - run-win-tests - node-latest - - node-12 + - node-16 - node-14 - hold - prepublish @@ -281,8 +281,8 @@ workflows: requires: - run-win-tests - node-latest - - node-12 + - node-16 - node-14 - hold - prepublish - - publish-apex-node \ No newline at end of file + - publish-apex-node diff --git a/.prettierrc b/.prettierrc index 0b73d5ea..57a10132 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,4 +2,4 @@ "printWidth": 80, "tabWidth": 2, "singleQuote": true -} \ No newline at end of file +} diff --git a/package.json b/package.json index 40e9602a..16a7956e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "salesforcedx-apex", "dependencies": { - "node": "12.4.0", + "node": "^14.14.0", "npm": "^6.9.0" }, "devDependencies": { @@ -22,7 +22,7 @@ "lint-staged": "^10.2.11", "mocha": "^5", "prettier": "1.19.1", - "typescript": "3.7.5" + "typescript": "4.6.4" }, "repository": { "type": "git", @@ -56,7 +56,7 @@ }, "private": true, "volta": { - "node": "12.4.0", + "node": "14.0.0", "yarn": "1.22.4" }, "config": { diff --git a/packages/apex-node/.gitignore b/packages/apex-node/.gitignore index 2ddfeaa4..4ba1076c 100644 --- a/packages/apex-node/.gitignore +++ b/packages/apex-node/.gitignore @@ -13,6 +13,7 @@ lerna-debug.log* # test results +/path /testTmp test-results.xml xunit.xml @@ -95,4 +96,4 @@ jspm_packages/ .env.test # parcel-bundler cache (https://parceljs.org/) -.cache \ No newline at end of file +.cache diff --git a/packages/apex-node/package.json b/packages/apex-node/package.json index 7d64f998..80f7f621 100644 --- a/packages/apex-node/package.json +++ b/packages/apex-node/package.json @@ -7,24 +7,32 @@ "main": "lib/src/index.js", "dependencies": { "@salesforce/core": "^2.35.0", - "faye": "1.4.0" + "faye": "1.4.0", + "glob": "^8.0.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4" }, "devDependencies": { "@salesforce/ts-sinon": "^1.1.2", "@salesforce/ts-types": "1.2.2", "@types/chai": "^4", + "@types/istanbul-lib-coverage": "^2.0.4", + "@types/istanbul-lib-report": "^3.0.0", + "@types/istanbul-reports": "^3.0.1", "@types/mkdirp": "0.5.2", "@types/mocha": "^5", - "@types/node": "^10", + "@types/node": "^14", "@types/sinon": "^7.5.2", "chai": "^4", "mocha": "^5", "mocha-junit-reporter": "^1.23.3", "nyc": "^14.1.1", - "shx": "0.2.2", + "shx": "^0.3.4", "sinon": "^7.3.1", "source-map-support": "^0.5.16", - "typescript": "4.3.2" + "ts-node": "^10.7.0", + "typescript": "4.6.4" }, "homepage": "https://github.com/forcedotcom/salesforcedx-apex", "keywords": [ @@ -56,6 +64,6 @@ }, "license": "BSD-3-Clause", "engines": { - "node": ">=10.17.0" + "node": ">=14.14.0" } } diff --git a/packages/apex-node/src/i18n/i18n.ts b/packages/apex-node/src/i18n/i18n.ts index 981fd7e9..0905d220 100644 --- a/packages/apex-node/src/i18n/i18n.ts +++ b/packages/apex-node/src/i18n/i18n.ts @@ -24,6 +24,8 @@ export const messages = { numLogsError: 'Expected number of logs to be greater than 0.', optionExecAnonError: 'Please specify an option to execute anonymous Apex.', unexpectedExecAnonInputError: 'Unexpected error while reading user input. %s', + coverageReportCreationError: + 'Unexpected error occurred while creating coverage reports. %s', execAnonInputPrompt: 'Start typing Apex code. Press the Enter key after each line, then press CTRL+D when finished.\n', execAnonInputTimeout: 'Timed out while waiting for user input.', diff --git a/packages/apex-node/src/index.ts b/packages/apex-node/src/index.ts index af0cc516..e80e0060 100644 --- a/packages/apex-node/src/index.ts +++ b/packages/apex-node/src/index.ts @@ -12,8 +12,19 @@ export { ApexExecuteOptions } from './execute'; export { LogService, ApexLogGetOptions, LogRecord, LogResult } from './logs'; -export { JUnitReporter, TapReporter, HumanReporter } from './reporters'; export { + JUnitReporter, + TapReporter, + HumanReporter, + CoverageReporterOptions, + CoverageReporter, + CoverageReportFormats, + DefaultReportOptions, + DefaultWatermarks +} from './reporters'; +export { + ApexCodeCoverageAggregate, + ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestResultData, ApexTestResultOutcome, diff --git a/packages/apex-node/src/reporters/coverageReporter.ts b/packages/apex-node/src/reporters/coverageReporter.ts new file mode 100644 index 00000000..ccf1cf0e --- /dev/null +++ b/packages/apex-node/src/reporters/coverageReporter.ts @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { + ApexCodeCoverage, + ApexCodeCoverageAggregate, + ApexCodeCoverageAggregateRecord, + ApexCodeCoverageRecord +} from '../tests/types'; +import * as libReport from 'istanbul-lib-report'; +import * as reports from 'istanbul-reports'; +import * as libCoverage from 'istanbul-lib-coverage'; +import * as path from 'path'; +import { glob } from 'glob'; +import * as fs from 'fs'; +import { nls } from '../i18n'; + +const startOfSource = (source: string): number => { + if (source) { + return source.search(/\S/) || 0; + } + return 0; +}; +const endOfSource = (source: string): number => { + if (source) { + return source.search(/\S$/) || 0; + } + return 0; +}; + +export type CoverageReportFormats = reports.ReportType; + +export const DefaultWatermarks: libReport.Watermarks = { + statements: [50, 75], + functions: [50, 75], + branches: [50, 75], + lines: [50, 75] +}; + +export const DefaultReportOptions: Partial = { + clover: { file: 'clover.xml', projectRoot: '.' }, + cobertura: { file: 'cobertura.xml', projectRoot: '.' }, + 'html-spa': { + verbose: false, + skipEmpty: false, + subdir: 'html-spa', + linkMapper: undefined, + metricsToShow: ['lines', 'statements', 'branches'] + }, + html: { + verbose: false, + skipEmpty: false, + subdir: 'html', + linkMapper: undefined + }, + json: { file: 'coverage.json' }, + 'json-summary': { file: 'coverage-summary.json' }, + lcovonly: { file: 'lcovonly.info', projectRoot: '.' }, + none: {} as never, + teamcity: { file: 'teamcity.txt', blockName: 'coverage' }, + text: { file: 'text.txt', maxCols: 160, skipEmpty: false, skipFull: false }, + 'text-summary': { file: 'text-summary.txt' } +}; + +export interface CoverageReporterOptions { + reportFormats?: CoverageReportFormats[]; + reportOptions?: Partial; + watermark?: typeof DefaultWatermarks; +} + +/** + * Utility class to produce various well-known code coverage reports from Apex test coverage results. + */ +export class CoverageReporter { + private readonly coverageMap: libCoverage.CoverageMap; + + /** + * + * @param coverage - instance of either a ApexCodeCoverageAggregate or ApexCodeCoverage object + * @param reportDir - Directory to where the requested coverage reports will be written + * @param sourceDir - Source directory for those Apex classes or triggers included in coverage data + * @param options - CoverageReporterOptions + */ + constructor( + private readonly coverage: ApexCodeCoverageAggregate | ApexCodeCoverage, + private readonly reportDir: string, + private readonly sourceDir: string, + private readonly options?: CoverageReporterOptions + ) { + this.coverageMap = this.buildCoverageMap(); + } + + public generateReports(): void { + try { + const reportDirStat = fs.statSync(this.reportDir); + const context = libReport.createContext({ + dir: this.reportDir, + defaultSummarizer: 'nested', + watermarks: this.options?.watermark || DefaultWatermarks, + coverageMap: this.coverageMap + }); + const formats = this.options?.reportFormats || ['text-summary']; + formats.forEach(format => { + const report = reports.create( + format, + this.options?.reportOptions[format] || DefaultReportOptions[format] + ); + report.execute(context); + }); + } catch (e) { + throw new Error(nls.localize('coverageReportCreationError', e.message)); + } + } + + private buildCoverageMap(): libCoverage.CoverageMap { + const coverageMap = libCoverage.createCoverageMap(); + this.coverage.records.forEach( + (record: ApexCodeCoverageRecord | ApexCodeCoverageAggregateRecord) => { + const fileCoverageData: libCoverage.FileCoverageData = {} as libCoverage.FileCoverageData; + fileCoverageData.fnMap = {}; + fileCoverageData.branchMap = {}; + fileCoverageData.path = path.join( + this.sourceDir, + this.findFullPathToClass(record.ApexClassOrTrigger.Name) + ); + fileCoverageData.f = {}; + fileCoverageData.b = {}; + fileCoverageData.s = [ + ...record.Coverage.coveredLines.map(line => [line, 1]), + ...record.Coverage.uncoveredLines.map(line => [line, 0]) + ] + .map(([line, covered]) => [Number(line).toString(10), covered]) + .reduce((acc, [line, value]) => { + return Object.assign(acc, { [line]: value }); + }, {}); + let sourceLines: string[] = []; + try { + sourceLines = fs + .readFileSync(fileCoverageData.path, 'utf8') + .split('\n'); + } catch { + // file not found + } + fileCoverageData.statementMap = [ + ...record.Coverage.coveredLines, + ...record.Coverage.uncoveredLines + ] + .sort() + .map(line => { + const statement: libCoverage.Range = { + start: { + line, + column: startOfSource(sourceLines[line - 1]) + }, + end: { + line, + column: endOfSource(sourceLines[line - 1]) + } + }; + + return [Number(line).toString(10), statement]; + }) + .reduce((acc, [line, value]) => { + return Object.assign(acc, { [Number(line).toString()]: value }); + }, {}); + coverageMap.addFileCoverage(fileCoverageData); + } + ); + return coverageMap; + } + + private findFullPathToClass(classOrTriggerName: string): string { + const searchPattern = `**/${classOrTriggerName}.{cls,trigger}`; + const files = glob.sync(searchPattern, { cwd: this.sourceDir }); + return files[0] ? files[0] : classOrTriggerName; + } +} diff --git a/packages/apex-node/src/reporters/index.ts b/packages/apex-node/src/reporters/index.ts index a5ba0bc1..b84be0ee 100644 --- a/packages/apex-node/src/reporters/index.ts +++ b/packages/apex-node/src/reporters/index.ts @@ -8,3 +8,10 @@ export { TapReporter } from './tapReporter'; export { JUnitReporter } from './junitReporter'; export { HumanReporter } from './humanReporter'; +export { + CoverageReporter, + CoverageReporterOptions, + CoverageReportFormats, + DefaultReportOptions, + DefaultWatermarks +} from './coverageReporter'; diff --git a/packages/apex-node/src/tests/codeCoverage.ts b/packages/apex-node/src/tests/codeCoverage.ts index 08db141a..0e9ba152 100644 --- a/packages/apex-node/src/tests/codeCoverage.ts +++ b/packages/apex-node/src/tests/codeCoverage.ts @@ -91,14 +91,6 @@ export class CodeCoverage { return perClassCoverageMap; } - private async queryPerClassCodeCov( - apexTestClassSet: Set - ): Promise { - const perClassCodeCovQuery = - 'SELECT ApexTestClassId, ApexClassOrTrigger.Id, ApexClassOrTrigger.Name, TestMethodName, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverage WHERE ApexTestClassId IN (%s)'; - return this.fetchResults(apexTestClassSet, perClassCodeCovQuery); - } - /** * Returns the aggregate code coverage information from ApexCodeCoverageAggregate entity for a given set of Apex classes * @param apexClassIdSet Set of ids for Apex classes @@ -160,6 +152,14 @@ export class CodeCoverage { }; } + private async queryPerClassCodeCov( + apexTestClassSet: Set + ): Promise { + const perClassCodeCovQuery = + 'SELECT ApexTestClassId, ApexClassOrTrigger.Id, ApexClassOrTrigger.Name, TestMethodName, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverage WHERE ApexTestClassId IN (%s)'; + return this.fetchResults(apexTestClassSet, perClassCodeCovQuery); + } + private async queryAggregateCodeCov( apexClassIdSet: Set ): Promise { diff --git a/packages/apex-node/src/tests/index.ts b/packages/apex-node/src/tests/index.ts index d999b6df..0a2e2498 100644 --- a/packages/apex-node/src/tests/index.ts +++ b/packages/apex-node/src/tests/index.ts @@ -7,6 +7,8 @@ export { TestService } from './testService'; export { + ApexCodeCoverageAggregate, + ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestRunResultStatus, AsyncTestConfiguration, diff --git a/packages/apex-node/test/mocha.opts b/packages/apex-node/test/mocha.opts index 00ac7e95..f0856373 100644 --- a/packages/apex-node/test/mocha.opts +++ b/packages/apex-node/test/mocha.opts @@ -1,6 +1,7 @@ +--require ts-node/register --reporter ./test/combinedTestReporter.js --reporter-options mochaFile=./test-results/test-results.xml --require source-map-support/register lib/test/**/*.test.js --colors ---exit \ No newline at end of file +--exit diff --git a/packages/apex-node/test/reporters/coverageReporter.test.ts b/packages/apex-node/test/reporters/coverageReporter.test.ts new file mode 100644 index 00000000..a9f94be4 --- /dev/null +++ b/packages/apex-node/test/reporters/coverageReporter.test.ts @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2022, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { expect } from 'chai'; +import { CoverageReporter } from '../../src/reporters/coverageReporter'; +import { tmpdir } from 'os'; +import * as path from 'path'; +import * as crypto from 'crypto'; +import * as fs from 'fs'; +import mkdirp = require('mkdirp'); + +const multipleCoverageAggregate = { + done: true, + totalSize: 4, + records: [ + { + attributes: { + type: 'ApexCodeCoverageAggregate', + url: + '/services/data/v54.0/tooling/sobjects/ApexCodeCoverageAggregate/71511000006fb7kAAA' + }, + ApexClassOrTrigger: { + attributes: { + type: 'Name', + url: + '/services/data/v54.0/tooling/sobjects/ApexClass/01p1100000TqGm6AAF' + }, + Id: '01p1100000TqGm6AAF', + Name: 'PagedResult' + }, + NumLinesCovered: 3, + NumLinesUncovered: 1, + Coverage: { + coveredLines: [3, 6, 9], + uncoveredLines: [12] + } + }, + { + attributes: { + type: 'ApexCodeCoverageAggregate', + url: + '/services/data/v54.0/tooling/sobjects/ApexCodeCoverageAggregate/71511000006fb7lAAA' + }, + ApexClassOrTrigger: { + attributes: { + type: 'Name', + url: + '/services/data/v54.0/tooling/sobjects/ApexClass/01p1100000TqGm8AAF' + }, + Id: '01p1100000TqGm8AAF', + Name: 'SampleDataController' + }, + NumLinesCovered: 34, + NumLinesUncovered: 0, + Coverage: { + coveredLines: [ + 3, + 4, + 5, + 6, + 7, + 9, + 10, + 11, + 14, + 15, + 20, + 21, + 22, + 23, + 25, + 28, + 29, + 34, + 35, + 36, + 37, + 39, + 40, + 43, + 44, + 49, + 50, + 51, + 52, + 54, + 57, + 58, + 59, + 60 + ], + uncoveredLines: [] + } + }, + { + attributes: { + type: 'ApexCodeCoverageAggregate', + url: + '/services/data/v54.0/tooling/sobjects/ApexCodeCoverageAggregate/71511000006fb7mAAA' + }, + ApexClassOrTrigger: { + attributes: { + type: 'Name', + url: + '/services/data/v54.0/tooling/sobjects/ApexClass/01p1100000TqGm7AAF' + }, + Id: '01p1100000TqGm7AAF', + Name: 'PropertyController' + }, + NumLinesCovered: 41, + NumLinesUncovered: 3, + Coverage: { + coveredLines: [ + 2, + 3, + 16, + 25, + 27, + 28, + 29, + 30, + 32, + 33, + 35, + 36, + 38, + 39, + 40, + 41, + 45, + 46, + 47, + 48, + 49, + 50, + 52, + 67, + 68, + 69, + 70, + 71, + 72, + 75, + 76, + 87, + 88, + 92, + 97, + 98, + 101, + 103, + 104, + 107, + 110 + ], + uncoveredLines: [26, 31, 78] + } + }, + { + attributes: { + type: 'ApexCodeCoverageAggregate', + url: + '/services/data/v54.0/tooling/sobjects/ApexCodeCoverageAggregate/71511000006fb7nAAA' + }, + ApexClassOrTrigger: { + attributes: { + type: 'Name', + url: + '/services/data/v54.0/tooling/sobjects/ApexClass/01p1100000TqGm4AAF' + }, + Id: '01p1100000TqGm4AAF', + Name: 'GeocodingService' + }, + NumLinesCovered: 36, + NumLinesUncovered: 0, + Coverage: { + coveredLines: [ + 5, + 8, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 38, + 39, + 40, + 41, + 42, + 44, + 48, + 50 + ], + uncoveredLines: [] + } + } + ] +}; + +describe('coverageReports', () => { + let testResultsDir: string; + + beforeEach(async () => { + testResultsDir = path.join( + tmpdir(), + crypto.randomBytes(10).toString('hex') + ); + await fs.promises.mkdir(testResultsDir, { recursive: true }); + }); + afterEach(async () => { + try { + await fs.promises.rmdir(testResultsDir, { recursive: true }); + } catch (err) {} + }); + it('should produce coverage report', async () => { + const coverageReport = new CoverageReporter( + multipleCoverageAggregate, + testResultsDir, + 'packages/apex-node/test/coverageReporters/testResources', + { + reportFormats: ['clover', 'html'], + reportOptions: { + clover: { + file: 'clover.xml', + projectRoot: + 'packages/apex-node/test/coverageReporters/testResources' + } + } + } + ); + coverageReport.generateReports(); + const cloverFile = path.join(testResultsDir, 'clover.xml'); + const htmlFile = path.join(testResultsDir, 'html', 'index.html'); + const cloverFileStat = await fs.promises.stat(cloverFile); + const htmlFileStat = await fs.promises.stat(htmlFile); + expect(cloverFileStat.isFile()).to.be.true; + expect(htmlFileStat.isFile()).to.be.true; + // ensure no other coverage reports were created + const dirEntries = await fs.promises.readdir(testResultsDir); + expect(dirEntries).to.have.lengthOf(2); + }); + it('should produce coverage report using default options', async () => { + const coverageReport = new CoverageReporter( + multipleCoverageAggregate, + testResultsDir, + 'packages/apex-node/test/coverageReporters/testResources' + ); + coverageReport.generateReports(); + const textSummaryFile = path.join(testResultsDir, 'text-summary.txt'); + const textSummaryFileStat = await fs.promises.stat(textSummaryFile); + expect(textSummaryFileStat.isFile()).to.be.true; + // ensure no other coverage reports were created + const dirEntries = await fs.promises.readdir(testResultsDir); + expect(dirEntries).to.have.lengthOf(1); + }); + it('should handle aggregate object with no coverage entries', async () => { + const coverageAggregate = JSON.parse( + JSON.stringify(multipleCoverageAggregate) + ); + coverageAggregate.totalSize = 0; + coverageAggregate.records = []; + const coverageReport = new CoverageReporter( + coverageAggregate, + testResultsDir, + 'packages/apex-node/test/coverageReporters/testResources' + ); + coverageReport.generateReports(); + const textSummaryFile = path.join(testResultsDir, 'text-summary.txt'); + const textSummaryFileStat = await fs.promises.stat(textSummaryFile); + expect(textSummaryFileStat.isFile()).to.be.true; + const textSummaryContents = await fs.promises.readFile( + textSummaryFile, + 'utf8' + ); + expect(textSummaryContents).to.include('Unknown%'); + // ensure no other coverage reports were created + const dirEntries = await fs.promises.readdir(testResultsDir); + expect(dirEntries).to.have.lengthOf(1); + }); + it('should handle non-existent sourceDir', async () => { + const coverageReport = new CoverageReporter( + multipleCoverageAggregate, + testResultsDir, + 'foo/bar/baz' + ); + coverageReport.generateReports(); + const textSummaryFile = path.join(testResultsDir, 'text-summary.txt'); + const textSummaryFileStat = await fs.promises.stat(textSummaryFile); + expect(textSummaryFileStat.isFile()).to.be.true; + // ensure no other coverage reports were created + const dirEntries = await fs.promises.readdir(testResultsDir); + expect(dirEntries).to.have.lengthOf(1); + }); +}); diff --git a/packages/apex-node/test/reporters/testResources/GeocodingService.cls b/packages/apex-node/test/reporters/testResources/GeocodingService.cls new file mode 100644 index 00000000..dc55c549 --- /dev/null +++ b/packages/apex-node/test/reporters/testResources/GeocodingService.cls @@ -0,0 +1,72 @@ +public with sharing class GeocodingService { + private static final String BASE_URL = 'https://nominatim.openstreetmap.org/search?format=json'; + + @InvocableMethod(callout=true label='Geocode address') + public static List geocodeAddresses( + List addresses + ) { + List computedCoordinates = new List(); + + for (GeocodingAddress address : addresses) { + String geocodingUrl = BASE_URL; + geocodingUrl += (String.isNotBlank(address.street)) + ? '&street=' + address.street + : ''; + geocodingUrl += (String.isNotBlank(address.city)) + ? '&city=' + address.city + : ''; + geocodingUrl += (String.isNotBlank(address.state)) + ? '&state=' + address.state + : ''; + geocodingUrl += (String.isNotBlank(address.country)) + ? '&country=' + address.country + : ''; + geocodingUrl += (String.isNotBlank(address.postalcode)) + ? '&postalcode=' + address.postalcode + : ''; + + Coordinates coords = new Coordinates(); + if (geocodingUrl != BASE_URL) { + Http http = new Http(); + HttpRequest request = new HttpRequest(); + request.setEndpoint(geocodingUrl); + request.setMethod('GET'); + request.setHeader( + 'http-referer', + URL.getSalesforceBaseUrl().toExternalForm() + ); + HttpResponse response = http.send(request); + if (response.getStatusCode() == 200) { + List deserializedCoords = (List) JSON.deserialize( + response.getBody(), + List.class + ); + coords = deserializedCoords[0]; + } + } + + computedCoordinates.add(coords); + } + return computedCoordinates; + } + + public class GeocodingAddress { + @InvocableVariable + public String street; + @InvocableVariable + public String city; + @InvocableVariable + public String state; + @InvocableVariable + public String country; + @InvocableVariable + public String postalcode; + } + + public class Coordinates { + @InvocableVariable + public Decimal lat; + @InvocableVariable + public Decimal lon; + } +} diff --git a/packages/apex-node/test/reporters/testResources/PagedResult.cls b/packages/apex-node/test/reporters/testResources/PagedResult.cls new file mode 100644 index 00000000..182bdcf9 --- /dev/null +++ b/packages/apex-node/test/reporters/testResources/PagedResult.cls @@ -0,0 +1,13 @@ +public with sharing class PagedResult { + @AuraEnabled + public Integer pageSize { get; set; } + + @AuraEnabled + public Integer pageNumber { get; set; } + + @AuraEnabled + public Integer totalItemCount { get; set; } + + @AuraEnabled + public Object[] records { get; set; } +} diff --git a/packages/apex-node/test/reporters/testResources/PropertyController.cls b/packages/apex-node/test/reporters/testResources/PropertyController.cls new file mode 100644 index 00000000..e27e3617 --- /dev/null +++ b/packages/apex-node/test/reporters/testResources/PropertyController.cls @@ -0,0 +1,115 @@ +public with sharing class PropertyController { + private static final Decimal DEFAULT_MAX_PRICE = 9999999; + private static final Integer DEFAULT_PAGE_SIZE = 9; + + /** + * Endpoint that retrieves a paged and filtered list of properties + * @param searchKey String used for searching on property title, city and tags + * @param maxPrice Maximum price + * @param minBedrooms Minimum number of bedrooms + * @param minBathrooms Minimum number of bathrooms + * @param pageSize Number of properties per page + * @param pageNumber Page number + * @return PagedResult object holding the paged and filtered list of properties + */ + @AuraEnabled(cacheable=true) + public static PagedResult getPagedPropertyList( + String searchKey, + Decimal maxPrice, + Integer minBedrooms, + Integer minBathrooms, + Integer pageSize, + Integer pageNumber + ) { + // Normalize inputs + Decimal safeMaxPrice = (maxPrice == null + ? DEFAULT_MAX_PRICE + : maxPrice); + Integer safeMinBedrooms = (minBedrooms == null ? 0 : minBedrooms); + Integer safeMinBathrooms = (minBathrooms == null ? 0 : minBathrooms); + Integer safePageSize = (pageSize == null + ? DEFAULT_PAGE_SIZE + : pageSize); + Integer safePageNumber = (pageNumber == null ? 1 : pageNumber); + + String searchPattern = '%' + searchKey + '%'; + Integer offset = (safePageNumber - 1) * safePageSize; + + PagedResult result = new PagedResult(); + result.pageSize = safePageSize; + result.pageNumber = safePageNumber; + result.totalItemCount = [ + SELECT COUNT() + FROM Property__c + WHERE + (Name LIKE :searchPattern + OR City__c LIKE :searchPattern + OR Tags__c LIKE :searchPattern) + AND Price__c <= :safeMaxPrice + AND Beds__c >= :safeMinBedrooms + AND Baths__c >= :safeMinBathrooms + ]; + result.records = [ + SELECT + Id, + Address__c, + City__c, + State__c, + Description__c, + Price__c, + Baths__c, + Beds__c, + Thumbnail__c, + Location__Latitude__s, + Location__Longitude__s + FROM Property__c + WHERE + (Name LIKE :searchPattern + OR City__c LIKE :searchPattern + OR Tags__c LIKE :searchPattern) + AND Price__c <= :safeMaxPrice + AND Beds__c >= :safeMinBedrooms + AND Baths__c >= :safeMinBathrooms + WITH SECURITY_ENFORCED + ORDER BY Price__c + LIMIT :safePageSize + OFFSET :offset + ]; + return result; + } + + /** + * Endpoint that retrieves pictures associated with a property + * @param propertyId Property Id + * @return List of ContentVersion holding the pictures + */ + @AuraEnabled(cacheable=true) + public static List getPictures(Id propertyId) { + List links = [ + SELECT Id, LinkedEntityId, ContentDocumentId + FROM ContentDocumentLink + WHERE + LinkedEntityId = :propertyId + AND ContentDocument.FileType IN ('PNG', 'JPG', 'GIF') + WITH SECURITY_ENFORCED + ]; + + if (links.isEmpty()) { + return null; + } + + Set contentIds = new Set(); + + for (ContentDocumentLink link : links) { + contentIds.add(link.ContentDocumentId); + } + + return [ + SELECT Id, Title + FROM ContentVersion + WHERE ContentDocumentId IN :contentIds AND IsLatest = TRUE + WITH SECURITY_ENFORCED + ORDER BY CreatedDate + ]; + } +} diff --git a/packages/apex-node/test/reporters/testResources/README.md b/packages/apex-node/test/reporters/testResources/README.md new file mode 100644 index 00000000..ab0b4ccc --- /dev/null +++ b/packages/apex-node/test/reporters/testResources/README.md @@ -0,0 +1,2 @@ +# Attribution for Apex Files used for testing +The files in [testResources]() are from the [trailheadapps/dreamhouse-lwc](https://github.com/trailheadapps/dreamhouse-lwc) github repository and is being consumed here solely for testing purposes. diff --git a/packages/apex-node/test/reporters/testResources/SampleDataController.cls b/packages/apex-node/test/reporters/testResources/SampleDataController.cls new file mode 100644 index 00000000..dba8dade --- /dev/null +++ b/packages/apex-node/test/reporters/testResources/SampleDataController.cls @@ -0,0 +1,63 @@ +public with sharing class SampleDataController { + @AuraEnabled + public static void importSampleData() { + delete [SELECT Id FROM Case]; + delete [SELECT Id FROM Property__c]; + delete [SELECT Id FROM Broker__c]; + delete [SELECT Id FROM Contact]; + + insertBrokers(); + insertProperties(); + insertContacts(); + } + + private static void insertBrokers() { + StaticResource brokersResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_brokers' + ]; + String brokersJSON = brokersResource.body.toString(); + List brokers = (List) JSON.deserialize( + brokersJSON, + List.class + ); + insert brokers; + } + + private static void insertProperties() { + StaticResource propertiesResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_properties' + ]; + String propertiesJSON = propertiesResource.body.toString(); + List properties = (List) JSON.deserialize( + propertiesJSON, + List.class + ); + randomizeDateListed(properties); + insert properties; + } + + private static void insertContacts() { + StaticResource contactsResource = [ + SELECT Id, Body + FROM StaticResource + WHERE Name = 'sample_data_contacts' + ]; + String contactsJSON = contactsResource.body.toString(); + List contacts = (List) JSON.deserialize( + contactsJSON, + List.class + ); + insert contacts; + } + + private static void randomizeDateListed(List properties) { + for (Property__c property : properties) { + property.Date_Listed__c = + System.today() - Integer.valueof((Math.random() * 90)); + } + } +} diff --git a/packages/apex-node/tsconfig.json b/packages/apex-node/tsconfig.json index 0990a2c6..4def4289 100644 --- a/packages/apex-node/tsconfig.json +++ b/packages/apex-node/tsconfig.json @@ -9,7 +9,8 @@ "noImplicitAny": true, "rootDir": ".", "outDir": "lib", - "preserveConstEnums": true + "preserveConstEnums": true, + "skipLibCheck": true }, "exclude": ["node_modules", "lib"] } diff --git a/packages/apex-node/yarn.lock b/packages/apex-node/yarn.lock index 00cadd20..74b1f0f8 100644 --- a/packages/apex-node/yarn.lock +++ b/packages/apex-node/yarn.lock @@ -93,6 +93,18 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + "@salesforce/bunyan@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@salesforce/bunyan/-/bunyan-2.0.0.tgz#8dbe377f2cf7d35348a23260416fee15adba5f97" @@ -209,6 +221,26 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + "@types/chai@^4": version "4.2.14" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" @@ -221,6 +253,25 @@ dependencies: "@types/node" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*", "@types/istanbul-lib-report@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/jsforce@^1.9.38": version "1.9.41" resolved "https://registry.yarnpkg.com/@types/jsforce/-/jsforce-1.9.41.tgz#08b31a0d04e14fd5f8a232196e16bc742e22bbed" @@ -252,16 +303,26 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== -"@types/node@^10": - version "10.17.51" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.51.tgz#639538575befbcf3d3861f95c41de8e47124d674" - integrity sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg== +"@types/node@^14": + version "14.18.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.18.tgz#5c9503030df484ccffcbb935ea9a9e1d6fad1a20" + integrity sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig== "@types/sinon@^7.5.2": version "7.5.2" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.5.2.tgz#5e2f1d120f07b9cda07e5dedd4f3bf8888fccdb9" integrity sha512-T+m89VdXj/eidZyejvmoP9jivXgBDdkOSBVQjU9kF349NEx10QdPNGxHeZUaj1IlJ32/ewdyXJjnJxyxJroYwg== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + ajv@^6.12.3: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -330,6 +391,11 @@ archy@^1.0.0: resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -423,6 +489,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -611,6 +684,11 @@ crc32-stream@^4.0.2: crc-32 "^1.2.0" readable-stream "^3.4.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^4: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -717,6 +795,11 @@ diff@3.5.0, diff@^3.5.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dtrace-provider@~0.6: version "0.6.0" resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.6.0.tgz#0b078d5517937d873101452d9146737557b75e51" @@ -763,11 +846,6 @@ es6-error@^4.0.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-object-assign@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= - escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -944,6 +1022,18 @@ glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.1.tgz#00308f5c035aa0b2a447cd37ead267ddff1577d3" + integrity sha512-cF7FYZZ47YzmCu7dDy50xSRRfO3ErRfrXuLZcNIuyiJEco0XSrGtuilG19L5xp3NcwTx7Gn+X6Tv3fmsUPTbow== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -987,6 +1077,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1120,6 +1215,11 @@ istanbul-lib-coverage@^2.0.5: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + istanbul-lib-hook@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" @@ -1149,6 +1249,15 @@ istanbul-lib-report@^2.0.8: make-dir "^2.1.0" supports-color "^6.1.0" +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + istanbul-lib-source-maps@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" @@ -1167,6 +1276,14 @@ istanbul-reports@^2.2.4: dependencies: html-escaper "^2.0.0" +istanbul-reports@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1431,6 +1548,18 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + md5@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" @@ -1466,12 +1595,19 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -1961,15 +2097,6 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -shelljs@^0.7.3: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" @@ -1979,16 +2106,7 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" -shx@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/shx/-/shx-0.2.2.tgz#0a304d020b0edf1306ad81570e80f0346df58a39" - integrity sha1-CjBNAgsO3xMGrYFXDoDwNG31ijk= - dependencies: - es6-object-assign "^1.0.3" - minimist "^1.2.0" - shelljs "^0.7.3" - -shx@^0.3.3: +shx@^0.3.3, shx@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.4.tgz#74289230b4b663979167f94e1935901406e40f02" integrity sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g== @@ -2166,6 +2284,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -2209,6 +2334,25 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +ts-node@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" + yn "3.1.1" + ts-retry-promise@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/ts-retry-promise/-/ts-retry-promise-0.6.0.tgz#95643500d5388eed25abc90aa2e99c8b6c5a7bc9" @@ -2241,10 +2385,10 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -typescript@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" - integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== +typescript@4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" + integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== universalify@^0.1.2: version "0.1.2" @@ -2268,6 +2412,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +v8-compile-cache-lib@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -2396,6 +2545,11 @@ yargs@^13.2.2: y18n "^4.0.0" yargs-parser "^13.1.2" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + zip-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79" diff --git a/packages/plugin-apex/.gitignore b/packages/plugin-apex/.gitignore index 4c9ac92e..186a8d55 100644 --- a/packages/plugin-apex/.gitignore +++ b/packages/plugin-apex/.gitignore @@ -28,6 +28,7 @@ junit-custom.xml junit-custom-unitTests.xml junit-custom-integrationTests.xml junit-custom-vscodeIntegrationTests.xml +/my testsoutput/ testpage/ folder space/ @@ -41,4 +42,4 @@ GitIgnoreTest2/ # Coverage directory used by tools like istanbul coverage -coverage.lcov \ No newline at end of file +coverage.lcov diff --git a/packages/plugin-apex/package.json b/packages/plugin-apex/package.json index 2177a1ec..4122df59 100644 --- a/packages/plugin-apex/package.json +++ b/packages/plugin-apex/package.json @@ -26,22 +26,22 @@ "@types/chai": "^4", "@types/mkdirp": "0.5.2", "@types/mocha": "^5", - "@types/node": "^10", + "@types/node": "^14", "chai": "^4", "cross-env": "7.0.2", "globby": "^8", "mocha": "^5", "nyc": "^14.1.1", - "shx": "0.2.2", + "shx": "^0.3.4", "sinon": "^7.3.1", "ts-node": "^8.7.0", - "typescript": "4.3.2" + "typescript": "4.6.4" }, "resolutions": { "**/@salesforce/core": "^2.35.0" }, "engines": { - "node": ">=10.17.0" + "node": ">=14.14.0" }, "files": [ "yarn.lock", diff --git a/packages/plugin-apex/src/commands/force/apex/test/report.ts b/packages/plugin-apex/src/commands/force/apex/test/report.ts index 590c9819..294f4289 100644 --- a/packages/plugin-apex/src/commands/force/apex/test/report.ts +++ b/packages/plugin-apex/src/commands/force/apex/test/report.ts @@ -148,7 +148,9 @@ export default class Report extends SfdxCommand { } } catch (e) { this.ux.logJson(jsonOutput); - const msg = messages.getMessage('testResultProcessErr', [e]); + const msg = messages.getMessage('testResultProcessErr', [ + (e as Error).message + ]); this.ux.error(msg); } return jsonOutput as AnyJson; @@ -184,7 +186,9 @@ export default class Report extends SfdxCommand { return reporter.format(result); } catch (e) { this.ux.logJson(result); - const msg = messages.getMessage('testResultProcessErr', [e]); + const msg = messages.getMessage('testResultProcessErr', [ + (e as Error).message + ]); this.ux.error(msg); throw e; } diff --git a/packages/plugin-apex/src/commands/force/apex/test/run.ts b/packages/plugin-apex/src/commands/force/apex/test/run.ts index fefde16b..2ec103ec 100644 --- a/packages/plugin-apex/src/commands/force/apex/test/run.ts +++ b/packages/plugin-apex/src/commands/force/apex/test/run.ts @@ -252,7 +252,9 @@ export default class Run extends SfdxCommand { } } catch (e) { this.ux.logJson(result); - const msg = messages.getMessage('testResultProcessErr', [e]); + const msg = messages.getMessage('testResultProcessErr', [ + (e as Error).message + ]); this.ux.error(msg); } @@ -343,7 +345,9 @@ export default class Run extends SfdxCommand { : (result as TestRunIdResult); } catch (e) { this.ux.logJson(result); - const msg = messages.getMessage('testResultProcessErr', [e]); + const msg = messages.getMessage('testResultProcessErr', [ + (e as Error).message + ]); this.ux.error(msg); throw e; } diff --git a/packages/plugin-apex/test/commands/force/apex/test/report.test.ts b/packages/plugin-apex/test/commands/force/apex/test/report.test.ts index 0d8b9752..d8efb232 100644 --- a/packages/plugin-apex/test/commands/force/apex/test/report.test.ts +++ b/packages/plugin-apex/test/commands/force/apex/test/report.test.ts @@ -126,7 +126,7 @@ describe('force:apex:test:report', () => { .it('should handle a tap format parsing error', ctx => { expect(JSON.parse(ctx.stdout)).to.deep.equal(jsonResult); expect(ctx.stderr).to.contain( - messages.getMessage('testResultProcessErr', ['Error: Error with TAP']) + messages.getMessage('testResultProcessErr', ['Error with TAP']) ); }); @@ -181,7 +181,7 @@ describe('force:apex:test:report', () => { .it('should handle a junit format parsing error', ctx => { expect(JSON.parse(ctx.stdout)).to.deep.equal(jsonResult); expect(ctx.stderr).to.contain( - messages.getMessage('testResultProcessErr', ['Error: Error with JUnit']) + messages.getMessage('testResultProcessErr', ['Error with JUnit']) ); }); diff --git a/packages/plugin-apex/test/commands/force/apex/test/run.test.ts b/packages/plugin-apex/test/commands/force/apex/test/run.test.ts index b40a8436..9869fac6 100644 --- a/packages/plugin-apex/test/commands/force/apex/test/run.test.ts +++ b/packages/plugin-apex/test/commands/force/apex/test/run.test.ts @@ -125,7 +125,7 @@ describe('force:apex:test:run', () => { .it('should handle a tap format parsing error', ctx => { expect(ctx.stdout).to.contain('{\n "tests": []\n}\n'); expect(ctx.stderr).to.contain( - messages.getMessage('testResultProcessErr', ['TypeError: ']) + messages.getMessage('testResultProcessErr', ['']) ); expect(ctx.stderr).to.contain('testRunId'); }); @@ -175,7 +175,7 @@ describe('force:apex:test:run', () => { .it('should handle a junit format parsing error', ctx => { expect(ctx.stdout).to.contain('{\n "tests": []\n}\n'); expect(ctx.stderr).to.contain( - messages.getMessage('testResultProcessErr', ['TypeError: ']) + messages.getMessage('testResultProcessErr', ['']) ); expect(ctx.stderr).to.contain('testStartTime'); }); diff --git a/packages/plugin-apex/tsconfig.json b/packages/plugin-apex/tsconfig.json index f0bb08d7..2497640c 100644 --- a/packages/plugin-apex/tsconfig.json +++ b/packages/plugin-apex/tsconfig.json @@ -11,6 +11,7 @@ "outDir": "./lib", "preserveConstEnums": true, "strict": true, + "skipLibCheck": true, // We can replace the TS generated snippets with require statements // from the tslib dependency, making our code more efficient diff --git a/packages/plugin-apex/yarn.lock b/packages/plugin-apex/yarn.lock index 088a9b22..52e8efcd 100644 --- a/packages/plugin-apex/yarn.lock +++ b/packages/plugin-apex/yarn.lock @@ -139,18 +139,30 @@ debug "^4.1.1" semver "^7.3.2" -"@oclif/command@^1.8.1", "@oclif/command@^1.8.6": - version "1.8.7" - resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.7.tgz#825d34bea8e93cecfaf0cb9bf327f4ab87cd0714" - integrity sha512-5DRLd2WHppuKsudHe8rCZnjgEpA2/6P4zxrLwWBXrGz+/kzA/RWcPJgkcdfm1uBCEgHMSWZP4MX21d4lAB1vYA== +"@oclif/command@^1.8.1": + version "1.8.16" + resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.16.tgz#bea46f81b2061b47e1cda318a0b923e62ca4cc0c" + integrity sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w== dependencies: - "@oclif/config" "^1.18.1" + "@oclif/config" "^1.18.2" "@oclif/errors" "^1.3.5" + "@oclif/help" "^1.0.1" "@oclif/parser" "^3.8.6" - "@oclif/plugin-help" "^3.2.10" debug "^4.1.1" semver "^7.3.2" +"@oclif/config@1.18.2": + version "1.18.2" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.2.tgz#5bfe74a9ba6a8ca3dceb314a81bd9ce2e15ebbfe" + integrity sha512-cE3qfHWv8hGRCP31j7fIS7BfCflm/BNZ2HNqHexH+fDrdF2f1D5S8VmXWLC77ffv3oDvWyvE9AZeR0RfmHCCaA== + dependencies: + "@oclif/errors" "^1.3.3" + "@oclif/parser" "^3.8.0" + debug "^4.1.1" + globby "^11.0.1" + is-wsl "^2.1.1" + tslib "^2.0.0" + "@oclif/config@^1", "@oclif/config@^1.14.0", "@oclif/config@^1.15.1", "@oclif/config@^1.17.0": version "1.17.0" resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.17.0.tgz#ba8639118633102a7e481760c50054623d09fcab" @@ -163,17 +175,17 @@ is-wsl "^2.1.1" tslib "^2.0.0" -"@oclif/config@^1.18.1": - version "1.18.1" - resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.1.tgz#81207d3682fa967bcd6981954fcfe414a29dcc77" - integrity sha512-twRJO5RRl3CCDaAASb6LiynfFQl/SbkWWOQy1l0kJZSMPysEhz+fk3BKfmlCCm451Btkp4UezHUwI1JtH+/zYg== +"@oclif/config@^1.18.2": + version "1.18.3" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.3.tgz#ddfc144fdab66b1658c2f1b3478fa7fbfd317e79" + integrity sha512-sBpko86IrTscc39EvHUhL+c++81BVTsIZ3ETu/vG+cCdi0N6vb2DoahR67A9FI2CGnxRRHjnTfa3m6LulwNATA== dependencies: - "@oclif/errors" "^1.3.3" + "@oclif/errors" "^1.3.5" "@oclif/parser" "^3.8.0" debug "^4.1.1" globby "^11.0.1" is-wsl "^2.1.1" - tslib "^2.0.0" + tslib "^2.3.1" "@oclif/dev-cli@^1": version "1.26.0" @@ -194,6 +206,17 @@ qqjs "^0.3.10" tslib "^2.0.3" +"@oclif/errors@1.3.5", "@oclif/errors@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.5.tgz#a1e9694dbeccab10fe2fe15acb7113991bed636c" + integrity sha512-OivucXPH/eLLlOT7FkCMoZXiaVYf8I/w1eTAM1+gKzfhALwWTusxEx7wBmW0uzvkSg/9ovWLycPaBgJbM3LOCQ== + dependencies: + clean-stack "^3.0.0" + fs-extra "^8.1" + indent-string "^4.0.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + "@oclif/errors@^1", "@oclif/errors@^1.2.1", "@oclif/errors@^1.2.2", "@oclif/errors@^1.3.3": version "1.3.4" resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.4.tgz#a96f94536b4e25caa72eff47e8b3ed04f6995f55" @@ -205,23 +228,27 @@ strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -"@oclif/errors@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.5.tgz#a1e9694dbeccab10fe2fe15acb7113991bed636c" - integrity sha512-OivucXPH/eLLlOT7FkCMoZXiaVYf8I/w1eTAM1+gKzfhALwWTusxEx7wBmW0uzvkSg/9ovWLycPaBgJbM3LOCQ== +"@oclif/help@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@oclif/help/-/help-1.0.1.tgz#fd96a3dd9fb2314479e6c8584c91b63754a7dff5" + integrity sha512-8rsl4RHL5+vBUAKBL6PFI3mj58hjPCp2VYyXD4TAa7IMStikFfOH2gtWmqLzIlxAED2EpD0dfYwo9JJxYsH7Aw== dependencies: - clean-stack "^3.0.0" - fs-extra "^8.1" + "@oclif/config" "1.18.2" + "@oclif/errors" "1.3.5" + chalk "^4.1.2" indent-string "^4.0.0" + lodash "^4.17.21" + string-width "^4.2.0" strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" + widest-line "^3.1.0" + wrap-ansi "^6.2.0" "@oclif/linewrap@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== -"@oclif/parser@3.8.6", "@oclif/parser@^3.8.6": +"@oclif/parser@3.8.6": version "3.8.6" resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.6.tgz#d5a108af9c708a051cc6b1d27d47359d75f41236" integrity sha512-tXb0NKgSgNxmf6baN6naK+CCwOueaFk93FG9u202U7mTBHUKsioOUlw1SG/iPi9aJM3WE4pHLXmty59pci0OEw== @@ -241,6 +268,16 @@ chalk "^2.4.2" tslib "^1.9.3" +"@oclif/parser@^3.8.6": + version "3.8.7" + resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.7.tgz#236d48db05d0b00157d3b42d31f9dac7550d2a7c" + integrity sha512-b11xBmIUK+LuuwVGJpFs4LwQN2xj2cBWj2c4z1FtiXGrJ85h9xV6q+k136Hw0tGg1jQoRXuvuBnqQ7es7vO9/Q== + dependencies: + "@oclif/errors" "^1.3.5" + "@oclif/linewrap" "^1.0.0" + chalk "^4.1.0" + tslib "^2.3.1" + "@oclif/plugin-command-snapshot@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@oclif/plugin-command-snapshot/-/plugin-command-snapshot-1.1.0.tgz#cedb336939b2a9c6b7c085c101d42ba18d910e2c" @@ -282,22 +319,6 @@ widest-line "^3.1.0" wrap-ansi "^4.0.0" -"@oclif/plugin-help@^3.2.10": - version "3.2.10" - resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.2.10.tgz#1843ac05f8cd139b575ee8b1dfc34bb500110e68" - integrity sha512-U3Jk01MTnqnd9druulNSn6nTjPEE1Rr6PWhD4rJ6Z+NjLFTKhp3S1kutWDXJQd7CQ6m8tHd1AYgsIjiR+36bSw== - dependencies: - "@oclif/command" "^1.8.6" - "@oclif/config" "^1.18.1" - "@oclif/errors" "^1.3.5" - chalk "^4.1.2" - indent-string "^4.0.0" - lodash "^4.17.21" - string-width "^4.2.0" - strip-ansi "^6.0.0" - widest-line "^3.1.0" - wrap-ansi "^6.2.0" - "@oclif/screen@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-1.0.4.tgz#b740f68609dfae8aa71c3a6cab15d816407ba493" @@ -310,6 +331,14 @@ dependencies: fancy-test "^1.4.3" +"@salesforce/apex-node@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@salesforce/apex-node/-/apex-node-0.11.0.tgz#eccb05b7ad50ab0e44de83e0627a51e16c851bab" + integrity sha512-7x3QoTcl+5zKQ/PHglBz/IdJuMO65hbzboS2uTMISrFVzeeB06sDeGcv41IfrXn1dxR7NHJm+J3FE70zCgW/7w== + dependencies: + "@salesforce/core" "^2.35.0" + faye "1.4.0" + "@salesforce/bunyan@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@salesforce/bunyan/-/bunyan-2.0.0.tgz#8dbe377f2cf7d35348a23260416fee15adba5f97" @@ -566,10 +595,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== -"@types/node@^10": - version "10.17.51" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.51.tgz#639538575befbcf3d3861f95c41de8e47124d674" - integrity sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg== +"@types/node@^14": + version "14.18.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.18.tgz#5c9503030df484ccffcbb935ea9a9e1d6fad1a20" + integrity sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig== "@types/sinon@*": version "9.0.10" @@ -1476,11 +1505,6 @@ es6-error@^4.0.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-object-assign@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= - escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1643,7 +1667,7 @@ faye-websocket@>=0.9.1: dependencies: websocket-driver ">=0.5.1" -faye@^1.4.0: +faye@1.4.0, faye@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/faye/-/faye-1.4.0.tgz#01d3d26ed5642c1cb203eed358afb1c1444b8669" integrity sha512-kRrIg4be8VNYhycS2PY//hpBJSzZPr/DBbcy9VWelhZMW3KhyLkQR0HL0k0MNpmVoNFF4EdfMFkNAWjTP65g6w== @@ -2825,7 +2849,7 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -3622,15 +3646,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.7.3: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - shelljs@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" @@ -3640,14 +3655,14 @@ shelljs@^0.8.4: interpret "^1.0.0" rechoir "^0.6.2" -shx@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/shx/-/shx-0.2.2.tgz#0a304d020b0edf1306ad81570e80f0346df58a39" - integrity sha1-CjBNAgsO3xMGrYFXDoDwNG31ijk= +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== dependencies: - es6-object-assign "^1.0.3" - minimist "^1.2.0" - shelljs "^0.7.3" + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" shx@^0.3.3: version "0.3.3" @@ -3657,6 +3672,14 @@ shx@^0.3.3: minimist "^1.2.3" shelljs "^0.8.4" +shx@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.4.tgz#74289230b4b663979167f94e1935901406e40f02" + integrity sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g== + dependencies: + minimist "^1.2.3" + shelljs "^0.8.5" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -4110,6 +4133,11 @@ tslib@^2.2.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.3.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslint-microsoft-contrib@^5: version "5.2.1" resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz#a6286839f800e2591d041ea2800c77487844ad81" @@ -4184,10 +4212,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" - integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== +typescript@4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" + integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== typescript@^3: version "3.9.7" diff --git a/yarn.lock b/yarn.lock index 59e0d12e..f8f2780f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4519,9 +4519,10 @@ node-gyp@^5.0.2, node-gyp@^5.1.0: tar "^4.4.12" which "^1.3.1" -node@12.4.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/node/-/node-12.4.0.tgz#5501bf6d5dcbf41f84a9dbf80925ae6e7c2c91ae" +node@^14.14.0: + version "14.19.1" + resolved "https://registry.yarnpkg.com/node/-/node-14.19.1.tgz#99862d5846cd9e7a1208e37ac64cc039b2ae0a77" + integrity sha512-v0l0rw07F0J9oMgiHRyI2wJegrXdNzio7FPV0vd1FahfvIz3fVU0RED0tDSeeytKn+uQX1QxgFyw9qNAaHqXHg== dependencies: node-bin-setup "^1.0.0" @@ -6421,9 +6422,10 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@3.7.5: - version "3.7.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" +typescript@4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" + integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== uglify-js@^3.1.4: version "3.10.1"