knip 1.15.0 → 1.16.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
@@ -297,13 +297,14 @@ Knip contains a growing list of plugins:
297
297
  - [Remark][36]
298
298
  - [Remix][37]
299
299
  - [Rollup][38]
300
- - [Sentry][39]
301
- - [Storybook][40]
302
- - [Stryker][41]
303
- - [TypeDoc][42]
304
- - [TypeScript][43]
305
- - [Vitest][44]
306
- - [Webpack][45]
300
+ - [Semantic Release][39]
301
+ - [Sentry][40]
302
+ - [Storybook][41]
303
+ - [Stryker][42]
304
+ - [TypeDoc][43]
305
+ - [TypeScript][44]
306
+ - [Vitest][45]
307
+ - [Webpack][46]
307
308
 
308
309
  Plugins are automatically activated. Each plugin is automatically enabled based on simple heuristics. Most of them check
309
310
  whether one or one of a few (dev) dependencies are listed in `package.json`. Once enabled, they add a set of
@@ -311,7 +312,7 @@ configuration and/or entry files for Knip to analyze. These defaults can be over
311
312
 
312
313
  Most plugins use one or both of the following file types:
313
314
 
314
- - `config` - custom dependency resolvers are applied to the [config files][46]
315
+ - `config` - custom dependency resolvers are applied to the [config files][47]
315
316
  - `entry` - files to include with the analysis of the rest of the source code
316
317
 
317
318
  See each plugin's documentation for its default values.
@@ -337,7 +338,7 @@ Other configuration files use `require` or `import` statements to use dependenci
337
338
  rest of the source files. These configuration files are also considered `entry` files.
338
339
 
339
340
  For plugins related to test files, it's good to know that the following glob patterns are always included by default
340
- (see [TEST_FILE_PATTERNS in constants.ts][47]):
341
+ (see [TEST_FILE_PATTERNS in constants.ts][48]):
341
342
 
342
343
  - `**/*.{test,spec}.{js,jsx,ts,tsx,mjs,cjs}`
343
344
  - `**/__tests__/**/*.{js,jsx,ts,tsx,mjs,cjs}`
@@ -419,10 +420,10 @@ Each workspace can also have its own `paths` configured. Note that Knip `paths`
419
420
 
420
421
  Knip provides the following built-in reporters:
421
422
 
422
- - [`codeowners`][48]
423
- - [`compact`][49]
424
- - [`json`][50]
425
- - [`symbol`][51] (default)
423
+ - [`codeowners`][49]
424
+ - [`compact`][50]
425
+ - [`json`][51]
426
+ - [`symbol`][52] (default)
426
427
 
427
428
  The `compact` reporter shows the sorted files first, and then a list of symbols:
428
429
 
@@ -449,7 +450,7 @@ type ReporterOptions = {
449
450
 
450
451
  The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
451
452
 
452
- Find more details and ideas in [custom reporters][52].
453
+ Find more details and ideas in [custom reporters][53].
453
454
 
454
455
  ## Libraries and "unused" exports
455
456
 
@@ -503,11 +504,11 @@ instance by ignoring specific folders that are not related to the source code im
503
504
  Dependencies that are only imported in unused files are also marked as unused. So a long list of unused files would be
504
505
  good to remedy first.
505
506
 
506
- When unused dependencies are related to dependencies having a Knip [plugin][1], maybe the `config` and/or `entry` files
507
+ When unused dependencies are related to dependencies having a Knip [plugin][2], maybe the `config` and/or `entry` files
507
508
  for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
508
509
  to match the custom location(s).
509
510
 
510
- When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][53].
511
+ When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][54].
511
512
 
512
513
  #### Too many unused exports
513
514
 
@@ -515,7 +516,7 @@ When the project is a library and the exports are meant to be used by consumers
515
516
 
516
517
  1. By default, unused exports of `entry` files are not reported. You could re-export from an existing entry file, or
517
518
  add the containing file to the `entry` array in the configuration.
518
- 2. The exported values or types can be marked [using the JSDoc `@public` tag][54].
519
+ 2. The exported values or types can be marked [using the JSDoc `@public` tag][55].
519
520
 
520
521
  ### How to start using Knip in CI while having too many issues to sort out?
521
522
 
@@ -535,22 +536,22 @@ All of this is hiding problems, so please make sure to plan for fixing them and/
535
536
 
536
537
  This table is an ongoing comparison. Based on their docs (please report any mistakes):
537
538
 
