knip 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,29 +19,29 @@ The dots don't connect themselves. This is where Knip comes in:
19
19
  - [x] Finds used dependencies not listed in `package.json`
20
20
  - [x] Finds duplicate exports
21
21
  - [x] Finds unused members of classes and enums
22
- - [x] Built-in support for monorepos/workspaces
23
- - [x] Growing list of [built-in plugins][1]
22
+ - [x] Built-in support for [monorepos/workspaces][1]
23
+ - [x] Growing list of [built-in plugins][2]
24
24
  - [x] Checks npm scripts for used and unlisted dependencies
25
25
  - [x] Supports JavaScript (without `tsconfig.json`, or TypeScript `allowJs: true`)
26
- - [x] Features multiple [reporters][2] and supports [custom reporters][3]
26
+ - [x] Features multiple [reporters][3] and supports [custom reporters][4]
27
27
  - [x] Run Knip as part of your CI environment to detect issues and prevent regressions
28
28
 
29
29
  Knip shines in both small and large projects. It's a fresh take on keeping your projects clean & tidy!
30
30
 
31
- [![An orange cow with scissors, Van Gogh style][5]][4] <sup>_“An orange cow with scissors, Van Gogh style” - generated
31
+ [![An orange cow with scissors, Van Gogh style][6]][5] <sup>_“An orange cow with scissors, Van Gogh style” - generated
32
32
  with OpenAI_</sup>
33
33
 
34
34
  ## Migrating to v1.0.0
35
35
 
36
- When coming from version v0.13.3 or before, please see [migration to v1][6].
36
+ When coming from version v0.13.3 or before, please see [migration to v1][7].
37
37
 
38
38
  ## Issues
39
39
 
40
- Are you seeing false positives? Please report them by [opening an issue in this repo][7]. Bonus points for linking to a
40
+ Are you seeing false positives? Please report them by [opening an issue in this repo][8]. Bonus points for linking to a
41
41
  public repository using Knip, or even opening a pull request with a directory and example files in `test/fixtures`.
42
42
  Correctness and bug fixes have priority over performance and new features.
43
43
 
44
- Also see the [FAQ][8].
44
+ Also see the [FAQ][9].
45
45
 
46
46
  ## Installation
47
47
 
@@ -66,6 +66,8 @@ with a configuration file (or a `knip` property in `package.json`). Let's name t
66
66
  The `entry` files target the starting point(s) to resolve the rest of the imported code. The `project` files should
67
67
  contain all files to match against the files resolved from the entry files, including potentially unused files.
68
68
 
69
+ If you have, please see [workspaces & monorepos][1].
70
+
69
71
  Then run the checks with `npx knip`. Or first add this script to `package.json`:
70
72
 
71
73
  ```json
@@ -221,8 +223,13 @@ be part of the analysis. Here's an example:
221
223
  }
222
224
  ```
223
225
 
224
- All `workspaces` or `workspaces.packages` in `package.json` with a match in `workspaces` of `Knip.json` are part of the
225
- analysis.
226
+ Knip supports workspaces as defined in three possible locations:
227
+
228
+ - In the `workspaces` array in `package.json`.
229
+ - In the `workspaces.packages` array in `package.json`.
230
+ - In the `packages` array in `pnpm-workspace.yaml`.
231
+
232
+ Every directory with a match in `workspaces` of `knip.json` is part of the analysis.
226
233
 
227
234
  Extra "workspaces" not configured as a workspace in the root `package.json` can be configured as well, Knip is happy to
228
235
  analyze unused dependencies and exports from any directory with a `package.json`.
@@ -235,36 +242,36 @@ Here's some example output when running Knip in a workspace:
235
242
 
236
243
  Knip contains a growing list of plugins:
237
244
 
