Skip to content

Commit 53384e0

Browse files
committed
feat(plugin-typescript): log initializer and runner steps
1 parent 34247f5 commit 53384e0

File tree

11 files changed

+147
-80
lines changed

11 files changed

+147
-80
lines changed

packages/plugin-typescript/src/lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { TS_CODE_RANGE_NAMES } from './runner/ts-error-codes.js';
44
import type { AuditSlug } from './types.js';
55

66
export const TYPESCRIPT_PLUGIN_SLUG = 'typescript';
7+
export const TYPESCRIPT_PLUGIN_TITLE = 'TypeScript';
8+
79
export const DEFAULT_TS_CONFIG = 'tsconfig.json';
810

911
const AUDIT_DESCRIPTIONS: Record<AuditSlug, string> = {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { pluginMetaLogFormatter } from '@code-pushup/utils';
2+
import { TYPESCRIPT_PLUGIN_TITLE } from './constants.js';
3+
4+
export const formatMetaLog = pluginMetaLogFormatter(TYPESCRIPT_PLUGIN_TITLE);

packages/plugin-typescript/src/lib/runner/runner.int.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect } from 'vitest';
2-
import type { AuditOutputs } from '@code-pushup/models';
2+
import { type AuditOutputs, DEFAULT_PERSIST_CONFIG } from '@code-pushup/models';
33
import { osAgnosticAuditOutputs } from '@code-pushup/test-utils';
44
import { getAudits } from '../utils.js';
55
import { createRunnerFunction } from './runner.js';
@@ -12,7 +12,7 @@ describe('createRunnerFunction', () => {
1212
expectedAudits: getAudits(),
1313
});
1414

15-
const result = await runnerFunction();
15+
const result = await runnerFunction({ persist: DEFAULT_PERSIST_CONFIG });
1616

1717
expect(osAgnosticAuditOutputs(result as AuditOutputs)).toMatchSnapshot();
1818
}, 35_000);

