knip 0.7.1 → 0.7.3

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
@@ -1,42 +1,42 @@
1
1
  # ✂️ Knip
2
2
 
3
- Knip scans your JavaScript and TypeScript projects for **unused files, dependencies and exports**: things that can be
4
- removed! Less code means better performance and less to maintain, important for both UX and DX!
5
-
6
- For comparison, ESLint finds unused variables inside files in isolation, but this will not be flagged:
3
+ Knip finds **unused files, dependencies and exports** in your JavaScript and TypeScript projects. Less code leads to
4
+ improved performance, less maintenance and easier refactorings.
7
5
 
8
6
  ```ts
9
7
  export const myVar = true;
10
8
  ```
11
9
 
12
- Unused files will also not be detected by ESLint. So how do you know which files, dependencies and exports are no longer
13
- used? This requires an analysis of all the right files in the project.
10
+ ESLint handles files in isolation, so the `export` keyword "blocks" further analysis. Unused files and dependencies will
11
+ also not be detected. You could think of Knip as going (far!) beyond the `no-unused-vars` rule of ESLint. Knip lints the
12
+ project as a whole (or parts of it).
14
13
 
15
- This is where Knip comes in:
14
+ It's only human to forget removing things that you no longer use. But how do you find out? Where to even start finding
15
+ things that can be removed?
16
16
 
17
- - [x] Resolves all (unused) files in your project and reports **unused files, dependencies and exports**.
18
- - [x] Verifies that exported symbols are actually used in other files, even when part of an imported namespace.
17
+ The dots don't connect themselves. This is where Knip comes in:
18
+
19
+ - [x] Finds **unused files, dependencies and exports**.
19
20
  - [x] Finds dependencies not listed in `package.json`.
21
+ - [x] Verifies that exported symbols are actually used in other files, even when part of an imported namespace.
22
+ - [x] Supports JavaScript inside TypeScript projects (`"allowJs": true`).
20
23
  - [x] Finds duplicate exports of the same symbol.