238
- - [Babel][9]
239
- - [Capacitor][11]
240
- - [Changesets][12]
241
- - [commitlint][13]
242
- - [Cypress][14]
243
- - [ESLint][15]
244
- - [Gatsby][16]
245
- - [GitHub Actions][17]
246
- - [husky][18]
247
- - [Jest][19]
248
- - [lint-staged][20]
249
- - [markdownlint][21]
250
- - [Mocha][22]
251
- - [Next.js][23]
252
- - [npm-package-json-lint][24]
253
- - [Nx][25]
254
- - [nyc][26]
255
- - [Playwright][27]
256
- - [PostCSS][28]
257
- - [Prettier][29]
258
- - [Release It][30]
259
- - [Remark][31]
260
- - [Remix][32]
261
- - [Rollup][33]
262
- - [Sentry][34]
263
- - [Storybook][35]
264
- - [Stryker][36]
265
- - [TypeScript][37]
266
- - [Vitest][38]
267
- - [Webpack][39]
245
+ - [Babel][11]
246
+ - [Capacitor][12]
247
+ - [Changesets][13]
248
+ - [commitlint][14]
249
+ - [Cypress][15]
250
+ - [ESLint][16]
251
+ - [Gatsby][17]
252
+ - [GitHub Actions][18]
253
+ - [husky][19]
254
+ - [Jest][20]
255
+ - [lint-staged][21]
256
+ - [markdownlint][22]
257
+ - [Mocha][23]
258
+ - [Next.js][24]
259
+ - [npm-package-json-lint][25]
260
+ - [Nx][26]
261
+ - [nyc][27]
262
+ - [Playwright][28]
263
+ - [PostCSS][29]
264
+ - [Prettier][30]
265
+ - [Release It][31]
266
+ - [Remark][32]
267
+ - [Remix][33]
268
+ - [Rollup][34]
269
+ - [Sentry][35]
270
+ - [Storybook][36]
271
+ - [Stryker][37]
272
+ - [TypeScript][38]
273
+ - [Vitest][39]
274
+ - [Webpack][40]
268
275
 
269
276
  Plugins are automatically activated. Each plugin is automatically enabled based on simple heuristics. Most of them check
270
277
  whether one or one of a few (dev) dependencies are listed in `package.json`. Once enabled, they add a set of
@@ -272,7 +279,7 @@ configuration and/or entry files for Knip to analyze. These defaults can be over
272
279
 
273
280
  Most plugins use one or both of the following file types:
274
281
 
275
- - `config` - custom dependency resolvers are applied to the [config files][40]
282
+ - `config` - custom dependency resolvers are applied to the [config files][41]
276
283
  - `entry` - files to include with the analysis of the rest of the source code
277
284
 
278
285
  See each plugin's documentation for its default values.
@@ -373,10 +380,10 @@ Each workspace can also have its own `paths` configured. Note that Knip `paths`
373
380
 
374
381
  Knip provides the following built-in reporters:
375
382
 
376
- - [`codeowners`][41]
377
- - [`compact`][42]
378
- - [`json`][43]
379
- - [`symbol`][44] (default)
383
+ - [`codeowners`][42]
384
+ - [`compact`][43]
385
+ - [`json`][44]
386
+ - [`symbol`][45] (default)
380
387
 
381
388
  The `compact` reporter shows the sorted files first, and then a list of symbols:
382
389
 
@@ -403,7 +410,7 @@ type ReporterOptions = {
403
410
 
404
411
  The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
405
412
 
406
- Find more details and ideas in [custom reporters][45].
413
+ Find more details and ideas in [custom reporters][46].
407
414
 
408
415
  ## Libraries and "unused" exports
409
416
 
@@ -461,7 +468,7 @@ When unused dependencies are related to dependencies having a Knip [plugin][1],
461
468
  for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
462
469
  to match the custom location(s).
463
470
 
464
- When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][46].
471
+ When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][47].
465
472
 
466
473
  #### Too many unused exports
467
474
 
@@ -469,7 +476,7 @@ When the project is a library and the exports are meant to be used by consumers
469
476
 
470
477
  1. By default, unused exports of `entry` files are not reported. You could re-export from an existing entry file, or
471
478
  add the containing file to the `entry` array in the configuration.
472
- 2. The exported values or types can be marked [using the JSDoc `@public` tag][47].
479
+ 2. The exported values or types can be marked [using the JSDoc `@public` tag][48].
473
480
 
474
481
  ### How to start using Knip in CI while having too many issues to sort out?
475
482
 
@@ -489,7 +496,7 @@ All of this is hiding problems, so please make sure to plan for fixing them and/
489
496
 
490
497
  This table is an ongoing comparison. Based on their docs (please report any mistakes):
491
498
 
492
- | Feature | **knip** | [depcheck][48] | [unimported][49] | [ts-unused-exports][50] | [ts-prune][51] |
499
+ | Feature | **knip** | [depcheck][49] | [unimported][50] | [ts-unused-exports][51] | [ts-prune][52] |
493
500
  | :--------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
494
501
  | Unused files | ✅ | - | ✅ | - | - |
