Skip to content

Commit

Permalink
chore(plugin-js-packages): improve naming and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Tlacenka committed Mar 11, 2024
1 parent 0981748 commit 31a0c4f
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 65 deletions.
16 changes: 7 additions & 9 deletions .github/workflows/code-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ jobs:
fail-fast: false
matrix:
lib:
[
cli,
core,
models,
utils,
plugin-eslint,
plugin-coverage,
plugin-js-packages,
]
- cli
- core
- models
- utils
- plugin-eslint
- plugin-coverage
- plugin-js-packages
scope: [unit, integration]
name: Update code coverage
runs-on: ubuntu-latest
Expand Down
14 changes: 9 additions & 5 deletions packages/plugin-js-packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
📦 **Code PushUp plugin for JavaScript packages.** 🛡️

This plugin allows you to list outdated dependencies and run audit for known vulnerabilities.
It supports the following package managers: npm, yarn, yarn berry, pnpm.
It supports the following package managers:

- [NPM](https://docs.npmjs.com/)
- [Yarn v1](https://classic.yarnpkg.com/docs/) & [Yarn v2+](https://yarnpkg.com/getting-started)
- [PNPM](https://pnpm.io/pnpm-cli)

## Getting started

1. If you haven't already, install [@code-pushup/cli](../cli/README.md) and create a configuration file.

2. Insert plugin configuration. By default, npm audit and npm outdated commands will be run.
2. Insert plugin configuration. By default, `audit` and `outdated` commands will be run.

Default configuration will look as follows:

Expand All @@ -40,7 +44,7 @@ It supports the following package managers: npm, yarn, yarn berry, pnpm.
// ...
plugins: [
// ...
await jsPackagesPlugin({ packageManager: ['yarn'], features: ['audit'] }),
await jsPackagesPlugin({ packageManager: ['yarn'], checks: ['audit'] }),
],
};
```
Expand Down Expand Up @@ -78,8 +82,8 @@ It supports the following package managers: npm, yarn, yarn berry, pnpm.

The plugin accepts the following parameters:

- (optional) `packageManager`: The package manager you are using. Supported values: `npm`, `yarn` (v1), `yarn-berry` (v2+), `pnpm`. Default is `npm`.
- (optional) `features`: Array of commands to be run. Supported commands: `audit`, `outdated`. Both are configured by default.
- (optional) `packageManager`: The package manager you are using. Supported values: `npm`, `yarn-classic` (v1), `yarn-modern` (v2+), `pnpm`. Default is `npm`.
- (optional) `checks`: Array of checks to be run. Supported commands: `audit`, `outdated`. Both are configured by default.
- (optional) `auditLevelMapping`: If you wish to set a custom level of issue severity based on audit vulnerability level, you may do so here. Any omitted values will be filled in by defaults. Audit levels are: `critical`, `high`, `moderate`, `low` and `info`. Issue severities are: `error`, `warn` and `info`. By default the mapping is as follows: `critical` and `high``error`; `moderate` and `low``warning`; `info``info`.

> [!NOTE]
Expand Down
27 changes: 7 additions & 20 deletions packages/plugin-js-packages/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { IssueSeverity, issueSeveritySchema } from '@code-pushup/models';
const packageCommandSchema = z.enum(['audit', 'outdated']);
export type PackageCommand = z.infer<typeof packageCommandSchema>;

const packageManagerSchema = z.enum(['npm', 'yarn', 'yarn-berry', 'pnpm']);
const packageManagerSchema = z.enum([
'npm',
'yarn-classic',
'yarn-modern',
'pnpm',
]);
export type PackageManager = z.infer<typeof packageManagerSchema>;

const packageAuditLevelSchema = z.enum([
Expand Down Expand Up @@ -36,26 +41,8 @@ export function fillAuditLevelMapping(
};
}

// TODO how?
// export function objectKeys<T extends object>(obj: T): (keyof T)[] {
// return Object.keys(obj) as (keyof T)[];
// }

// function newFillAuditLevelMapping(
// mapping: Partial<Record<PackageAuditLevel, IssueSeverity>>,
// ): Record<PackageAuditLevel, IssueSeverity> {
// return Object.fromEntries(
// objectKeys(defaultAuditLevelMapping).map<
// [PackageAuditLevel, IssueSeverity]
// >(auditLevel => [
// auditLevel,
// mapping[auditLevel] ?? defaultAuditLevelMapping[auditLevel],
// ]),
// );
// }

export const jsPackagesPluginConfigSchema = z.object({
features: z
checks: z
.array(packageCommandSchema, {
description:
'Package manager commands to be run. Defaults to both audit and outdated.',
Expand Down
10 changes: 5 additions & 5 deletions packages/plugin-js-packages/src/lib/config.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ describe('jsPackagesPluginConfigSchema', () => {
expect(() =>
jsPackagesPluginConfigSchema.parse({
auditLevelMapping: { moderate: 'error' },
features: ['audit'],
packageManager: 'yarn',
checks: ['audit'],
packageManager: 'yarn-classic',
} satisfies JSPackagesPluginConfig),
).not.toThrow();
});
Expand All @@ -26,7 +26,7 @@ describe('jsPackagesPluginConfigSchema', () => {
it('should fill in default values', () => {
const config = jsPackagesPluginConfigSchema.parse({});
expect(config).toEqual<FinalJSPackagesPluginConfig>({
features: ['audit', 'outdated'],
checks: ['audit', 'outdated'],
packageManager: 'npm',
auditLevelMapping: {
critical: 'error',
Expand All @@ -38,8 +38,8 @@ describe('jsPackagesPluginConfigSchema', () => {
});
});

it('should throw for no features', () => {
expect(() => jsPackagesPluginConfigSchema.parse({ features: [] })).toThrow(
it('should throw for no passed commands', () => {
expect(() => jsPackagesPluginConfigSchema.parse({ checks: [] })).toThrow(
'too_small',
);
});
Expand Down
31 changes: 18 additions & 13 deletions packages/plugin-js-packages/src/lib/js-packages-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
jsPackagesPluginConfigSchema,
} from './config';
import { createRunnerConfig } from './runner';
import { auditDocs, outdatedDocs, pkgManagerDocs } from './utils';
import {
auditDocs,
outdatedDocs,
pkgManagerDocs,
pkgManagerIcons,
pkgManagerNames,
} from './utils';

/**
* Instantiates Code PushUp JS packages plugin for core config.
Expand All @@ -31,7 +37,7 @@ export async function jsPackagesPlugin(
): Promise<PluginConfig> {
const jsPackagesPluginConfig = jsPackagesPluginConfigSchema.parse(config);
const pkgManager = jsPackagesPluginConfig.packageManager;
const features = [...new Set(jsPackagesPluginConfig.features)];
const checks = [...new Set(jsPackagesPluginConfig.checks)];

const runnerScriptPath = join(
fileURLToPath(dirname(import.meta.url)),
Expand All @@ -41,40 +47,39 @@ export async function jsPackagesPlugin(
const audits: Record<PackageCommand, Audit> = {
audit: {
slug: `${pkgManager}-audit`,
title: `${pkgManager} audit`,
description: `Lists ${pkgManager} audit vulnerabilities.`,
title: `${pkgManagerNames[pkgManager]} audit`,
description: `Lists ${pkgManagerNames[pkgManager]} audit vulnerabilities.`,
docsUrl: auditDocs[pkgManager],
},
outdated: {
slug: `${pkgManager}-outdated`,
title: `${pkgManager} outdated dependencies`,
description: `Lists ${pkgManager} outdated dependencies.`,
title: `${pkgManagerNames[pkgManager]} outdated dependencies`,
description: `Lists ${pkgManagerNames[pkgManager]} outdated dependencies.`,
docsUrl: outdatedDocs[pkgManager],
},
};

const group: Group = {
slug: `${pkgManager}-package-manager`,
title: `${pkgManager} package manager`,
description: `Group containing both audit and dependencies command audits for the ${pkgManager} package manager.`,
title: `${pkgManagerNames[pkgManager]} package manager`,
description: `Group containing both audit and dependencies command audits for the ${pkgManagerNames[pkgManager]} package manager.`,
docsUrl: pkgManagerDocs[pkgManager],
refs: features.map(feature => ({
slug: `${pkgManager}-${feature}`,
refs: checks.map(check => ({
slug: `${pkgManager}-${check}`,
weight: 1,
})),
};

return {
slug: 'js-packages',
title: 'Plugin for JS packages',
icon:
pkgManager === 'npm' ? 'npm' : pkgManager === 'pnpm' ? 'pnpm' : 'yarn',
icon: pkgManagerIcons[pkgManager],
description:
'This plugin runs audit to uncover vulnerabilities and lists outdated dependencies. It supports npm, yarn classic and berry, pnpm package managers.',
docsUrl: pkgManagerDocs[pkgManager],
packageName: name,
version,
audits: features.map(feature => audits[feature]),
audits: checks.map(check => audits[check]),
groups: [group],
runner: await createRunnerConfig(runnerScriptPath, jsPackagesPluginConfig),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ vi.mock('./runner/index.ts', () => ({
describe('jsPackagesPlugin', () => {
it('should initialise a JS packages plugin', async () => {
await expect(
jsPackagesPlugin({ packageManager: 'npm', features: ['outdated'] }),
jsPackagesPlugin({ packageManager: 'npm', checks: ['outdated'] }),
).resolves.toStrictEqual(
expect.objectContaining({
slug: 'js-packages',
Expand All @@ -26,14 +26,14 @@ describe('jsPackagesPlugin', () => {

it('should set package manager and commands based on configuration', async () => {
await expect(
jsPackagesPlugin({ packageManager: 'yarn', features: ['audit'] }),
jsPackagesPlugin({ packageManager: 'yarn-classic', checks: ['audit'] }),
).resolves.toStrictEqual(
expect.objectContaining({
audits: [expect.objectContaining({ slug: 'yarn-audit' })],
audits: [expect.objectContaining({ slug: 'yarn-classic-audit' })],
groups: [
expect.objectContaining<Partial<Group>>({
slug: 'yarn-package-manager',
refs: [{ slug: 'yarn-audit', weight: 1 }],
slug: 'yarn-classic-package-manager',
refs: [{ slug: 'yarn-classic-audit', weight: 1 }],
}),
],
}),
Expand Down
31 changes: 23 additions & 8 deletions packages/plugin-js-packages/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
import { MaterialIcon } from '@code-pushup/models';
import { PackageManager } from './config';

export const pkgManagerNames: Record<PackageManager, string> = {
npm: 'NPM',
'yarn-classic': 'Yarn v1',
'yarn-modern': 'Yarn v2+',
pnpm: 'PNPM',
};

export const pkgManagerIcons: Record<PackageManager, MaterialIcon> = {
npm: 'npm',
'yarn-classic': 'yarn',
'yarn-modern': 'yarn',
pnpm: 'pnpm',
};

export const pkgManagerDocs: Record<PackageManager, string> = {
npm: 'https://docs.npmjs.com/',
yarn: 'https://classic.yarnpkg.com/lang/en/docs/',
'yarn-berry': 'https://yarnpkg.com/getting-started',
'yarn-classic': 'https://classic.yarnpkg.com/docs/',
'yarn-modern': 'https://yarnpkg.com/getting-started',
pnpm: 'https://pnpm.io/pnpm-cli',
};
export const auditDocs: Record<PackageManager, string> = {
npm: 'https://docs.npmjs.com/cli/v10/commands/npm-audit',
yarn: 'https://classic.yarnpkg.com/en/docs/cli/audit',
'yarn-berry': 'https://yarnpkg.com/cli/npm/audit',
npm: 'https://docs.npmjs.com/cli/commands/npm-audit',
'yarn-classic': 'https://classic.yarnpkg.com/docs/cli/audit',
'yarn-modern': 'https://yarnpkg.com/cli/npm/audit',
pnpm: 'https://pnpm.io/',
};

export const outdatedDocs: Record<PackageManager, string> = {
npm: 'https://docs.npmjs.com/cli/v10/commands/npm-outdated',
yarn: 'https://classic.yarnpkg.com/lang/en/docs/cli/outdated/',
'yarn-berry': 'https://github.com/mskelton/yarn-plugin-outdated',
npm: 'https://docs.npmjs.com/cli/commands/npm-outdated',
'yarn-classic': 'https://classic.yarnpkg.com/docs/cli/outdated/',
'yarn-modern': 'https://github.com/mskelton/yarn-plugin-outdated',
pnpm: 'https://pnpm.io/cli/outdated',
};

0 comments on commit 31a0c4f

Please sign in to comment.