knip 1.0.0-beta.7 → 1.0.0-beta.8

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
@@ -36,16 +36,11 @@ with OpenAI_</sup>
36
36
 
37
37
  ## Migrating to v1.0.0
38
38
 
39
- When coming from version v0.13.3 or before, here are the breaking changes:
40
-
41
- - The `entryFiles` and `projectFiles` options have been renamed to `entry` and `project`.
42
- - The `--dev` argument and `dev: true` option are gone, this is now the default mode (see [production mode][7]).
43
- - Workspaces have been moved from the root of the config to the `workspaces` key (see [workspaces][8]).
44
- - The `--dir` argument has been renamed to `--workspace`.
39
+ When coming from version v0.13.3 or before, please see [migration to v1][7].
45
40
 
46
41
  ## Issues
47
42
 
48
- Please report any false positives by [opening an issue in this repo][9]. Bonus points for linking to a public repository
43
+ Please report any false positives by [opening an issue in this repo][8]. Bonus points for linking to a public repository
49
44
  using Knip, or even opening a pull request with a directory and example files in `test/fixtures`. Correctness and bug
50
45
  fixes have priority over performance and new features.
51
46
 
@@ -182,24 +177,18 @@ As always, make sure to backup files or use Git before deleting files or making
182
177
  ## Workspaces & Monorepos
183
178
 
184
179
  Workspaces and monorepos are handled out-of-the-box by Knip. Every workspace that is part of the Knip configuration will
185
- be part of the analysis. Here's a simple example:
180
+ be part of the analysis. Here's an example:
186
181
 