495
502
  | Unused dependencies | ✅ | ✅ | ✅ | - | - |
@@ -554,56 +561,56 @@ userland territory, much like code linters.
554
561
  Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
555
562
  for the job. I'm motivated to make knip perfectly suited for the job of cutting projects to perfection! ✂️
556
563
 
557
- [1]: #plugins
558
- [2]: #reporters
559
- [3]: #custom-reporters
560
- [4]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
561
- [5]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
562
- [6]: ./docs/migration-to-v1.md
563
- [7]: https://github.com/webpro/knip/issues
564
- [8]: #faq
565
- [9]: ./src/plugins/babel
564
+ [1]: #workspaces--monorepos
565
+ [2]: #plugins
566
+ [3]: #reporters
567
+ [4]: #custom-reporters
568
+ [5]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
569
+ [6]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
570
+ [7]: ./docs/migration-to-v1.md
571
+ [8]: https://github.com/webpro/knip/issues
572
+ [9]: #faq
566
573
  [10]: #ignore
567
- [11]: ./src/plugins/capacitor
568
- [12]: ./src/plugins/changesets
569
- [13]: ./src/plugins/commitlint
570
- [14]: ./src/plugins/cypress
571
- [15]: ./src/plugins/eslint
572
- [16]: ./src/plugins/gatsby
573
- [17]: ./src/plugins/github-actions
574
- [18]: ./src/plugins/husky
575
- [19]: ./src/plugins/jest
576
- [20]: ./src/plugins/lint-staged
577
- [21]: ./src/plugins/markdownlint
578
- [22]: ./src/plugins/mocha
579
- [23]: ./src/plugins/next
580
- [24]: ./src/plugins/npm-package-json-lint
581
- [25]: ./src/plugins/nx
582
- [26]: ./src/plugins/nyc
583
- [27]: ./src/plugins/playwright
584
- [28]: ./src/plugins/postcss
585
- [29]: ./src/plugins/prettier
586
- [30]: ./src/plugins/release-it
587
- [31]: ./src/plugins/remark
588
- [32]: ./src/plugins/remix
589
- [33]: ./src/plugins/rollup
590
- [34]: ./src/plugins/sentry
591
- [35]: ./src/plugins/storybook
592
- [36]: ./src/plugins/stryker
593
- [37]: ./src/plugins/typescript
594
- [38]: ./src/plugins/vitest
595
- [39]: ./src/plugins/webpack
596
- [40]: #config
597
- [41]: #code-owners
598
- [42]: #compact
599
- [43]: #json
600
- [44]: #symbol-default
601
- [45]: ./docs/custom-reporters.md
602
- [46]: #create-a-new-plugin
603
- [47]: #libraries-and-unused-exports
604
- [48]: https://github.com/depcheck/depcheck
605
- [49]: https://github.com/smeijer/unimported
606
- [50]: https://github.com/pzavolinsky/ts-unused-exports
607
- [51]: https://github.com/nadeesha/ts-prune
608
- [52]: #workspaces--monorepos
574
+ [11]: ./src/plugins/babel
575
+ [12]: ./src/plugins/capacitor
576
+ [13]: ./src/plugins/changesets
577
+ [14]: ./src/plugins/commitlint
578
+ [15]: ./src/plugins/cypress
579
+ [16]: ./src/plugins/eslint
580
+ [17]: ./src/plugins/gatsby
581
+ [18]: ./src/plugins/github-actions
582
+ [19]: ./src/plugins/husky
583
+ [20]: ./src/plugins/jest
584
+ [21]: ./src/plugins/lint-staged
585
+ [22]: ./src/plugins/markdownlint
586
+ [23]: ./src/plugins/mocha
587
+ [24]: ./src/plugins/next
588
+ [25]: ./src/plugins/npm-package-json-lint
589
+ [26]: ./src/plugins/nx
590
+ [27]: ./src/plugins/nyc
591
+ [28]: ./src/plugins/playwright
592
+ [29]: ./src/plugins/postcss
593
+ [30]: ./src/plugins/prettier
594
+ [31]: ./src/plugins/release-it
595
+ [32]: ./src/plugins/remark
596
+ [33]: ./src/plugins/remix
597
+ [34]: ./src/plugins/rollup
598
+ [35]: ./src/plugins/sentry
599
+ [36]: ./src/plugins/storybook
600
+ [37]: ./src/plugins/stryker
601
+ [38]: ./src/plugins/typescript
602
+ [39]: ./src/plugins/vitest
603
+ [40]: ./src/plugins/webpack
604
+ [41]: #config
605
+ [42]: #code-owners
606
+ [43]: #compact
607
+ [44]: #json
608
+ [45]: #symbol-default
609
+ [46]: ./docs/custom-reporters.md
610
+ [47]: #create-a-new-plugin
611
+ [48]: #libraries-and-unused-exports
612
+ [49]: https://github.com/depcheck/depcheck
613
+ [50]: https://github.com/smeijer/unimported
614
+ [51]: https://github.com/pzavolinsky/ts-unused-exports
615
+ [52]: https://github.com/nadeesha/ts-prune
609
616
  [53]: #production-mode
