Skip to content

Commit b0c08a4

Browse files
Merge pull request #10 from barrymichaeldoyle/feat/ignore-peer-deps
feat: added ignore peer deps flag
2 parents 216db1d + 81f8cac commit b0c08a4

12 files changed

Lines changed: 156 additions & 11 deletions

File tree

packages/cli/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# patch-pulse
22

3+
## 4.1.0
4+
5+
### Minor Changes
6+
7+
- Add `--no-peer-deps` CLI flag and `ignorePeerDeps` config option to exclude `peerDependencies` from the scan. Useful for published libraries where peer dep ranges are intentionally broad and not something you manage directly.
8+
39
## 4.0.4
410

511
### Patch Changes

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "patch-pulse",
3-
"version": "4.0.4",
3+
"version": "4.1.0",
44
"description": "Check for outdated npm dependencies",
55
"type": "module",
66
"bin": {

packages/cli/src/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const VALID_FLAGS = [
6060
'--hide-clean',
6161
'--expand',
6262
'--fail',
63+
'--no-peer-deps',
6364
];
6465

6566
export async function runCli({
@@ -205,6 +206,10 @@ export async function runCli({
205206
}
206207

207208
for (const key of PACKAGE_JSON_DEPENDENCY_FIELDS) {
209+
if (key === 'peerDependencies' && config.ignorePeerDeps) {
210+
continue;
211+
}
212+
208213
const value = project.sections[key];
209214
if (!value) {
210215
continue;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
// Auto-generated file - do not edit manually
2-
export const VERSION = '4.0.4';
2+
export const VERSION = '4.1.0';

packages/cli/src/services/config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface PatchPulseConfig {
99
includePaths?: string[];
1010
packageManager?: PackageManager;
1111
interactive?: boolean;
12+
ignorePeerDeps?: boolean;
1213
}
1314

1415
/**
@@ -95,6 +96,11 @@ export function parseCliConfig(args: string[]): PatchPulseConfig {
9596
config.interactive = false;
9697
}
9798

99+
// Parse ignorePeerDeps flag
100+
if (args.includes('--no-peer-deps')) {
101+
config.ignorePeerDeps = true;
102+
}
103+
98104
return config;
99105
}
100106

@@ -160,6 +166,13 @@ export function mergeConfigs(
160166
merged.interactive = fileConfig.interactive;
161167
}
162168

169+
// Handle ignorePeerDeps (CLI takes precedence)
170+
if (cliConfig.ignorePeerDeps !== undefined) {
171+
merged.ignorePeerDeps = cliConfig.ignorePeerDeps;
172+
} else if (fileConfig?.ignorePeerDeps !== undefined) {
173+
merged.ignorePeerDeps = fileConfig.ignorePeerDeps;
174+
}
175+
163176
return merged;
164177
}
165178

@@ -200,6 +213,10 @@ function validateConfig(config: any): PatchPulseConfig {
200213
validated.interactive = config.interactive;
201214
}
202215

216+
if (typeof config.ignorePeerDeps === 'boolean') {
217+
validated.ignorePeerDeps = config.ignorePeerDeps;
218+
}
219+
203220
return validated;
204221
}
205222

packages/cli/src/services/tests/config.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,28 @@ describe('Configuration Service', () => {
8282
consoleSpy.mockRestore();
8383
});
8484

85+
it('should read ignorePeerDeps from file config', () => {
86+
vi.mocked(existsSync).mockReturnValue(true);
87+
vi.mocked(join).mockReturnValue('/test/patchpulse.json');
88+
vi.mocked(readFileSync).mockReturnValue(
89+
JSON.stringify({ ignorePeerDeps: true }),
90+
);
91+
92+
const result = readConfigFile('/test');
93+
expect(result).toEqual({ ignorePeerDeps: true });
94+
});
95+
96+
it('should ignore non-boolean ignorePeerDeps from file config', () => {
97+
vi.mocked(existsSync).mockReturnValue(true);
98+
vi.mocked(join).mockReturnValue('/test/patchpulse.json');
99+
vi.mocked(readFileSync).mockReturnValue(
100+
JSON.stringify({ ignorePeerDeps: 'yes' }),
101+
);
102+
103+
const result = readConfigFile('/test');
104+
expect(result?.ignorePeerDeps).toBeUndefined();
105+
});
106+
85107
it('should ignore unsupported package manager values from file config', () => {
86108
vi.mocked(existsSync).mockReturnValue(true);
87109
vi.mocked(join).mockReturnValue('/test/patchpulse.json');
@@ -134,6 +156,16 @@ describe('Configuration Service', () => {
134156

135157
expect(result).toEqual({});
136158
});
159+
160+
it('should parse --no-peer-deps flag', () => {
161+
const result = parseCliConfig(['--no-peer-deps']);
162+
expect(result).toEqual({ ignorePeerDeps: true });
163+
});
164+
165+
it('should not set ignorePeerDeps when --no-peer-deps is absent', () => {
166+
const result = parseCliConfig([]);
167+
expect(result.ignorePeerDeps).toBeUndefined();
168+
});
137169
});
138170

139171
describe('mergeConfigs', () => {
@@ -191,6 +223,24 @@ describe('Configuration Service', () => {
191223
interactive: false,
192224
});
193225
});
226+
227+
it('CLI ignorePeerDeps takes precedence over file config', () => {
228+
const result = mergeConfigs(
229+
{ ignorePeerDeps: false },
230+
{ ignorePeerDeps: true },
231+
);
232+
expect(result.ignorePeerDeps).toBe(true);
233+
});
234+
235+
it('file ignorePeerDeps is used when CLI does not set it', () => {
236+
const result = mergeConfigs({ ignorePeerDeps: true }, {});
237+
expect(result.ignorePeerDeps).toBe(true);
238+
});
239+
240+
it('ignorePeerDeps is undefined when neither config sets it', () => {
241+
const result = mergeConfigs(null, {});
242+
expect(result.ignorePeerDeps).toBeUndefined();
243+
});
194244
});
195245

196246
describe('shouldSkipPackage', () => {

packages/cli/src/ui/display/help.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ ${ansi.cyanBoldUnderline('🔧 Configuration Options:')}
3535
${ansi.white('--project <name|path>')} ${ansi.gray('Limit the scan output to one project in a monorepo')}
3636
${ansi.white('-i, --interactive')} ${ansi.gray('Show interactive update prompt after summary')}
3737
${ansi.white('--no-interactive')} ${ansi.gray('Skip update prompt after summary (default)')}
38+
${ansi.white('--no-peer-deps')} ${ansi.gray('Exclude peerDependencies from the scan')}
3839
${ansi.white('--hide-clean')} ${ansi.gray('Hide clean projects in monorepos')}
3940
${ansi.white('--expand')} ${ansi.gray('Show full output for every project in monorepos')}
4041
${ansi.white('--fail')} ${ansi.gray('Exit with code 1 if any outdated packages are found')}
@@ -46,7 +47,8 @@ ${ansi.cyanBoldUnderline('📁 Configuration File:')}
4647
${ansi.gray('"skip": ["lodash", "@types/*", "test-*"],')}
4748
${ansi.gray('"ignorePaths": ["packages/cli/e2e"],')}
4849
${ansi.gray('"packageManager": "npm",')}
49-
${ansi.gray('"interactive": true')}
50+
${ansi.gray('"interactive": true,')}
51+
${ansi.gray('"ignorePeerDeps": true')}
5052
${ansi.gray('}')}
5153
5254
${ansi.cyanBoldUnderline('📝 Description:')}
@@ -74,6 +76,7 @@ ${ansi.cyanBoldUnderline('💡 Examples:')}
7476
${ansi.white('npx patch-pulse --expand')} ${ansi.gray('# Show full monorepo output including clean projects')}
7577
${ansi.white('npx patch-pulse --fail')} ${ansi.gray('# Exit 1 if any outdated packages found (useful in CI)')}
7678
${ansi.white('npx patch-pulse --json --fail')} ${ansi.gray('# Machine-readable output + non-zero exit for CI scripts')}
79+
${ansi.white('npx patch-pulse --no-peer-deps')} ${ansi.gray('# Exclude peerDependencies from the scan')}
7780
7881
${ansi.cyanBoldUnderline('🔗 Links:')}
7982
${ansi.blue('📚 Docs:')} ${ansi.white(ansi.link('barrymichaeldoyle.github.io/patch-pulse', DOCS_URL))}

packages/docs/src/content/docs/cli/commands.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,15 @@ npx patch-pulse --json --fail
148148
Combine `--json` and `--fail` for machine-readable output with a non-zero exit
149149
code when updates are available.
150150
</Aside>
151+
152+
---
153+
154+
### `--no-peer-deps`
155+
156+
Exclude `peerDependencies` from the scan. Useful for published libraries where peer dep ranges are intentionally broad and not something you manage directly.
157+
158+
```bash
159+
npx patch-pulse --no-peer-deps
160+
```
161+
162+
Can also be set persistently via [`ignorePeerDeps`](../configuration#ignorePeerDeps) in your config file.

packages/docs/src/content/docs/cli/configuration.mdx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ The CLI supports a configuration file for persistent settings. Use `patchpulse.j
1919
"skip": ["lodash", "@types/*", "test-*"],
2020
"ignorePaths": ["packages/cli/e2e"],
2121
"packageManager": "pnpm",
22-
"interactive": true
22+
"interactive": true,
23+
"ignorePeerDeps": true
2324
}
2425
```
2526

@@ -101,6 +102,20 @@ Enable the interactive update prompt automatically after every run.
101102

102103
---
103104

105+
### `ignorePeerDeps`
106+
107+
Exclude `peerDependencies` from the scan entirely. Useful for published libraries where peer dep ranges are intentionally broad and not something you manage directly.
108+
109+
```json
110+
{
111+
"ignorePeerDeps": true
112+
}
113+
```
114+
115+
Can also be set via the [`--no-peer-deps`](../commands#--no-peer-deps) CLI flag.
116+
117+
---
118+
104119
## CLI vs file precedence
105120

106121
CLI flags take precedence over file settings for most options. The `skip` array is an exception — values from both sources are **merged**.

packages/docs/src/content/docs/github-action/configuration.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ Use `ignore` to permanently exclude packages from ever getting a PR. Supports ex
7777
<Aside type="note">
7878
The ignore list is also respected by the PatchPulse CLI's `skip`
7979
configuration. Packages skipped in `patchpulse.json` are filtered out before
80-
the action even sees them.
80+
the action even sees them. Setting [`ignorePeerDeps:
81+
true`](../../cli/configuration#ignorePeerDeps) in `patchpulse.json` has the
82+
same effect — peer dependencies are excluded from the CLI output and will
83+
never trigger a PR.
8184
</Aside>
8285

8386
---

0 commit comments

Comments
 (0)