187
182
  ```jsonc
188
183
  {
189
- "ignore": "**/fixtures/**",
190
- "ignoreBinaries": ["rm", "docker-compose"],
191
184
  "ignoreWorkspaces": ["packages/ignore-me"],
192
185
  "workspaces": {
193
186
  "packages/*": {
194
- "entry": "{index,cli}.ts!",
187
+ "entry": "{index,cli}.ts",
195
188
  "project": "**/*.ts"
196
189
  },
197
- "packages/exception": {
198
- "entry": "something/different.js"
199
- },
200
- "not-a-workspace/in-package.json/but-has-package.json": {
201
- "entry": ["src/index.ts"],
202
- "project": "src/**/*.ts"
190
+ "packages/my-lib": {
191
+ "entry": "main.js"
203
192
  }
204
193
  }
205
194
  }
@@ -219,29 +208,29 @@ Here's a small output example when running Knip in a workspace:
219
208
 
220
209
  Knip contains a growing list of plugins:
221
210
 
222
- - [Babel][10]
223
- - [Capacitor][11]
224
- - [Changesets][12]
225
- - [commitlint][13]
226
- - [Cypress][14]
227
- - [ESLint][15]
228
- - [Gatsby][16]
229
- - [Jest][17]
230
- - [Mocha][18]
231
- - [Next.js][19]
232
- - [Nx][20]
233
- - [nyc][21]
234
- - [Playwright][22]
235
- - [PostCSS][23]
236
- - [Prettier][24]
237
- - [Remark][25]
238
- - [Remix][26]
239
- - [Rollup][27]
240
- - [Sentry][28]
241
- - [Storybook][29]
242
- - [Stryker][30]
243
- - [TypeScript][31]
244
- - [Webpack][32]
211
+ - [Babel][9]
212
+ - [Capacitor][10]
213
+ - [Changesets][11]
214
+ - [commitlint][12]
215
+ - [Cypress][13]
216
+ - [ESLint][14]
217
+ - [Gatsby][15]
218
+ - [Jest][16]
219
+ - [Mocha][17]
220
+ - [Next.js][18]
221
+ - [Nx][19]
222
+ - [nyc][20]
223
+ - [Playwright][21]
224
+ - [PostCSS][22]
225
+ - [Prettier][23]
226
+ - [Remark][24]
227
+ - [Remix][25]
228
+ - [Rollup][26]
229
+ - [Sentry][27]
230
+ - [Storybook][28]
231
+ - [Stryker][29]
232
+ - [TypeScript][30]
233
+ - [Webpack][31]
245
234
 
246
235
  Plugins are automatically activated, no need to enable anything. Each plugin is automatically enabled based on simple
247
236
  heuristics. Most of them check whether one or one of a few (dev) dependencies are listed in `package.json`. Once
@@ -249,7 +238,7 @@ enabled, they add a set of configuration and/or entry files for Knip to analyze.
249
238
 
250
239
  Most plugins use one or both of the following file types:
251
240
 
252
- - `config` - custom dependency resolvers are applied to the [config files][33]
241
+ - `config` - custom dependency resolvers are applied to the [config files][32]
253
242
  - `entry` - files to include with the analysis of the rest of the source code
254
243
 
255
244
  ### `config`
@@ -341,10 +330,10 @@ locations. The more plugins Knip will have, the more projects can be analyzed ou
341
330
 
342
331
  Knip provides the following built-in reporters:
343
332
 
344
- - [`codeowners`][34]
345
- - [`compact`][35]
346
- - [`json`][36]
347
- - [`symbol`][37] (default)
333
+ - [`codeowners`][33]
334
+ - [`compact`][34]
335
+ - [`json`][35]
336
+ - [`symbol`][36] (default)
348
337
 
349
338
  The `compact` reporter shows the sorted files first, and then a list of symbols:
350
339
 
@@ -352,7 +341,7 @@ The `compact` reporter shows the sorted files first, and then a list of symbols:
352
341
 
353
342
  ### Custom Reporters
354
343
 
355
- When the provided built-in reporters are not quite sufficient, a custom reporter can be implemented.
344
+ When the provided built-in reporters are not sufficient, a custom reporter can be implemented.
356
345
 
357
346
  Pass `--reporter ./my-reporter`, with the default export of that module having this interface:
358
347
 
@@ -371,7 +360,7 @@ type ReporterOptions = {
371
360
 
372
361
  The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
373
362
 
374
- Find more details and ideas in [custom reporters][38].
363
+ Find more details and ideas in [custom reporters][37].
375
364
 
376
365
  ## Really, another unused file/dependency/export finder?
377
366
 
@@ -385,12 +374,12 @@ all of this, why not collect the various issues in one go?
385
374
 
386
375
  This table is an ongoing comparison. Based on their docs (please report any mistakes):
387
376
 
388
- | Feature | **knip** | [depcheck][39] | [unimported][40] | [ts-unused-exports][41] | [ts-prune][42] | [find-unused-exports][43] |
377
+ | Feature | **knip** | [depcheck][38] | [unimported][39] | [ts-unused-exports][40] | [ts-prune][41] | [find-unused-exports][42] |
389
378
  | :--------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: | :-----------------------: |
390
379
  | Unused files | ✅ | - | ✅ | - | - | - |
391
380
  | Unused dependencies | ✅ | ✅ | ✅ | - | - | - |
392
381
  | Unlisted dependencies | ✅ | ✅ | ✅ | - | - | - |
393
- | [Custom dependency resolvers][44] | ✅ | ✅ | ❌ | - | - | - |
382
+ | [Custom dependency resolvers][43] | ✅ | ✅ | ❌ | - | - | - |
394
383
  | Unused exports | ✅ | - | - | ✅ | ✅ | ✅ |
395
384
  | Unused class members | ✅ | - | - | - | - | - |
396
385
  | Unused enum members | ✅ | - | - | - | - | - |
@@ -399,7 +388,7 @@ This table is an ongoing comparison. Based on their docs (please report any mist
399
388
  | Custom reporters | ✅ | - | - | - | - | - |
400
389
  | JavaScript support | ✅ | ✅ | ✅ | - | - | ✅ |
401
390
  | Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
402
- | [Support workspaces/monorepos][45] | ✅ | ❌ | ❌ | - | - | - |
391
+ | [Support workspaces/monorepos][44] | ✅ | ❌ | ❌ | - | - | - |
403
392
  | ESLint plugin available | - | - | - | ✅ | - | - |
404
393
 
405
394
  ✅ = Supported, ❌ = Not supported, - = Out of scope
@@ -422,7 +411,7 @@ The following commands are similar:
422
411
  unimported
423
412
  knip --production --include files,dependencies,unlisted
424
413
 
425
- See [production mode][7].
414
+ See [production mode][45].
426
415
 
427
416
  ## TypeScript language services
428
417
 
@@ -442,42 +431,42 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
442
431
  [4]: #really-another-unused-filedependencyexport-finder
443
432
  [5]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
444
433
  [6]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
445
- [7]: #production-mode
446
- [8]: #workspaces--monorepos
447
- [9]: https://github.com/webpro/knip/issues
448
- [10]: ./src/plugins/babel
449
- [11]: ./src/plugins/capacitor
450
- [12]: ./src/plugins/changesets
451
- [13]: ./src/plugins/commitlint
452
- [14]: ./src/plugins/cypress
453
- [15]: ./src/plugins/eslint
454
- [16]: ./src/plugins/gatsby
455
- [17]: ./src/plugins/jest
456
- [18]: ./src/plugins/mocha
457
- [19]: ./src/plugins/next
458
- [20]: ./src/plugins/nx
459
- [21]: ./src/plugins/nyc
460
- [22]: ./src/plugins/playwright
461
- [23]: ./src/plugins/postcss
462
- [24]: ./src/plugins/prettier
463
- [25]: ./src/plugins/remark
464
- [26]: ./src/plugins/remix
465
- [27]: ./src/plugins/rollup
466
- [28]: ./src/plugins/sentry
467
- [29]: ./src/plugins/storybook
468
- [30]: ./src/plugins/stryker
469
- [31]: ./src/plugins/typescript
470
- [32]: ./src/plugins/webpack
471
- [33]: #config
472
- [34]: #code-owners
473
- [35]: #compact
474
- [36]: #json
475
- [37]: #symbol-default
476
- [38]: ./docs/custom-reporters.md
477
- [39]: https://github.com/depcheck/depcheck
478
- [40]: https://github.com/smeijer/unimported
479
- [41]: https://github.com/pzavolinsky/ts-unused-exports
480
- [42]: https://github.com/nadeesha/ts-prune
481
- [43]: https://github.com/jaydenseric/find-unused-exports
482
- [44]: #custom-dependency-resolvers
483
- [45]: #workspaces--monorepos
434
+ [7]: ./docs/migration-to-v1.md
435
+ [8]: https://github.com/webpro/knip/issues
436
+ [9]: ./src/plugins/babel
437
+ [10]: ./src/plugins/capacitor
438
+ [11]: ./src/plugins/changesets
439
+ [12]: ./src/plugins/commitlint
440
+ [13]: ./src/plugins/cypress
441
+ [14]: ./src/plugins/eslint
442
+ [15]: ./src/plugins/gatsby
443
+ [16]: ./src/plugins/jest
444
+ [17]: ./src/plugins/mocha
445
+ [18]: ./src/plugins/next
446
+ [19]: ./src/plugins/nx
447
+ [20]: ./src/plugins/nyc
448
+ [21]: ./src/plugins/playwright
449
+ [22]: ./src/plugins/postcss
450
+ [23]: ./src/plugins/prettier
451
+ [24]: ./src/plugins/remark
452
+ [25]: ./src/plugins/remix
453
+ [26]: ./src/plugins/rollup
454
+ [27]: ./src/plugins/sentry
455
+ [28]: ./src/plugins/storybook
456
+ [29]: ./src/plugins/stryker
457
+ [30]: ./src/plugins/typescript
458
+ [31]: ./src/plugins/webpack
459
+ [32]: #config
460
+ [33]: #code-owners
461
+ [34]: #compact
462
+ [35]: #json
463
+ [36]: #symbol-default
464
+ [37]: ./docs/custom-reporters.md
465
+ [38]: https://github.com/depcheck/depcheck
466
+ [39]: https://github.com/smeijer/unimported
467
+ [40]: https://github.com/pzavolinsky/ts-unused-exports
468
+ [41]: https://github.com/nadeesha/ts-prune
469
+ [42]: https://github.com/jaydenseric/find-unused-exports
470
+ [43]: #custom-dependency-resolvers
471
+ [44]: #workspaces--monorepos
472
+ [45]: #production-mode
@@ -1,6 +1,8 @@
1
1
  import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ import type { BabelConfig } from './types.js';
2
3
  export declare const NAME = "Babel";
3
4
  export declare const ENABLERS: string[];
4
5
  export declare const isEnabled: IsPluginEnabledCallback;
5
6
  export declare const CONFIG_FILE_PATTERNS: string[];
7
+ export declare const getDependenciesFromConfig: (config: BabelConfig) => string[];
6
8
  export declare const findDependencies: GenericPluginCallback;
@@ -17,7 +17,7 @@ export const CONFIG_FILE_PATTERNS = [
17
17
  const api = {
18
18
  caller: () => true,
19
19
  };
20
- const getDependenciesFromConfig = (config) => {
20
+ export const getDependenciesFromConfig = (config) => {
21
21
  const presets = config.presets?.map(preset => (typeof preset === 'string' ? preset : preset[0])).map(resolvePresetName) ?? [];
22
22
  const plugins = config.plugins?.map(plugin => (typeof plugin === 'string' ? plugin : plugin[0])).map(resolvePluginName) ?? [];
23
23
  const nested = config.env ? Object.values(config.env).flatMap(getDependenciesFromConfig) : [];
@@ -1,18 +1,30 @@
1
1
  import { compact } from '../../util/array.js';
2
2
  import { _load } from '../../util/loader.js';
3
3
  import { timerify } from '../../util/performance.js';
4
+ import { getDependenciesFromConfig } from '../babel/index.js';
4
5
  export const NAME = 'Webpack';
5
6
  export const ENABLERS = ['webpack'];
6
7
  export const isEnabled = ({ dependencies }) => ENABLERS.some(enabler => dependencies.has(enabler));
7
8
  export const CONFIG_FILE_PATTERNS = ['webpack.config*.{js,ts}'];
8
- const resolveRuleSetLoaders = (rule) => {
9
+ const hasBabelOptions = (use) => Boolean(use) &&
10
+ typeof use !== 'string' &&
11
+ 'loader' in use &&
12
+ typeof use.loader === 'string' &&
13
+ use.loader === 'babel-loader' &&
14
+ typeof use.options === 'object';
15
+ const resolveRuleSetDependencies = (rule) => {
9
16
  if (!rule || typeof rule === 'string')
10
17
  return [];
11
18
  if (typeof rule.use === 'string')
12
19
  return [rule.use];
13
- if (Array.isArray(rule.use))
14
- return rule.use.flatMap(resolveUseItemLoader);
15
- return rule.use && typeof rule.use !== 'function' ? resolveUseItemLoader(rule.use) : [];
20
+ if (!rule.use || typeof rule.use === 'function')
21
+ return [];
22
+ return [rule.use].flat().flatMap((use) => {
23
+ if (hasBabelOptions(use)) {
24
+ return [...resolveUseItemLoader(use), ...getDependenciesFromConfig(use.options)];
25
+ }
26
+ return resolveUseItemLoader(use);
27
+ });
16
28
  };
17
29
  const resolveUseItemLoader = (use) => {
18
30
  if (!use)
@@ -23,17 +35,19 @@ const resolveUseItemLoader = (use) => {
23
35
  return [use.loader];
24
36
  return [];
25
37
  };
26
- const findWebpackDependencies = async (configFilePath, { manifest }) => {
38
+ const findWebpackDependencies = async (configFilePath, { manifest, isProduction }) => {
27
39
  let config = await _load(configFilePath);
28
40
  if (typeof config === 'function') {
29
- config = config();
41
+ config = config({ production: isProduction }, { mode: isProduction ? 'production' : 'development' });
30
42
  }
31
- const loaders = (config.module?.rules?.flatMap(resolveRuleSetLoaders) ?? [])
32
- .map(loader => loader.replace(/\?.*/, ''))
33
- .filter(loader => !loader.startsWith('/'));
43
+ const dependencies = [config].flat().flatMap(config => {
44
+ return (config.module?.rules?.flatMap(resolveRuleSetDependencies) ?? [])
45
+ .map(loader => loader.replace(/\?.*/, ''))
46
+ .filter(loader => !loader.startsWith('/'));
47
+ });
34
48
  const scripts = Object.values(manifest.scripts ?? {});
35
49
  const webpackCLI = scripts.some(script => script?.includes('webpack ')) ? ['webpack-cli'] : [];
36
50
  const webpackDevServer = scripts.some(script => script?.includes('webpack serve')) ? ['webpack-dev-server'] : [];
37
- return compact([...loaders, ...webpackCLI, ...webpackDevServer]);
51
+ return compact([...dependencies, ...webpackCLI, ...webpackDevServer]);
38
52
  };
39
53
  export const findDependencies = timerify(findWebpackDependencies);
@@ -0,0 +1,10 @@
1
+ import type { Configuration } from 'webpack';
2
+ type Mode = 'none' | 'development' | 'production';
3
+ type Env = {
4
+ production: boolean;
5
+ };
6
+ type Argv = {
7
+ mode: Mode;
8
+ };
9
+ export type WebpackConfig = Configuration | ((env: Env, argv: Argv) => Configuration);
10
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -10,6 +10,7 @@ type GenericPluginCallbackOptions = {
10
10
  manifest: PackageJson;
11
11
  config: PluginConfiguration;
12
12
  workspaceConfig: WorkspaceConfiguration;
13
+ isProduction: boolean;
13
14
  };
14
- export type GenericPluginCallback = (configFilePath: string, { cwd, manifest, config, workspaceConfig }: GenericPluginCallbackOptions) => Promise<string[]> | string[];
15
+ export type GenericPluginCallback = (configFilePath: string, { cwd, manifest, config, workspaceConfig, isProduction }: GenericPluginCallbackOptions) => Promise<string[]> | string[];
15
16
  export {};
@@ -230,6 +230,7 @@ export default class WorkspaceWorker {
230
230
  manifest: this.manifest,
231
231
  config: pluginConfig,
232
232
  workspaceConfig: this.config,
233
+ isProduction: this.isProduction,
233
234
  });
234
235
  return dependencies.map(symbol => ({ type: 'unlisted', filePath: configFilePath, symbol }));
235
236
  }))).flat();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0-beta.8",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
5
5
  "keywords": [
6
6
  "find",
@@ -42,7 +42,7 @@
42
42
  "docs": "npm run docs:cli && npm run docs:plugins && npm run docs:format",
43
43
  "docs:cli": "tsx ./scripts/update-cli-usage-in-readme.ts",
44
44
  "docs:plugins": "tsx ./scripts/generate-plugin-docs.ts",
45
- "docs:format": "remark README.md src/plugins/*/README.md -o",
45
+ "docs:format": "remark README.md docs/*.md src/plugins/*/README.md -o",
46
46
  "release": "release-it",
47
47
  "postinstall": "patch-package",
48
48
  "create-plugin": "tsx ./scripts/create-new-plugin.ts"