538
- | Feature | **knip** | [depcheck][55] | [unimported][56] | [ts-unused-exports][57] | [ts-prune][58] |
539
- | :--------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
540
- | Unused files | ✅ | - | ✅ | - | - |
541
- | Unused dependencies | ✅ | ✅ | ✅ | - | - |
542
- | Unlisted dependencies | ✅ | ✅ | ✅ | - | - |
543
- | [Plugins][1] | ✅ | ✅ | ❌ | - | - |
544
- | Unused exports | ✅ | - | - | ✅ | ✅ |
545
- | Unused class members | ✅ | - | - | - | - |
546
- | Unused enum members | ✅ | - | - | - | - |
547
- | Duplicate exports | ✅ | - | - | ❌ | ❌ |
548
- | Search namespaces | ✅ | - | - | ✅ | ❌ |
549
- | Custom reporters | ✅ | - | - | - | - |
550
- | JavaScript support | ✅ | ✅ | ✅ | - | - |
551
- | Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ |
552
- | [Support workspaces/monorepos][52] | ✅ | ❌ | ❌ | - | - |
553
- | ESLint plugin available | - | - | - | ✅ | - |
539
+ | Feature | **knip** | [depcheck][56] | [unimported][57] | [ts-unused-exports][58] | [ts-prune][59] |
540
+ | :-------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
541
+ | Unused files | ✅ | - | ✅ | - | - |
542
+ | Unused dependencies | ✅ | ✅ | ✅ | - | - |
543
+ | Unlisted dependencies | ✅ | ✅ | ✅ | - | - |
544
+ | [Plugins][2] | ✅ | ✅ | ❌ | - | - |
545
+ | Unused exports | ✅ | - | - | ✅ | ✅ |
546
+ | Unused class members | ✅ | - | - | - | - |
547
+ | Unused enum members | ✅ | - | - | - | - |
548
+ | Duplicate exports | ✅ | - | - | ❌ | ❌ |
549
+ | Search namespaces | ✅ | - | - | ✅ | ❌ |
550
+ | Custom reporters | ✅ | - | - | - | - |
551
+ | JavaScript support | ✅ | ✅ | ✅ | - | - |
552
+ | Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ |
553
+ | [Support workspaces/monorepos][1] | ✅ | ❌ | ❌ | - | - |
554
+ | ESLint plugin available | - | - | - | ✅ | - |
554
555
 
555
556
  ✅ = Supported, ❌ = Not supported, - = Out of scope
556
557
 
@@ -570,7 +571,7 @@ The following commands are similar:
570
571
  unimported
571
572
  knip --production --dependencies --include files
572
573
 
573
- Also see [production mode][59].
574
+ Also see [production mode][60].
574
575
 
575
576
  ### ts-unused-exports
576
577
 
@@ -600,6 +601,12 @@ userland territory, much like code linters.
600
601
  Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
601
602
  for the job. I'm motivated to make knip perfectly suited for the job of cutting projects to perfection! ✂️
602
603
 
604
+ ## Contributors
605
+
606
+ Special thanks to the wonderful people who have contributed to this project:
607
+
608
+ [![Contributors][62]][61]
609
+
603
610
  [1]: #workspaces--monorepos
604
611
  [2]: #plugins
605
612
  [3]: #reporters
@@ -638,24 +645,27 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
638
645
  [36]: ./src/plugins/remark
639
646
  [37]: ./src/plugins/remix
640
647
  [38]: ./src/plugins/rollup
