Skip to content

Commit

Permalink
Add --preprocessor argument + support multiple reporters (resolves #204)
Browse files Browse the repository at this point in the history
  • Loading branch information
webpro committed Aug 30, 2023
1 parent 7011a51 commit 298245e
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,8 @@ for false positives, and how to handle them.
--exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
--include-entry-exports Include entry files when reporting unused exports
-n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
--reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
--preprocessor Preprocess the results before providing it to the reporter(s), can be repeated
--reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)
--reporter-options Pass extra options to the reporter (as JSON string, see example)
--no-config-hints Suppress configuration hints
--no-exit-code Always exit with code zero (0)
Expand Down
5 changes: 5 additions & 0 deletions fixtures/preprocessors/identity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ReporterOptions } from '../../src/types/issues';

export default function identity(value: ReporterOptions): ReporterOptions {
return value;
}
11 changes: 11 additions & 0 deletions fixtures/preprocessors/minimal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Preprocessor } from '../../src/types/issues';

const minimal: Preprocessor = value => ({
...value,
issues: {
...value.issues,
files: new Set([...value.issues.files, import.meta.url]),
},
});

export default minimal;
17 changes: 17 additions & 0 deletions fixtures/reporters/minimal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ReporterOptions, IssueSet, IssueRecords } from '../../src/types/issues.js';
import type { Entries } from 'type-fest';

export default ({ report, issues }: ReporterOptions) => {
for (const [reportType, isReportType] of Object.entries(report) as Entries<typeof report>) {
if (isReportType) {
const isSet = issues[reportType] instanceof Set;
const issuesForType = isSet
? Array.from(issues[reportType] as IssueSet)
: reportType === 'duplicates'
? Object.values(issues[reportType]).map(Object.values).flat()
: Object.values(issues[reportType] as IssueRecords);

console.log(reportType, issuesForType.length);
}
}
};
29 changes: 22 additions & 7 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import './util/register.js';
import prettyMilliseconds from 'pretty-ms';
import reporters from './reporters/index.js';
import internalReporters from './reporters/index.js';
import parsedArgValues, { helpText } from './util/cli-arguments.js';
import { isKnownError, getKnownError, isConfigurationError, hasCause } from './util/errors.js';
import { _load } from './util/loader.js';
import { cwd, resolve } from './util/path.js';
import { Performance } from './util/Performance.js';
import { version } from './version.js';
import { main } from './index.js';
import type { IssueType } from './types/issues.js';
import type { ReporterOptions, IssueType } from './types/issues.js';

const {
debug: isDebug = false,
Expand All @@ -24,7 +24,8 @@ const {
'include-entry-exports': isIncludeEntryExports = false,
performance: isObservePerf = false,
production: isProduction = false,
reporter = 'symbols',
preprocessor = [],
reporter = ['symbols'],
'reporter-options': reporterOptions = '',
strict: isStrict = false,
tsConfig,
Expand All @@ -44,8 +45,18 @@ if (isVersion) {
const isShowProgress =
!isDebug && isNoProgress === false && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function';

const printReport =
reporter in reporters ? reporters[reporter as keyof typeof reporters] : await _load(resolve(reporter));
const preprocessors = await Promise.all(preprocessor.map(processor => _load(resolve(processor))));

const processAsync = (data: ReporterOptions, processors: typeof preprocessors): Promise<ReporterOptions> =>
processors.length === 0 ? Promise.resolve(data) : processAsync(processors[0](data), processors.slice(1));

const reporters = await Promise.all(
reporter.map(async reporter => {
return reporter in internalReporters
? internalReporters[reporter as keyof typeof internalReporters]
: await _load(resolve(reporter));
})
);

const run = async () => {
try {
Expand All @@ -62,7 +73,7 @@ const run = async () => {
isIncludeEntryExports,
});

await printReport({
const initialData: ReporterOptions = {
report,
issues,
configurationHints,
Expand All @@ -71,7 +82,11 @@ const run = async () => {
isProduction,
isShowProgress,
options: reporterOptions,
});
};

const finalData = await processAsync(initialData, preprocessors);

for (const reporter of reporters) await reporter(finalData);

const totalErrorCount = (Object.keys(report) as IssueType[])
.filter(reportGroup => report[reportGroup] && rules[reportGroup] === 'error')
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type HandleReferencedDependencyOptions = {
};

export type { RawConfiguration as KnipConfig } from './types/config.js';
export type { Reporter, ReporterOptions } from './types/issues.js';
export type { Preprocessor, Reporter, ReporterOptions } from './types/issues.js';

export const main = async (unresolvedConfiguration: CommandLineOptions) => {
const {
Expand Down
3 changes: 2 additions & 1 deletion src/types/issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ export type ReporterOptions = {
configurationHints: ConfigurationHints;
noConfigHints: boolean;
cwd: string;
workingDir: string;
isProduction: boolean;
isShowProgress: boolean;
options: string;
};

export type Reporter = (options: ReporterOptions) => void;

export type Preprocessor = (options: ReporterOptions) => ReporterOptions;

export type IssueSeverity = 'error' | 'warn' | 'off';

export type Rules = Record<IssueType, IssueSeverity>;
Expand Down
6 changes: 4 additions & 2 deletions src/util/cli-arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Options:
--exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
--include-entry-exports Include entry files when reporting unused exports
-n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
--reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
--preprocessor Preprocess the results before providing it to the reporter(s), can be repeated
--reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)
--reporter-options Pass extra options to the reporter (as JSON string, see example)
--no-config-hints Suppress configuration hints
--no-exit-code Always exit with code zero (0)
Expand Down Expand Up @@ -63,7 +64,8 @@ try {
'no-progress': { type: 'boolean', short: 'n' },
performance: { type: 'boolean' },
production: { type: 'boolean' },
reporter: { type: 'string' },
preprocessor: { type: 'string', multiple: true },
reporter: { type: 'string', multiple: true },
'reporter-options': { type: 'string' },
strict: { type: 'boolean' },
tsConfig: { type: 'string', short: 't' },
Expand Down

0 comments on commit 298245e

Please sign in to comment.