knip 1.2.0 → 1.4.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.
Files changed (56) hide show
  1. package/README.md +67 -61
  2. package/dist/cli.js +2 -1
  3. package/dist/configuration-chief.d.ts +2 -4
  4. package/dist/configuration-chief.js +5 -3
  5. package/dist/configuration-validator.d.ts +112 -0
  6. package/dist/configuration-validator.js +2 -0
  7. package/dist/constants.d.ts +0 -1
  8. package/dist/constants.js +0 -1
  9. package/dist/index.d.ts +2 -0
  10. package/dist/manifest/helpers.d.ts +0 -1
  11. package/dist/manifest/helpers.js +0 -36
  12. package/dist/manifest/index.js +3 -5
  13. package/dist/plugins/github-actions/index.d.ts +6 -0
  14. package/dist/plugins/github-actions/index.js +26 -0
  15. package/dist/plugins/index.d.ts +3 -0
  16. package/dist/plugins/index.js +3 -0
  17. package/dist/plugins/lint-staged/index.js +3 -3
  18. package/dist/plugins/markdownlint/index.d.ts +6 -0
  19. package/dist/plugins/markdownlint/index.js +20 -0
  20. package/dist/plugins/markdownlint/types.d.ts +3 -0
  21. package/dist/plugins/markdownlint/types.js +1 -0
  22. package/dist/plugins/npm-package-json-lint/index.d.ts +6 -0
  23. package/dist/plugins/npm-package-json-lint/index.js +14 -0
  24. package/dist/plugins/npm-package-json-lint/types.d.ts +3 -0
  25. package/dist/plugins/npm-package-json-lint/types.js +1 -0
  26. package/dist/reporters/index.d.ts +4 -4
  27. package/dist/types/config.d.ts +3 -0
  28. package/dist/types/plugins.d.ts +2 -1
  29. package/dist/util/binaries/binaries/cross-env.d.ts +1 -0
  30. package/dist/util/binaries/binaries/cross-env.js +5 -0
  31. package/dist/util/binaries/binaries/dotenv.d.ts +1 -0
  32. package/dist/util/binaries/binaries/dotenv.js +5 -0
  33. package/dist/util/binaries/binaries/index.d.ts +2 -0
  34. package/dist/util/binaries/binaries/index.js +2 -0
  35. package/dist/util/binaries/globals/index.d.ts +4 -0
  36. package/dist/util/binaries/globals/index.js +4 -0
  37. package/dist/util/binaries/globals/node.d.ts +1 -0
  38. package/dist/util/binaries/globals/node.js +5 -0
  39. package/dist/util/binaries/globals/npx.d.ts +1 -0
  40. package/dist/util/binaries/globals/npx.js +8 -0
  41. package/dist/util/binaries/globals/pnpm.d.ts +2 -0
  42. package/dist/util/binaries/globals/pnpm.js +43 -0
  43. package/dist/util/binaries/globals/yarn.d.ts +2 -0
  44. package/dist/util/binaries/globals/yarn.js +42 -0
  45. package/dist/util/binaries/index.d.ts +7 -0
  46. package/dist/util/binaries/index.js +46 -0
  47. package/dist/util/debug.js +0 -10
  48. package/dist/util/fs.d.ts +2 -2
  49. package/dist/util/fs.js +8 -12
  50. package/dist/util/object.d.ts +1 -0
  51. package/dist/util/object.js +15 -0
  52. package/dist/util/plugin.d.ts +2 -0
  53. package/dist/util/plugin.js +7 -0
  54. package/dist/workspace-worker.js +1 -0
  55. package/package.json +7 -6
  56. package/schema.json +13 -1
package/README.md CHANGED
@@ -233,24 +233,27 @@ Knip contains a growing list of plugins:
233
233
  - [Cypress][14]
234
234
  - [ESLint][15]
235
235
  - [Gatsby][16]
236
- - [Jest][17]
237
- - [lint-staged][18]
238
- - [Mocha][19]
239
- - [Next.js][20]
240
- - [Nx][21]
241
- - [nyc][22]
242
- - [Playwright][23]
243
- - [PostCSS][24]
244
- - [Prettier][25]
245
- - [Release It][26]
246
- - [Remark][27]
247
- - [Remix][28]
248
- - [Rollup][29]
249
- - [Sentry][30]
250
- - [Storybook][31]
251
- - [Stryker][32]
252
- - [TypeScript][33]
253
- - [Webpack][34]
236
+ - [GitHub Actions][17]
237
+ - [Jest][18]
238
+ - [lint-staged][19]
239
+ - [markdownlint][20]
240
+ - [Mocha][21]
241
+ - [Next.js][22]
242
+ - [npm-package-json-lint][23]
243
+ - [Nx][24]
244
+ - [nyc][25]
245
+ - [Playwright][26]
246
+ - [PostCSS][27]
247
+ - [Prettier][28]
248
+ - [Release It][29]
249
+ - [Remark][30]
250
+ - [Remix][31]
251
+ - [Rollup][32]
252
+ - [Sentry][33]
253
+ - [Storybook][34]
254
+ - [Stryker][35]
255
+ - [TypeScript][36]
256
+ - [Webpack][37]
254
257
 
255
258
  Plugins are automatically activated, no need to enable anything. Each plugin is automatically enabled based on simple
256
259
  heuristics. Most of them check whether one or one of a few (dev) dependencies are listed in `package.json`. Once
@@ -258,7 +261,7 @@ enabled, they add a set of configuration and/or entry files for Knip to analyze.
258
261
 
259
262
  Most plugins use one or both of the following file types:
260
263
 
261
- - `config` - custom dependency resolvers are applied to the [config files][35]
264
+ - `config` - custom dependency resolvers are applied to the [config files][38]
262
265
  - `entry` - files to include with the analysis of the rest of the source code
263
266
 
264
267
  See each plugin's documentation for its default values.
@@ -338,10 +341,10 @@ locations. The more plugins Knip will have, the more projects can be analyzed ou
338
341
 
339
342
  Knip provides the following built-in reporters:
340
343
 
341
- - [`codeowners`][36]
342
- - [`compact`][37]
343
- - [`json`][38]
344
- - [`symbol`][39] (default)
344
+ - [`codeowners`][39]
345
+ - [`compact`][40]
346
+ - [`json`][41]
347
+ - [`symbol`][42] (default)
345
348
 
346
349
  The `compact` reporter shows the sorted files first, and then a list of symbols:
347
350
 
@@ -368,7 +371,7 @@ type ReporterOptions = {
368
371
 
369
372
  The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
370
373
 
371
- Find more details and ideas in [custom reporters][40].
374
+ Find more details and ideas in [custom reporters][43].
372
375
 
373
376
  ## Libraries and "unused" exports
374
377
 
@@ -425,14 +428,14 @@ When unused dependencies are related to dependencies having a Knip [plugin][1],
425
428
  for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
426
429
  to match the custom location(s).
427
430
 
428
- When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][41].
431
+ When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][44].
429
432
 
430
433
  #### Too many unused exports
431
434
 
432
435
  When the project is a library and the exports are meant to be used by consumers of the library, there are two options:
433
436
 
434
437
  1. By default, unused exports of `entry` files are not reported, so you can add the containing file to it.
435
- 2. The exported values or types can be marked [using the JSDoc `@public` tag][42].
438
+ 2. The exported values or types can be marked [using the JSDoc `@public` tag][45].
436
439
 
