knip 0.8.1 → 0.8.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/dist/cli.js +7 -8
- package/dist/index.d.ts +1 -12
- package/dist/index.js +6 -0
- package/dist/progress.d.ts +5 -0
- package/dist/progress.js +41 -0
- package/dist/reporters/symbols.js +9 -6
- package/dist/runner.d.ts +2 -13
- package/dist/runner.js +9 -27
- package/dist/types.d.ts +1 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -37,7 +37,7 @@ if (help) {
|
|
|
37
37
|
}
|
|
38
38
|
const cwd = process.cwd();
|
|
39
39
|
const workingDir = dir ? node_path_1.default.resolve(dir) : cwd;
|
|
40
|
-
const isShowProgress = noProgress === false
|
|
40
|
+
const isShowProgress = !isDebug && noProgress === false && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function';
|
|
41
41
|
const printReport = reporter in reporters_1.default ? reporters_1.default[reporter] : require(node_path_1.default.join(workingDir, reporter));
|
|
42
42
|
const run = async () => {
|
|
43
43
|
try {
|
|
@@ -60,13 +60,12 @@ const run = async () => {
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
printReport({ report, issues, cwd, workingDir, isDev, options: reporterOptions });
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
63
|
+
const totalErrorCount = Object.keys(report)
|
|
64
|
+
.filter((reportGroup) => report[reportGroup])
|
|
65
|
+
.map(reportGroup => reportGroup === 'unlisted' ? 'unresolved' : reportGroup)
|
|
66
|
+
.reduce((errorCount, reportGroup) => errorCount + counters[reportGroup], 0);
|
|
67
|
+
if (totalErrorCount > Number(maxIssues))
|
|
68
|
+
process.exit(totalErrorCount);
|
|
70
69
|
}
|
|
71
70
|
catch (error) {
|
|
72
71
|
if (error instanceof errors_1.ConfigurationError) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,16 +2,5 @@ import type { UnresolvedConfiguration } from './types';
|
|
|
2
2
|
export declare const main: (options: UnresolvedConfiguration) => Promise<{
|
|
3
3
|
report: import("./types").Report;
|
|
4
4
|
issues: import("./types").Issues;
|
|
5
|
-
counters:
|
|
6
|
-
files: number;
|
|
7
|
-
dependencies: number;
|
|
8
|
-
devDependencies: number;
|
|
9
|
-
unresolved: number;
|
|
10
|
-
exports: number;
|
|
11
|
-
types: number;
|
|
12
|
-
nsExports: number;
|
|
13
|
-
nsTypes: number;
|
|
14
|
-
duplicates: number;
|
|
15
|
-
processed: number;
|
|
16
|
-
};
|
|
5
|
+
counters: import("./types").Counters;
|
|
17
6
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -13,9 +13,12 @@ const project_1 = require("./util/project");
|
|
|
13
13
|
const runner_1 = require("./runner");
|
|
14
14
|
const errors_1 = require("./util/errors");
|
|
15
15
|
const debug_1 = require("./util/debug");
|
|
16
|
+
const progress_1 = require("./progress");
|
|
16
17
|
const main = async (options) => {
|
|
17
18
|
const { cwd, workingDir, configFilePath: configFilePathArg, tsConfigFilePath: tsConfigFilePathArg, include, exclude, ignore, gitignore, isIncludeEntryFiles, isDev, isShowProgress, jsDoc, debug, } = options;
|
|
19
|
+
const updateMessage = (0, progress_1.getMessageUpdater)(options);
|
|
18
20
|
(0, debug_1.debugLogObject)(options, 1, 'Unresolved onfiguration', options);
|
|
21
|
+
updateMessage('Reading configuration and manifest files...');
|
|
19
22
|
const manifestPath = await (0, fs_1.findFile)(cwd, workingDir, 'package.json');
|
|
20
23
|
const manifest = manifestPath && require(manifestPath);
|
|
21
24
|
const configFilePath = configFilePathArg ?? 'knip.json';
|
|
@@ -51,6 +54,7 @@ const main = async (options) => {
|
|
|
51
54
|
const projectOptions = resolvedTsConfigFilePath
|
|
52
55
|
? { tsConfigFilePath: resolvedTsConfigFilePath }
|
|
53
56
|
: { compilerOptions: { allowJs: true } };
|
|
57
|
+
updateMessage('Resolving entry files...');
|
|
54
58
|
const entryPaths = await (0, path_1.resolvePaths)({
|
|
55
59
|
cwd,
|
|
56
60
|
workingDir,
|
|
@@ -65,6 +69,7 @@ const main = async (options) => {
|
|
|
65
69
|
production.resolveSourceFileDependencies();
|
|
66
70
|
const productionFiles = production.getSourceFiles();
|
|
67
71
|
(0, debug_1.debugLogSourceFiles)(options, 1, 'Included production source files', productionFiles);
|
|
72
|
+
updateMessage('Resolving project files...');
|
|
68
73
|
const projectPaths = await (0, path_1.resolvePaths)({
|
|
69
74
|
cwd,
|
|
70
75
|
workingDir,
|
|
@@ -79,6 +84,7 @@ const main = async (options) => {
|
|
|
79
84
|
return { entryFiles, productionFiles, projectFiles };
|
|
80
85
|
}
|
|
81
86
|
else {
|
|
87
|
+
updateMessage('Resolving project files...');
|
|
82
88
|
const project = (0, project_1.createProject)({ tsConfigFilePath: resolvedTsConfigFilePath });
|
|
83
89
|
const files = project.getSourceFiles();
|
|
84
90
|
return { entryFiles: files, productionFiles: files, projectFiles: files };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Configuration, Counters, Issue } from './types';
|
|
2
|
+
export declare const getMessageUpdater: (configuration: {
|
|
3
|
+
isShowProgress: boolean;
|
|
4
|
+
}) => (message: string) => void;
|
|
5
|
+
export declare const getCountersUpdater: (configuration: Configuration, counters: Counters) => (issue?: Issue) => void;
|
package/dist/progress.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getCountersUpdater = exports.getMessageUpdater = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const log_1 = require("./log");
|
|
9
|
+
const lineRewriter = new log_1.LineRewriter();
|
|
10
|
+
const getMessageUpdater = (configuration) => {
|
|
11
|
+
const { isShowProgress } = configuration;
|
|
12
|
+
if (!isShowProgress)
|
|
13
|
+
return () => { };
|
|
14
|
+
return (message) => lineRewriter.update([message]);
|
|
15
|
+
};
|
|
16
|
+
exports.getMessageUpdater = getMessageUpdater;
|
|
17
|
+
const getCountersUpdater = (configuration, counters) => {
|
|
18
|
+
const { workingDir, isShowProgress, report } = configuration;
|
|
19
|
+
if (!isShowProgress)
|
|
20
|
+
return () => { };
|
|
21
|
+
return (issue) => {
|
|
22
|
+
if (!issue)
|
|
23
|
+
return lineRewriter.resetLines();
|
|
24
|
+
const { processed, total } = counters;
|
|
25
|
+
const percentage = Math.floor((processed / total) * 100);
|
|
26
|
+
const messages = [(0, log_1.getLine)(`${percentage}%`, `of files processed (${processed} of ${total})`)];
|
|
27
|
+
report.files && messages.push((0, log_1.getLine)(counters.files, 'unused files'));
|
|
28
|
+
report.unlisted && messages.push((0, log_1.getLine)(counters.unresolved, 'unlisted dependencies'));
|
|
29
|
+
report.exports && messages.push((0, log_1.getLine)(counters.exports, 'unused exports'));
|
|
30
|
+
report.nsExports && messages.push((0, log_1.getLine)(counters.nsExports, 'unused exports in namespace'));
|
|
31
|
+
report.types && messages.push((0, log_1.getLine)(counters.types, 'unused types'));
|
|
32
|
+
report.nsTypes && messages.push((0, log_1.getLine)(counters.nsTypes, 'unused types in namespace'));
|
|
33
|
+
report.duplicates && messages.push((0, log_1.getLine)(counters.duplicates, 'duplicate exports'));
|
|
34
|
+
if (processed < total) {
|
|
35
|
+
messages.push('');
|
|
36
|
+
messages.push(`Processing: ${node_path_1.default.relative(workingDir, issue.filePath)}`);
|
|
37
|
+
}
|
|
38
|
+
lineRewriter.update(messages);
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
exports.getCountersUpdater = getCountersUpdater;
|
|
@@ -4,9 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const node_path_1 = __importDefault(require("node:path"));
|
|
7
|
-
const
|
|
7
|
+
const TRUNCATE_WIDTH = 40;
|
|
8
|
+
const logIssueLine = (issue, workingDir, maxWidth) => {
|
|
8
9
|
const symbols = issue.symbols ? issue.symbols.join(', ') : issue.symbol;
|
|
9
|
-
|
|
10
|
+
const truncatedSymbol = symbols.length > maxWidth ? symbols.slice(0, maxWidth - 3) + '...' : symbols;
|
|
11
|
+
const filePath = node_path_1.default.relative(workingDir, issue.filePath);
|
|
12
|
+
console.log(`${truncatedSymbol.padEnd(maxWidth + 2)}${issue.symbolType?.padEnd(11) || ''}${filePath}`);
|
|
10
13
|
};
|
|
11
14
|
const logIssueGroupResult = (issues, workingDir, title) => {
|
|
12
15
|
title && console.log(`--- ${title} (${issues.length})`);
|
|
@@ -17,12 +20,12 @@ const logIssueGroupResult = (issues, workingDir, title) => {
|
|
|
17
20
|
console.log('Not found');
|
|
18
21
|
}
|
|
19
22
|
};
|
|
20
|
-
const logIssueGroupResults = (issues, workingDir, title) => {
|
|
23
|
+
const logIssueGroupResults = (issues, workingDir, title, isTruncate = false) => {
|
|
21
24
|
title && console.log(`--- ${title} (${issues.length})`);
|
|
22
25
|
if (issues.length) {
|
|
23
26
|
const sortedByFilePath = issues.sort((a, b) => (a.filePath > b.filePath ? 1 : -1));
|
|
24
|
-
const
|
|
25
|
-
sortedByFilePath.forEach(issue => logIssueLine(
|
|
27
|
+
const maxWidth = isTruncate ? TRUNCATE_WIDTH : issues.reduce((max, issue) => Math.max(issue.symbol.length, max), 0);
|
|
28
|
+
sortedByFilePath.forEach(issue => logIssueLine(issue, workingDir, maxWidth));
|
|
26
29
|
}
|
|
27
30
|
else {
|
|
28
31
|
console.log('Not found');
|
|
@@ -64,6 +67,6 @@ exports.default = ({ report, issues, workingDir, isDev }) => {
|
|
|
64
67
|
}
|
|
65
68
|
if (report.duplicates) {
|
|
66
69
|
const unreferencedDuplicates = Object.values(issues.duplicates).map(Object.values).flat();
|
|
67
|
-
logIssueGroupResults(unreferencedDuplicates, workingDir, reportMultipleGroups && 'DUPLICATE EXPORTS');
|
|
70
|
+
logIssueGroupResults(unreferencedDuplicates, workingDir, reportMultipleGroups && 'DUPLICATE EXPORTS', true);
|
|
68
71
|
}
|
|
69
72
|
};
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
import type { Configuration, Issues } from './types';
|
|
1
|
+
import type { Configuration, Issues, Counters } from './types';
|
|
2
2
|
export declare function findIssues(configuration: Configuration): Promise<{
|
|
3
3
|
issues: Issues;
|
|
4
|
-
counters:
|
|
5
|
-
files: number;
|
|
6
|
-
dependencies: number;
|
|
7
|
-
devDependencies: number;
|
|
8
|
-
unresolved: number;
|
|
9
|
-
exports: number;
|
|
10
|
-
types: number;
|
|
11
|
-
nsExports: number;
|
|
12
|
-
nsTypes: number;
|
|
13
|
-
duplicates: number;
|
|
14
|
-
processed: number;
|
|
15
|
-
};
|
|
4
|
+
counters: Counters;
|
|
16
5
|
}>;
|
package/dist/runner.js
CHANGED
|
@@ -10,12 +10,12 @@ const ts_morph_helpers_1 = require("ts-morph-helpers");
|
|
|
10
10
|
const project_1 = require("./util/project");
|
|
11
11
|
const type_1 = require("./util/type");
|
|
12
12
|
const dependencies_1 = require("./util/dependencies");
|
|
13
|
-
const log_1 = require("./log");
|
|
14
13
|
const debug_1 = require("./util/debug");
|
|
15
|
-
const
|
|
14
|
+
const progress_1 = require("./progress");
|
|
16
15
|
async function findIssues(configuration) {
|
|
17
|
-
const { workingDir,
|
|
16
|
+
const { workingDir, report, isDev, jsDocOptions } = configuration;
|
|
18
17
|
const { entryFiles, productionFiles, projectFiles, isIncludeEntryFiles } = configuration;
|
|
18
|
+
const updateMessage = (0, progress_1.getMessageUpdater)(configuration);
|
|
19
19
|
const { getUnresolvedDependencies, getUnusedDependencies, getUnusedDevDependencies } = (0, dependencies_1.getDependencyAnalyzer)(configuration);
|
|
20
20
|
const [usedProductionFiles, unreferencedProductionFiles] = (0, project_1.partitionSourceFiles)(projectFiles, productionFiles);
|
|
21
21
|
const [usedEntryFiles, usedNonEntryFiles] = (0, project_1.partitionSourceFiles)(usedProductionFiles, entryFiles);
|
|
@@ -45,42 +45,25 @@ async function findIssues(configuration) {
|
|
|
45
45
|
nsTypes: 0,
|
|
46
46
|
duplicates: 0,
|
|
47
47
|
processed: issues.files.size,
|
|
48
|
+
total: projectFiles.length,
|
|
48
49
|
};
|
|
49
|
-
const
|
|
50
|
-
if (!isShowProgress)
|
|
51
|
-
return;
|
|
52
|
-
const counter = counters.processed;
|
|
53
|
-
const total = projectFiles.length;
|
|
54
|
-
const percentage = Math.floor((counter / total) * 100);
|
|
55
|
-
const messages = [(0, log_1.getLine)(`${percentage}%`, `of files processed (${counter} of ${total})`)];
|
|
56
|
-
report.files && messages.push((0, log_1.getLine)(unreferencedProductionFiles.length, 'unused files'));
|
|
57
|
-
report.unlisted && messages.push((0, log_1.getLine)(counters.unresolved, 'unlisted dependencies'));
|
|
58
|
-
report.exports && messages.push((0, log_1.getLine)(counters.exports, 'unused exports'));
|
|
59
|
-
report.nsExports && messages.push((0, log_1.getLine)(counters.nsExports, 'unused exports in namespace'));
|
|
60
|
-
report.types && messages.push((0, log_1.getLine)(counters.types, 'unused types'));
|
|
61
|
-
report.nsTypes && messages.push((0, log_1.getLine)(counters.nsTypes, 'unused types in namespace'));
|
|
62
|
-
report.duplicates && messages.push((0, log_1.getLine)(counters.duplicates, 'duplicate exports'));
|
|
63
|
-
if (counter < total) {
|
|
64
|
-
messages.push('');
|
|
65
|
-
messages.push(`Processing: ${node_path_1.default.relative(workingDir, item.filePath)}`);
|
|
66
|
-
}
|
|
67
|
-
lineRewriter.update(messages);
|
|
68
|
-
};
|
|
50
|
+
const updateCounters = (0, progress_1.getCountersUpdater)(configuration, counters);
|
|
69
51
|
const addSymbolIssue = (issueType, issue) => {
|
|
70
52
|
const { filePath, symbol } = issue;
|
|
71
53
|
const key = node_path_1.default.relative(workingDir, filePath);
|
|
72
54
|
issues[issueType][key] = issues[issueType][key] ?? {};
|
|
73
55
|
issues[issueType][key][symbol] = issue;
|
|
74
56
|
counters[issueType]++;
|
|
75
|
-
|
|
57
|
+
updateCounters(issue);
|
|
76
58
|
};
|
|
77
59
|
const addProjectIssue = (issueType, issue) => {
|
|
78
60
|
if (!issues[issueType].has(issue.symbol)) {
|
|
79
61
|
issues[issueType].add(issue.symbol);
|
|
80
62
|
counters[issueType]++;
|
|
81
63
|
}
|
|
82
|
-
|
|
64
|
+
updateCounters(issue);
|
|
83
65
|
};
|
|
66
|
+
updateMessage('Connecting the dots...');
|
|
84
67
|
if (report.dependencies ||
|
|
85
68
|
report.unlisted ||
|
|
86
69
|
report.exports ||
|
|
@@ -197,8 +180,7 @@ async function findIssues(configuration) {
|
|
|
197
180
|
unusedDevDependencies.forEach(symbol => addProjectIssue('devDependencies', { filePath: '', symbol }));
|
|
198
181
|
}
|
|
199
182
|
}
|
|
200
|
-
|
|
201
|
-
lineRewriter.resetLines();
|
|
183
|
+
updateCounters();
|
|
202
184
|
return { issues, counters };
|
|
203
185
|
}
|
|
204
186
|
exports.findIssues = findIssues;
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"find",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"knip": "dist/cli.js"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"knip": "node ./dist/cli.js",
|
|
27
|
+
"knip": "node ./dist/cli.js --include files,dependencies,unlisted",
|
|
28
28
|
"test": "node --loader tsx --test test/*.spec.ts",
|
|
29
29
|
"watch": "tsc --watch",
|
|
30
30
|
"build": "rm -rf dist && tsc",
|