Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import type { PackageManagerId } from '../config.js';
import { npmPackageManager } from './npm/npm.js';
import { pnpmPackageManager } from './pnpm/pnpm.js';
import type { PackageManager } from './types.js';
import { yarnv1PackageManager } from './yarn-classic/yarn-classic.js';
import { yarnv2PackageManager } from './yarn-modern/yarn-modern.js';
import { yarnClassicPackageManager } from './yarn-classic/yarn-classic.js';
import { yarnModernPackageManager } from './yarn-modern/yarn-modern.js';

export const packageManagers: Record<PackageManagerId, PackageManager> = {
npm: npmPackageManager,
'yarn-classic': yarnv1PackageManager,
'yarn-modern': yarnv2PackageManager,
'yarn-classic': yarnClassicPackageManager,
'yarn-modern': yarnModernPackageManager,
pnpm: pnpmPackageManager,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { fromJsonLines } from '@code-pushup/utils';
import type { AuditResult, Vulnerability } from '../../runner/audit/types.js';
import { filterAuditResult } from '../../runner/utils.js';
import type {
Yarnv1AuditAdvisory,
Yarnv1AuditResultJson,
Yarnv1AuditSummary,
YarnClassicAuditAdvisory,
YarnClassicAuditResultJson,
YarnClassicAuditSummary,
} from './types.js';

export function yarnv1ToAuditResult(output: string): AuditResult {
const yarnv1Result = fromJsonLines<Yarnv1AuditResultJson>(output);
const [yarnv1Advisory, yarnv1Summary] = validateYarnv1Result(yarnv1Result);
export function yarnClassicToAuditResult(output: string): AuditResult {
const yarnResult = fromJsonLines<YarnClassicAuditResultJson>(output);
const [yarnAdvisories, yarnSummary] = validateYarnAuditResult(yarnResult);

const vulnerabilities = yarnv1Advisory.map(
const vulnerabilities = yarnAdvisories.map(
({ data: { resolution, advisory } }): Vulnerability => {
const { id, path } = resolution;
const directDependency = path.slice(0, path.indexOf('>'));
Expand Down Expand Up @@ -39,8 +39,8 @@ export function yarnv1ToAuditResult(output: string): AuditResult {
);

const summary = {
...yarnv1Summary.data.vulnerabilities,
total: Object.values(yarnv1Summary.data.vulnerabilities).reduce(
...yarnSummary.data.vulnerabilities,
total: Object.values(yarnSummary.data.vulnerabilities).reduce(
(acc, amount) => acc + amount,
0,
),
Expand All @@ -50,17 +50,15 @@ export function yarnv1ToAuditResult(output: string): AuditResult {
return filterAuditResult({ vulnerabilities, summary }, 'id');
}

function validateYarnv1Result(
result: Yarnv1AuditResultJson,
): [Yarnv1AuditAdvisory[], Yarnv1AuditSummary] {
function validateYarnAuditResult(
result: YarnClassicAuditResultJson,
): [YarnClassicAuditAdvisory[], YarnClassicAuditSummary] {
const summary = result.at(-1);
if (summary?.type !== 'auditSummary') {
throw new Error('Invalid Yarn v1 audit result - no summary found.');
}

const vulnerabilities = result.filter(
(item): item is Yarnv1AuditAdvisory => item.type === 'auditAdvisory',
);
const vulnerabilities = result.filter(item => item.type === 'auditAdvisory');

return [vulnerabilities, summary];
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { describe, expect, it } from 'vitest';
import { toJsonLines } from '@code-pushup/utils';
import type { AuditResult } from '../../runner/audit/types.js';
import { yarnv1ToAuditResult } from './audit-result.js';
import type { Yarnv1AuditAdvisory, Yarnv1AuditSummary } from './types.js';
import { yarnClassicToAuditResult } from './audit-result.js';
import type {
YarnClassicAuditAdvisory,
YarnClassicAuditSummary,
} from './types.js';

describe('yarnv1ToAuditResult', () => {
describe('yarnClassicToAuditResult', () => {
it('should transform Yarn v1 audit to unified audit result', () => {
const advisory = {
type: 'auditAdvisory',
Expand All @@ -19,7 +22,7 @@ describe('yarnv1ToAuditResult', () => {
url: 'https://github.com/advisories',
},
},
} satisfies Yarnv1AuditAdvisory;
} satisfies YarnClassicAuditAdvisory;
const summary = {
type: 'auditSummary',
data: {
Expand All @@ -31,10 +34,10 @@ describe('yarnv1ToAuditResult', () => {
info: 0,
},
},
} satisfies Yarnv1AuditSummary;
} satisfies YarnClassicAuditSummary;

expect(
yarnv1ToAuditResult(toJsonLines([advisory, summary])),
yarnClassicToAuditResult(toJsonLines([advisory, summary])),
).toEqual<AuditResult>({
vulnerabilities: [
{
Expand All @@ -57,7 +60,7 @@ describe('yarnv1ToAuditResult', () => {
data: {},
type: 'auditAdvisory',
};
expect(() => yarnv1ToAuditResult(toJsonLines([advisory]))).toThrow(
expect(() => yarnClassicToAuditResult(toJsonLines([advisory]))).toThrow(
'no summary found',
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { OutdatedDependency } from '../../runner/outdated/types.js';
import type { Yarnv1FieldName } from './types.js';
import type { YarnClassicFieldName } from './types.js';

export const outdatedtoFieldMapper: Record<
keyof OutdatedDependency,
Yarnv1FieldName
YarnClassicFieldName
> = {
name: 'Package',
current: 'Current',
Expand All @@ -12,7 +12,7 @@ export const outdatedtoFieldMapper: Record<
url: 'URL',
};

export const REQUIRED_OUTDATED_FIELDS: Yarnv1FieldName[] = [
export const REQUIRED_OUTDATED_FIELDS: YarnClassicFieldName[] = [
'Package',
'Current',
'Latest',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import {
outdatedtoFieldMapper,
} from './constants.js';
import {
type Yarnv1FieldName,
type Yarnv1OutdatedResultJson,
yarnv1FieldNames,
type YarnClassicFieldName,
type YarnClassicOutdatedResultJson,
yarnClassicFieldNames,
} from './types.js';

export function yarnv1ToOutdatedResult(output: string): OutdatedResult {
const yarnv1Outdated = fromJsonLines<Yarnv1OutdatedResultJson>(output);
const fields = yarnv1Outdated[1]?.data.head ?? [];
const dependencies = yarnv1Outdated[1]?.data.body ?? [];
export function yarnClassicToOutdatedResult(output: string): OutdatedResult {
const yarnOutdated = fromJsonLines<YarnClassicOutdatedResultJson>(output);
const fields = yarnOutdated[1]?.data.head ?? [];
const dependencies = yarnOutdated[1]?.data.body ?? [];

// no outdated dependencies
if (dependencies.length === 0) {
Expand All @@ -46,24 +46,24 @@ export function yarnv1ToOutdatedResult(output: string): OutdatedResult {
}

export function validateOutdatedFields(head: string[]) {
const relevantFields = head.filter(isYarnv1FieldName);
const relevantFields = head.filter(isYarnClassicFieldName);
if (hasAllRequiredFields(relevantFields)) {
return true;
}

throw new Error(
`Yarn v1 outdated: Template [${head.join(
', ',
)}] does not contain all required fields [${yarnv1FieldNames.join(', ')}]`,
)}] does not contain all required fields [${yarnClassicFieldNames.join(', ')}]`,
);
}

function isYarnv1FieldName(value: string): value is Yarnv1FieldName {
const names: readonly string[] = yarnv1FieldNames;
function isYarnClassicFieldName(value: string): value is YarnClassicFieldName {
const names: readonly string[] = yarnClassicFieldNames;
return names.includes(value);
}

function hasAllRequiredFields(head: Yarnv1FieldName[]) {
function hasAllRequiredFields(head: YarnClassicFieldName[]) {
return REQUIRED_OUTDATED_FIELDS.every(field => head.includes(field));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import { REQUIRED_OUTDATED_FIELDS } from './constants.js';
import {
getOutdatedFieldIndexes,
validateOutdatedFields,
yarnv1ToOutdatedResult,
yarnClassicToOutdatedResult,
} from './outdated-result.js';
import type { Yarnv1FieldName } from './types.js';
import type { YarnClassicFieldName } from './types.js';

describe('yarnv1ToOutdatedResult', () => {
describe('yarnClassicToOutdatedResult', () => {
const yarnInfo = { type: 'info', data: 'Colours' };

it('should transform Yarn v1 outdated to unified outdated result', () => {
Expand All @@ -25,13 +25,13 @@ describe('yarnv1ToOutdatedResult', () => {
'Latest',
'Package Type',
'URL',
] satisfies Yarnv1FieldName[],
] satisfies YarnClassicFieldName[],
body: [['nx', '16.8.1', '17.0.0', 'dependencies', 'https://nx.dev/']],
},
};

expect(
yarnv1ToOutdatedResult(toJsonLines([yarnInfo, table])),
yarnClassicToOutdatedResult(toJsonLines([yarnInfo, table])),
).toEqual<OutdatedResult>([
{
name: 'nx',
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('yarnv1ToOutdatedResult', () => {
};

expect(
yarnv1ToOutdatedResult(toJsonLines([yarnInfo, table])),
yarnClassicToOutdatedResult(toJsonLines([yarnInfo, table])),
).toEqual<OutdatedResult>([
{
name: 'cypress',
Expand All @@ -76,7 +76,9 @@ describe('yarnv1ToOutdatedResult', () => {
it('should transform no dependencies to empty array', () => {
const table = { type: 'table', data: { head: [], body: [] } };

expect(yarnv1ToOutdatedResult(toJsonLines([yarnInfo, table]))).toEqual([]);
expect(yarnClassicToOutdatedResult(toJsonLines([yarnInfo, table]))).toEqual(
[],
);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PackageAuditLevel } from '../../config.js';

// Subset of Yarn v1 audit JSON type
export type Yarnv1AuditAdvisory = {
export type YarnClassicAuditAdvisory = {
type: 'auditAdvisory';
data: {
resolution: {
Expand All @@ -19,36 +19,37 @@ export type Yarnv1AuditAdvisory = {
};
};

export type Yarnv1AuditSummary = {
export type YarnClassicAuditSummary = {
type: 'auditSummary';
data: {
vulnerabilities: Record<PackageAuditLevel, number>;
};
};

// NOTE: When rest operator can be at the beginning, the process will be much simpler
export type Yarnv1AuditResultJson = [
...Yarnv1AuditAdvisory[],
Yarnv1AuditSummary,
export type YarnClassicAuditResultJson = [
...YarnClassicAuditAdvisory[],
YarnClassicAuditSummary,
];

export const yarnv1FieldNames = [
export const yarnClassicFieldNames = [
'Package',
'Current',
'Latest',
'Package Type',
'URL',
] as const;

export type Yarnv1FieldName = (typeof yarnv1FieldNames)[number];
export type YarnClassicFieldName = (typeof yarnClassicFieldNames)[number];

type Yarnv1Info = { type: 'info' };
type Yarnv1Table = {
type YarnClassicInfo = { type: 'info' };
type YarnClassicTable = {
type: 'table';
data: {
head: string[];
body: string[][];
};
};

export type Yarnv1OutdatedResultJson = [Yarnv1Info, Yarnv1Table] | [];
export type YarnClassicOutdatedResultJson =
| [YarnClassicInfo, YarnClassicTable]
| [];
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { dependencyGroupToLong } from '../../constants.js';
import { COMMON_AUDIT_ARGS, COMMON_OUTDATED_ARGS } from '../constants.js';
import type { PackageManager } from '../types.js';
import { yarnv1ToAuditResult } from './audit-result.js';
import { yarnv1ToOutdatedResult } from './outdated-result.js';
import { yarnClassicToAuditResult } from './audit-result.js';
import { yarnClassicToOutdatedResult } from './outdated-result.js';

export const yarnv1PackageManager: PackageManager = {
export const yarnClassicPackageManager: PackageManager = {
slug: 'yarn-classic',
name: 'Yarn v1',
command: 'yarn',
Expand All @@ -21,10 +21,10 @@ export const yarnv1PackageManager: PackageManager = {
dependencyGroupToLong[groupDep],
],
ignoreExitCode: true,
unifyResult: yarnv1ToAuditResult,
unifyResult: yarnClassicToAuditResult,
},
outdated: {
commandArgs: COMMON_OUTDATED_ARGS,
unifyResult: yarnv1ToOutdatedResult,
unifyResult: yarnClassicToOutdatedResult,
},
};
Loading