437
440
  ### How to start using Knip in CI while having too many issues to sort out?
438
441
 
@@ -449,7 +452,7 @@ All of this is hiding problems, so please make sure to plan for fixing them and/
449
452
 
450
453
  This table is an ongoing comparison. Based on their docs (please report any mistakes):
451
454
 
452
- | Feature | **knip** | [depcheck][43] | [unimported][44] | [ts-unused-exports][45] | [ts-prune][46] |
455
+ | Feature | **knip** | [depcheck][46] | [unimported][47] | [ts-unused-exports][48] | [ts-prune][49] |
453
456
  | :--------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
454
457
  | Unused files | ✅ | - | ✅ | - | - |
455
458
  | Unused dependencies | ✅ | ✅ | ✅ | - | - |
@@ -463,7 +466,7 @@ This table is an ongoing comparison. Based on their docs (please report any mist
463
466
  | Custom reporters | ✅ | - | - | - | - |
464
467
  | JavaScript support | ✅ | ✅ | ✅ | - | - |
465
468
  | Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ |
466
- | [Support workspaces/monorepos][47] | ✅ | ❌ | ❌ | - | - |
469
+ | [Support workspaces/monorepos][50] | ✅ | ❌ | ❌ | - | - |
467
470
  | ESLint plugin available | - | - | - | ✅ | - |
468
471
 
469
472
  ✅ = Supported, ❌ = Not supported, - = Out of scope
@@ -484,7 +487,7 @@ The following commands are similar:
484
487
  unimported
485
488
  knip --production --dependencies --include files
486
489
 
487
- Also see [production mode][48].
490
+ Also see [production mode][51].
488
491
 
489
492
  ### ts-unused-exports
490
493
 
@@ -530,35 +533,38 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
530
533
  [14]: ./src/plugins/cypress
531
534
  [15]: ./src/plugins/eslint
532
535
  [16]: ./src/plugins/gatsby
533
- [17]: ./src/plugins/jest
534
- [18]: ./src/plugins/lint-staged
535
- [19]: ./src/plugins/mocha
536
- [20]: ./src/plugins/next
537
- [21]: ./src/plugins/nx
538
- [22]: ./src/plugins/nyc
539
- [23]: ./src/plugins/playwright
540
- [24]: ./src/plugins/postcss
541
- [25]: ./src/plugins/prettier
542
- [26]: ./src/plugins/release-it
543
- [27]: ./src/plugins/remark
544
- [28]: ./src/plugins/remix
545
- [29]: ./src/plugins/rollup
546
- [30]: ./src/plugins/sentry
547
- [31]: ./src/plugins/storybook
548
- [32]: ./src/plugins/stryker
549
- [33]: ./src/plugins/typescript
550
- [34]: ./src/plugins/webpack
551
- [35]: #config
552
- [36]: #code-owners
553
- [37]: #compact
554
- [38]: #json
555
- [39]: #symbol-default
556
- [40]: ./docs/custom-reporters.md
557
- [41]: #create-a-new-plugin
558
- [42]: #libraries-and-unused-exports
559
- [43]: https://github.com/depcheck/depcheck
560
- [44]: https://github.com/smeijer/unimported
561
- [45]: https://github.com/pzavolinsky/ts-unused-exports
562
- [46]: https://github.com/nadeesha/ts-prune
563
- [47]: #workspaces--monorepos
564
- [48]: #production-mode
536
+ [17]: ./src/plugins/github-actions
537
+ [18]: ./src/plugins/jest
538
+ [19]: ./src/plugins/lint-staged
539
+ [20]: ./src/plugins/markdownlint
540
+ [21]: ./src/plugins/mocha
541
+ [22]: ./src/plugins/next
542
+ [23]: ./src/plugins/npm-package-json-lint
543
+ [24]: ./src/plugins/nx
544
+ [25]: ./src/plugins/nyc
545
+ [26]: ./src/plugins/playwright
546
+ [27]: ./src/plugins/postcss
547
+ [28]: ./src/plugins/prettier
548
+ [29]: ./src/plugins/release-it
549
+ [30]: ./src/plugins/remark
550
+ [31]: ./src/plugins/remix
551
+ [32]: ./src/plugins/rollup
552
+ [33]: ./src/plugins/sentry
553
+ [34]: ./src/plugins/storybook
554
+ [35]: ./src/plugins/stryker
555
+ [36]: ./src/plugins/typescript
556
+ [37]: ./src/plugins/webpack
557
+ [38]: #config
558
+ [39]: #code-owners
559
+ [40]: #compact
560
+ [41]: #json
561
+ [42]: #symbol-default
562
+ [43]: ./docs/custom-reporters.md
563
+ [44]: #create-a-new-plugin
564
+ [45]: #libraries-and-unused-exports
565
+ [46]: https://github.com/depcheck/depcheck
566
+ [47]: https://github.com/smeijer/unimported
567
+ [48]: https://github.com/pzavolinsky/ts-unused-exports
568
+ [49]: https://github.com/nadeesha/ts-prune
569
+ [50]: #workspaces--monorepos
570
+ [51]: #production-mode
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import { register } from 'esbuild-register/dist/node.js';
4
4
  import reporters from './reporters/index.js';
5
5
  import parsedArgs, { helpText } from './util/cli-arguments.js';
6
6
  import { ConfigurationError } from './util/errors.js';
7
+ import { _load } from './util/loader.js';
7
8
  import { measure } from './util/performance.js';
8
9
  import { main } from './index.js';
9
10
  register();
@@ -14,7 +15,7 @@ if (help) {
14
15
  }
15
16
  const cwd = process.cwd();
16
17
  const isShowProgress = !isDebug && isNoProgress === false && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function';
17
- const printReport = reporter in reporters ? reporters[reporter] : await import(path.join(cwd, reporter));
18
+ const printReport = reporter in reporters ? reporters[reporter] : await _load(path.join(cwd, reporter));
18
19
  const run = async () => {
19
20
  try {
20
21
  const { report, issues, counters } = await main({
@@ -1,7 +1,5 @@
1
1
  /// <reference types="npmcli__package-json" />
2
- import { z } from 'zod';
3
- import { ConfigurationValidator } from './configuration-validator.js';
4
- import type { Configuration, WorkspaceConfiguration } from './types/config.js';
2
+ import type { RawConfiguration, Configuration, WorkspaceConfiguration } from './types/config.js';
5
3
  import type { PackageJson } from '@npmcli/package-json';
6
4
  type ConfigurationManagerOptions = {
7
5
  cwd: string;
@@ -16,7 +14,7 @@ export default class ConfigurationChief {
16
14
  manifestWorkspaces: undefined | string[];
17
15
  constructor({ cwd, isProduction }: ConfigurationManagerOptions);
18
16
  loadLocalConfig(): Promise<void>;
19
- normalize(rawLocalConfig: z.infer<typeof ConfigurationValidator>): {
17
+ normalize(rawLocalConfig: RawConfiguration): {
20
18
  include: string[];
21
19
  exclude: string[];
22
20
  ignore: string[];
@@ -10,6 +10,7 @@ import { ConfigurationError } from './util/errors.js';
10
10
  import { findFile, loadJSON } from './util/fs.js';
11
11
  import { ensurePosixPath } from './util/glob.js';
12
12
  import { _load } from './util/loader.js';
13
+ import { toCamelCase } from './util/plugin.js';
13
14
  import { resolveIncludedIssueTypes } from './util/resolve-included-issue-types.js';
14
15
  import { byPathDepth } from './util/workspace.js';
15
16
  const { values: { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [], dependencies = false, exports = false, }, } = parsedArgs;
@@ -95,16 +96,17 @@ export default class ConfigurationChief {
95
96
  ignore: arrayify(workspaceConfig.ignore),
96
97
  };
97
98
  for (const [pluginName, pluginConfig] of Object.entries(workspaceConfig)) {
98
- if (PLUGIN_NAMES.includes(pluginName)) {
99
+ const name = toCamelCase(pluginName);
100
+ if (PLUGIN_NAMES.includes(name)) {
99
101
  if (pluginConfig === false) {
100
- workspaces[workspaceName][pluginName] = false;
102
+ workspaces[workspaceName][name] = false;
101
103
  }
102
104
  else {
103
105
  const isObject = typeof pluginConfig !== 'string' && !Array.isArray(pluginConfig);
104
106
  const config = isObject ? arrayify(pluginConfig.config) : pluginConfig ? arrayify(pluginConfig) : null;
105
107
  const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : null;
106
108
  const project = isObject && 'project' in pluginConfig ? arrayify(pluginConfig.project) : entry;
107
- workspaces[workspaceName][pluginName] = {
109
+ workspaces[workspaceName][name] = {
108
110
  config,
109
111
  entry,
110
112
  project,
@@ -119,6 +119,19 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
119
119
  entry?: string | string[] | undefined;
120
120
  project?: string | string[] | undefined;
121
121
  }>]>>;
122
+ 'github-actions': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
123
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
124
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
125
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
126
+ }, "strip", z.ZodTypeAny, {
127
+ config?: string | string[] | undefined;
128
+ entry?: string | string[] | undefined;
129
+ project?: string | string[] | undefined;
130
+ }, {
131
+ config?: string | string[] | undefined;
132
+ entry?: string | string[] | undefined;
133
+ project?: string | string[] | undefined;
134
+ }>]>>;
122
135
  'lint-staged': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
123
136
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
124
137
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -158,6 +171,19 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
158
171
  entry?: string | string[] | undefined;
159
172
  project?: string | string[] | undefined;
160
173
  }>]>>;
174
+ 'npm-package-json-lint': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
175
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
176
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
177
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
178
+ }, "strip", z.ZodTypeAny, {
179
+ config?: string | string[] | undefined;
180
+ entry?: string | string[] | undefined;
181
+ project?: string | string[] | undefined;
182
+ }, {
183
+ config?: string | string[] | undefined;
184
+ entry?: string | string[] | undefined;
185
+ project?: string | string[] | undefined;
186
+ }>]>>;
161
187
  nx: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
162
188
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
163
189
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -384,6 +410,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
384
410
  entry?: string | string[] | undefined;
385
411
  project?: string | string[] | undefined;
386
412
  } | undefined;
413
+ 'github-actions'?: string | false | string[] | {
414
+ config?: string | string[] | undefined;
415
+ entry?: string | string[] | undefined;
416
+ project?: string | string[] | undefined;
417
+ } | undefined;
387
418
  'lint-staged'?: string | false | string[] | {
388
419
  config?: string | string[] | undefined;
389
420
  entry?: string | string[] | undefined;
@@ -399,6 +430,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
399
430
  entry?: string | string[] | undefined;
400
431
  project?: string | string[] | undefined;
401
432
  } | undefined;
433
+ 'npm-package-json-lint'?: string | false | string[] | {
434
+ config?: string | string[] | undefined;
435
+ entry?: string | string[] | undefined;
436
+ project?: string | string[] | undefined;
437
+ } | undefined;
402
438
  nx?: string | false | string[] | {
403
439
  config?: string | string[] | undefined;
404
440
  entry?: string | string[] | undefined;
@@ -513,6 +549,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
513
549
  entry?: string | string[] | undefined;
514
550
  project?: string | string[] | undefined;
515
551
  } | undefined;
552
+ 'github-actions'?: string | false | string[] | {
553
+ config?: string | string[] | undefined;
554
+ entry?: string | string[] | undefined;
555
+ project?: string | string[] | undefined;
556
+ } | undefined;
516
557
  'lint-staged'?: string | false | string[] | {
517
558
  config?: string | string[] | undefined;
518
559
  entry?: string | string[] | undefined;
@@ -528,6 +569,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
528
569
  entry?: string | string[] | undefined;
529
570
  project?: string | string[] | undefined;
530
571
  } | undefined;
572
+ 'npm-package-json-lint'?: string | false | string[] | {
573
+ config?: string | string[] | undefined;
574
+ entry?: string | string[] | undefined;
575
+ project?: string | string[] | undefined;
576
+ } | undefined;
531
577
  nx?: string | false | string[] | {
532
578
  config?: string | string[] | undefined;
533
579
  entry?: string | string[] | undefined;
@@ -704,6 +750,19 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
704
750
  entry?: string | string[] | undefined;
705
751
  project?: string | string[] | undefined;
706
752
  }>]>>;
753
+ 'github-actions': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
754
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
755
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
756
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
757
+ }, "strip", z.ZodTypeAny, {
758
+ config?: string | string[] | undefined;
759
+ entry?: string | string[] | undefined;
760
+ project?: string | string[] | undefined;
761
+ }, {
762
+ config?: string | string[] | undefined;
763
+ entry?: string | string[] | undefined;
764
+ project?: string | string[] | undefined;
765
+ }>]>>;
707
766
  'lint-staged': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
708
767
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
709
768
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -743,6 +802,19 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
743
802
  entry?: string | string[] | undefined;
744
803
  project?: string | string[] | undefined;
745
804
  }>]>>;
805
+ 'npm-package-json-lint': z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
806
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
807
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
808
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
809
+ }, "strip", z.ZodTypeAny, {
810
+ config?: string | string[] | undefined;
811
+ entry?: string | string[] | undefined;
812
+ project?: string | string[] | undefined;
813
+ }, {
814
+ config?: string | string[] | undefined;
815
+ entry?: string | string[] | undefined;
816
+ project?: string | string[] | undefined;
817
+ }>]>>;
746
818
  nx: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