641
- [39]: ./src/plugins/sentry
642
- [40]: ./src/plugins/storybook
643
- [41]: ./src/plugins/stryker
644
- [42]: ./src/plugins/typedoc
645
- [43]: ./src/plugins/typescript
646
- [44]: ./src/plugins/vitest
647
- [45]: ./src/plugins/webpack
648
- [46]: #config
649
- [47]: https://github.com/webpro/knip/blob/main/src/constants.ts
650
- [48]: #code-owners
651
- [49]: #compact
652
- [50]: #json
653
- [51]: #symbol-default
654
- [52]: ./docs/custom-reporters.md
655
- [53]: #create-a-new-plugin
656
- [54]: #libraries-and-unused-exports
657
- [55]: https://github.com/depcheck/depcheck
658
- [56]: https://github.com/smeijer/unimported
659
- [57]: https://github.com/pzavolinsky/ts-unused-exports
660
- [58]: https://github.com/nadeesha/ts-prune
661
- [59]: #production-mode
648
+ [39]: ./src/plugins/semantic-release
649
+ [40]: ./src/plugins/sentry
650
+ [41]: ./src/plugins/storybook
651
+ [42]: ./src/plugins/stryker
652
+ [43]: ./src/plugins/typedoc
653
+ [44]: ./src/plugins/typescript
654
+ [45]: ./src/plugins/vitest
655
+ [46]: ./src/plugins/webpack
656
+ [47]: #config
657
+ [48]: https://github.com/webpro/knip/blob/main/src/constants.ts
658
+ [49]: #code-owners
659
+ [50]: #compact
660
+ [51]: #json
661
+ [52]: #symbol-default
662
+ [53]: ./docs/custom-reporters.md
663
+ [54]: #create-a-new-plugin
664
+ [55]: #libraries-and-unused-exports
665
+ [56]: https://github.com/depcheck/depcheck
666
+ [57]: https://github.com/smeijer/unimported
667
+ [58]: https://github.com/pzavolinsky/ts-unused-exports
668
+ [59]: https://github.com/nadeesha/ts-prune
669
+ [60]: #production-mode
670
+ [61]: https://github.com/webpro/knip/graphs/contributors
671
+ [62]: https://contrib.rocks/image?repo=webpro/knip
package/dist/cli.js CHANGED
File without changes
@@ -24,6 +24,7 @@ export * as releaseIt from './release-it/index.js';
24
24
  export * as remark from './remark/index.js';
25
25
  export * as remix from './remix/index.js';
26
26
  export * as rollup from './rollup/index.js';
27
+ export * as semanticRelease from './semantic-release/index.js';
27
28
  export * as sentry from './sentry/index.js';
28
29
  export * as storybook from './storybook/index.js';
29
30
  export * as stryker from './stryker/index.js';
@@ -24,6 +24,7 @@ export * as releaseIt from './release-it/index.js';
24
24
  export * as remark from './remark/index.js';
25
25
  export * as remix from './remix/index.js';
26
26
  export * as rollup from './rollup/index.js';
27
+ export * as semanticRelease from './semantic-release/index.js';
27
28
  export * as sentry from './sentry/index.js';
28
29
  export * as storybook from './storybook/index.js';
29
30
  export * as stryker from './stryker/index.js';