21
- - [x] Supports JavaScript inside TypeScript projects (`"allowJs": true`)
22
- - [x] Supports JavaScript-only projects using ESM (without a `tsconfig.json`)
23
- - [x] Features multiple [reporters](#reporters) and supports [custom reporters](#custom-reporters).
24
+ - [x] Supports JavaScript ES Module-based projects without a `tsconfig.json`.
25
+ - [x] Features multiple [reporters][1] and supports [custom reporters][2].
24
26
 
25
- Knip really shines in larger projects where you have non-production files (such as `/docs`, `/tools` and `/scripts`).
26
- The `includes` setting in `tsconfig.json` is often too broad, resulting in too many false negatives. To produce good
27
- results it's essential to configure entry files. A comparison with similar toos answers the question
28
- [Why yet another unused file/dependency/export finder?](#why-yet-another-unused-filedependencyexport-finder)
27
+ Knip really shines in larger projects. A little bit of configuration will pay off, I promise. A comparison with similar
28
+ tools answers the question [why another unused file/dependency/export finder?][3]
29
29
 
30
30
  Knip is a fresh take on keeping your projects clean & tidy!
31
31
 
32
- [![An orange cow with scissors, Van Gogh style](./assets/cow-with-orange-scissors-van-gogh-style.webp)](https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC)
33
- <sup>_“An orange cow with scissors, Van Gogh style” - generated with OpenAI_</sup>
32
+ [![An orange cow with scissors, Van Gogh style][5]][4] <sup>_“An orange cow with scissors, Van Gogh style” - generated
33
+ with OpenAI_</sup>
34
34
 
35
35
  ## Installation
36
36
 
37
- ```
38
- npm install -D knip
39
- ```
37
+ npm install -D knip
38
+
39
+ Knip requires at least Node.js v16.17 or v18. Knip is _cutting edge!_
40
40
 
41
41
  ## Usage
42
42
 
@@ -54,112 +54,127 @@ all files it should match them against, including potentially unused files.
54
54
 
55
55
  Then run the checks:
56
56
 
57
- ```
58
- npx knip
59
- ```
57
+ npx knip
60
58
 
61
59
  This will analyze the project and output unused files, exports, types and duplicate exports.
62
60
 
63
- Use `--include files` when configuring knip the first time for faster initial results.
64
-
65
61
  ## How It Works
66
62
 
67
63
  Knip works by creating two sets of files:
68
64
 
69
- 1. Production code is the set of files resolved from the `entryFiles`.
70
- 2. They are matched against the set of `projectFiles`.
71
- 3. The subset of project files that is not production code will be reported as unused files (in red).
72
- 4. Then the production code (in blue) will be scanned for unused exports.
73
-
74
- ![How it works](./assets/how-it-works.drawio.svg)
65
+ 1. Production code is the set of files resolved from the `entryFiles`.
66
+ 2. They are matched against the set of `projectFiles`.
67
+ 3. The subset of project files that is not production code will be reported as unused files (in red).
68
+ 4. Then the production code (in blue) will be analyzed for unused exports.
75
69
 
76
- Please read on if you think you have too many results: [too many false positives?](#too-many-false-positives)
70
+ ![How it works][6]
77
71
 
78
72
  ## Options
79
73
 
80
- ```
81
- npx knip
82
- knip [options]
83
-
84
- Options:
85
- -c/--config [file] Configuration file path (default: ./knip.json or package.json#knip)
86
- -t/--tsConfig [file] TypeScript configuration path (default: ./tsconfig.json)
87
- --dir Working directory (default: current working directory)
88
- --include Report only listed issue group(s) (see below)
89
- --exclude Exclude issue group(s) from report (see below)
90
- --ignore Ignore files matching this glob pattern (can be set multiple times)
91
- --no-gitignore Don't use .gitignore
92
- --dev Include `devDependencies` in report(s)
93
- --no-progress Don't show dynamic progress updates
94
- --max-issues Maximum number of issues before non-zero exit code (default: 0)
95
- --reporter Select reporter: symbols, compact, codeowners (default: symbols)
96
- --reporter-options Pass extra options to the reporter (as JSON string, see example)
97
- --jsdoc Enable JSDoc parsing, with options: public
98
- --debug Show debug output
99
- --debug-level Set verbosity of debug output (default: 1, max: 2)
100
-
101
- Issue groups: files, dependencies, unlisted, exports, nsExports, types, nsTypes, duplicates
102
-
103
- Examples:
104
-
105
- $ knip
106
- $ knip --dir packages/client --include files
107
- $ knip -c ./knip.js --reporter compact --jsdoc public
108
- $ knip --ignore 'lib/**/*.ts' --ignore build
109
- $ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
110
-
111
- More info: https://github.com/webpro/knip
112
- ```
74
+ ❯ npx knip
75
+ knip [options]
76
+
77
+ Options:
78
+ -c/--config [file] Configuration file path (default: ./knip.json or package.json#knip)
79
+ -t/--tsConfig [file] TypeScript configuration path (default: ./tsconfig.json)
80
+ --dir Working directory (default: current working directory)
81
+ --include Report only listed issue type(s) (see below)
82
+ --exclude Exclude issue type(s) from report (see below)
83
+ --ignore Ignore files matching this glob pattern (can be set multiple times)
84
+ --no-gitignore Don't use .gitignore
85
+ --dev Include `devDependencies` in report(s)
86
+ --no-progress Don't show dynamic progress updates
87
+ --max-issues Maximum number of issues before non-zero exit code (default: 0)
88
+ --reporter Select reporter: symbols, compact, codeowners (default: symbols)
89
+ --reporter-options Pass extra options to the reporter (as JSON string, see example)
90
+ --jsdoc Enable JSDoc parsing, with options: public
91
+ --debug Show debug output
92
+ --debug-level Set verbosity of debug output (default: 1, max: 2)
93
+
94
+ Issue types: files, dependencies, unlisted, exports, nsExports, types, nsTypes, duplicates
95
+
96
+ Examples:
97
+
98
+ $ knip
99
+ $ knip --dir packages/client --include files
100
+ $ knip -c ./knip.js --reporter compact --jsdoc public
101
+ $ knip --ignore 'lib/**/*.ts' --ignore build
102
+ $ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
113
103
 
114
- 🚀 Knip is considerably faster when only the `files` and/or `duplicates` groups are included.
104
+ More info: https://github.com/webpro/knip
105
+
106
+ ## Performance
107
+
108
+ 🚀 Knip is considerably faster when only the `files` and/or `duplicates` types are included. Finding unused exports
109
+ requires deeper analysis (`exports`, `nsExports`, `types`, `nsTypes`). The following example commands do the same:
110
+
111
+ knip --include files --include duplicates
112
+ knip --include files,duplicates
115
113
 
116
114
  ## Reading the report
117
115
 
118
116
  After analyzing all the files resolved from the `entryFiles` against the `projectFiles`, the report contains the
119
- following groups of issues:
117
+ following types of issues:
120
118
 
121
119
  - `files` - Unused files: did not find references to this file
122
120
  - `dependencies` - Unused dependencies: did not find references to this dependency
123
- - `unlisted` - Unlisted dependencies: this dependency is used, but not listed in package.json (1)
121
+ - `unlisted` - Unlisted dependencies: imported dependencies, but not listed in package.json (1)
124
122
  - `exports` - Unused exports: did not find references to this exported variable
125
123
  - `nsExports` - Unused exports in namespaces: did not find direct references to this exported variable (2)
126
124
  - `types` - Unused types: did not find references to this exported type
127
125
  - `nsTypes` - Unused types in namespaces: did not find direct references to this exported variable (2)
128
- - `duplicates` - Duplicate exports: the same thing is exported more than once with different names
126
+ - `duplicates` - Duplicate exports: the same thing is exported more than once with different names from the same file
129
127
 
130
- Each group type can be an `--include` or `--exclude` to slice & dice the report to your needs.
128
+ 1. This may also include dependencies that could not be resolved properly (such as non-relative `local/dir/file.ts` not
129
+ and `local` not being in `node_modules`).
130
+ 2. The variable or type is not referenced directly, and has become a member of a namespace. That's why Knip is not sure
131
+ whether this export can be removed, so please look into it:
131
132
 
132
- 1. This may also include dependencies that could not be resolved properly, such as `local/dir/file.ts`.
133
- 2. The variable or type is not referenced directly, and has become a member of a namespace. That's why Knip is not sure
134
- whether this export can be removed, so please look into it:
133
+ You can `--include` or `--exclude` any of the types to slice & dice the report to your needs. Alternatively, they can be
134
+ added to the configuration (e.g. `"exclude": ["dependencies"]`).
135
135
 
136
136
  ## Now what?
137
137
 
138
138
  As always, make sure to backup files or use Git before deleting files or making changes. Run tests to verify results.
139
139
 
140
- - Unused files can be deleted.
140
+ - Unused files can be removed.
141
141
  - Unused dependencies can be removed from `package.json`.
142
142
  - Unlisted dependencies should be added to `package.json`.
143
- - Unused exports and types: remove the `export` keyword in front of unused exports. Then you (or tools such as ESLint)
144
- can see whether the variable or type is used within its own file. If this is not the case, it can be removed.
143
+ - Unused exports and types: remove the `export` keyword in front of unused exports. Then you (or tools such as the
144
+ TypeScript language server in VS Code and/or ESLint) can see whether the variable or type is used within the same
145
+ file. If this is not the case, it can be removed.
146
+
147
+ 🔁 Repeat the process to reveal new unused files and exports. Sometimes it's so liberating to remove things!
148
+
149
+ ## Production versus non-production code
145
150
 
146
- 🔁 Repeat the process to reveal new unused files and exports. Sometimes it's so liberating to delete things.
151
+ Feels like you're getting too many false positives? Let's talk about `entryFiles` and `projectFiles`.
147
152
 
148
- ## Too many false positives?
153
+ ### Production code
149
154
 
150
- The default configuration for Knip is very strict and targets production code. For best results, it is recommended to
151
- exclude files such as tests from the project files. Here's why: when including tests and other non-production files,
152
- they may import production files, which will prevent them from being reported as unused.
155
+ The default configuration for Knip is very strict and targets production code. Non-production files such as tests should
156
+ not be part of the `entryFiles` and `projectFiles`. Here's why: test and other non-production files often import
157
+ production files, which will prevent the production files from being reported as unused. For best results:
153
158
 
154
- Excluding non-production files from the `projectFiles` allows Knip to understand what production code can be removed
155
- (including dependent files!).
159
+ - Include only production entry files to the `entryFiles`.
160
+ - Include only and all production files to the `projectFiles`.
161
+ - If necessary, add globs to exclude non-production files from the `projectFiles` (using negation pattern).
156
162
 
157
- Non-production code includes files such as end-to-end tests, tooling, scripts, Storybook stories, etc.
163
+ This will ensure Knip understands what production code can be removed.
158
164
 
159
- Think of it the same way as you would split `dependencies` and `devDependencies` in `package.json`.
165
+ ### Non-production code
160
166
 
161
- To include both production and test files to analyze the project as a whole, include both sets of files to `entryFiles`,
162
- and add `dev: true` to a file named such as `knip.dev.json`:
167
+ Non-production code includes files such as unit tests, end-to-end tests, tooling, scripts, Storybook stories, etc. Think
168
+ of it the same way as the convention to split `dependencies` and `devDependencies` in `package.json`.
169
+
170
+ To analyze the project as a whole:
171
+
172
+ - Include both production entry files and test files to the `entryFiles`.
173
+ - Include all production files to the `projectFiles`.
174
+ - If necessary, add globs for non-production files to the `projectFiles`.
175
+ - Set `dev: true` in the configuration or add `--dev` as a command line flag (to add `devDependencies`).
176
+
177
+ Here's an example:
163
178
 
164
179
  ```json
165
180
  {
@@ -169,7 +184,7 @@ and add `dev: true` to a file named such as `knip.dev.json`:
169
184
  }
170
185
  ```
171
186
 
172
- Now use `-c knip.dev.json` to find unused files and exports for the combined set of files as configured in `entryFiles`.
187
+ Now use `-c knip.dev.json` to find unused files, dependencies and exports for the project as a whole.
173
188
 
174
189
  An alternative way to store `dev` configuration is in this example `package.json`:
175
190
 
@@ -190,7 +205,9 @@ An alternative way to store `dev` configuration is in this example `package.json
190
205
  }
191
206
  ```
192
207
 
193
- This way, the `--dev` flag will use the `dev` options (and also add `devDependencies` to the `dependencies` report).
208
+ Using the `--dev` flag will now switch to the non-production analysis.
209
+
210
+ Depending on the complexity of the project, be aware that it might require some fine-tuning on your end.
194
211
 
195
212
  ## More configuration examples
196
213
 
@@ -198,7 +215,7 @@ This way, the `--dev` flag will use the `dev` options (and also add `devDependen
198
215
 
199
216
  #### Separate packages
200
217
 
201
- In repos with multiple (published) packages, the `--dir` option comes in handy. With similar package structures, the
218
+ In repos with multiple (publishable) packages, the `--dir` option comes in handy. With similar package structures, the
202
219
  packages can be configured using globs:
203
220
 
204
221
  ```json
@@ -212,18 +229,18 @@ packages can be configured using globs:
212
229
 
213
230
  Packages can also be explicitly configured per package directory.
214
231
 
215
- To scan the packages separately, using the first match from the configuration file:
232
+ To analyze the packages separately, using the matching pattern from the configuration file:
216
233
 
217
- ```
218
- knip --dir packages/client
219
- knip --dir packages/services
220
- ```
234
+ knip --dir packages/client
235
+ knip --dir packages/services
221
236
 
222
237
  #### Connected projects
223
238
 
224
- A good example of a large project setup is a monorepo, such as created with Nx. Let's take an example project
225
- configuration for an Nx project using Next.js, Jest and Storybook. This configuration file can also be a JavaScript
226
- file, which allows to add logic and/or comments (e.g. `knip.js`):
239
+ A good example of a large project setup is a monorepo. Let's take an example (Nx) project configuration using Next.js,
240
+ Jest and Storybook, which has multiple apps and libs. They are not published separately and don't have their own
241
+ `package.json`.
242
+
243
+ This configuration file can also be a JavaScript file, which allows to add logic and/or comments (e.g. `knip.js`):
227
244
 
228
245
  ```js
229
246
  const entryFiles = ['apps/**/pages/**/*.{js,ts,tsx}'];
@@ -245,8 +262,8 @@ const projectFiles = [
245
262
  module.exports = { entryFiles, projectFiles };
246
263
  ```
247
264
 
248
- This should give good results about unused files and exports for the monorepo. After the first run, the configuration
249
- can be tweaked further to the project structure.
265
+ This should give good results about unused files, dependencies and exports for the monorepo. After the first run, the
266
+ configuration can be tweaked further to the project structure.
250
267
 
251
268
  ## Reporters
252
269
 
@@ -281,95 +298,88 @@ The data can then be used to write issues to `stdout`, a JSON or CSV file, or se
281
298
 
282
299
  The default reporter shows the sorted symbols first:
283
300
 
284
- ```
285
- $ knip
286
- --- UNUSED FILES (2)
287
- src/chat/helpers.ts
288
- src/components/SideBar.tsx
289
- --- UNUSED DEPENDENCIES (1)
290
- moment
291
- --- UNLISTED DEPENDENCIES (1)
292
- react
293
- --- UNUSED EXPORTS (5)
294
- lowercaseFirstLetter src/common/src/string/index.ts
295
- RegistrationBox src/components/Registration.tsx
296
- clamp src/css.ts
297
- restoreSession src/services/authentication.ts
298
- PREFIX src/services/authentication.ts
299
- --- UNUSED TYPES (4)
300
- enum RegistrationServices src/components/Registration/registrationMachine.ts
301
- type RegistrationAction src/components/Registration/registrationMachine.ts
302
- type ComponentProps src/components/Registration.tsx
303
- interface ProductDetail src/types/Product.ts
304
- --- DUPLICATE EXPORTS (2)
305
- Registration, default src/components/Registration.tsx
306
- ProductsList, default src/components/Products.tsx
307
- ```
301
+ $ knip
302
+ --- UNUSED FILES (2)
303
+ src/chat/helpers.ts
304
+ src/components/SideBar.tsx
305
+ --- UNUSED DEPENDENCIES (1)
306
+ moment
307
+ --- UNLISTED DEPENDENCIES (1)
308
+ react
309
+ --- UNUSED EXPORTS (5)
310
+ lowercaseFirstLetter src/common/src/string/index.ts
311
+ RegistrationBox src/components/Registration.tsx
312
+ clamp src/css.ts
313
+ restoreSession src/services/authentication.ts
314
+ PREFIX src/services/authentication.ts
315
+ --- UNUSED TYPES (4)
316
+ enum RegistrationServices src/components/Registration/registrationMachine.ts
317
+ type RegistrationAction src/components/Registration/registrationMachine.ts
318
+ type ComponentProps src/components/Registration.tsx
319
+ interface ProductDetail src/types/Product.ts
320
+ --- DUPLICATE EXPORTS (2)
321
+ Registration, default src/components/Registration.tsx
322
+ ProductsList, default src/components/Products.tsx
308
323
 
309
324
  #### Compact
310
325
 
311
326
  The compact reporter shows the sorted files first, and then a list of symbols:
312
327
 
313
- ```
314
- $ knip --reporter compact
315
- --- UNUSED FILES (2)
316
- src/chat/helpers.ts
317
- src/components/SideBar.tsx
318
- --- UNUSED DEPENDENCIES (1)
319
- moment
320
- --- UNLISTED DEPENDENCIES (1)
321
- react
322
- --- UNUSED EXPORTS (4)
323
- src/common/src/string/index.ts: lowercaseFirstLetter
324
- src/components/Registration.tsx: RegistrationBox
325
- src/css.ts: clamp
326
- src/services/authentication.ts: restoreSession, PREFIX
327
- --- UNUSED TYPES (3)
328
- src/components/Registration/registrationMachine.ts: RegistrationServices, RegistrationAction
329
- src/components/Registration.tsx: ComponentProps
330
- src/types/Product.ts: ProductDetail
331
- --- DUPLICATE EXPORTS (2)
332
- src/components/Registration.tsx: Registration, default
333
- src/components/Products.tsx: ProductsList, default
334
- ```
328
+ $ knip --reporter compact
329
+ --- UNUSED FILES (2)
330
+ src/chat/helpers.ts
331
+ src/components/SideBar.tsx
332
+ --- UNUSED DEPENDENCIES (1)
333
+ moment
334
+ --- UNLISTED DEPENDENCIES (1)
335
+ react
336
+ --- UNUSED EXPORTS (4)
337
+ src/common/src/string/index.ts: lowercaseFirstLetter
338
+ src/components/Registration.tsx: RegistrationBox
339
+ src/css.ts: clamp
340
+ src/services/authentication.ts: restoreSession, PREFIX
341
+ --- UNUSED TYPES (3)
342
+ src/components/Registration/registrationMachine.ts: RegistrationServices, RegistrationAction
343
+ src/components/Registration.tsx: ComponentProps
344
+ src/types/Product.ts: ProductDetail
345
+ --- DUPLICATE EXPORTS (2)
346
+ src/components/Registration.tsx: Registration, default
347
+ src/components/Products.tsx: ProductsList, default
335
348
 
336
349
  #### Code Owners
337
350
 
338
351
  The `codeowners` reporter is like `compact`, but shows the sorted code owners (according to `.github/CODEOWNERS`) first:
339
352
 
340
- ```
341
- $ knip --reporter codeowners
342
- --- UNUSED FILES (2)
343
- @org/team src/chat/helpers.ts
344
- @org/owner src/components/SideBar.tsx
345
- --- UNUSED DEPENDENCIES (1)
346
- @org/admin moment
347
- --- UNLISTED DEPENDENCIES (1)
348
- @org/owner src/components/Registration.tsx react
349
- --- UNUSED EXPORTS (4)
350
- @org/team src/common/src/string/index.ts: lowercaseFirstLetter
351
- @org/owner src/components/Registration.tsx: RegistrationBox
352
- @org/owner src/css.ts: clamp
353
- @org/owner src/services/authentication.ts: restoreSession, PREFIX
354
- --- UNUSED TYPES (3)
355
- @org/owner src/components/Registration/registrationMachine.ts: RegistrationServices, RegistrationAction
356
- @org/owner src/components/Registration.tsx: ComponentProps
357
- @org/owner src/types/Product.ts: ProductDetail
358
- --- DUPLICATE EXPORTS (2)
359
- @org/owner src/components/Registration.tsx: Registration, default
360
- @org/owner src/components/Products.tsx: ProductsList, default
361
- ```
353
+ $ knip --reporter codeowners
354
+ --- UNUSED FILES (2)
355
+ @org/team src/chat/helpers.ts
356
+ @org/owner src/components/SideBar.tsx
357
+ --- UNUSED DEPENDENCIES (1)
358
+ @org/admin moment
359
+ --- UNLISTED DEPENDENCIES (1)
360
+ @org/owner src/components/Registration.tsx react
361
+ --- UNUSED EXPORTS (4)
362
+ @org/team src/common/src/string/index.ts: lowercaseFirstLetter
363
+ @org/owner src/components/Registration.tsx: RegistrationBox
364
+ @org/owner src/css.ts: clamp
365
+ @org/owner src/services/authentication.ts: restoreSession, PREFIX
366
+ --- UNUSED TYPES (3)
367
+ @org/owner src/components/Registration/registrationMachine.ts: RegistrationServices, RegistrationAction
368
+ @org/owner src/components/Registration.tsx: ComponentProps
369
+ @org/owner src/types/Product.ts: ProductDetail
370
+ --- DUPLICATE EXPORTS (2)
371
+ @org/owner src/components/Registration.tsx: Registration, default
372
+ @org/owner src/components/Products.tsx: ProductsList, default
362
373
 
363
374
  The owner of `package.json` is considered the owner of unused (dev) dependencies.
364
375
 
365
376
  Use `--reporter-options '{"path":".github/CODEOWNERS"}'` to pass another location for the code owners file.
366
377
 
367
- ## Why Yet Another unused file/dependency/export finder?
378
+ ## Really, another unused file/dependency/export finder?
379
+
380
+ There are already some great packages available if you want to find unused dependencies OR unused exports.
368
381
 
369
- There are already some great packages available. Getting good results when finding unused files, dependencies and
370
- exports is not trivial. Repositories don't seem to get any smaller and with the rise of monorepos even more so. Tools
371
- like this need to analyze potentially many and/or large files, which is memory and time-consuming. Although I normally
372
- try to stick to the Unix philosophy, here I believe it's efficient to merge these issue reports into a single tool. When
382
+ Although I love the Unix philosophy, here I believe it's efficient to handle multiple concerns in a single tool. When
373
383
  building a dependency graph of the project, an abstract syntax tree for each file, and traversing all of this, why not
374
384
  collect the various issues in one go?
375
385
 
@@ -377,35 +387,64 @@ collect the various issues in one go?
377
387
 
378
388
  This table is a work in progress, but here's a first impression. Based on their docs (please report any mistakes):
379
389
 
380
- | Feature | **knip** | [depcheck][1] | [unimported][2] | [ts-unused-exports][3] | [ts-prune][4] | [find-unused-exports][5] |
381
- | --------------------------- | :--------: | :-----------: | :-------------: | :--------------------: | :-----------: | :----------------------: |
382
- | Unused files | | - | ✅ | - | - | - |
383
- | Unused dependencies | | ✅ | ✅ | - | - | - |
384
- | Unlisted dependencies | | ✅ | ✅ | - | - | - |
385
- | Custom dependency resolvers | ❌ [#7][6] | ✅ | (1) | - | - | - |
386
- | Unused exports | | - | - | ✅ | ✅ | ✅ |
387
- | Duplicate exports | | - | - | ❌ | ❌ | ❌ |
388
- | Search namespaces | | - | - | ✅ | ❌ | ❌ |
389
- | Custom reporters | | - | - | - | - | - |
390
- | Pure JavaScript/ESM | | ✅ | ✅ | - | - | ✅ |
391
- | Configure entry files | | ❌ | ✅ | ❌ | ❌ | ❌ |
392
- | Support monorepo | 🟠 (2) | - | - | - | - | - |
393
- | ESLint plugin available | - | - | - | ✅ | - | - |
390
+ | Feature | **knip** | [depcheck][7] | [unimported][8] | [ts-unused-exports][9] | [ts-prune][10] | [find-unused-exports][11] |
391
+ | --------------------------------- | :------: | :-----------: | :-------------: | :--------------------: | :------------: | :-----------------------: |
392
+ | Unused files | | - | ✅ | - | - | - |
393
+ | Unused dependencies | | ✅ | ✅ | - | - | - |
394
+ | Unlisted dependencies | | ✅ | ✅ | - | - | - |
395
+ | [Custom dependency resolvers][12] | ❌ | ✅ | | - | - | - |
396
+ | Unused exports | | - | - | ✅ | ✅ | ✅ |
397
+ | Duplicate exports | | - | - | ❌ | ❌ | ❌ |
398
+ | Search namespaces | | - | - | ✅ | ❌ | ❌ |
399
+ | Custom reporters | | - | - | - | - | - |
400
+ | Pure JavaScript/ESM | | ✅ | ✅ | - | - | ✅ |
401
+ | Configure entry files | | ❌ | ✅ | ❌ | ❌ | ❌ |
402
+ | [Support monorepos][13] | 🟠 | - | - | - | - | - |
403
+ | ESLint plugin available | - | - | - | ✅ | - | - |
394
404
 
395
405
  ✅ = Supported, ❌ = Not supported, - = Out of scope
396
406
 
397
- 1. unimported is strict and works based on production files and `dependencies`, so does not have custom dependency
398
- resolvers which are usually only needed for `devDependencies`.
399
- 2. knip wants to [support monorepos](#monorepos) properly, the first steps in this direction are implemented.
407
+ ## Monorepos
408
+
409
+ Knip wants to [support monorepos][14] properly, the first steps in this direction are implemented.
410
+
411
+ ## Custom dependency resolvers
412
+
413
+ Using a string like `"plugin:cypress/recommended"` in the `extends` property of a `.eslintrc.json` in a package
414
+ directory of a monorepo is nice for DX. But Knip will need some help to find it and to understand this _resolves to_ the
415
+ `eslint-plugin-cypress` _dependency_. Or see it is not listed in `package.json`. Or that the dependency is still listed,
416
+ but no longer in use. Many popular projects reference plugins in similar ways, such as Babel, Webpack and Storybook.
417
+
418
+ Big compliments to [depcheck][15] which already does this! They call this "specials". [Knip has this ambition][16], too.
419
+
420
+ unimported is strict in this regard and works based on production files and `dependencies`, so does not have custom
421
+ dependency resolvers which are usually only needed for `devDependencies`.
422
+
423
+ ## TypeScript language services
424
+
425
+ TypeScript language services could play a major role in most of the "unused" areas, as they have an overview of the
426
+ project as a whole. This powers things in VS Code like "Find references" or the "Module "./some" declares 'Thing'
427
+ locally, but it is not exported" message. I think features like "duplicate exports" or "custom dependency resolvers" are
428
+ userland territory, much like code linters.
400
429
 
401
430
  ## Knip?!
402
431
 
403
432
  Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
404
433
  for the job. I'm motivated to make knip perfectly suited for the job of cutting projects to perfection! ✂️
405
434
 
406
- [1]: https://github.com/depcheck/depcheck
407
- [2]: https://github.com/smeijer/unimported
408
- [3]: https://github.com/pzavolinsky/ts-unused-exports
409
- [4]: https://github.com/nadeesha/ts-prune
410
- [5]: https://github.com/jaydenseric/find-unused-exports
411
- [6]: https://github.com/webpro/knip/issues/7
435
+ [1]: #reporters
436
+ [2]: #custom-reporters
437
+ [3]: #why-yet-another-unused-filedependencyexport-finder
438
+ [4]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
439
+ [5]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
440
+ [6]: ./assets/how-it-works.drawio.svg
441
+ [7]: https://github.com/depcheck/depcheck
442
+ [8]: https://github.com/smeijer/unimported
443
+ [9]: https://github.com/pzavolinsky/ts-unused-exports
444
+ [10]: https://github.com/nadeesha/ts-prune
445
+ [11]: https://github.com/jaydenseric/find-unused-exports
446
+ [12]: #custom-dependency-resolvers
447
+ [13]: #monorepos-1
448
+ [14]: #monorepos
449
+ [15]: https://github.com/depcheck/depcheck#special
450
+ [16]: https://github.com/webpro/knip/issues/7
package/dist/help.js CHANGED
@@ -8,8 +8,8 @@ Options:
8
8
  -c/--config [file] Configuration file path (default: ./knip.json or package.json#knip)
9
9
  -t/--tsConfig [file] TypeScript configuration path (default: ./tsconfig.json)
10
10
  --dir Working directory (default: current working directory)
11
- --include Report only listed issue group(s) (see below)
12
- --exclude Exclude issue group(s) from report (see below)
11
+ --include Report only listed issue type(s) (see below)
12
+ --exclude Exclude issue type(s) from report (see below)
13
13
  --ignore Ignore files matching this glob pattern (can be set multiple times)
14
14
  --no-gitignore Don't use .gitignore
15
15
  --dev Include \`devDependencies\` in report(s)
@@ -21,7 +21,7 @@ Options:
21
21
  --debug Show debug output
22
22
  --debug-level Set verbosity of debug output (default: 1, max: 2)
23
23
 
24
- Issue groups: files, dependencies, unlisted, exports, nsExports, types, nsTypes, duplicates
24
+ Issue types: files, dependencies, unlisted, exports, nsExports, types, nsTypes, duplicates
25
25
 
26
26
  Examples:
27
27
 
@@ -9,7 +9,7 @@ const logArray = (collection) => console.log(node_util_1.default.inspect(collect
9
9
  const debugLogObject = (config, minimumLevel, name, obj) => {
10
10
  if (minimumLevel > config.debug.level)
11
11
  return;
12
- console.log(`[exportman] ${name}:`);
12
+ console.log(`[knip] ${name}:`);
13
13
  console.log(node_util_1.default.inspect(obj, { depth: null, colors: true }));
14
14
  };
15
15
  exports.debugLogObject = debugLogObject;
@@ -18,11 +18,11 @@ const debugLogFiles = (config, minimumLevel, name, filePaths) => {
18
18
  return;
19
19
  const { debug } = config;
20
20
  if (debug.level > 1) {
21
- console.debug(`[exportman] ${name} (${filePaths.length}):`);
21
+ console.debug(`[knip] ${name} (${filePaths.length}):`);
22
22
  logArray(filePaths);
23
23
  }
24
24
  else {
25
- console.debug(`[exportman] ${name} (${filePaths.length})`);
25
+ console.debug(`[knip] ${name} (${filePaths.length})`);
26
26
  }
27
27
  };
28
28
  exports.debugLogFiles = debugLogFiles;
@@ -31,11 +31,11 @@ const debugLogSourceFiles = (config, minimumLevel, name, sourceFiles) => {
31
31
  return;
32
32
  const { debug } = config;
33
33
  if (debug.level > 1) {
34
- console.debug(`[exportman] ${name} (${sourceFiles.length}):`);
34
+ console.debug(`[knip] ${name} (${sourceFiles.length}):`);
35
35
  logArray(sourceFiles.map(sourceFile => sourceFile.getFilePath()));
36
36
  }
37
37
  else {
38
- console.debug(`[exportman] ${name} (${sourceFiles.length})`);
38
+ console.debug(`[knip] ${name} (${sourceFiles.length})`);
39
39
  }
40
40
  };
41
41
  exports.debugLogSourceFiles = debugLogSourceFiles;
@@ -44,11 +44,11 @@ const debugLogDiff = (config, minimumLevel, name, arrA, arrB) => {
44
44
  return;
45
45
  const onlyInA = arrA.filter(itemA => !arrB.includes(itemA)).sort();
46
46
  const onlyInB = arrB.filter(itemB => !arrA.includes(itemB)).sort();
47
- console.log(`[exportman] ${name}`);
48
- console.log(`[exportman] Only in left:`);
47
+ console.log(`[knip] ${name}`);
48
+ console.log(`[knip] Only in left:`);
49
49
  logArray(onlyInA);
50
50
  console.log();
51
- console.log(`[exportman] Only in right:`);
51
+ console.log(`[knip] Only in right:`);
52
52
  logArray(onlyInB);
53
53
  };
54
54
  exports.debugLogDiff = debugLogDiff;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
5
5
  "keywords": [
6
6
  "find",