747
819
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
748
820
  entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -974,6 +1046,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
974
1046
  entry?: string | string[] | undefined;
975
1047
  project?: string | string[] | undefined;
976
1048
  } | undefined;
1049
+ 'github-actions'?: string | false | string[] | {
1050
+ config?: string | string[] | undefined;
1051
+ entry?: string | string[] | undefined;
1052
+ project?: string | string[] | undefined;
1053
+ } | undefined;
977
1054
  'lint-staged'?: string | false | string[] | {
978
1055
  config?: string | string[] | undefined;
979
1056
  entry?: string | string[] | undefined;
@@ -989,6 +1066,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
989
1066
  entry?: string | string[] | undefined;
990
1067
  project?: string | string[] | undefined;
991
1068
  } | undefined;
1069
+ 'npm-package-json-lint'?: string | false | string[] | {
1070
+ config?: string | string[] | undefined;
1071
+ entry?: string | string[] | undefined;
1072
+ project?: string | string[] | undefined;
1073
+ } | undefined;
992
1074
  nx?: string | false | string[] | {
993
1075
  config?: string | string[] | undefined;
994
1076
  entry?: string | string[] | undefined;
@@ -1103,6 +1185,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1103
1185
  entry?: string | string[] | undefined;
1104
1186
  project?: string | string[] | undefined;
1105
1187
  } | undefined;