packages/plugin-typescript/src/lib/runner/runner.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import type {
44
Issue,
55
RunnerFunction,
66
} from '@code-pushup/models';
7-
import { pluralizeToken } from '@code-pushup/utils';
7+
import {
8+
formatAsciiTable,
9+
logger,
10+
pluralizeToken,
11+
toSentenceCase,
12+
} from '@code-pushup/utils';
813
import type { AuditSlug } from '../types.js';
914
import {
1015
type DiagnosticsOptions,
@@ -19,8 +24,10 @@ export type RunnerOptions = DiagnosticsOptions & {
1924

2025
export function createRunnerFunction(options: RunnerOptions): RunnerFunction {
2126
const { tsconfig, expectedAudits } = options;
22-
return async (): Promise<AuditOutputs> => {
23-
const diagnostics = await getTypeScriptDiagnostics({ tsconfig });
27+
28+
return (): AuditOutputs => {
29+
const diagnostics = getTypeScriptDiagnostics({ tsconfig });
30+
2431
const result = diagnostics.reduce<
2532
Partial<Record<CodeRangeName, Pick<AuditOutput, 'slug' | 'details'>>>
2633
>((acc, diag) => {
@@ -37,6 +44,19 @@ export function createRunnerFunction(options: RunnerOptions): RunnerFunction {
3744
};
3845
}, {});
3946

47+
logger.debug(
48+
formatAsciiTable(
49+
{
50+
columns: ['left', 'right'],
51+
rows: Object.values(result).map(audit => [
52+
`• ${toSentenceCase(audit.slug)}`,
53+
audit.details?.issues?.length ?? 0,
54+
]),
55+
},
56+
{ borderless: true },
57+
),
58+
);
59+
4060
return expectedAudits.map(({ slug }): AuditOutput => {
4161
const { details } = result[slug] ?? {};
4262

packages/plugin-typescript/src/lib/runner/runner.unit.test.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
type SourceFile,
55
} from 'typescript';
66
import { beforeEach, describe, expect } from 'vitest';
7-
import { auditOutputsSchema } from '@code-pushup/models';
7+
import {
8+
DEFAULT_PERSIST_CONFIG,
9+
type RunnerArgs,
10+
auditOutputsSchema,
11+
} from '@code-pushup/models';
812
import { createRunnerFunction } from './runner.js';
913
import * as runnerModule from './ts-runner.js';
1014
import * as utilsModule from './utils.js';
@@ -20,6 +24,8 @@ describe('createRunnerFunction', () => {
2024
'getIssueFromDiagnostic',
2125
);
2226

27+
const runnerArgs: RunnerArgs = { persist: DEFAULT_PERSIST_CONFIG };
28+
2329
const semanticTsCode = 2322;
2430
const mockSemanticDiagnostic = {
2531
code: semanticTsCode, // "Type 'string' is not assignable to type 'number'"
@@ -47,51 +53,51 @@ describe('createRunnerFunction', () => {
4753
getTypeScriptDiagnosticsSpy.mockReset();
4854
});
4955

50-
it('should return empty array if no diagnostics are found', async () => {
51-
getTypeScriptDiagnosticsSpy.mockResolvedValue([]);
56+
it('should return empty array if no diagnostics are found', () => {
57+
getTypeScriptDiagnosticsSpy.mockReturnValue([]);
5258
const runner = createRunnerFunction({
5359
tsconfig: 'tsconfig.json',
5460
expectedAudits: [],
5561
});
56-
await expect(runner(() => void 0)).resolves.toStrictEqual([]);
62+
expect(runner(runnerArgs)).toStrictEqual([]);
5763
});
5864

59-
it('should return empty array if no supported diagnostics are found', async () => {
60-
getTypeScriptDiagnosticsSpy.mockResolvedValue([mockSemanticDiagnostic]);
65+
it('should return empty array if no supported diagnostics are found', () => {
66+
getTypeScriptDiagnosticsSpy.mockReturnValue([mockSemanticDiagnostic]);
6167
const runner = createRunnerFunction({
6268
tsconfig: 'tsconfig.json',
6369
expectedAudits: [],
6470
});
65-
await expect(runner(() => void 0)).resolves.toStrictEqual([]);
71+
expect(runner(runnerArgs)).toStrictEqual([]);
6672
});
6773

68-
it('should pass the diagnostic code to tsCodeToSlug', async () => {
69-
getTypeScriptDiagnosticsSpy.mockResolvedValue([mockSemanticDiagnostic]);
74+
it('should pass the diagnostic code to tsCodeToSlug', () => {
75+
getTypeScriptDiagnosticsSpy.mockReturnValue([mockSemanticDiagnostic]);
7076
const runner = createRunnerFunction({
7177
tsconfig: 'tsconfig.json',
7278
expectedAudits: [],
7379
});
74-
await expect(runner(() => void 0)).resolves.toStrictEqual([]);
80+
expect(runner(runnerArgs)).toStrictEqual([]);
7581
expect(tSCodeToAuditSlugSpy).toHaveBeenCalledTimes(1);
7682
expect(tSCodeToAuditSlugSpy).toHaveBeenCalledWith(semanticTsCode);
7783
});
7884

79-
it('should pass the diagnostic to getIssueFromDiagnostic', async () => {
80-
getTypeScriptDiagnosticsSpy.mockResolvedValue([mockSemanticDiagnostic]);
85+
it('should pass the diagnostic to getIssueFromDiagnostic', () => {
86+
getTypeScriptDiagnosticsSpy.mockReturnValue([mockSemanticDiagnostic]);
8187
const runner = createRunnerFunction({
8288
tsconfig: 'tsconfig.json',
8389
expectedAudits: [],
8490
});
85-
await expect(runner(() => void 0)).resolves.toStrictEqual([]);
91+
expect(runner(runnerArgs)).toStrictEqual([]);
8692
expect(getIssueFromDiagnosticSpy).toHaveBeenCalledTimes(1);
8793
expect(getIssueFromDiagnosticSpy).toHaveBeenCalledWith(
8894
mockSemanticDiagnostic,
8995
);
9096
});
9197

92-
it('should return multiple issues per audit', async () => {
98+
it('should return multiple issues per audit', () => {
9399
const code = 2222;
94-
getTypeScriptDiagnosticsSpy.mockResolvedValue([
100+
getTypeScriptDiagnosticsSpy.mockReturnValue([
95101
mockSemanticDiagnostic,
96102
{
97103
...mockSemanticDiagnostic,
@@ -104,7 +110,7 @@ describe('createRunnerFunction', () => {
104110
expectedAudits: [{ slug: 'semantic-errors' }],
105111
});
106112

107-
const auditOutputs = await runner(() => void 0);
113+
const auditOutputs = runner(runnerArgs);
108114
expect(auditOutputs).toStrictEqual([
109115
{
110116
slug: 'semantic-errors',
@@ -126,8 +132,8 @@ describe('createRunnerFunction', () => {
126132
expect(() => auditOutputsSchema.parse(auditOutputs)).not.toThrow();
127133
});
128134

129-
it('should return multiple audits', async () => {
130-
getTypeScriptDiagnosticsSpy.mockResolvedValue([
135+
it('should return multiple audits', () => {
136+
getTypeScriptDiagnosticsSpy.mockReturnValue([
131137
mockSyntacticDiagnostic,
132138
mockSemanticDiagnostic,
133139
]);
@@ -136,7 +142,7 @@ describe('createRunnerFunction', () => {
136142
expectedAudits: [{ slug: 'semantic-errors' }, { slug: 'syntax-errors' }],
137143
});
138144

139-
const auditOutputs = await runner(() => void 0);
145+
const auditOutputs = runner(runnerArgs);
140146
expect(auditOutputs).toStrictEqual([
141147
expect.objectContaining({
142148
slug: 'semantic-errors',
@@ -159,8 +165,8 @@ describe('createRunnerFunction', () => {
159165
]);
160166
});
161167

162-
it('should return valid AuditOutput shape', async () => {
163-
getTypeScriptDiagnosticsSpy.mockResolvedValue([
168+
it('should return valid AuditOutput shape', () => {
169+
getTypeScriptDiagnosticsSpy.mockReturnValue([
164170
mockSyntacticDiagnostic,
165171
{
166172
...mockSyntacticDiagnostic,
@@ -178,7 +184,7 @@ describe('createRunnerFunction', () => {
178184
tsconfig: 'tsconfig.json',
179185
expectedAudits: [{ slug: 'semantic-errors' }, { slug: 'syntax-errors' }],
180186
});
181-
const auditOutputs = await runner(() => void 0);
187+
const auditOutputs = runner(runnerArgs);
182188
expect(() => auditOutputsSchema.parse(auditOutputs)).not.toThrow();
183189
});
184190
});

packages/plugin-typescript/src/lib/runner/ts-runner.int.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import { describe, expect } from 'vitest';
22
import { getTypeScriptDiagnostics } from './ts-runner.js';
33

44
describe('getTypeScriptDiagnostics', () => {
5-
it('should return valid diagnostics', async () => {
6-
await expect(
5+
it('should return valid diagnostics', () => {
6+
expect(
77
getTypeScriptDiagnostics({
88
tsconfig:
99
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.json',
1010
}),
11-
).resolves.toHaveLength(8);
11+
).toHaveLength(8);
1212
});
1313
});

packages/plugin-typescript/src/lib/runner/ts-runner.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,30 @@ import {
33
createProgram,
44
getPreEmitDiagnostics,
55
} from 'typescript';
6-
import { stringifyError } from '@code-pushup/utils';
6+
import { logger, pluralizeToken, stringifyError } from '@code-pushup/utils';
77
import { loadTargetConfig } from './utils.js';
88

99
export type DiagnosticsOptions = {
1010
tsconfig: string;
1111
};
1212

13-
export async function getTypeScriptDiagnostics({
13+
export function getTypeScriptDiagnostics({
1414
tsconfig,
15-
}: DiagnosticsOptions): Promise<readonly Diagnostic[]> {
15+
}: DiagnosticsOptions): readonly Diagnostic[] {
1616
const { fileNames, options } = loadTargetConfig(tsconfig);
17+
logger.info(
18+
`Parsed TypeScript config file ${tsconfig}, program includes ${pluralizeToken('file', fileNames.length)}`,
19+
);
1720
try {
1821
const program = createProgram(fileNames, options);
19-
return getPreEmitDiagnostics(program);
22+
const diagnostics = getPreEmitDiagnostics(program);
23+
logger.info(
24+
`TypeScript compiler found ${pluralizeToken('diagnostic', diagnostics.length)}`,
25+
);
26+
return diagnostics;
2027
} catch (error) {
2128
throw new Error(
22-
`Can't create TS program in getDiagnostics. \n ${stringifyError(error)}`,
29+
`Can't create TS program and get diagnostics.\n${stringifyError(error)}`,
2330
);
2431
}
2532
}

packages/plugin-typescript/src/lib/runner/utils.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type { CodeRangeName } from './types.js';
1414

1515
/**
1616
* Transform the TypeScript error code to the audit slug.
17-
* @param code - The TypeScript error code.
17+
* @param code The TypeScript error code.
1818
* @returns The audit slug.
1919
* @throws Error if the code is not supported.
2020
*/
@@ -31,7 +31,7 @@ export function tsCodeToAuditSlug(code: number): CodeRangeName {
3131
* - ts.DiagnosticCategory.Error (2)
3232
* - ts.DiagnosticCategory.Suggestion (3)
3333
* - ts.DiagnosticCategory.Message (4)
34-
* @param category - The TypeScript diagnostic category.
34+
* @param category The TypeScript diagnostic category.
3535
* @returns The severity of the issue.
3636
*/
3737
export function getSeverity(category: DiagnosticCategory): Issue['severity'] {
@@ -47,7 +47,7 @@ export function getSeverity(category: DiagnosticCategory): Issue['severity'] {
4747

4848
/**
4949
* Format issue message from the TypeScript diagnostic.
50-
* @param diag - The TypeScript diagnostic.
50+
* @param diag The TypeScript diagnostic.
5151
* @returns The issue message.
5252
*/
5353
export function getMessage(diag: Diagnostic): string {
@@ -60,7 +60,7 @@ export function getMessage(diag: Diagnostic): string {
6060

6161
/**
6262
* Get the issue from the TypeScript diagnostic.
63-
* @param diag - The TypeScript diagnostic.
63+
* @param diag The TypeScript diagnostic.
6464
* @returns The issue.
6565
* @throws Error if the diagnostic is global (e.g., invalid compiler option).
6666
*/
@@ -84,13 +84,7 @@ export function getIssueFromDiagnostic(diag: Diagnostic) {
8484
...issue,
8585
source: {
8686
file: path.relative(process.cwd(), diag.file.fileName),
87-
...(startLine
88-
? {
89-
position: {
90-
startLine,
91-
},
92-
}
93-
: {}),
87+
...(startLine ? { position: { startLine } } : {}),
9488
},
9589
} satisfies Issue;
9690
}

packages/plugin-typescript/src/lib/typescript-plugin.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { createRequire } from 'node:module';
22
import { type PluginConfig, validate } from '@code-pushup/models';
33
import { stringifyError } from '@code-pushup/utils';
4-
import { DEFAULT_TS_CONFIG, TYPESCRIPT_PLUGIN_SLUG } from './constants.js';
4+
import {
5+
DEFAULT_TS_CONFIG,
6+
TYPESCRIPT_PLUGIN_SLUG,
7+
TYPESCRIPT_PLUGIN_TITLE,
8+
} from './constants.js';
59
import { createRunnerFunction } from './runner/runner.js';
610
import {
711
type TypescriptPluginConfig,
812
type TypescriptPluginOptions,
913
typescriptPluginConfigSchema,
1014
} from './schema.js';
11-
import { getAudits, getGroups, logSkippedAudits } from './utils.js';
15+
import { getAudits, getGroups, logAuditsAndGroups } from './utils.js';
1216

1317
const packageJson = createRequire(import.meta.url)(
1418
'../../package.json',
@@ -23,24 +27,24 @@ export function typescriptPlugin(
2327
scoreTargets,
2428
} = parseOptions(options ?? {});
2529

26-
const filteredAudits = getAudits({ onlyAudits });
27-
const filteredGroups = getGroups({ onlyAudits });
30+
const audits = getAudits({ onlyAudits });
31+
const groups = getGroups({ onlyAudits });
2832

29-
logSkippedAudits(filteredAudits);
33+
logAuditsAndGroups(audits, groups);
3034

3135
return {
3236
slug: TYPESCRIPT_PLUGIN_SLUG,
33-
packageName: packageJson.name,
34-
version: packageJson.version,
35-
title: 'TypeScript',
37+
title: TYPESCRIPT_PLUGIN_TITLE,
38+
icon: 'typescript',
3639
description: 'Official Code PushUp TypeScript plugin.',
3740
docsUrl: 'https://www.npmjs.com/package/@code-pushup/typescript-plugin/',
38-
icon: 'typescript',
39-
audits: filteredAudits,
40-
groups: filteredGroups,
41+
packageName: packageJson.name,
42+
version: packageJson.version,
43+
audits,
44+
groups,
4145
runner: createRunnerFunction({
4246
tsconfig,
43-
expectedAudits: filteredAudits,
47+
expectedAudits: audits,
4448
}),
4549
...(scoreTargets && { scoreTargets }),
4650
};

0 commit comments

Comments
 (0)