@@ -0,0 +1,6 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const NAME = "Semantic Release";
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,18 @@
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 = 'Semantic Release';
5
+ export const ENABLERS = ['semantic-release'];
6
+ export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
7
+ export const CONFIG_FILE_PATTERNS = [
8
+ '.releaserc',
9
+ '.releaserc.{yaml,yml,json,js,cjs}',
10
+ 'release.config.{js,cjs}',
11
+ 'package.json',
12
+ ];
13
+ const findPluginDependencies = async (configFilePath, { manifest }) => {
14
+ const config = configFilePath.endsWith('package.json') ? manifest.release : await _load(configFilePath);
15
+ const plugins = config?.plugins ?? [];
16
+ return plugins.map(plugin => (Array.isArray(plugin) ? plugin[0] : plugin));
17
+ };
18
+ export const findDependencies = timerify(findPluginDependencies);
@@ -0,0 +1,3 @@
1
+ export type PluginConfig = {
2
+ plugins?: (string | [string, Record<string, unknown>])[];
3
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/util/fs.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  export declare const isFile: (filePath: string) => boolean;
2
2
  export declare const findFile: (workingDir: string, fileName: string) => string | undefined;
3
+ export declare const loadFile: (filePath: string) => Promise<string>;
3
4
  export declare const loadJSON: (filePath: string) => Promise<any>;
5
+ export declare const loadYAML: (filePath: string) => Promise<unknown>;
6
+ export declare const parseJSON: (contents: string) => Promise<any>;
7
+ export declare const parseYAML: (contents: string) => Promise<unknown>;
package/dist/util/fs.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { statSync } from 'node:fs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
+ import yaml from 'js-yaml';
4
5
  import stripJsonComments from 'strip-json-comments';
5
6
  import { LoaderError } from './errors.js';
6
7
  export const isFile = (filePath) => {
@@ -11,12 +12,26 @@ export const findFile = (workingDir, fileName) => {
11
12
  const filePath = path.join(workingDir, fileName);
12
13
  return isFile(filePath) ? filePath : undefined;
13
14
  };
14
- export const loadJSON = async (filePath) => {
15
+ export const loadFile = async (filePath) => {
15
16
  try {
16
17
  const contents = await readFile(filePath);
17
- return JSON.parse(stripJsonComments(contents.toString()));
18
+ return contents.toString();
18
19
  }
19
20
  catch (error) {
20
21
  throw new LoaderError(`Error loading ${filePath}`, { cause: error });
21
22
  }
22
23
  };
24
+ export const loadJSON = async (filePath) => {
25
+ const contents = await loadFile(filePath);
26
+ return parseJSON(contents);
27
+ };
28
+ export const loadYAML = async (filePath) => {
29
+ const contents = await loadFile(filePath);
30
+ return parseYAML(contents);
31
+ };
32
+ export const parseJSON = async (contents) => {
33
+ return JSON.parse(stripJsonComments(contents));
34
+ };
35
+ export const parseYAML = async (contents) => {
36
+ return yaml.load(contents);
37
+ };
@@ -1,20 +1,22 @@
1
- import fs from 'node:fs/promises';
2
1
  import path from 'node:path';
3
2
  import { pathToFileURL } from 'node:url';
4
3
  import { load as esmLoad } from '@esbuild-kit/esm-loader';
5
- import yaml from 'js-yaml';
6
4
  import { require } from '../util/require.js';
7
5
  import { LoaderError } from './errors.js';
8
- import { loadJSON } from './fs.js';
6
+ import { loadJSON, loadYAML, loadFile, parseJSON, parseYAML } from './fs.js';
9
7
  import { timerify } from './performance.js';
10
8
  const load = async (filePath) => {
11
9
  try {
12
10
  const ext = path.extname(filePath);
13
- if (ext === '.json' || ext === '.jsonc' || /rc$/.test(filePath)) {
11
+ if (/rc$/.test(filePath)) {
12
+ const contents = await loadFile(filePath);
13
+ return parseYAML(contents).catch(() => parseJSON(contents));
14
+ }
15
+ if (ext === '.json' || ext === '.jsonc') {
14
16
  return loadJSON(filePath);
15
17
  }
16
18
  if (ext === '.yaml' || ext === '.yml') {
17
- return yaml.load((await fs.readFile(filePath)).toString());
19
+ return loadYAML(filePath);
18
20
  }
19
21
  if (ext === '.mjs') {
20
22
  const fileUrl = pathToFileURL(filePath);
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "1.15.0";
1
+ export declare const version = "1.16.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '1.15.0';
1
+ export const version = '1.16.0';
@@ -51,7 +51,7 @@ export default class WorkspaceWorker {
51
51
  installedBinaries: InstalledBinaries;
52
52
  referencedDependencyIssues: ReferencedDependencyIssues;
53
53
  entryFiles: Set<string>;
54
- enabledPlugins: ("babel" | "capacitor" | "changesets" | "commitlint" | "cypress" | "eslint" | "gatsby" | "husky" | "jest" | "markdownlint" | "mocha" | "next" | "nx" | "nyc" | "playwright" | "postcss" | "prettier" | "remark" | "remix" | "rollup" | "sentry" | "storybook" | "stryker" | "typescript" | "vitest" | "webpack" | "cspell" | "githubActions" | "lefthook" | "lintStaged" | "npmPackageJsonLint" | "releaseIt" | "typedoc")[];
54
+ enabledPlugins: ("babel" | "capacitor" | "changesets" | "commitlint" | "cypress" | "eslint" | "gatsby" | "husky" | "jest" | "markdownlint" | "mocha" | "next" | "nx" | "nyc" | "playwright" | "postcss" | "prettier" | "remark" | "remix" | "rollup" | "sentry" | "storybook" | "stryker" | "typescript" | "vitest" | "webpack" | "cspell" | "githubActions" | "lefthook" | "lintStaged" | "npmPackageJsonLint" | "releaseIt" | "semanticRelease" | "typedoc")[];
55
55
  };
56
56
  }
57
57
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.15.0",
3
+ "version": "1.16.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",
package/schema.json CHANGED
@@ -268,6 +268,10 @@
268
268
  "title": "Rollup plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/rollup/README.md)",
269
269
  "$ref": "#/definitions/plugin"
270
270
  },
271
+ "semantic-release": {
272
+ "title": "semantic-release plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/semantic-release/README.md)",
273
+ "$ref": "#/definitions/plugin"
274
+ },
271
275
  "sentry": {
272
276
  "title": "Sentry plugin configuration (https://github.com/webpro/knip/blob/main/src/plugins/sentry/README.md)",
273
277
  "$ref": "#/definitions/plugin"