UNPKG

@codechecks/type-coverage-watcher

Version:

Track missing type coverage in TypeScript projects to ensure type safety

91 lines (90 loc) 3.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const client_1 = require("@codechecks/client"); const type_coverage_core_1 = require("type-coverage-core"); const lodash_1 = require("lodash"); const formatters_1 = require("./formatters"); async function typeCoverageWatcher(_options = {}) { const options = normalizeOptions(_options); const _typeCoverage = await type_coverage_core_1.lint(options.tsconfigPath, { debug: false, ignoreCatch: _options.ignoreCatch, ignoreFiles: _options.ignoreFiles, strict: _options.strict, }); const typeCoverage = normalizeTypeCoverage(_typeCoverage); await client_1.codechecks.saveValue(options.artifactName, typeCoverage); if (!client_1.codechecks.isPr()) { return; } const baseTypeCoverage = await client_1.codechecks.getValue(options.artifactName); const report = getReport(typeCoverage, baseTypeCoverage, options); await client_1.codechecks.report(report); } exports.typeCoverageWatcher = typeCoverageWatcher; exports.default = typeCoverageWatcher; function getReport(headTypeCoverageArtifact, baseTypeCoverageArtifact, options) { const headTypeCoverage = (headTypeCoverageArtifact.typedSymbols / headTypeCoverageArtifact.totalSymbols) * 100; const baseTypeCoverage = baseTypeCoverageArtifact ? (baseTypeCoverageArtifact.typedSymbols / baseTypeCoverageArtifact.totalSymbols) * 100 : 0; const coverageDiff = headTypeCoverage - baseTypeCoverage; const newUntypedSymbols = findNew(headTypeCoverageArtifact.allUntypedSymbols, baseTypeCoverageArtifact ? baseTypeCoverageArtifact.allUntypedSymbols : []); const shortDescription = formatters_1.formatShortDescription({ coverageDiffPerc: coverageDiff, atLeast: options.atLeast, headTypeCoveragePerc: headTypeCoverage, newUntypedSymbols: newUntypedSymbols.length, }); let longDescription = `New untyped symbols: ${newUntypedSymbols.length}`; if (newUntypedSymbols.length > 0) { longDescription += ` | File | line:character | Symbol | |:-----:|:-----:|:-----:| ${newUntypedSymbols .slice(0, 100) .map(s => `| ${s.filename} | ${s.line}:${s.character} | ${s.symbol} |`) .join("\n")}`; } const status = options.atLeast === undefined || headTypeCoverage > options.atLeast ? "success" : "failure"; return { name: options.name, status, shortDescription, longDescription, }; } function findNew(headSymbols, baseSymbols) { const baseSymbolsByFilename = lodash_1.groupBy(baseSymbols, s => s.filename); const newSymbols = []; for (const headSymbol of headSymbols) { // we assess if symbols are the same only by looking at filename and symbol name (we ignore line and character) const baseSymbolMatch = (baseSymbolsByFilename[headSymbol.filename] || []).filter(s => s.symbol === headSymbol.symbol).length > 0; if (!baseSymbolMatch) { newSymbols.push(headSymbol); } } return newSymbols; } function normalizeTypeCoverage(rawTypeCoverage) { return { typedSymbols: rawTypeCoverage.correctCount, totalSymbols: rawTypeCoverage.totalCount, allUntypedSymbols: rawTypeCoverage.anys.map(a => ({ filename: a.file, line: a.line, character: a.character, symbol: a.text, })), }; } function normalizeOptions(options = {}) { const name = options.name || "Type Coverage"; return { name, tsconfigPath: options.name || "tsconfig.json", artifactName: `type-coverage:${name}`, atLeast: options.atLeast, }; } //# sourceMappingURL=index.js.map