@@ -40,16 +40,21 @@ export default class ConfigurationChief {
40
40
  this.config = defaultConfig;
41
41
  }
42
42
  async loadLocalConfig() {
43
- const manifestPath = await findFile(this.cwd, 'package.json');
43
+ const manifestPath = findFile(this.cwd, 'package.json');
44
44
  const manifest = manifestPath && (await loadJSON(manifestPath));
45
45
  if (!manifestPath || !manifest) {
46
46
  throw new ConfigurationError('Unable to find package.json');
47
47
  }
48
48
  this.manifestPath = manifestPath;
49
49
  this.manifest = manifest;
50
+ const pnpmWorkspacesPath = findFile(this.cwd, 'pnpm-workspace.yaml');
51
+ const pnpmWorkspaces = pnpmWorkspacesPath && (await _load(pnpmWorkspacesPath));
52
+ if (this.manifest && !this.manifest.workspaces && pnpmWorkspaces) {
53
+ this.manifest.workspaces = pnpmWorkspaces;
54
+ }
50
55
  let resolvedConfigFilePath;
51
56
  for (const configPath of rawConfigArg ? [rawConfigArg] : KNIP_CONFIG_LOCATIONS) {
52
- resolvedConfigFilePath = await findFile(this.cwd, configPath);
57
+ resolvedConfigFilePath = findFile(this.cwd, configPath);
53
58
  if (resolvedConfigFilePath)
54
59
  break;
55
60
  }
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ export const main = async (unresolvedConfiguration) => {
34
34
  for (const { name, dir, config, ancestors } of workspaces) {
35
35
  const isRoot = name === ROOT_WORKSPACE_NAME;
36
36
  const suffix = isRoot ? '' : ` (${name})`;
37
- const manifestPath = isRoot ? chief.manifestPath : await findFile(dir, 'package.json');
37
+ const manifestPath = isRoot ? chief.manifestPath : findFile(dir, 'package.json');
38
38
  const manifest = isRoot ? chief.manifest : manifestPath && (await loadJSON(manifestPath));
39
39
  if (!manifestPath || !manifest)
40
40
  continue;
@@ -7,6 +7,6 @@ export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABL
7
7
  export const CONFIG_FILE_PATTERNS = ['commitlint.config.{js,ts}'];
8
8
  const findCommitLintDependencies = async (configFilePath) => {
9
9
  const config = await _load(configFilePath);
10
- return config.extends;
10
+ return config?.extends ? [config.extends].flat() : [];
11
11
  };
12
12
  export const findDependencies = timerify(findCommitLintDependencies);
@@ -13,7 +13,7 @@ export default async ({ report, issues, options }) => {
13
13
  }
14
14
  const json = {};
15
15
  const codeownersFilePath = path.resolve(opts.codeowners ?? '.github/CODEOWNERS');
16
- const codeownersEngine = (await isFile(codeownersFilePath)) && OwnershipEngine.FromCodeownersFile(codeownersFilePath);
16
+ const codeownersEngine = isFile(codeownersFilePath) && OwnershipEngine.FromCodeownersFile(codeownersFilePath);
17
17
  const flatten = (issues) => Object.values(issues).map(Object.values).flat();
18
18
  const initRow = (filePath) => {
19
19
  const file = relative(filePath);
@@ -3,7 +3,7 @@ import { isFile } from './fs.js';
3
3
  import { logIfDebug } from './log.js';
4
4
  export const loadTSConfig = async (tsConfigFilePath) => {
5
5
  try {
6
- if (await isFile(tsConfigFilePath)) {
6
+ if (isFile(tsConfigFilePath)) {
7
7
  return parseTsconfig(tsConfigFilePath);
8
8
  }
9
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",