knip 6.33.0 → 6.35.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/dist/CatalogCounselor.d.ts +2 -0
- package/dist/CatalogCounselor.js +30 -7
- package/dist/ConfigurationChief.d.ts +6 -0
- package/dist/ConfigurationChief.js +3 -5
- package/dist/ProjectPrincipal.d.ts +12 -10
- package/dist/ProjectPrincipal.js +56 -41
- package/dist/WorkspaceWorker.d.ts +3 -3
- package/dist/WorkspaceWorker.js +6 -6
- package/dist/YamlCatalogPeeker.d.ts +4 -0
- package/dist/YamlCatalogPeeker.js +17 -0
- package/dist/binaries/bash-parser.d.ts +1 -1
- package/dist/binaries/bash-parser.js +12 -58
- package/dist/binaries/command.d.ts +5 -0
- package/dist/binaries/command.js +47 -0
- package/dist/binaries/fallback.d.ts +2 -0
- package/dist/binaries/fallback.js +2 -0
- package/dist/binaries/plugins.d.ts +1 -0
- package/dist/binaries/plugins.js +2 -1
- package/dist/binaries/resolvers/pnpm.js +1 -0
- package/dist/binaries/util.d.ts +1 -0
- package/dist/binaries/util.js +12 -0
- package/dist/cli.js +9 -27
- package/dist/compilers/index.d.ts +3 -1866
- package/dist/compilers/index.js +17 -27
- package/dist/compilers/types.d.ts +4 -5
- package/dist/graph/analyze.js +74 -56
- package/dist/graph/build.d.ts +3 -3
- package/dist/graph/build.js +64 -32
- package/dist/plugins/_vue/auto-import.js +28 -4
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.js +2 -0
- package/dist/plugins/mise/index.d.ts +3 -0
- package/dist/plugins/mise/index.js +82 -0
- package/dist/plugins/mise/scripts.d.ts +7 -0
- package/dist/plugins/mise/scripts.js +108 -0
- package/dist/plugins/mise/types.d.ts +26 -0
- package/dist/plugins/mise/types.js +1 -0
- package/dist/plugins/node/index.js +5 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.d.ts +2 -0
- package/dist/plugins/node/visitors/fsPromisesGlob.js +89 -0
- package/dist/plugins/nuxt/index.js +13 -10
- package/dist/plugins/rstest/index.js +3 -2
- package/dist/plugins/rstest/types.d.ts +3 -1
- package/dist/plugins/vite/helpers.d.ts +2 -2
- package/dist/plugins/vite/helpers.js +18 -11
- package/dist/plugins/vite/visitors/importMetaGlob.js +12 -0
- package/dist/plugins/vitest/index.js +5 -2
- package/dist/plugins/vitest/types.d.ts +1 -0
- package/dist/run.js +1 -1
- package/dist/schema/configuration.d.ts +20 -4
- package/dist/schema/configuration.js +5 -6
- package/dist/schema/plugins.d.ts +5 -0
- package/dist/schema/plugins.js +1 -0
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/session.js +22 -4
- package/dist/types/PluginNames.d.ts +2 -2
- package/dist/types/PluginNames.js +1 -0
- package/dist/types/config.d.ts +5 -4
- package/dist/types/module-graph.d.ts +4 -0
- package/dist/types.d.ts +1 -0
- package/dist/typescript/SourceFileManager.d.ts +13 -9
- package/dist/typescript/SourceFileManager.js +58 -22
- package/dist/typescript/get-imports-and-exports.js +5 -1
- package/dist/typescript/glob-imports.js +8 -3
- package/dist/typescript/visitors/calls.js +1 -1
- package/dist/typescript/visitors/exports.js +8 -4
- package/dist/typescript/visitors/walk.d.ts +3 -1
- package/dist/typescript/visitors/walk.js +78 -13
- package/dist/util/catalog.d.ts +5 -0
- package/dist/util/catalog.js +37 -17
- package/dist/util/cli-arguments.d.ts +1 -0
- package/dist/util/cli-arguments.js +9 -0
- package/dist/util/create-options.d.ts +19 -4
- package/dist/util/create-options.js +17 -4
- package/dist/util/errors.d.ts +3 -1
- package/dist/util/errors.js +6 -1
- package/dist/util/file-entry-cache.js +2 -2
- package/dist/util/module-graph.js +1 -0
- package/dist/util/package-json.d.ts +1 -0
- package/dist/util/preprocessor.d.ts +6 -0
- package/dist/util/preprocessor.js +24 -0
- package/dist/util/reporter.d.ts +0 -1
- package/dist/util/reporter.js +0 -7
- package/dist/util/watch.d.ts +1 -1
- package/dist/util/watch.js +33 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -8
- package/schema.json +12 -0
package/dist/util/catalog.js
CHANGED
|
@@ -27,7 +27,7 @@ export const getCatalogContainer = async (cwd, manifest, manifestPath, pnpmWorks
|
|
|
27
27
|
yarnWorkspace?.catalogs ??
|
|
28
28
|
manifest.catalogs ??
|
|
29
29
|
((!Array.isArray(manifest.workspaces) && manifest.workspaces?.catalogs) || {});
|
|
30
|
-
return { filePath, catalog, catalogs };
|
|
30
|
+
return { filePath, catalog, catalogs, overrides: pnpmWorkspace?.overrides };
|
|
31
31
|
};
|
|
32
32
|
const extractEntries = (catalog) => {
|
|
33
33
|
if (catalog && typeof catalog === 'object')
|
|
@@ -56,23 +56,43 @@ export const parseCatalog = (container) => {
|
|
|
56
56
|
entries.add(id);
|
|
57
57
|
return entries;
|
|
58
58
|
};
|
|
59
|
+
const OVERRIDE_DELIMITER = /[^ |@]>/;
|
|
60
|
+
const toCatalogReference = (packageName, version) => {
|
|
61
|
+
if (typeof version !== 'string' || !version.startsWith('catalog:'))
|
|
62
|
+
return;
|
|
63
|
+
return { catalogName: version.slice('catalog:'.length) || DEFAULT_CATALOG, packageName };
|
|
64
|
+
};
|
|
65
|
+
const collectCatalogReferences = (dependencies, catalogReferences) => {
|
|
66
|
+
if (!dependencies)
|
|
67
|
+
return;
|
|
68
|
+
for (const [packageName, version] of Object.entries(dependencies)) {
|
|
69
|
+
const reference = toCatalogReference(packageName, version);
|
|
70
|
+
if (reference)
|
|
71
|
+
catalogReferences.push(reference);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export const getOverrideCatalogReferences = (overrides) => {
|
|
75
|
+
const catalogReferences = [];
|
|
76
|
+
if (!overrides)
|
|
77
|
+
return catalogReferences;
|
|
78
|
+
for (const [selector, version] of Object.entries(overrides)) {
|
|
79
|
+
const delimiterIndex = selector.search(OVERRIDE_DELIMITER);
|
|
80
|
+
const target = delimiterIndex === -1 ? selector : selector.slice(delimiterIndex + 2);
|
|
81
|
+
const packageName = getPackageNameFromModuleSpecifier(target);
|
|
82
|
+
if (!packageName)
|
|
83
|
+
continue;
|
|
84
|
+
const reference = toCatalogReference(packageName, version);
|
|
85
|
+
if (reference)
|
|
86
|
+
catalogReferences.push({ ...reference, selector });
|
|
87
|
+
}
|
|
88
|
+
return catalogReferences;
|
|
89
|
+
};
|
|
59
90
|
export const extractCatalogReferences = (manifest) => {
|
|
60
91
|
const catalogReferences = [];
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const catalogName = version.slice('catalog:'.length) || DEFAULT_CATALOG;
|
|
67
|
-
catalogReferences.push({ catalogName, packageName: name });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
checkDependencies(manifest.dependencies);
|
|
72
|
-
checkDependencies(manifest.devDependencies);
|
|
73
|
-
checkDependencies(manifest.peerDependencies);
|
|
74
|
-
checkDependencies(manifest.optionalDependencies);
|
|
75
|
-
checkDependencies(manifest.resolutions);
|
|
76
|
-
checkDependencies(manifest.pnpm?.overrides);
|
|
92
|
+
collectCatalogReferences(manifest.dependencies, catalogReferences);
|
|
93
|
+
collectCatalogReferences(manifest.devDependencies, catalogReferences);
|
|
94
|
+
collectCatalogReferences(manifest.peerDependencies, catalogReferences);
|
|
95
|
+
collectCatalogReferences(manifest.optionalDependencies, catalogReferences);
|
|
96
|
+
collectCatalogReferences(manifest.resolutions, catalogReferences);
|
|
77
97
|
return catalogReferences;
|
|
78
98
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const helpText = "\u2702\uFE0F Find unused dependencies, exports and files in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -h, --help Print this help text\n -V, --version Print version\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n -c, --config [file] Configuration file path\n (default: [.]knip.json[c], knip.(js|ts), knip.config.(js|ts) or package.json#knip)\n --use-tsconfig-files Use tsconfig.json to define project files (override `project` patterns)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n\nMode\n --cache Enable caching\n --cache-location Change cache location (default: node_modules/.cache/knip)\n --include-entry-exports Include entry files when reporting unused exports\n --no-gitignore Don't respect .gitignore\n -p, --production Analyze only production source files (e.g. no test files, devDependencies)\n -s, --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n -w, --watch Watch mode\n\nScope\n -W, --workspace [filter] Filter workspaces by name, directory, or glob (can be repeated)\n -D, --directory [dir] Run process from a different directory (default: cwd)\n --include Include provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,binaries,unresolved,catalog,catalogReferences\n --exports Shortcut for --include exports,nsExports,types,nsTypes,enumMembers,namespaceMembers,duplicates\n --files Shortcut for --include files\n --cycles Shortcut for --include cycles (circular dependencies)\n --tags Include or exclude tagged exports\n\nFix\n -f, --fix Fix issues (modifies files in your repo)\n --fix-type Fix only issues of type, can be comma-separated or repeated (2)\n --allow-remove-files Allow Knip to remove files (with --fix)\n -F, --format Format modified files after --fix using the local formatter\n\nOutput\n --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated\n --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)\n --reporter Select reporter (default: symbols), can be repeated (3)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-config-hints Suppress configuration hints\n --no-tag-hints Suppress tag hints\n --treat-config-hints-as-errors Exit with non-zero code (1) if there are any configuration hints\n --treat-tag-hints-as-errors Exit with non-zero code (1) if there are any tag hints\n --max-issues Maximum number of total issues before non-zero exit code (default: 0)\n --max-show-issues Maximum number of issues to display per type\n --no-exit-code Always exit with code zero (0)\n\nTroubleshooting\n -d, --debug Show debug output\n --memory Measure memory usage and display data table\n --memory-realtime Log memory usage in realtime\n --performance Measure count and running time of key functions and display stats table\n --performance-fn [name] Measure only function [name]\n -u, --duration Print total running time (zero overhead, no instrumentation)\n --trace Show trace output\n --trace-dependency [name] Show files that import the named dependency\n --trace-export [name] Show trace output for named export(s)\n --trace-file [file] Show trace output for exports in file\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, types, nsTypes, enumMembers, namespaceMembers, duplicates, catalog, catalogReferences, cycles\n(2) Fixable issue types: dependencies, exports, types, files, catalog\n(3) Built-in reporters: symbols (default), compact, codeowners, cycles, json, codeclimate, markdown, disclosure, github-actions, sarif\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip --workspace @myorg/* --workspace '!@myorg/legacy'\n$ knip --workspace './apps/*' --workspace '@shared/utils'\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --tags=-lintignore\n\nWebsite: https://knip.dev";
|
|
2
2
|
export type ParsedCLIArgs = ReturnType<typeof parseCLIArgs>;
|
|
3
|
+
export declare const parseNumericOption: (value: string | undefined, option: string) => number | undefined;
|
|
3
4
|
export default function parseCLIArgs(): {
|
|
4
5
|
cache?: boolean | undefined;
|
|
5
6
|
'cache-location'?: string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseArgs } from 'node:util';
|
|
2
|
+
import { ConfigurationError } from './errors.js';
|
|
2
3
|
export const helpText = `✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects
|
|
3
4
|
|
|
4
5
|
Usage: knip [options]
|
|
@@ -79,6 +80,14 @@ $ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
|
|
|
79
80
|
$ knip --tags=-lintignore
|
|
80
81
|
|
|
81
82
|
Website: https://knip.dev`;
|
|
83
|
+
export const parseNumericOption = (value, option) => {
|
|
84
|
+
if (value === undefined)
|
|
85
|
+
return undefined;
|
|
86
|
+
if (!/^\d+$/.test(value)) {
|
|
87
|
+
throw new ConfigurationError(`Option --${option} expects a non-negative integer, got: ${value}`);
|
|
88
|
+
}
|
|
89
|
+
return Number(value);
|
|
90
|
+
};
|
|
82
91
|
export default function parseCLIArgs() {
|
|
83
92
|
return parseArgs({
|
|
84
93
|
options: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Options } from '../types/options.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type ParsedCLIArgs } from './cli-arguments.ts';
|
|
3
3
|
interface CreateOptions extends Partial<Options> {
|
|
4
4
|
args?: ParsedCLIArgs;
|
|
5
5
|
}
|
|
@@ -43,6 +43,7 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
43
43
|
isTreatTagHintsAsErrors: boolean;
|
|
44
44
|
isUseTscFiles: boolean | undefined;
|
|
45
45
|
isWatch: boolean;
|
|
46
|
+
maxIssues: number;
|
|
46
47
|
maxShowIssues: number | undefined;
|
|
47
48
|
parsedConfig: {
|
|
48
49
|
angular?: string | boolean | string[] | {
|
|
@@ -365,6 +366,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
365
366
|
entry?: string | string[] | undefined;
|
|
366
367
|
project?: string | string[] | undefined;
|
|
367
368
|
} | undefined;
|
|
369
|
+
mise?: string | boolean | string[] | {
|
|
370
|
+
config?: string | string[] | undefined;
|
|
371
|
+
entry?: string | string[] | undefined;
|
|
372
|
+
project?: string | string[] | undefined;
|
|
373
|
+
} | undefined;
|
|
368
374
|
mocha?: string | boolean | string[] | {
|
|
369
375
|
config?: string | string[] | undefined;
|
|
370
376
|
entry?: string | string[] | undefined;
|
|
@@ -974,12 +980,13 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
974
980
|
} | undefined;
|
|
975
981
|
ignoreWorkspaces?: string[] | undefined;
|
|
976
982
|
includeEntryExports?: boolean | undefined;
|
|
977
|
-
compilers?: Record<string, true | import("../
|
|
978
|
-
|
|
979
|
-
asyncCompilers?: Record<string, import("../compilers/types.ts").CompilerAsync> | undefined;
|
|
983
|
+
compilers?: Record<string, true | import("../types.ts").Compiler> | undefined;
|
|
984
|
+
asyncCompilers?: Record<string, import("../types.ts").Compiler> | undefined;
|
|
980
985
|
tags?: string[] | undefined;
|
|
981
986
|
treatConfigHintsAsErrors?: boolean | undefined;
|
|
982
987
|
treatTagHintsAsErrors?: boolean | undefined;
|
|
988
|
+
preprocessor?: string | string[] | undefined;
|
|
989
|
+
preprocessorOptions?: Record<string, unknown> | undefined;
|
|
983
990
|
include?: ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
984
991
|
exclude?: ("binaries" | "catalog" | "catalogReferences" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
985
992
|
workspaces?: Record<string, {
|
|
@@ -1303,6 +1310,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
1303
1310
|
entry?: string | string[] | undefined;
|
|
1304
1311
|
project?: string | string[] | undefined;
|
|
1305
1312
|
} | undefined;
|
|
1313
|
+
mise?: string | boolean | string[] | {
|
|
1314
|
+
config?: string | string[] | undefined;
|
|
1315
|
+
entry?: string | string[] | undefined;
|
|
1316
|
+
project?: string | string[] | undefined;
|
|
1317
|
+
} | undefined;
|
|
1306
1318
|
mocha?: string | boolean | string[] | {
|
|
1307
1319
|
config?: string | string[] | undefined;
|
|
1308
1320
|
entry?: string | string[] | undefined;
|
|
@@ -1907,6 +1919,9 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
|
|
|
1907
1919
|
includeEntryExports?: boolean | undefined;
|
|
1908
1920
|
}> | undefined;
|
|
1909
1921
|
};
|
|
1922
|
+
preprocessor: string[];
|
|
1923
|
+
preprocessorInputs: string[];
|
|
1924
|
+
preprocessorOptions: string;
|
|
1910
1925
|
rules: {
|
|
1911
1926
|
binaries: import("../types/issues.ts").IssueSeverity;
|
|
1912
1927
|
catalog: import("../types/issues.ts").IssueSeverity;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { partitionCompilers } from '../compilers/index.js';
|
|
2
1
|
import { ISSUE_TYPES, KNIP_CONFIG_LOCATIONS } from '../constants.js';
|
|
3
2
|
import { knipConfigurationSchema } from '../schema/configuration.js';
|
|
3
|
+
import { arrayify } from './array.js';
|
|
4
4
|
import { getCatalogContainer } from './catalog.js';
|
|
5
|
+
import { parseNumericOption } from './cli-arguments.js';
|
|
5
6
|
import { ConfigurationError } from './errors.js';
|
|
6
7
|
import { findFile, loadJSON } from './fs.js';
|
|
7
8
|
import { getIncludedIssueTypes, shorthandCycles, shorthandDeps, shorthandExports, shorthandFiles, } from './get-included-issue-types.js';
|
|
@@ -10,7 +11,7 @@ import { loadResolvedConfigFile } from './load-config.js';
|
|
|
10
11
|
import { _load } from './loader.js';
|
|
11
12
|
import { logWarning } from './log.js';
|
|
12
13
|
import { getKeysByValue } from './object.js';
|
|
13
|
-
import { isAbsolute, join, normalize, toAbsolute, toPosix } from './path.js';
|
|
14
|
+
import { isAbsolute, isInternal, join, normalize, toAbsolute, toPosix } from './path.js';
|
|
14
15
|
import { splitTags } from './tag.js';
|
|
15
16
|
export const createOptions = async (options) => {
|
|
16
17
|
const { args = {} } = options;
|
|
@@ -55,7 +56,7 @@ export const createOptions = async (options) => {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
|
-
const parsedConfig = knipConfigurationSchema.parse(
|
|
59
|
+
const parsedConfig = knipConfigurationSchema.parse(loadedConfig);
|
|
59
60
|
if (!configFilePath && manifest.knip)
|
|
60
61
|
configFilePath = manifestPath;
|
|
61
62
|
const pnpmWorkspacePath = findFile(cwd, 'pnpm-workspace.yaml');
|
|
@@ -93,6 +94,14 @@ export const createOptions = async (options) => {
|
|
|
93
94
|
const isFixFiles = args['allow-remove-files'] && (fixTypes.length === 0 || fixTypes.includes('files'));
|
|
94
95
|
const tags = splitTags(args.tags ?? options.tags ?? parsedConfig.tags ?? []);
|
|
95
96
|
const workspace = options.workspace ?? args.workspace;
|
|
97
|
+
const toPreprocessor = (specifier) => (isInternal(specifier) ? toAbsolute(specifier, cwd) : specifier);
|
|
98
|
+
const configuredPreprocessor = arrayify(parsedConfig.preprocessor).map(toPreprocessor);
|
|
99
|
+
const preprocessor = args.preprocessor ? args.preprocessor.map(toPreprocessor) : configuredPreprocessor;
|
|
100
|
+
const preprocessorInputs = args.preprocessor
|
|
101
|
+
? [...new Set([...configuredPreprocessor, ...preprocessor])]
|
|
102
|
+
: preprocessor;
|
|
103
|
+
const preprocessorOptions = args['preprocessor-options'] ??
|
|
104
|
+
(parsedConfig.preprocessorOptions ? JSON.stringify(parsedConfig.preprocessorOptions) : '');
|
|
96
105
|
return {
|
|
97
106
|
cacheLocation: args['cache-location'] ?? join(cwd, 'node_modules', '.cache', 'knip'),
|
|
98
107
|
catalog: await getCatalogContainer(cwd, manifest, manifestPath, pnpmWorkspacePath, pnpmWorkspace),
|
|
@@ -150,8 +159,12 @@ export const createOptions = async (options) => {
|
|
|
150
159
|
isTreatTagHintsAsErrors: args['treat-tag-hints-as-errors'] ?? parsedConfig.treatTagHintsAsErrors ?? false,
|
|
151
160
|
isUseTscFiles: options.isUseTscFiles ?? args['use-tsconfig-files'] ?? (options.isSession && !configFilePath),
|
|
152
161
|
isWatch: args.watch ?? options.isWatch ?? false,
|
|
153
|
-
|
|
162
|
+
maxIssues: parseNumericOption(args['max-issues'], 'max-issues') ?? 0,
|
|
163
|
+
maxShowIssues: parseNumericOption(args['max-show-issues'], 'max-show-issues'),
|
|
154
164
|
parsedConfig,
|
|
165
|
+
preprocessor,
|
|
166
|
+
preprocessorInputs,
|
|
167
|
+
preprocessorOptions,
|
|
155
168
|
rules,
|
|
156
169
|
tags,
|
|
157
170
|
traceDependency: args['trace-dependency'],
|
package/dist/util/errors.d.ts
CHANGED
|
@@ -4,9 +4,11 @@ interface ErrorWithCause extends Error {
|
|
|
4
4
|
}
|
|
5
5
|
export declare class ConfigurationError extends Error {
|
|
6
6
|
}
|
|
7
|
+
export declare class CompilerError extends Error {
|
|
8
|
+
}
|
|
7
9
|
export declare class LoaderError extends Error {
|
|
8
10
|
}
|
|
9
|
-
export declare const isKnownError: (error: Error) => error is core.$ZodError<any> | ConfigurationError | LoaderError;
|
|
11
|
+
export declare const isKnownError: (error: Error) => error is core.$ZodError<any> | CompilerError | ConfigurationError | LoaderError;
|
|
10
12
|
export declare const hasErrorCause: (error: Error) => error is ErrorWithCause;
|
|
11
13
|
export declare const isConfigurationError: (error: Error) => error is ConfigurationError;
|
|
12
14
|
export declare const isModuleNotFoundError: (error: Error) => boolean;
|
package/dist/util/errors.js
CHANGED
|
@@ -3,9 +3,14 @@ import { substringBefore } from './string.js';
|
|
|
3
3
|
const isZodErrorLike = (error) => error instanceof core.$ZodError;
|
|
4
4
|
export class ConfigurationError extends Error {
|
|
5
5
|
}
|
|
6
|
+
export class CompilerError extends Error {
|
|
7
|
+
}
|
|
6
8
|
export class LoaderError extends Error {
|
|
7
9
|
}
|
|
8
|
-
export const isKnownError = (error) => error instanceof ConfigurationError ||
|
|
10
|
+
export const isKnownError = (error) => error instanceof ConfigurationError ||
|
|
11
|
+
error instanceof CompilerError ||
|
|
12
|
+
error instanceof LoaderError ||
|
|
13
|
+
isZodErrorLike(error);
|
|
9
14
|
export const hasErrorCause = (error) => !isZodErrorLike(error) && error.cause instanceof Error;
|
|
10
15
|
export const isConfigurationError = (error) => error instanceof ConfigurationError;
|
|
11
16
|
export const isModuleNotFoundError = (error) => 'code' in error && error.code === 'MODULE_NOT_FOUND';
|
|
@@ -4,7 +4,7 @@ import { deserialize, serialize } from 'node:v8';
|
|
|
4
4
|
import { debugLog } from './debug.js';
|
|
5
5
|
import { isDirectory, isFile } from './fs.js';
|
|
6
6
|
import { timerify } from './Performance.js';
|
|
7
|
-
import {
|
|
7
|
+
import { isAbsolute, resolve } from './path.js';
|
|
8
8
|
const createCache = (filePath) => {
|
|
9
9
|
try {
|
|
10
10
|
return deserialize(fs.readFileSync(filePath));
|
|
@@ -70,7 +70,7 @@ export class FileEntryCache {
|
|
|
70
70
|
}
|
|
71
71
|
reconcile() {
|
|
72
72
|
try {
|
|
73
|
-
const dir = dirname(this.filePath);
|
|
73
|
+
const dir = path.dirname(this.filePath);
|
|
74
74
|
if (!isDirectory(dir))
|
|
75
75
|
fs.mkdirSync(dir, { recursive: true });
|
|
76
76
|
fs.writeFileSync(this.filePath, serialize(this.cache));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Results } from '../run.ts';
|
|
2
|
+
import type { ReporterOptions } from '../types/issues.ts';
|
|
3
|
+
import type { ParsedCLIArgs } from './cli-arguments.ts';
|
|
4
|
+
import type { MainOptions } from './create-options.ts';
|
|
5
|
+
export declare const toReporterOptions: (options: MainOptions, results: Results, args?: ParsedCLIArgs) => ReporterOptions;
|
|
6
|
+
export declare const createPreprocessor: (processors: string[]) => Promise<(data: ReporterOptions) => Promise<ReporterOptions>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { _load } from './loader.js';
|
|
2
|
+
export const toReporterOptions = (options, results, args) => ({
|
|
3
|
+
...results,
|
|
4
|
+
report: options.includedIssueTypes,
|
|
5
|
+
cwd: options.cwd,
|
|
6
|
+
configFilePath: options.configFilePath,
|
|
7
|
+
isDisableConfigHints: options.isDisableConfigHints,
|
|
8
|
+
isDisableTagHints: options.isDisableTagHints,
|
|
9
|
+
isProduction: options.isProduction,
|
|
10
|
+
isShowProgress: options.isShowProgress,
|
|
11
|
+
isTreatConfigHintsAsErrors: options.isTreatConfigHintsAsErrors,
|
|
12
|
+
isTreatTagHintsAsErrors: options.isTreatTagHintsAsErrors,
|
|
13
|
+
maxShowIssues: options.maxShowIssues,
|
|
14
|
+
options: args?.['reporter-options'] ?? '',
|
|
15
|
+
preprocessorOptions: options.preprocessorOptions,
|
|
16
|
+
});
|
|
17
|
+
export const createPreprocessor = async (processors) => {
|
|
18
|
+
const preprocessors = await Promise.all(processors.map(_load));
|
|
19
|
+
return async (data) => {
|
|
20
|
+
for (const preprocessor of preprocessors)
|
|
21
|
+
data = await preprocessor(data);
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
};
|
package/dist/util/reporter.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import type { ReporterOptions } from '../types/issues.ts';
|
|
2
|
-
export declare const runPreprocessors: (processors: string[], data: ReporterOptions) => Promise<ReporterOptions>;
|
|
3
2
|
export declare const runReporters: (reporter: string[], options: ReporterOptions) => Promise<void>;
|
package/dist/util/reporter.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import internalReporters from '../reporters/index.js';
|
|
2
2
|
import { _load } from './loader.js';
|
|
3
3
|
import { isAbsolute, isInternal, resolve } from './path.js';
|
|
4
|
-
export const runPreprocessors = async (processors, data) => {
|
|
5
|
-
const preprocessors = await Promise.all(processors.map(proc => _load(isInternal(proc) && !isAbsolute(proc) ? resolve(proc) : proc)));
|
|
6
|
-
let result = data;
|
|
7
|
-
for (const preprocessor of preprocessors)
|
|
8
|
-
result = await preprocessor(result);
|
|
9
|
-
return result;
|
|
10
|
-
};
|
|
11
4
|
export const runReporters = async (reporter, options) => {
|
|
12
5
|
const reporters = await Promise.all(reporter.map(async (reporter) => {
|
|
13
6
|
return reporter in internalReporters
|
package/dist/util/watch.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type WatchChange = {
|
|
|
17
17
|
export type SessionHandler = Awaited<ReturnType<typeof getSessionHandler>>;
|
|
18
18
|
type WatchOptions = {
|
|
19
19
|
analyzedFiles: Set<string>;
|
|
20
|
-
analyzeSourceFile: (filePath: string
|
|
20
|
+
analyzeSourceFile: (filePath: string) => Promise<void>;
|
|
21
21
|
chief: ConfigurationChief;
|
|
22
22
|
collector: IssueCollector;
|
|
23
23
|
analyze: () => Promise<void>;
|
package/dist/util/watch.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
1
|
import { invalidateCache } from '../graph-explorer/cache.js';
|
|
3
2
|
import { debugLog } from './debug.js';
|
|
3
|
+
import { hasErrorCause } from './errors.js';
|
|
4
4
|
import { isFile } from './fs.js';
|
|
5
|
+
import { logError } from './log.js';
|
|
5
6
|
import { updateImportMap } from './module-graph.js';
|
|
6
7
|
import { toAbsolute, toPosix, toRelative } from './path.js';
|
|
7
8
|
import { clearModuleResolutionCaches } from '../typescript/resolve-module-names.js';
|
|
@@ -13,11 +14,12 @@ const createUpdate = (options) => {
|
|
|
13
14
|
return { duration, mem };
|
|
14
15
|
};
|
|
15
16
|
export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, principal, graph, isIgnored, onFileChange, unreferencedFiles, entryPaths, }) => {
|
|
16
|
-
const
|
|
17
|
+
const added = new Set();
|
|
18
|
+
const deleted = new Set();
|
|
19
|
+
const modified = new Set();
|
|
20
|
+
const processFileChanges = async (changes) => {
|
|
17
21
|
const startTime = performance.now();
|
|
18
|
-
|
|
19
|
-
const deleted = new Set();
|
|
20
|
-
const modified = new Set();
|
|
22
|
+
let hasRelevantChanges = false;
|
|
21
23
|
for (const change of changes) {
|
|
22
24
|
const filePath = toAbsolute(change.filePath, options.cwd);
|
|
23
25
|
const relativePath = toRelative(change.filePath, options.cwd);
|
|
@@ -28,23 +30,24 @@ export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceF
|
|
|
28
30
|
const workspace = chief.findWorkspaceByFilePath(filePath);
|
|
29
31
|
if (!workspace)
|
|
30
32
|
continue;
|
|
33
|
+
hasRelevantChanges = true;
|
|
31
34
|
switch (change.type) {
|
|
32
35
|
case 'added':
|
|
33
36
|
principal.addProjectPath(filePath);
|
|
34
|
-
|
|
37
|
+
deleted.delete(filePath);
|
|
35
38
|
if (principal.projectPaths.has(filePath))
|
|
36
39
|
added.add(filePath);
|
|
37
40
|
debugLog(workspace.name, `Watcher: + ${relativePath}`);
|
|
38
41
|
break;
|
|
39
42
|
case 'deleted':
|
|
40
43
|
deleted.add(filePath);
|
|
44
|
+
added.delete(filePath);
|
|
41
45
|
analyzedFiles.delete(filePath);
|
|
42
46
|
principal.removeProjectPath(filePath);
|
|
43
47
|
debugLog(workspace.name, `Watcher: - ${relativePath}`);
|
|
44
48
|
break;
|
|
45
49
|
default: {
|
|
46
|
-
|
|
47
|
-
if (cached !== undefined && cached === readFileSync(filePath, 'utf8')) {
|
|
50
|
+
if (!principal.fileManager.hasChanged(filePath)) {
|
|
48
51
|
debugLog(workspace.name, `Watcher: = ${relativePath}`);
|
|
49
52
|
continue;
|
|
50
53
|
}
|
|
@@ -55,31 +58,31 @@ export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceF
|
|
|
55
58
|
}
|
|
56
59
|
principal.invalidateFile(filePath);
|
|
57
60
|
}
|
|
58
|
-
if (added.size === 0 && deleted.size === 0 && modified.size === 0)
|
|
61
|
+
if (!hasRelevantChanges || (added.size === 0 && deleted.size === 0 && modified.size === 0))
|
|
59
62
|
return;
|
|
60
63
|
clearResolverCache();
|
|
61
64
|
clearModuleResolutionCaches();
|
|
62
65
|
clearGlobCache();
|
|
63
66
|
invalidateCache(graph);
|
|
67
|
+
const filePaths = await principal.getUsedResolvedFiles();
|
|
64
68
|
unreferencedFiles.clear();
|
|
65
69
|
const cachedUnusedFiles = collector.purge();
|
|
66
70
|
for (const filePath of added)
|
|
67
71
|
cachedUnusedFiles.add(filePath);
|
|
68
72
|
for (const filePath of deleted)
|
|
69
73
|
cachedUnusedFiles.delete(filePath);
|
|
70
|
-
const filePaths = principal.getUsedResolvedFiles();
|
|
71
74
|
if (added.size > 0 || deleted.size > 0) {
|
|
72
75
|
graph.clear();
|
|
73
76
|
for (const filePath of filePaths) {
|
|
74
77
|
const workspace = chief.findWorkspaceByFilePath(filePath);
|
|
75
78
|
if (workspace) {
|
|
76
|
-
analyzeSourceFile(filePath
|
|
79
|
+
await analyzeSourceFile(filePath);
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
else {
|
|
81
84
|
for (const [filePath, file] of graph) {
|
|
82
|
-
if (filePaths.
|
|
85
|
+
if (filePaths.has(filePath)) {
|
|
83
86
|
file.importedBy = undefined;
|
|
84
87
|
}
|
|
85
88
|
else {
|
|
@@ -94,7 +97,7 @@ export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceF
|
|
|
94
97
|
if (!graph.has(filePath)) {
|
|
95
98
|
const workspace = chief.findWorkspaceByFilePath(filePath);
|
|
96
99
|
if (workspace) {
|
|
97
|
-
analyzeSourceFile(filePath
|
|
100
|
+
await analyzeSourceFile(filePath);
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
}
|
|
@@ -103,7 +106,7 @@ export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceF
|
|
|
103
106
|
const workspace = chief.findWorkspaceByFilePath(filePath);
|
|
104
107
|
if (workspace) {
|
|
105
108
|
if (principal.projectPaths.has(filePath) || graph.has(filePath)) {
|
|
106
|
-
analyzeSourceFile(filePath
|
|
109
|
+
await analyzeSourceFile(filePath);
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
112
|
}
|
|
@@ -120,17 +123,32 @@ export const getSessionHandler = async (options, { analyzedFiles, analyzeSourceF
|
|
|
120
123
|
collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
|
|
121
124
|
for (const issue of collector.getRetainedIssues())
|
|
122
125
|
collector.addIssue(issue);
|
|
126
|
+
added.clear();
|
|
127
|
+
deleted.clear();
|
|
128
|
+
modified.clear();
|
|
123
129
|
const update = createUpdate({ startTime });
|
|
124
130
|
if (onFileChange)
|
|
125
131
|
onFileChange(Object.assign({ issues: getIssues().issues }, update));
|
|
126
132
|
return update;
|
|
127
133
|
};
|
|
134
|
+
const clearSourceText = () => principal.fileManager.sourceTextCache.clear();
|
|
135
|
+
let pending = Promise.resolve();
|
|
136
|
+
const handleFileChanges = (changes) => {
|
|
137
|
+
const update = pending.then(() => processFileChanges(changes));
|
|
138
|
+
pending = update.then(clearSourceText, clearSourceText);
|
|
139
|
+
return update;
|
|
140
|
+
};
|
|
128
141
|
const listener = (eventType, filePath) => {
|
|
129
142
|
debugLog('*', `(raw) ${eventType} ${filePath}`);
|
|
130
143
|
if (typeof filePath === 'string') {
|
|
131
144
|
const normalizedPath = toPosix(filePath);
|
|
132
145
|
const type = eventType === 'rename' ? (isFile(options.cwd, normalizedPath) ? 'added' : 'deleted') : 'modified';
|
|
133
|
-
handleFileChanges([{ type, filePath: normalizedPath }])
|
|
146
|
+
handleFileChanges([{ type, filePath: normalizedPath }]).catch(error => {
|
|
147
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
148
|
+
const reason = error instanceof Error && hasErrorCause(error) ? `\nReason: ${error.cause.message}` : '';
|
|
149
|
+
logError(message + reason);
|
|
150
|
+
process.exitCode = 2;
|
|
151
|
+
});
|
|
134
152
|
}
|
|
135
153
|
};
|
|
136
154
|
const getIssues = () => collector.getIssues();
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "6.
|
|
1
|
+
export declare const version = "6.35.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '6.
|
|
1
|
+
export const version = '6.35.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.35.0",
|
|
4
4
|
"description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analysis",
|
|
@@ -85,25 +85,25 @@
|
|
|
85
85
|
"formatly": "^0.7.0",
|
|
86
86
|
"get-tsconfig": "4.14.3",
|
|
87
87
|
"jiti": "^2.7.0",
|
|
88
|
-
"oxc-parser": "^0.
|
|
88
|
+
"oxc-parser": "^0.148.0",
|
|
89
89
|
"oxc-resolver": "11.24.2",
|
|
90
90
|
"picomatch": "^4.0.7",
|
|
91
91
|
"smol-toml": "^1.8.0",
|
|
92
92
|
"strip-json-comments": "5.0.3",
|
|
93
93
|
"tinyglobby": "^0.2.17",
|
|
94
|
-
"unbash": "^4.0.
|
|
94
|
+
"unbash": "^4.0.11",
|
|
95
95
|
"yaml": "^2.9.0",
|
|
96
96
|
"zod": "^4.4.3"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
-
"@jest/types": "^30.
|
|
100
|
-
"@types/bun": "^1.4.
|
|
99
|
+
"@jest/types": "^30.5.1",
|
|
100
|
+
"@types/bun": "^1.4.1",
|
|
101
101
|
"@types/picomatch": "^4.0.3",
|
|
102
|
-
"@types/webpack": "^5.28.5",
|
|
103
102
|
"codeclimate-types": "^0.3.1",
|
|
104
103
|
"prettier": "^3.9.6",
|
|
105
|
-
"tsx": "^4.23.
|
|
106
|
-
"typescript": "7.0.2"
|
|
104
|
+
"tsx": "^4.23.13",
|
|
105
|
+
"typescript": "7.0.2",
|
|
106
|
+
"webpack": "^5.110.3"
|
|
107
107
|
},
|
|
108
108
|
"engines": {
|
|
109
109
|
"node": "^20.19.0 || >=22.12.0"
|
package/schema.json
CHANGED
|
@@ -173,6 +173,14 @@
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
},
|
|
176
|
+
"preprocessor": {
|
|
177
|
+
"title": "Preprocess the results before providing them to the reporter(s)",
|
|
178
|
+
"oneOf": [{ "type": "string" }, { "$ref": "#/definitions/list" }]
|
|
179
|
+
},
|
|
180
|
+
"preprocessorOptions": {
|
|
181
|
+
"title": "Extra options to pass to the preprocessor",
|
|
182
|
+
"type": "object"
|
|
183
|
+
},
|
|
176
184
|
"treatConfigHintsAsErrors": {
|
|
177
185
|
"title": "Exit with non-zero code (1) if there are any configuration hints",
|
|
178
186
|
"type": "boolean"
|
|
@@ -650,6 +658,10 @@
|
|
|
650
658
|
"title": "metro plugin configuration (https://knip.dev/reference/plugins/metro)",
|
|
651
659
|
"$ref": "#/definitions/plugin"
|
|
652
660
|
},
|
|
661
|
+
"mise": {
|
|
662
|
+
"title": "mise plugin configuration (https://knip.dev/reference/plugins/mise)",
|
|
663
|
+
"$ref": "#/definitions/plugin"
|
|
664
|
+
},
|
|
653
665
|
"mocha": {
|
|
654
666
|
"title": "Mocha plugin configuration (https://knip.dev/reference/plugins/mocha)",
|
|
655
667
|
"$ref": "#/definitions/plugin"
|