1188
+ 'github-actions'?: string | false | string[] | {
1189
+ config?: string | string[] | undefined;
1190
+ entry?: string | string[] | undefined;
1191
+ project?: string | string[] | undefined;
1192
+ } | undefined;
1106
1193
  'lint-staged'?: string | false | string[] | {
1107
1194
  config?: string | string[] | undefined;
1108
1195
  entry?: string | string[] | undefined;
@@ -1118,6 +1205,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1118
1205
  entry?: string | string[] | undefined;
1119
1206
  project?: string | string[] | undefined;
1120
1207
  } | undefined;
1208
+ 'npm-package-json-lint'?: string | false | string[] | {
1209
+ config?: string | string[] | undefined;
1210
+ entry?: string | string[] | undefined;
1211
+ project?: string | string[] | undefined;
1212
+ } | undefined;
1121
1213
  nx?: string | false | string[] | {
1122
1214
  config?: string | string[] | undefined;
1123
1215
  entry?: string | string[] | undefined;
@@ -1238,6 +1330,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1238
1330
  entry?: string | string[] | undefined;
1239
1331
  project?: string | string[] | undefined;
1240
1332
  } | undefined;
1333
+ 'github-actions'?: string | false | string[] | {
1334
+ config?: string | string[] | undefined;
1335
+ entry?: string | string[] | undefined;
1336
+ project?: string | string[] | undefined;
1337
+ } | undefined;
1241
1338
  'lint-staged'?: string | false | string[] | {
1242
1339
  config?: string | string[] | undefined;
1243
1340
  entry?: string | string[] | undefined;
@@ -1253,6 +1350,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1253
1350
  entry?: string | string[] | undefined;
1254
1351
  project?: string | string[] | undefined;
1255
1352
  } | undefined;
1353
+ 'npm-package-json-lint'?: string | false | string[] | {
1354
+ config?: string | string[] | undefined;
1355
+ entry?: string | string[] | undefined;
1356
+ project?: string | string[] | undefined;
1357
+ } | undefined;
1256
1358
  nx?: string | false | string[] | {
1257
1359
  config?: string | string[] | undefined;
1258
1360
  entry?: string | string[] | undefined;
@@ -1367,6 +1469,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1367
1469
  entry?: string | string[] | undefined;
1368
1470
  project?: string | string[] | undefined;
1369
1471
  } | undefined;
1472
+ 'github-actions'?: string | false | string[] | {
1473
+ config?: string | string[] | undefined;
1474
+ entry?: string | string[] | undefined;
1475
+ project?: string | string[] | undefined;
1476
+ } | undefined;
1370
1477
  'lint-staged'?: string | false | string[] | {
1371
1478
  config?: string | string[] | undefined;
1372
1479
  entry?: string | string[] | undefined;
@@ -1382,6 +1489,11 @@ export declare const ConfigurationValidator: z.ZodObject<z.extendShape<z.extendS
1382
1489
  entry?: string | string[] | undefined;
1383
1490
  project?: string | string[] | undefined;
1384
1491
  } | undefined;
