knip 2.2.0 → 2.2.2
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 +10 -8
- package/dist/index.js +1 -1
- package/dist/types/imports.d.ts +1 -0
- package/dist/typescript/getImportsAndExports.d.ts +1 -0
- package/dist/typescript/getImportsAndExports.js +9 -8
- package/dist/typescript/visitors/imports/importCall.js +13 -16
- package/dist/typescript/visitors/imports/requireCall.js +1 -2
- package/dist/typescript/visitors/imports/requireResolveCall.js +2 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ The dots don't connect themselves. This is where Knip comes in:
|
|
|
20
20
|
- [x] Built-in support for [workspaces (monorepos)][1]
|
|
21
21
|
- [x] Growing list of [built-in plugins][2]
|
|
22
22
|
- [x] Use [compilers][3] to include other file types (e.g. `.mdx`, `.vue`, `.svelte`)
|
|
23
|
-
- [x]
|
|
23
|
+
- [x] Finds binaries and dependencies in npm scripts, and a lot more locations
|
|
24
24
|
- [x] Finds unused members of classes and enums
|
|
25
25
|
- [x] Finds duplicate exports
|
|
26
26
|
- [x] Supports any combination of JavaScript and TypeScript
|
|
@@ -237,9 +237,9 @@ As always, make sure to backup files or use Git before deleting files or making
|
|
|
237
237
|
|
|
238
238
|
Workspaces and monorepos are handled out-of-the-box by Knip. Every workspace is part of the analysis.
|
|
239
239
|
|
|
240
|
-
Here's an example configuration with some custom `entry` and `project` patterns:
|
|
240
|
+
Here's an example `knip.json` configuration with some custom `entry` and `project` patterns:
|
|
241
241
|
|
|
242
|
-
```
|
|
242
|
+
```json
|
|
243
243
|
{
|
|
244
244
|
"workspaces": {
|
|
245
245
|
".": {
|
|
@@ -280,6 +280,9 @@ Here's some example output when running Knip in a workspace:
|
|
|
280
280
|
|
|
281
281
|
Use `--debug` to get more verbose output.
|
|
282
282
|
|
|
283
|
+
Use `ignoreBinaries` and `ignoreDependencies` at the root of `knip.json` for global effect, or inside any workspace
|
|
284
|
+
config for local effect.
|
|
285
|
+
|
|
283
286
|
## Plugins
|
|
284
287
|
|
|
285
288
|
Plugins tell Knip where to look for configuration and entry files, and if necessary have a custom dependency finder.
|
|
@@ -439,10 +442,9 @@ use the `--production` flag. Here's an example:
|
|
|
439
442
|
Here's what's included in production mode analysis:
|
|
440
443
|
|
|
441
444
|
- Only `entry` and `project` patterns suffixed with `!`.
|
|
442
|
-
- Only `entry` patterns
|
|
443
|
-
- Only the `
|
|
444
|
-
- Only `exports`, `nsExports` and `classMembers` are
|
|
445
|
-
ignored).
|
|
445
|
+
- Only production `entry` file patterns exported for plugins (such as Next.js and Gatsby).
|
|
446
|
+
- Only the `start` and `postinstall` scripts (e.g. not the `test` or other npm scripts in `package.json`).
|
|
447
|
+
- Only unused `exports`, `nsExports` and `classMembers` are reported (not `types`, `nsTypes`, `enumMembers`).
|
|
446
448
|
|
|
447
449
|
### Strict
|
|
448
450
|
|
|
@@ -587,7 +589,7 @@ This table is an ongoing comparison. Based on their docs (please report any mist
|
|
|
587
589
|
| Custom reporters | ✅ | - | - | - | - |
|
|
588
590
|
| JavaScript support | ✅ | ✅ | ✅ | - | - |
|
|
589
591
|
| Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ |
|
|
590
|
-
| [
|
|
592
|
+
| [Workspaces][1] | ✅ | ❌ | ❌ | - | - |
|
|
591
593
|
| ESLint plugin available | - | - | - | ✅ | - |
|
|
592
594
|
|
|
593
595
|
✅ = Supported, ❌ = Not supported, - = Out of scope
|
package/dist/index.js
CHANGED
|
@@ -283,7 +283,7 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
283
283
|
if (['enum', 'type', 'interface'].includes(exportedItem.type)) {
|
|
284
284
|
collector.addIssue({ type: 'types', filePath, symbol, symbolType: exportedItem.type });
|
|
285
285
|
}
|
|
286
|
-
else {
|
|
286
|
+
else if (!importedModule.isDynamic || !principal.hasExternalReferences(filePath, exportedItem)) {
|
|
287
287
|
collector.addIssue({ type: 'exports', filePath, symbol });
|
|
288
288
|
}
|
|
289
289
|
}
|
package/dist/types/imports.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
19
19
|
const scripts = new Set();
|
|
20
20
|
const importedInternalSymbols = new Map();
|
|
21
21
|
const visitors = getVisitors(sourceFile);
|
|
22
|
-
const addInternalImport = ({ identifier
|
|
22
|
+
const addInternalImport = ({ identifier, specifier, symbol, filePath, isDynamic }) => {
|
|
23
23
|
const isStar = identifier === '*';
|
|
24
24
|
const isReExported = Boolean(isStar && !symbol);
|
|
25
25
|
if (!internalImports.has(filePath)) {
|
|
@@ -29,6 +29,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
29
29
|
isReExported,
|
|
30
30
|
isReExportedBy: new Set(),
|
|
31
31
|
symbols: new Set(),
|
|
32
|
+
isDynamic,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
const internalImport = internalImports.get(filePath);
|
|
@@ -36,17 +37,17 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
36
37
|
internalImport.isReExported = isReExported;
|
|
37
38
|
internalImport.isReExportedBy.add(sourceFile.fileName);
|
|
38
39
|
}
|
|
39
|
-
if (isStar)
|
|
40
|
+
if (isStar)
|
|
40
41
|
internalImport.isStar = isStar;
|
|
41
|
-
|
|
42
|
-
if (!isStar) {
|
|
42
|
+
if (!isStar)
|
|
43
43
|
internalImport.symbols.add(identifier);
|
|
44
|
-
}
|
|
45
44
|
if (isStar && symbol) {
|
|
46
45
|
importedInternalSymbols.set(symbol, filePath);
|
|
47
46
|
}
|
|
47
|
+
if (isDynamic)
|
|
48
|
+
internalImport.isDynamic = isDynamic;
|
|
48
49
|
};
|
|
49
|
-
const addImport = ({ specifier, symbol, identifier = '__anonymous' }) => {
|
|
50
|
+
const addImport = ({ specifier, symbol, identifier = '__anonymous', isDynamic = false }) => {
|
|
50
51
|
if (isBuiltin(specifier))
|
|
51
52
|
return;
|
|
52
53
|
const module = sourceFile.resolvedModules?.get(specifier, undefined);
|
|
@@ -55,7 +56,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
55
56
|
if (filePath) {
|
|
56
57
|
if (module.resolvedModule.isExternalLibraryImport) {
|
|
57
58
|
if (!isInNodeModules(filePath)) {
|
|
58
|
-
addInternalImport({ identifier, specifier, symbol, filePath });
|
|
59
|
+
addInternalImport({ identifier, specifier, symbol, filePath, isDynamic });
|
|
59
60
|
}
|
|
60
61
|
else if (isDeclarationFileExtension(module.resolvedModule.extension)) {
|
|
61
62
|
externalImports.add(specifier);
|
|
@@ -65,7 +66,7 @@ export const getImportsAndExports = (sourceFile, options) => {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
else {
|
|
68
|
-
addInternalImport({ identifier, specifier, symbol, filePath });
|
|
69
|
+
addInternalImport({ identifier, specifier, symbol, filePath, isDynamic });
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
}
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import { isImportCall, isAccessExpression,
|
|
2
|
+
import { isImportCall, isAccessExpression, isVariableDeclarationList, findDescendants } from '../../ast-helpers.js';
|
|
3
3
|
import { importVisitor as visit } from '../index.js';
|
|
4
4
|
export default visit(() => true, node => {
|
|
5
5
|
if (isImportCall(node)) {
|
|
6
6
|
if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
|
|
7
7
|
const specifier = node.arguments[0].text;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
}
|
|
19
|
-
if (isVariableDeclarationList(_node)) {
|
|
20
|
-
return findDescendants(_node, ts.isVariableDeclaration).flatMap(variableDeclaration => {
|
|
8
|
+
if (isAccessExpression(node.parent)) {
|
|
9
|
+
return { specifier, isDynamic: true };
|
|
10
|
+
}
|
|
11
|
+
let _ancestor = node.parent?.parent?.parent;
|
|
12
|
+
if (_ancestor && isAccessExpression(_ancestor)) {
|
|
13
|
+
return { specifier, isDynamic: true };
|
|
14
|
+
}
|
|
15
|
+
while (_ancestor) {
|
|
16
|
+
if (_ancestor && isVariableDeclarationList(_ancestor)) {
|
|
17
|
+
return findDescendants(_ancestor, ts.isVariableDeclaration).flatMap(variableDeclaration => {
|
|
21
18
|
if (ts.isIdentifier(variableDeclaration.name)) {
|
|
22
19
|
return { identifier: 'default', specifier };
|
|
23
20
|
}
|
|
24
21
|
else {
|
|
25
|
-
const binds = findDescendants(variableDeclaration, _node => ts.isBindingElement(_node));
|
|
22
|
+
const binds = findDescendants(variableDeclaration, _node => ts.isBindingElement(_node) && ts.isIdentifier(_node.name));
|
|
26
23
|
return binds.flatMap(element => {
|
|
27
24
|
const symbol = element.propertyName?.getText() || element.name.getText();
|
|
28
25
|
return { identifier: symbol, specifier };
|
|
@@ -30,7 +27,7 @@ export default visit(() => true, node => {
|
|
|
30
27
|
}
|
|
31
28
|
});
|
|
32
29
|
}
|
|
33
|
-
|
|
30
|
+
_ancestor = _ancestor.parent;
|
|
34
31
|
}
|
|
35
32
|
return { specifier };
|
|
36
33
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { isRequireCall, findAncestor, findDescendants } from '../../ast-helpers.js';
|
|
3
|
-
import { isJS } from '../helpers.js';
|
|
4
3
|
import { importVisitor as visit } from '../index.js';
|
|
5
|
-
export default visit(
|
|
4
|
+
export default visit(() => true, node => {
|
|
6
5
|
if (isRequireCall(node)) {
|
|
7
6
|
if (ts.isStringLiteralLike(node.arguments[0])) {
|
|
8
7
|
const specifier = node.arguments[0].text;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { isRequireResolveCall } from '../../ast-helpers.js';
|
|
3
|
-
import { isJS } from '../helpers.js';
|
|
4
3
|
import { importVisitor as visit } from '../index.js';
|
|
5
|
-
export default visit(
|
|
4
|
+
export default visit(() => true, node => {
|
|
6
5
|
if (isRequireResolveCall(node)) {
|
|
7
6
|
if (node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])) {
|
|
8
7
|
const specifier = node.arguments[0].text;
|
|
9
|
-
if (specifier)
|
|
8
|
+
if (specifier)
|
|
10
9
|
return { specifier };
|
|
11
|
-
}
|
|
12
10
|
}
|
|
13
11
|
}
|
|
14
12
|
});
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.2.
|
|
1
|
+
export declare const version = "2.2.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.2.
|
|
1
|
+
export const version = '2.2.2';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
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",
|
|
@@ -66,14 +66,14 @@
|
|
|
66
66
|
"@types/js-yaml": "4.0.5",
|
|
67
67
|
"@types/micromatch": "4.0.2",
|
|
68
68
|
"@types/minimist": "1.2.2",
|
|
69
|
-
"@types/node": "18.15.
|
|
69
|
+
"@types/node": "18.15.11",
|
|
70
70
|
"@types/npmcli__map-workspaces": "3.0.0",
|
|
71
|
-
"@types/webpack": "5.28.
|
|
72
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
73
|
-
"@typescript-eslint/parser": "5.
|
|
71
|
+
"@types/webpack": "5.28.1",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "5.57.0",
|
|
73
|
+
"@typescript-eslint/parser": "5.57.0",
|
|
74
74
|
"c8": "7.13.0",
|
|
75
|
-
"eslint": "8.
|
|
76
|
-
"eslint-import-resolver-typescript": "3.5.
|
|
75
|
+
"eslint": "8.37.0",
|
|
76
|
+
"eslint-import-resolver-typescript": "3.5.4",
|
|
77
77
|
"eslint-plugin-import": "2.27.5",
|
|
78
78
|
"globstar": "1.0.0",
|
|
79
79
|
"prettier": "2.8.7",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"remark-cli": "11.0.0",
|
|
82
82
|
"remark-preset-webpro": "0.0.2",
|
|
83
83
|
"tsx": "3.12.6",
|
|
84
|
-
"type-fest": "3.7.
|
|
84
|
+
"type-fest": "3.7.2"
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=16.17.0 <17 || >=18.6.0"
|