1492
+ 'npm-package-json-lint'?: string | false | string[] | {
1493
+ config?: string | string[] | undefined;
1494
+ entry?: string | string[] | undefined;
1495
+ project?: string | string[] | undefined;
1496
+ } | undefined;
1385
1497
  nx?: string | false | string[] | {
1386
1498
  config?: string | string[] | undefined;
1387
1499
  entry?: string | string[] | undefined;
@@ -30,9 +30,11 @@ const pluginsSchema = z.object({
30
30
  eslint: pluginSchema,
31
31
  gatsby: pluginSchema,
32
32
  jest: pluginSchema,
33
+ 'github-actions': pluginSchema,
33
34
  'lint-staged': pluginSchema,
34
35
  mocha: pluginSchema,
35
36
  next: pluginSchema,
37
+ 'npm-package-json-lint': pluginSchema,
36
38
  nx: pluginSchema,
37
39
  nyc: pluginSchema,
38
40
  playwright: pluginSchema,
@@ -9,6 +9,5 @@ export declare const DEFAULT_WORKSPACE_CONFIG: {
9
9
  export declare const TEST_FILE_PATTERNS: string[];
10
10
  export declare const IGNORED_GLOBAL_BINARIES: string[];
11
11
  export declare const IGNORE_DEFINITELY_TYPED: string[];
12
- export declare const FIRST_ARGUMENT_AS_BINARY_EXCEPTIONS: string[];
13
12
  export declare const ISSUE_TYPES: IssueType[];
14
13
  export declare const ISSUE_TYPE_TITLE: Record<IssueType, string>;
package/dist/constants.js CHANGED
@@ -8,7 +8,6 @@ export const DEFAULT_WORKSPACE_CONFIG = {
8
8
  export const TEST_FILE_PATTERNS = ['**/*.{test,spec}.{js,jsx,ts,tsx}', '**/__tests__/**/*.{js,jsx,ts,tsx}'];
9
9
  export const IGNORED_GLOBAL_BINARIES = ['npm', 'npx', 'node', 'yarn', 'pnpm', 'deno', 'git'];
10
10
  export const IGNORE_DEFINITELY_TYPED = ['node'];
11
- export const FIRST_ARGUMENT_AS_BINARY_EXCEPTIONS = ['npx', 'cross-env', 'dotenv'];
12
11
  export const ISSUE_TYPES = [
13
12
  'files',
14
13
  'dependencies',
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { CommandLineOptions } from './types/cli.js';
2
2
  import type { Report } from './types/issues.js';
3
+ export type { RawConfiguration as KnipConfig } from './types/config.js';
4
+ export type { Reporter, ReporterOptions } from './types/issues.js';
3
5
  export declare const main: (unresolvedConfiguration: CommandLineOptions) => Promise<{
4
6
  report: Report;
5
7
  issues: import("./types/issues.js").Issues;
@@ -1,2 +1 @@
1
- export declare const getBinariesFromScripts: (npmScripts: string[]) => string[];
2
1
  export declare const getPackageManifest: (workingDir: string, packageName: string, isRoot: boolean, cwd: string) => Promise<any>;
@@ -1,41 +1,5 @@
1
1
  import path from 'node:path';
2
- import { FIRST_ARGUMENT_AS_BINARY_EXCEPTIONS } from '../constants.js';
3
2
  import { require } from '../util/require.js';
4
- const normalizeBinaries = (command) => command.replace(/(\.\/)?node_modules\/\.bin\/(\w+)/, '$2').replace(/\$\(npm bin\)\/(\w+)/, '$1');
5
- const stripEnvironmentVariables = (value) => value.replace(/([A-Z][^ ]*)=([^ ])+ /g, '');
6
- const getLoaderArgumentValues = (value) => {
7
- const match = value.match(/ (--(experimental-)?loader|--require|-r)[ =]([^ ]+)/g);
8
- if (match)
9
- return match.map(value => value.trim().split(/[ =]/)[1].trim());
10
- return [];
11
- };
12
- const getDependenciesFromLoaderArguments = (args) => getLoaderArgumentValues(' ' + args.join(' '))
13
- .filter(scripts => !scripts.startsWith('.'))
14
- .map(script => {
15
- if (script.startsWith('@')) {
16
- const [scope, packageName] = script.split('/');
17
- return [scope, packageName].join('/');
18
- }
19
- return script.split('/')[0];
20
- });
21
- export const getBinariesFromScripts = (npmScripts) => Array.from(npmScripts.reduce((binaries, script) => {
22
- script
23
- .split(' && ')
24
- .flatMap(command => command.split(' -- '))
25
- .map(normalizeBinaries)
26
- .filter(command => /^\w/.test(command))
27
- .map(stripEnvironmentVariables)
28
- .flatMap(command => {
29
- const [binary, ...args] = command.trim().split(' ');
30
- if (binary === 'npx' && /-y|--yes/.test(args[0]))
31
- return [binary];
32
- const firstArgument = FIRST_ARGUMENT_AS_BINARY_EXCEPTIONS.includes(binary) && args.find(arg => !arg.startsWith('-'));
33
- const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
34
- return [binary, firstArgument, ...dependenciesFromArguments];
35
- })
36
- .forEach(binary => binary && binaries.add(binary));
37
- return binaries;
38
- }, new Set()));
39
3
  export const getPackageManifest = async (workingDir, packageName, isRoot, cwd) => {
40
4
  try {
41
5
  return require(path.join(workingDir, 'node_modules', packageName, 'package.json'));
@@ -1,6 +1,6 @@
1
- import { IGNORED_GLOBAL_BINARIES } from '../constants.js';
1
+ import { getBinariesFromScripts } from '../util/binaries/index.js';
2
2
  import { timerify } from '../util/performance.js';
3
- import { getBinariesFromScripts, getPackageManifest } from './helpers.js';
3
+ import { getPackageManifest } from './helpers.js';
4
4
  const findManifestDependencies = async ({ rootConfig, manifest, isRoot, isProduction, dir, cwd }) => {
5
5
  const { ignoreBinaries } = rootConfig;
6
6
  const scriptFilter = isProduction ? ['start', 'postinstall'] : [];
@@ -12,9 +12,7 @@ const findManifestDependencies = async ({ rootConfig, manifest, isRoot, isProduc
12
12
  }
13
13
  return scripts;
14
14
  }, []);
15
- const referencedBinaries = getBinariesFromScripts(scripts)
16
- .filter(binaryName => !IGNORED_GLOBAL_BINARIES.includes(binaryName))
17
- .filter(binaryName => !ignoreBinaries.includes(binaryName));
15
+ const referencedBinaries = getBinariesFromScripts(scripts, { manifest, ignore: rootConfig.ignoreBinaries });
18
16
  const installedBinaries = new Map();
19
17
  const packageNames = [...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.devDependencies ?? {})];
20
18
  for (const packageName of packageNames) {
@@ -0,0 +1,6 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const NAME = "GitHub Actions";
3
+ export declare const ENABLERS = "This plugin is enabled when a `.yml` file is found in the `.github/workflows` folder.";
4
+ export declare const isEnabled: IsPluginEnabledCallback;
5
+ export declare const CONFIG_FILE_PATTERNS: string[];
6
+ export declare const findDependencies: GenericPluginCallback;
@@ -0,0 +1,26 @@
1
+ import { EOL } from 'os';
2
+ import { getBinariesFromScripts } from '../../util/binaries/index.js';
3
+ import { _firstGlob } from '../../util/glob.js';
4
+ import { _load } from '../../util/loader.js';
5
+ import { getValuesByKeyDeep } from '../../util/object.js';
6
+ import { timerify } from '../../util/performance.js';
7
+ export const NAME = 'GitHub Actions';
8
+ export const ENABLERS = 'This plugin is enabled when a `.yml` file is found in the `.github/workflows` folder.';
9
+ export const isEnabled = () => Boolean(_firstGlob({ cwd: process.cwd(), patterns: ['.github/workflows/*.yml'] }));
10
+ export const CONFIG_FILE_PATTERNS = ['.github/workflows/*.yml'];
11
+ const findGithubActionsDependencies = async (configFilePath, { manifest, rootConfig }) => {
12
+ const config = await _load(configFilePath);
13
+ if (!config)
14
+ return [];
15
+ const scripts = getValuesByKeyDeep(config, 'run')
16
+ .filter((value) => typeof value === 'string')
17
+ .flatMap(script => script.split(EOL))
18
+ .map(script => script.trim());
19
+ const binaries = getBinariesFromScripts(scripts, {
20
+ manifest,
21
+ ignore: rootConfig.ignoreBinaries,
22
+ knownGlobalsOnly: true,
23
+ });
24
+ return binaries;
25
+ };
26
+ export const findDependencies = timerify(findGithubActionsDependencies);
@@ -5,10 +5,13 @@ export * as commitlint from './commitlint/index.js';
5
5
  export * as cypress from './cypress/index.js';
6
6
  export * as eslint from './eslint/index.js';
7
7
  export * as gatsby from './gatsby/index.js';
8
+ export * as githubActions from './github-actions/index.js';
8
9
  export * as jest from './jest/index.js';
9
10
  export * as lintStaged from './lint-staged/index.js';
11
+ export * as markdownlint from './markdownlint/index.js';
10
12
  export * as mocha from './mocha/index.js';
11
13
  export * as next from './next/index.js';
14
+ export * as npmPackageJsonLint from './npm-package-json-lint/index.js';
12
15
  export * as nx from './nx/index.js';
13
16
  export * as nyc from './nyc/index.js';
14
17
  export * as playwright from './playwright/index.js';
@@ -5,10 +5,13 @@ export * as commitlint from './commitlint/index.js';
5
5
  export * as cypress from './cypress/index.js';
6
6
  export * as eslint from './eslint/index.js';
7
7
  export * as gatsby from './gatsby/index.js';
8
+ export * as githubActions from './github-actions/index.js';
8
9
  export * as jest from './jest/index.js';
9
10
  export * as lintStaged from './lint-staged/index.js';
11
+ export * as markdownlint from './markdownlint/index.js';
10
12
  export * as mocha from './mocha/index.js';
11
13
  export * as next from './next/index.js';
14
+ export * as npmPackageJsonLint from './npm-package-json-lint/index.js';
12
15
  export * as nx from './nx/index.js';
13
16
  export * as nyc from './nyc/index.js';
14
17
  export * as playwright from './playwright/index.js';
@@ -1,4 +1,4 @@
1
- import { getBinariesFromScripts } from '../../manifest/helpers.js';
1
+ import { getBinariesFromScripts } from '../../util/binaries/index.js';
2
2
  import { _load } from '../../util/loader.js';
3
3
  import { timerify } from '../../util/performance.js';
4
4
  import { hasDependency } from '../../util/plugin.js';
@@ -13,7 +13,7 @@ export const CONFIG_FILE_PATTERNS = [
13
13
  'lint-staged.config.{js,mjs,cjs}',
14
14
  'package.json',
15
15
  ];
16
- const findLintStagedDependencies = async (configFilePath, { manifest }) => {
16
+ const findLintStagedDependencies = async (configFilePath, { manifest, rootConfig }) => {
17
17
  let config = configFilePath.endsWith('package.json')
18
18
  ? manifest['lint-staged']
19
19
  : await _load(configFilePath);
@@ -25,7 +25,7 @@ const findLintStagedDependencies = async (configFilePath, { manifest }) => {
25
25
  const binaries = new Set();
26
26
  for (const entry of Object.values(config).flat()) {
27
27
  const scripts = [typeof entry === 'function' ? await entry([]) : entry].flat();
28
- getBinariesFromScripts(scripts).forEach(binary => binaries.add(binary));
28
+ getBinariesFromScripts(scripts, { manifest, ignore: rootConfig.ignoreBinaries }).forEach(bin => binaries.add(bin));
29
29
  }
30
30
  return Array.from(binaries);
31
31
  };
@@ -0,0 +1,6 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const NAME = "markdownlint";
3
+ export declare const ENABLERS: string[];
4
+ export declare const isEnabled: IsPluginEnabledCallback;
5
+ export declare const CONFIG_FILE_PATTERNS: string[];
6
+ export declare const findDependencies: GenericPluginCallback;
@@ -0,0 +1,20 @@
1
+ import { _load } from '../../util/loader.js';
2
+ import { getPackageName } from '../../util/modules.js';
3
+ import { timerify } from '../../util/performance.js';
4
+ import { hasDependency, getArgumentValues } from '../../util/plugin.js';
5
+ export const NAME = 'markdownlint';
6
+ export const ENABLERS = ['markdownlint-cli'];
7
+ export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
8
+ export const CONFIG_FILE_PATTERNS = ['.markdownlint.{json,jsonc}', '.markdownlint.{yml,yaml}'];
9
+ const findMarkdownlintConfigDependencies = async (configFilePath, { manifest }) => {
10
+ const config = await _load(configFilePath);
11
+ const extend = config?.extends ? [getPackageName(config.extends)] : [];
12
+ const scripts = manifest.scripts
13
+ ? Object.values(manifest.scripts).filter((script) => typeof script === 'string')
14
+ : [];
15
+ const uses = scripts
16
+ .filter(script => script.includes('markdownlint '))
17
+ .flatMap(script => getArgumentValues(script, / (--rules|-r)[ =]([^ ]+)/g));
18
+ return [...extend, ...uses];
19
+ };
20
+ export const findDependencies = timerify(findMarkdownlintConfigDependencies);
@@ -0,0 +1,3 @@
1
+ export type MarkdownlintConfig = {
2
+ extends?: string;
3
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const NAME = "npm-package-json-lint";
3
+ export declare const ENABLERS: string[];
4
+ export declare const isEnabled: IsPluginEnabledCallback;
5
+ export declare const CONFIG_FILE_PATTERNS: string[];
6
+ export declare const findDependencies: GenericPluginCallback;
@@ -0,0 +1,14 @@
1
+ import { _load } from '../../util/loader.js';
2
+ import { timerify } from '../../util/performance.js';
3
+ import { hasDependency } from '../../util/plugin.js';
4
+ export const NAME = 'npm-package-json-lint';
5
+ export const ENABLERS = ['npm-package-json-lint'];
6
+ export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
7
+ export const CONFIG_FILE_PATTERNS = ['.npmpackagejsonlintrc.json', 'npmpackagejsonlint.config.js', 'package.json'];
8
+ const findNpmPkgJsonLintConfigDependencies = async (configFilePath, { manifest }) => {
9
+ const config = configFilePath.endsWith('package.json')
10
+ ? manifest.npmpackagejsonlint
11
+ : await _load(configFilePath);
12
+ return config?.extends ? [config.extends] : [];
13
+ };
14
+ export const findDependencies = timerify(findNpmPkgJsonLintConfigDependencies);
@@ -0,0 +1,3 @@
1
+ export type NpmPkgJsonLintConfig = {
2
+ extends?: string;
3
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  declare const _default: {
2
- symbols: ({ report, issues }: import("../types/issues.js").ReporterOptions) => void;
3
- compact: ({ report, issues }: import("../types/issues.js").ReporterOptions) => void;
4
- codeowners: ({ report, issues, options }: import("../types/issues.js").ReporterOptions) => void;
5
- json: ({ report, issues, options }: import("../types/issues.js").ReporterOptions) => Promise<void>;
2
+ symbols: ({ report, issues }: import("../index.js").ReporterOptions) => void;
3
+ compact: ({ report, issues }: import("../index.js").ReporterOptions) => void;
4
+ codeowners: ({ report, issues, options }: import("../index.js").ReporterOptions) => void;
5
+ json: ({ report, issues, options }: import("../index.js").ReporterOptions) => Promise<void>;
6
6
  };
7
7
  export default _default;
@@ -1,4 +1,7 @@
1
+ import { z } from 'zod';
2
+ import { ConfigurationValidator } from '../configuration-validator.js';
1
3
  import * as Plugins from '../plugins/index.js';
4
+ export type RawConfiguration = z.infer<typeof ConfigurationValidator>;
2
5
  type NormalizedGlob = string[];
3
6
  export type PluginName = keyof typeof Plugins;
4
7
  export type PluginConfiguration = {
@@ -1,4 +1,4 @@
1
- import { PluginConfiguration, WorkspaceConfiguration } from './config.js';
1
+ import { Configuration, PluginConfiguration, WorkspaceConfiguration } from './config.js';
2
2
  import type { PackageJson } from 'type-fest';
3
3
  type IsPluginEnabledCallbackOptions = {
4
4
  manifest: PackageJson;
@@ -10,6 +10,7 @@ type GenericPluginCallbackOptions = {
10
10
  manifest: PackageJson;
11
11
  config: PluginConfiguration;
12
12
  workspaceConfig: WorkspaceConfiguration;
13
+ rootConfig: Configuration;
13
14
  isProduction: boolean;
14
15
  };
15
16
  export type GenericPluginCallback = (configFilePath: string, { cwd, manifest, config, workspaceConfig, isProduction }: GenericPluginCallbackOptions) => Promise<string[]> | string[];
@@ -0,0 +1 @@
1
+ export declare const resolve: (binary: string, args: string[]) => string[];
@@ -0,0 +1,5 @@
1
+ import { getDependenciesFromLoaderArguments } from '../index.js';
2
+ export const resolve = (binary, args) => {
3
+ const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
4
+ return [binary, args[0], ...dependenciesFromArguments];
5
+ };
@@ -0,0 +1 @@
1
+ export declare const resolve: (binary: string, args: string[]) => string[];
@@ -0,0 +1,5 @@
1
+ import { getDependenciesFromLoaderArguments } from '../index.js';
2
+ export const resolve = (binary, args) => {
3
+ const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
4
+ return [binary, args[0], ...dependenciesFromArguments];
5
+ };
@@ -0,0 +1,2 @@
1
+ export * as crossEnv from './cross-env.js';
2
+ export * as dotenv from './dotenv.js';
@@ -0,0 +1,2 @@
1
+ export * as crossEnv from './cross-env.js';
2
+ export * as dotenv from './dotenv.js';
@@ -0,0 +1,4 @@
1
+ export * as node from './node.js';
2
+ export * as npx from './npx.js';
3
+ export * as pnpm from './pnpm.js';
4
+ export * as yarn from './yarn.js';
@@ -0,0 +1,4 @@
1
+ export * as node from './node.js';
2
+ export * as npx from './npx.js';
3
+ export * as pnpm from './pnpm.js';
4
+ export * as yarn from './yarn.js';
@@ -0,0 +1 @@
1
+ export declare const resolve: (binary: string, args: string[]) => string[];
@@ -0,0 +1,5 @@
1
+ import { getDependenciesFromLoaderArguments } from '../index.js';
2
+ export const resolve = (binary, args) => {
3
+ const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
4
+ return dependenciesFromArguments;
5
+ };
@@ -0,0 +1 @@
1
+ export declare const resolve: (binary: string, args: string[]) => (string | undefined)[];
@@ -0,0 +1,8 @@
1
+ import { getDependenciesFromLoaderArguments } from '../index.js';
2
+ export const resolve = (binary, args) => {
3
+ if (/-y|--yes/.test(args[0]))
4
+ return [];
5
+ const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
6
+ const firstArgument = args.find(arg => !arg.startsWith('-'));
7
+ return [firstArgument, ...dependenciesFromArguments];
8
+ };
@@ -0,0 +1,2 @@
1
+ import type { PackageJson } from 'type-fest';
2
+ export declare const resolve: (binary: string, args: string[], manifest: PackageJson) => string | never[] | undefined;
@@ -0,0 +1,43 @@
1
+ const commands = [
2
+ 'add',
3
+ 'i',
4
+ 'install',
5
+ 'up',
6
+ 'update',
7
+ 'upgrade',
8
+ 'remove',
9
+ 'rm',
10
+ 'uninstall',
11
+ 'un',
12
+ 'link',
13
+ 'ln',
14
+ 'unlink',
15
+ 'import',
16
+ 'rebuild',
17
+ 'rb',
18
+ 'prune',
19
+ 'fetch',
20
+ 'install-test',
21
+ 'it',
22
+ 'patch',
23
+ 'patch-commit',
24
+ 'audit',
25
+ 'list',
26
+ 'ls',
27
+ 'outdated',
28
+ 'why',
29
+ 'test',
30
+ 't',
31
+ 'tst',
32
+ ];
33
+ export const resolve = (binary, args, manifest) => {
34
+ const scripts = manifest.scripts ? Object.keys(manifest.scripts) : [];
35
+ const [command, ...commandArgs] = args;
36
+ if (scripts.includes(command) || commands.includes(command))
37
+ return [];
38
+ if (command === 'run' && scripts.includes(commandArgs[0]))
39
+ return [];
40
+ if (command === 'run' || command === 'exec')
41
+ return commandArgs.find(arg => !arg.startsWith('-'));
42
+ return args.find(arg => !arg.startsWith('-'));
43
+ };
@@ -0,0 +1,2 @@
1
+ import type { PackageJson } from 'type-fest';
2
+ export declare const resolve: (binary: string, args: string[], manifest: PackageJson) => string | never[] | undefined;
@@ -0,0 +1,42 @@
1
+ const commands = [
2
+ 'add',
3
+ 'bin',
4
+ 'cache',
5
+ 'config',
6
+ 'constraints',
7
+ 'dedupe',
8
+ 'dlx',
9
+ 'explain',
10
+ 'info',
11
+ 'init',
12
+ 'install',
13
+ 'link',
14
+ 'pack',
15
+ 'patch',
16
+ 'patch-commit',
17
+ 'plugin',
18
+ 'rebuild',
19
+ 'remove',
20
+ 'search',
21
+ 'set',
22
+ 'stage',
23
+ 'unlink',
24
+ 'unplug',
25
+ 'up',
26
+ 'upgrade-interactive',
27
+ 'version',
28
+ 'why',
29
+ 'workspace',
30
+ 'workspaces',
31
+ ];
32
+ export const resolve = (binary, args, manifest) => {
33
+ const scripts = manifest.scripts ? Object.keys(manifest.scripts) : [];
34
+ const [command, ...commandArgs] = args;
35
+ if (scripts.includes(command) || commands.includes(command))
36
+ return [];
37
+ if (command === 'run' && scripts.includes(commandArgs[0]))
38
+ return [];
39
+ if (command === 'run' || command === 'exec')
40
+ return commandArgs.find(arg => !arg.startsWith('-'));
41
+ return args.find(arg => !arg.startsWith('-'));
42
+ };
@@ -0,0 +1,7 @@
1
+ import type { PackageJson } from 'type-fest';
2
+ export declare const getDependenciesFromLoaderArguments: (args: string[]) => string[];
3
+ export declare const getBinariesFromScripts: (npmScripts: string[], { manifest, ignore, knownGlobalsOnly, }: {
4
+ manifest: PackageJson;
5
+ ignore?: string[] | undefined;
6
+ knownGlobalsOnly?: boolean | undefined;
7
+ }) => string[];
@@ -0,0 +1,46 @@
1
+ import { IGNORED_GLOBAL_BINARIES } from '../../constants.js';
2
+ import { getArgumentValues } from '../plugin.js';
3
+ import { toCamelCase } from '../plugin.js';
4
+ import * as BinaryResolvers from './binaries/index.js';
5
+ import * as GlobalBinaryResolvers from './globals/index.js';
6
+ const normalizeBinaries = (command) => command
7
+ .replace(/(\.\/)?node_modules\/\.bin\/(\w+)/, '$2')
8
+ .replace(/\$\(npm bin\)\/(\w+)/, '$1')
9
+ .replace(/(\S+)@.*/, '$1');
10
+ const stripEnvironmentVariables = (value) => value.replace(/([A-Z][^ ]*)=([^ ])+ /g, '');
11
+ const getLoaderArgumentValues = (value) => getArgumentValues(value, / (--(experimental-)?loader|--require|-r)[ =]([^ ]+)/g);
12
+ export const getDependenciesFromLoaderArguments = (args) => getLoaderArgumentValues(' ' + args.join(' '))
13
+ .filter(scripts => !scripts.startsWith('.'))
14
+ .map(script => {
15
+ if (script.startsWith('@')) {
16
+ const [scope, packageName] = script.split('/');
17
+ return [scope, packageName].join('/');
18
+ }
19
+ return script.split('/')[0];
20
+ });
21
+ export const getBinariesFromScripts = (npmScripts, { manifest, ignore = [], knownGlobalsOnly = false, }) => Array.from(npmScripts.reduce((binaries, script) => {
22
+ script
23
+ .split(' && ')
24
+ .flatMap(command => command.split(' -- '))
25
+ .map(normalizeBinaries)
26
+ .filter(command => /^\w/.test(command))
27
+ .map(stripEnvironmentVariables)
28
+ .flatMap(command => {
29
+ const [binary, ...args] = command.trim().split(' ');
30
+ const camelCased = toCamelCase(binary);
31
+ if (['bun', 'deno'].includes(binary))
32
+ return [];
33
+ if (camelCased in GlobalBinaryResolvers) {
34
+ return GlobalBinaryResolvers[camelCased].resolve(binary, args, manifest);
35
+ }
36
+ if (knownGlobalsOnly)
37
+ return [];
38
+ if (camelCased in BinaryResolvers) {
39
+ return BinaryResolvers[camelCased].resolve(binary, args);
40
+ }
41
+ const dependenciesFromArguments = getDependenciesFromLoaderArguments(args);
42
+ return [binary, ...dependenciesFromArguments];
43
+ })
44
+ .forEach(binary => binary && binaries.add(binary));
45
+ return binaries;
46
+ }, new Set())).filter(binaryName => !IGNORED_GLOBAL_BINARIES.includes(binaryName) && !ignore.includes(binaryName));
@@ -47,13 +47,3 @@ export const debugLogIssues = (name, issues) => {
47
47
  console.debug(`[knip] ${name} (${symbols.length})`);
48
48
  logArray(symbols);
49
49
  };
50
- const debugLogDiff = (name, arrA, arrB) => {
51
- const onlyInA = arrA.filter(itemA => !arrB.includes(itemA)).sort();
52
- const onlyInB = arrB.filter(itemB => !arrA.includes(itemB)).sort();
53
- console.log(`[knip] ${name}`);
54
- console.log(`[knip] Only in left:`);
55
- logArray(onlyInA);
56
- console.log();
57
- console.log(`[knip] Only in right:`);
58
- logArray(onlyInB);
59
- };
package/dist/util/fs.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const isFile: (filePath: string) => Promise<boolean>;
2
- export declare const findFile: (workingDir: string, fileName: string) => Promise<string | undefined>;
1
+ export declare const isFile: (filePath: string) => boolean;
2
+ export declare const findFile: (workingDir: string, fileName: string) => string | undefined;
3
3
  export declare const loadJSON: (filePath: string) => Promise<any>;
package/dist/util/fs.js CHANGED
@@ -1,20 +1,16 @@
1
- import fs from 'node:fs/promises';
1
+ import { statSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import stripJsonComments from 'strip-json-comments';
4
- export const isFile = async (filePath) => {
5
- try {
6
- const stats = await fs.stat(filePath);
7
- return stats.isFile();
8
- }
9
- catch {
10
- return false;
11
- }
5
+ export const isFile = (filePath) => {
6
+ const stat = statSync(filePath, { throwIfNoEntry: false });
7
+ return stat !== undefined && stat.isFile();
12
8
  };
13
- export const findFile = async (workingDir, fileName) => {
9
+ export const findFile = (workingDir, fileName) => {
14
10
  const filePath = path.join(workingDir, fileName);
15
- return (await isFile(filePath)) ? filePath : undefined;
11
+ return isFile(filePath) ? filePath : undefined;
16
12
  };
17
13
  export const loadJSON = async (filePath) => {
18
- const contents = await fs.readFile(filePath);
14
+ const contents = await readFile(filePath);
19
15
  return JSON.parse(stripJsonComments(contents.toString()));
20
16
  };
@@ -0,0 +1 @@
1
+ export declare const getValuesByKeyDeep: (obj: any, key: string) => unknown[];
@@ -0,0 +1,15 @@
1
+ export const getValuesByKeyDeep = (obj, key) => {
2
+ const objects = [];
3
+ if (obj && typeof obj === 'object') {
4
+ for (const i in obj) {
5
+ if (obj[i] && typeof obj[i] === 'object') {
6
+ const values = getValuesByKeyDeep(obj[i], key);
7
+ objects.push(...values);
8
+ }
9
+ else if (i === key) {
10
+ objects.push(obj[i]);
11
+ }
12
+ }
13
+ }
14
+ return objects;
15
+ };
@@ -1 +1,3 @@
1
+ export declare const toCamelCase: (name: string) => string;
2
+ export declare const getArgumentValues: (value: string, matcher: RegExp) => string[];
1
3
  export declare const hasDependency: (dependencies: Set<string>, values: (string | RegExp)[]) => boolean;
@@ -1,3 +1,10 @@
1
+ export const toCamelCase = (name) => name.toLowerCase().replace(/(-[a-z])/g, group => group.toUpperCase().replace('-', ''));
2
+ export const getArgumentValues = (value, matcher) => {
3
+ const match = value.match(matcher);
4
+ if (match)
5
+ return match.map(value => value.trim().split(/[ =]/)[1].trim());
6
+ return [];
7
+ };
1
8
  export const hasDependency = (dependencies, values) => values.some(value => {
2
9
  if (typeof value === 'string') {
3
10
  return dependencies.has(value);
@@ -229,6 +229,7 @@ export default class WorkspaceWorker {
229
229
  cwd,
230
230
  manifest: this.manifest,
231
231
  config: pluginConfig,
232
+ rootConfig: this.rootConfig,
232
233
  workspaceConfig: this.config,
233
234
  isProduction: this.isProduction,
234
235
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.2.0",
3
+ "version": "1.4.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",
@@ -10,11 +10,12 @@
10
10
  "name": "Lars Kappert",
11
11
  "email": "lars@webpro.nl"
12
12
  },
13
- "main": "dist/index.js",
13
+ "main": "./dist/index.js",
14
14
  "bin": {
15
- "knip": "dist/cli.js"
15
+ "knip": "./dist/cli.js"
16
16
  },
17
17
  "type": "module",
18
+ "types": "./dist/index.d.ts",
18
19
  "scripts": {
19
20
  "knip": "node ./dist/cli.js",
20
21
  "knip:production": "node ./dist/cli.js --production --strict",
@@ -42,9 +43,9 @@
42
43
  "@snyk/github-codeowners": "1.1.0",
43
44
  "chalk": "5.2.0",
44
45
  "easy-table": "1.2.0",
45
- "esbuild": "0.16.16",
46
+ "esbuild": "0.17.0",
46
47
  "esbuild-register": "3.4.2",
47
- "eslint": "8.31.0",
48
+ "eslint": "8.32.0",
48
49
  "fast-glob": "3.2.12",
49
50
  "get-tsconfig": "4.3.0",
50
51
  "globby": "13.1.3",
@@ -77,7 +78,7 @@
77
78
  "remark-cli": "11.0.0",
78
79
  "remark-preset-webpro": "0.0.1",
79
80
  "tsx": "3.12.2",
80
- "type-fest": "3.5.1",
81
+ "type-fest": "3.5.2",
81
82
  "typescript": "4.9.4"
82
83
  },
83
84
  "engines": {
package/schema.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "properties": {
24
24
  "ignoreBinaries": {
25
25
  "title": "Binaries to ignore",
26
- "examples": ["rm", "docker-compose", "eslint"],
26
+ "examples": ["rm", "docker-compose", "curl"],
27
27
  "$ref": "#/definitions/list"
28
28
  },
29
29
  "ignoreDependencies": {
@@ -184,6 +184,10 @@
184
184
  "title": "Gatsby plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/gatsby/README.md)",
185
185
  "$ref": "#/definitions/plugin"
186
186
  },
187
+ "github-actions": {
188
+ "title": "github-actions plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/github-actions/README.md)",
189
+ "$ref": "#/definitions/plugin"
190
+ },
187
191
  "jest": {
188
192
  "title": "Jest plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/jest/README.md)",
189
193
  "$ref": "#/definitions/plugin"
@@ -192,6 +196,10 @@
192
196
  "title": "lint-staged plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/lint-staged/README.md)",
193
197
  "$ref": "#/definitions/plugin"
194
198
  },
199
+ "markdownlint": {
200
+ "title": "markdownlint plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/markdownlint/README.md)",
201
+ "$ref": "#/definitions/plugin"
202
+ },
195
203
  "mocha": {
196
204
  "title": "Mocha plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/mocha/README.md)",
197
205
  "$ref": "#/definitions/plugin"
@@ -200,6 +208,10 @@
200
208
  "title": "Next.js plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/main/README.md)",
201
209
  "$ref": "#/definitions/plugin"
202
210
  },
211
+ "npm-package-json-lint": {
212
+ "title": "npm-package-json-lint plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/npm-package-json-lint/README.md)",
213
+ "$ref": "#/definitions/plugin"
214
+ },
203
215
  "nx": {
204
216
  "title": "Nx plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/nx/README.md)",
205
217
  "$ref": "#/definitions/plugin"