knip 5.66.0 → 5.66.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.
Files changed (44) hide show
  1. package/dist/ConfigurationChief.d.ts +6 -6
  2. package/dist/ConsoleStreamer.d.ts +2 -1
  3. package/dist/ConsoleStreamer.js +10 -5
  4. package/dist/IssueCollector.d.ts +4 -1
  5. package/dist/IssueCollector.js +8 -1
  6. package/dist/compilers/index.d.ts +5 -12
  7. package/dist/constants.d.ts +28 -3
  8. package/dist/constants.js +10 -0
  9. package/dist/graph/build.js +4 -2
  10. package/dist/index.js +5 -1
  11. package/dist/plugins/nuxt/index.js +5 -1
  12. package/dist/plugins/rsbuild/index.js +7 -7
  13. package/dist/reporters/util/util.d.ts +2 -2
  14. package/dist/reporters/util/util.js +2 -3
  15. package/dist/reporters/watch.d.ts +2 -2
  16. package/dist/reporters/watch.js +3 -3
  17. package/dist/schema/configuration.d.ts +1 -6
  18. package/dist/schema/configuration.js +3 -8
  19. package/dist/types/config.d.ts +1 -1
  20. package/dist/types/issues.d.ts +2 -10
  21. package/dist/types/issues.js +1 -11
  22. package/dist/typescript/ast-helpers.d.ts +3 -3
  23. package/dist/typescript/ast-helpers.js +11 -12
  24. package/dist/typescript/visitors/exports/exportDeclaration.js +4 -5
  25. package/dist/typescript/visitors/exports/exportKeyword.js +9 -10
  26. package/dist/typescript/visitors/exports/exportsAccessExpression.js +2 -3
  27. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +5 -6
  28. package/dist/util/Performance.d.ts +1 -1
  29. package/dist/util/Performance.js +2 -2
  30. package/dist/util/create-options.d.ts +7 -14
  31. package/dist/util/create-options.js +1 -1
  32. package/dist/util/get-included-issue-types.js +1 -4
  33. package/dist/util/get-referenced-inputs.d.ts +2 -2
  34. package/dist/util/get-referenced-inputs.js +5 -5
  35. package/dist/util/has-strictly-ns-references.d.ts +1 -1
  36. package/dist/util/string.js +5 -1
  37. package/dist/util/to-source-path.d.ts +1 -1
  38. package/dist/util/to-source-path.js +4 -4
  39. package/dist/util/watch.d.ts +7 -3
  40. package/dist/util/watch.js +106 -67
  41. package/dist/version.d.ts +1 -1
  42. package/dist/version.js +1 -1
  43. package/package.json +1 -1
  44. package/schema.json +3 -0
@@ -1,6 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { FIX_FLAGS } from '../../../constants.js';
3
- import { SymbolType } from '../../../types/issues.js';
2
+ import { FIX_FLAGS, SYMBOL_TYPE } from '../../../constants.js';
4
3
  import { compact } from '../../../util/array.js';
5
4
  import { getClassMember, getDefaultKeywordNode, getEnumMember, getExportKeywordNode, isNonPrivatePropertyOrMethodDeclaration, } from '../../ast-helpers.js';
6
5
  import { isModule } from '../helpers.js';
@@ -20,7 +19,7 @@ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassM
20
19
  node: element,
21
20
  symbol: element.symbol,
22
21
  identifier: element.name.escapedText.toString(),
23
- type: SymbolType.UNKNOWN,
22
+ type: SYMBOL_TYPE.UNKNOWN,
24
23
  pos: element.name.getStart(),
25
24
  fix,
26
25
  };
@@ -35,7 +34,7 @@ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassM
35
34
  node: element,
36
35
  symbol: element.symbol,
37
36
  identifier: element.getText(),
38
- type: SymbolType.UNKNOWN,
37
+ type: SYMBOL_TYPE.UNKNOWN,
39
38
  pos: element.getStart(),
40
39
  fix,
41
40
  };
@@ -45,7 +44,7 @@ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassM
45
44
  const identifier = declaration.name.getText();
46
45
  const pos = declaration.name.getStart();
47
46
  const fix = getFix(exportKeyword);
48
- return { node: declaration, identifier, type: SymbolType.UNKNOWN, pos, fix };
47
+ return { node: declaration, identifier, type: SYMBOL_TYPE.UNKNOWN, pos, fix };
49
48
  });
50
49
  }
51
50
  const defaultKeyword = getDefaultKeywordNode(node);
@@ -53,7 +52,7 @@ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassM
53
52
  const identifier = defaultKeyword ? 'default' : node.name.getText();
54
53
  const pos = (node.name ?? node.body ?? node).getStart();
55
54
  const fix = getFix(exportKeyword, defaultKeyword);
56
- return { node, identifier, pos, type: SymbolType.FUNCTION, fix };
55
+ return { node, identifier, pos, type: SYMBOL_TYPE.FUNCTION, fix };
57
56
  }
58
57
  if (ts.isClassDeclaration(node) && node.name) {
59
58
  const identifier = defaultKeyword ? 'default' : node.name.getText();
@@ -62,26 +61,26 @@ export default visit(isModule, (node, { isFixExports, isFixTypes, isReportClassM
62
61
  const members = isReportClassMembers
63
62
  ? node.members.filter(isNonPrivatePropertyOrMethodDeclaration).map(member => getClassMember(member, isFixTypes))
64
63
  : [];
65
- return { node, identifier, type: SymbolType.CLASS, pos, members, fix };
64
+ return { node, identifier, type: SYMBOL_TYPE.CLASS, pos, members, fix };
66
65
  }
67
66
  if (ts.isTypeAliasDeclaration(node)) {
68
67
  const identifier = node.name.getText();
69
68
  const pos = node.name.getStart();
70
69
  const fix = getTypeFix(exportKeyword);
71
- return { node, identifier, type: SymbolType.TYPE, pos, fix };
70
+ return { node, identifier, type: SYMBOL_TYPE.TYPE, pos, fix };
72
71
  }
73
72
  if (ts.isInterfaceDeclaration(node)) {
74
73
  const identifier = defaultKeyword ? 'default' : node.name.getText();
75
74
  const pos = node.name.getStart();
76
75
  const fix = getTypeFix(exportKeyword);
77
- return { node, identifier, type: SymbolType.INTERFACE, pos, fix };
76
+ return { node, identifier, type: SYMBOL_TYPE.INTERFACE, pos, fix };
78
77
  }
79
78
  if (ts.isEnumDeclaration(node)) {
80
79
  const identifier = node.name.getText();
81
80
  const pos = node.name.getStart();
82
81
  const fix = getTypeFix(exportKeyword);
83
82
  const members = node.members.map(member => getEnumMember(member, isFixExports));
84
- return { node, identifier, type: SymbolType.ENUM, pos, members, fix };
83
+ return { node, identifier, type: SYMBOL_TYPE.ENUM, pos, members, fix };
85
84
  }
86
85
  }
87
86
  });
@@ -1,6 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { FIX_FLAGS } from '../../../constants.js';
3
- import { SymbolType } from '../../../types/issues.js';
2
+ import { FIX_FLAGS, SYMBOL_TYPE } from '../../../constants.js';
4
3
  import { isJS } from '../helpers.js';
5
4
  import { exportVisitor as visit } from '../index.js';
6
5
  export default visit(isJS, (node, { isFixExports }) => {
@@ -12,7 +11,7 @@ export default visit(isJS, (node, { isFixExports }) => {
12
11
  return {
13
12
  node: node.left.name,
14
13
  identifier,
15
- type: SymbolType.UNKNOWN,
14
+ type: SYMBOL_TYPE.UNKNOWN,
16
15
  pos,
17
16
  fix,
18
17
  };
@@ -1,6 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { FIX_FLAGS } from '../../../constants.js';
3
- import { SymbolType } from '../../../types/issues.js';
2
+ import { FIX_FLAGS, SYMBOL_TYPE } from '../../../constants.js';
4
3
  import { hasRequireCall, isModuleExportsAccess, stripQuotes } from '../../ast-helpers.js';
5
4
  import { isJS } from '../helpers.js';
6
5
  import { exportVisitor as visit } from '../index.js';
@@ -16,7 +15,7 @@ export default visit(isJS, (node, { isFixExports }) => {
16
15
  return {
17
16
  node: node.expression.left.name,
18
17
  identifier,
19
- type: SymbolType.UNKNOWN,
18
+ type: SYMBOL_TYPE.UNKNOWN,
20
19
  pos,
21
20
  fix,
22
21
  };
@@ -26,13 +25,13 @@ export default visit(isJS, (node, { isFixExports }) => {
26
25
  if (ts.isObjectLiteralExpression(expr) && expr.properties.every(ts.isShorthandPropertyAssignment)) {
27
26
  return expr.properties.map(node => {
28
27
  const fix = isFixExports ? [node.getStart(), node.getEnd(), FIX_FLAGS.NONE] : undefined;
29
- return { node, identifier: node.getText(), type: SymbolType.UNKNOWN, pos: node.getStart(), fix };
28
+ return { node, identifier: node.getText(), type: SYMBOL_TYPE.UNKNOWN, pos: node.getStart(), fix };
30
29
  });
31
30
  }
32
31
  if (ts.isCallExpression(node.expression.right) && hasRequireCall(node.expression.right)) {
33
32
  return;
34
33
  }
35
- return { node, identifier: 'default', type: SymbolType.UNKNOWN, pos: expr.pos + 1, fix: undefined };
34
+ return { node, identifier: 'default', type: SYMBOL_TYPE.UNKNOWN, pos: expr.pos + 1, fix: undefined };
36
35
  }
37
36
  }
38
37
  else if (ts.isElementAccessExpression(node.expression.left) &&
@@ -45,7 +44,7 @@ export default visit(isJS, (node, { isFixExports }) => {
45
44
  return {
46
45
  node: node.expression.left.argumentExpression,
47
46
  identifier,
48
- type: SymbolType.UNKNOWN,
47
+ type: SYMBOL_TYPE.UNKNOWN,
49
48
  pos,
50
49
  fix,
51
50
  };
@@ -34,7 +34,7 @@ declare class Performance {
34
34
  getTimerifiedFunctionsTable(): string;
35
35
  addMemoryMark(index: number): void;
36
36
  getMemoryUsageTable(): string;
37
- getCurrentDurationInMs(startTime?: number): number;
37
+ getCurrentDurationInMs(): number;
38
38
  getMemHeapUsage(): number;
39
39
  getCurrentMemUsageInMb(): any;
40
40
  finalize(): Promise<void>;
@@ -133,8 +133,8 @@ class Performance {
133
133
  }
134
134
  return table.toString();
135
135
  }
136
- getCurrentDurationInMs(startTime) {
137
- return performance.now() - (startTime ?? this.startTime);
136
+ getCurrentDurationInMs() {
137
+ return performance.now() - this.startTime;
138
138
  }
139
139
  getMemHeapUsage() {
140
140
  return (memoryUsage().heapUsed ?? 0) - (this.memoryUsageStart?.heapUsed ?? 0);
@@ -1200,10 +1200,10 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1200
1200
  ignoreUnresolved?: (string | RegExp)[] | undefined;
1201
1201
  includeEntryExports?: boolean | undefined;
1202
1202
  }> | undefined;
1203
- include?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
1204
- exclude?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
1203
+ include?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[] | undefined;
1204
+ exclude?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[] | undefined;
1205
1205
  $schema?: string | undefined;
1206
- rules?: Partial<Record<"files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers", "error" | "warn" | "off">> | undefined;
1206
+ rules?: Partial<Record<"files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates", "error" | "warn" | "off">> | undefined;
1207
1207
  entry?: string | string[] | undefined;
1208
1208
  project?: string | string[] | undefined;
1209
1209
  paths?: Record<string, string[]> | undefined;
@@ -1213,15 +1213,8 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1213
1213
  ignoreDependencies?: (string | RegExp)[] | undefined;
1214
1214
  ignoreMembers?: (string | RegExp)[] | undefined;
1215
1215
  ignoreUnresolved?: (string | RegExp)[] | undefined;
1216
- ignoreExportsUsedInFile?: boolean | {
1217
- class?: boolean | undefined;
1218
- enum?: boolean | undefined;
1219
- function?: boolean | undefined;
1220
- interface?: boolean | undefined;
1221
- member?: boolean | undefined;
1222
- type?: boolean | undefined;
1223
- } | undefined;
1224
- ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[]> | undefined;
1216
+ ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
1217
+ ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[]> | undefined;
1225
1218
  ignoreWorkspaces?: string[] | undefined;
1226
1219
  includeEntryExports?: boolean | undefined;
1227
1220
  compilers?: Record<string, true | ((filename: string, contents: string) => string) | ((filename: string, contents: string) => Promise<string>)> | undefined;
@@ -1239,12 +1232,12 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1239
1232
  binaries: import("../types/issues.js").IssueSeverity;
1240
1233
  unresolved: import("../types/issues.js").IssueSeverity;
1241
1234
  exports: import("../types/issues.js").IssueSeverity;
1242
- types: import("../types/issues.js").IssueSeverity;
1243
1235
  nsExports: import("../types/issues.js").IssueSeverity;
1236
+ types: import("../types/issues.js").IssueSeverity;
1244
1237
  nsTypes: import("../types/issues.js").IssueSeverity;
1245
- duplicates: import("../types/issues.js").IssueSeverity;
1246
1238
  enumMembers: import("../types/issues.js").IssueSeverity;
1247
1239
  classMembers: import("../types/issues.js").IssueSeverity;
1240
+ duplicates: import("../types/issues.js").IssueSeverity;
1248
1241
  _files: import("../types/issues.js").IssueSeverity;
1249
1242
  };
1250
1243
  tags: import("../types/options.js").Tags;
@@ -94,7 +94,7 @@ export const createOptions = async (options) => {
94
94
  includedIssueTypes.binaries,
95
95
  isReportTypes: includedIssueTypes.types || includedIssueTypes.nsTypes || includedIssueTypes.enumMembers,
96
96
  isReportValues: includedIssueTypes.exports || includedIssueTypes.nsExports || isReportClassMembers,
97
- isShowProgress: parsedCLIArgs['no-progress'] === false && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function',
97
+ isShowProgress: parsedCLIArgs['no-progress'] !== true && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function',
98
98
  isSkipLibs: !(isIncludeLibs || includedIssueTypes.classMembers),
99
99
  isStrict,
100
100
  isTrace: Boolean(parsedCLIArgs.trace ?? parsedCLIArgs['trace-file'] ?? parsedCLIArgs['trace-export']),
@@ -31,8 +31,5 @@ export const getIncludedIssueTypes = (options) => {
31
31
  ? _include
32
32
  : [..._include, ...defaultIssueTypes]
33
33
  : defaultIssueTypes).filter(group => !_exclude.includes(group));
34
- return ISSUE_TYPES.filter(i => i !== '_files').reduce((types, group) => {
35
- types[group] = included.includes(group);
36
- return types;
37
- }, {});
34
+ return Object.fromEntries(ISSUE_TYPES.map(group => [group, included.includes(group)]));
38
35
  };
@@ -1,5 +1,5 @@
1
1
  import type { ConfigurationChief, Workspace } from '../ConfigurationChief.js';
2
2
  import type { DependencyDeputy } from '../DependencyDeputy.js';
3
- import type { IssueCollector } from '../IssueCollector.js';
3
+ import type { Issue } from '../types/issues.js';
4
4
  import { type Input } from './input.js';
5
- export declare const getReferencedInputsHandler: (collector: IssueCollector, deputy: DependencyDeputy, chief: ConfigurationChief, isGitIgnored: (s: string) => boolean) => (input: Input, workspace: Workspace) => string | undefined;
5
+ export declare const getReferencedInputsHandler: (deputy: DependencyDeputy, chief: ConfigurationChief, isGitIgnored: (s: string) => boolean, addIssue: (issue: Issue) => void) => (input: Input, workspace: Workspace) => string | undefined;
@@ -7,7 +7,7 @@ import { _resolveSync } from './resolve.js';
7
7
  const getWorkspaceFor = (input, chief, workspace) => (input.dir && chief.findWorkspaceByFilePath(`${input.dir}/`)) ||
8
8
  (input.containingFilePath && chief.findWorkspaceByFilePath(input.containingFilePath)) ||
9
9
  workspace;
10
- export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnored) => (input, workspace) => {
10
+ export const getReferencedInputsHandler = (deputy, chief, isGitIgnored, addIssue) => (input, workspace) => {
11
11
  const { specifier, containingFilePath } = input;
12
12
  if (!containingFilePath || IGNORED_RUNTIME_DEPENDENCIES.has(specifier))
13
13
  return;
@@ -17,7 +17,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
17
17
  const isHandled = deputy.maybeAddReferencedBinary(inputWorkspace, binaryName);
18
18
  if (isHandled || input.optional)
19
19
  return;
20
- collector.addIssue({
20
+ addIssue({
21
21
  type: 'binaries',
22
22
  filePath: containingFilePath,
23
23
  workspace: workspace.name,
@@ -35,7 +35,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
35
35
  if (isWorkspace || isDependency(input)) {
36
36
  if (!isHandled) {
37
37
  if (!input.optional && ((deputy.isProduction && input.production) || !deputy.isProduction)) {
38
- collector.addIssue({
38
+ addIssue({
39
39
  type: 'unlisted',
40
40
  filePath: containingFilePath,
41
41
  workspace: inputWorkspace.name,
@@ -65,7 +65,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
65
65
  if (input.optional)
66
66
  return;
67
67
  if (!isInternal(filePath)) {
68
- collector.addIssue({
68
+ addIssue({
69
69
  type: 'unlisted',
70
70
  filePath: containingFilePath,
71
71
  workspace: workspace.name,
@@ -75,7 +75,7 @@ export const getReferencedInputsHandler = (collector, deputy, chief, isGitIgnore
75
75
  }
76
76
  else if (!isGitIgnored(filePath)) {
77
77
  if (!isDeferResolveEntry(input) && !isConfig(input)) {
78
- collector.addIssue({
78
+ addIssue({
79
79
  type: 'unresolved',
80
80
  filePath: containingFilePath,
81
81
  workspace: workspace.name,
@@ -1,4 +1,4 @@
1
1
  import type { ImportDetails, ModuleGraph } from '../types/module-graph.js';
2
2
  export declare const hasStrictlyEnumReferences: (importsForExport: ImportDetails | undefined, id: string) => boolean;
3
3
  export declare const hasStrictlyNsReferences: (graph: ModuleGraph, importsForExport: ImportDetails | undefined, id: string) => [boolean, string?];
4
- export declare const getType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "types" | "nsExports" | "nsTypes";
4
+ export declare const getType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
@@ -64,5 +64,9 @@ export const prettyMilliseconds = (ms) => {
64
64
  return `${hours}h ${minutes % 60}m ${Math.floor(seconds % 60)}s`;
65
65
  if (minutes > 0)
66
66
  return `${minutes}m ${Math.floor(seconds % 60)}s`;
67
- return seconds % 1 ? `${seconds.toFixed(1)}s` : `${Math.floor(seconds)}s`;
67
+ if (seconds > 10)
68
+ return `${Math.round(seconds)}s`;
69
+ if (seconds > 1)
70
+ return `${seconds.toFixed(1)}s`;
71
+ return `${Math.round(ms)}ms`;
68
72
  };
@@ -2,5 +2,5 @@ import type { CompilerOptions } from 'typescript';
2
2
  import type { ConfigurationChief, Workspace } from '../ConfigurationChief.js';
3
3
  export declare const augmentWorkspace: (workspace: Workspace, dir: string, compilerOptions: CompilerOptions) => void;
4
4
  export declare const getToSourcePathHandler: (chief: ConfigurationChief) => (filePath: string) => string | undefined;
5
- export declare const getToSourcePathsHandler: (chief: ConfigurationChief) => (specifiers: Set<string>, dir: string, extensions?: string) => Promise<string[]>;
5
+ export declare const getToSourcePathsHandler: (chief: ConfigurationChief) => (specifiers: Set<string>, dir: string, extensions: string | undefined, label: string) => Promise<string[]>;
6
6
  export type ToSourceFilePath = ReturnType<typeof getToSourcePathHandler>;
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_EXTENSIONS } from '../constants.js';
2
2
  import { debugLog, debugLogArray } from './debug.js';
3
3
  import { isDirectory } from './fs.js';
4
- import { _glob, _syncGlob } from './glob.js';
4
+ import { _glob, _syncGlob, prependDirToPattern } from './glob.js';
5
5
  import { isAbsolute, isInternal, join, toRelative } from './path.js';
6
6
  const defaultExtensions = `.{${DEFAULT_EXTENSIONS.map(ext => ext.slice(1)).join(',')}}`;
7
7
  const hasTSExt = /(?<!\.d)\.(m|c)?tsx?$/;
@@ -35,10 +35,10 @@ export const getToSourcePathHandler = (chief) => {
35
35
  };
36
36
  };
37
37
  export const getToSourcePathsHandler = (chief) => {
38
- return async (specifiers, dir, extensions = defaultExtensions) => {
38
+ return async (specifiers, dir, extensions = defaultExtensions, label) => {
39
39
  const patterns = new Set();
40
40
  for (const specifier of specifiers) {
41
- const absSpecifier = isAbsolute(specifier) ? specifier : join(dir, specifier);
41
+ const absSpecifier = isAbsolute(specifier) ? specifier : prependDirToPattern(dir, specifier);
42
42
  const ws = chief.findWorkspaceByFilePath(absSpecifier);
43
43
  if (ws?.srcDir && ws.outDir && !absSpecifier.startsWith(ws.srcDir) && absSpecifier.startsWith(ws.outDir)) {
44
44
  const pattern = absSpecifier.replace(ws.outDir, ws.srcDir).replace(matchExt, extensions);
@@ -48,7 +48,7 @@ export const getToSourcePathsHandler = (chief) => {
48
48
  patterns.add(absSpecifier);
49
49
  }
50
50
  }
51
- const filePaths = await _glob({ patterns: Array.from(patterns), cwd: dir });
51
+ const filePaths = await _glob({ patterns: Array.from(patterns), cwd: dir, label });
52
52
  debugLogArray(toRelative(dir, chief.cwd), 'Source mapping (package.json)', filePaths);
53
53
  return filePaths;
54
54
  };
@@ -1,11 +1,15 @@
1
1
  import type { WatchListener } from 'node:fs';
2
2
  import type { ConfigurationChief } from '../ConfigurationChief.js';
3
- import type { ConsoleStreamer } from '../ConsoleStreamer.js';
4
3
  import type { IssueCollector } from '../IssueCollector.js';
5
4
  import type { PrincipalFactory } from '../PrincipalFactory.js';
6
5
  import type { ProjectPrincipal } from '../ProjectPrincipal.js';
6
+ import type { Issues } from '../types/issues.js';
7
7
  import type { ModuleGraph } from '../types/module-graph.js';
8
8
  import type { MainOptions } from './create-options.js';
9
+ export type OnUpdate = (options: {
10
+ issues: Issues;
11
+ duration?: number;
12
+ }) => void;
9
13
  type Watch = {
10
14
  analyzedFiles: Set<string>;
11
15
  analyzeSourceFile: (filePath: string, principal: ProjectPrincipal) => void;
@@ -15,8 +19,8 @@ type Watch = {
15
19
  factory: PrincipalFactory;
16
20
  graph: ModuleGraph;
17
21
  isIgnored: (path: string) => boolean;
18
- streamer: ConsoleStreamer;
22
+ onUpdate: OnUpdate;
19
23
  unreferencedFiles: Set<string>;
20
24
  };
21
- export declare const getWatchHandler: (options: MainOptions, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, streamer, unreferencedFiles, }: Watch) => Promise<WatchListener<string | Buffer<ArrayBufferLike>>>;
25
+ export declare const getWatchHandler: (options: MainOptions, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, onUpdate, unreferencedFiles, }: Watch) => Promise<WatchListener<string | Buffer<ArrayBufferLike>>>;
22
26
  export {};
@@ -1,85 +1,124 @@
1
- import watchReporter from '../reporters/watch.js';
2
1
  import { debugLog } from './debug.js';
3
2
  import { isFile } from './fs.js';
4
3
  import { updateImportMap } from './module-graph.js';
5
- import { join, toPosix } from './path.js';
6
- export const getWatchHandler = async (options, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, streamer, unreferencedFiles, }) => {
7
- const reportIssues = async (startTime) => {
8
- const { issues } = collector.getIssues();
9
- watchReporter(options, { issues, streamer, startTime, size: analyzedFiles.size });
10
- };
11
- const listener = async (eventType, filename) => {
12
- debugLog('*', `(raw) ${eventType} ${filename}`);
13
- if (typeof filename === 'string') {
14
- const startTime = performance.now();
15
- const filePath = join(options.cwd, toPosix(filename));
4
+ import { join, toAbsolute, toRelative } from './path.js';
5
+ export const getWatchHandler = async (options, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, onUpdate, unreferencedFiles, }) => {
6
+ const getIssues = () => collector.getIssues().issues;
7
+ const processBatch = async (changes) => {
8
+ const startTime = performance.now();
9
+ const added = new Set();
10
+ const deleted = new Set();
11
+ const modified = new Set();
12
+ for (const [type, _path] of changes) {
13
+ const filePath = toAbsolute(_path, options.cwd);
14
+ const relativePath = toRelative(_path, options.cwd);
16
15
  if (isIgnored(filePath)) {
17
- debugLog('*', `ignoring ${eventType} ${filename}`);
18
- return;
16
+ debugLog('*', `ignoring ${type} ${relativePath}`);
17
+ continue;
19
18
  }
20
19
  const workspace = chief.findWorkspaceByFilePath(filePath);
21
- if (workspace) {
22
- const principal = factory.getPrincipalByPackageName(workspace.pkgName);
23
- if (principal) {
24
- const event = eventType === 'rename' ? (isFile(filePath) ? 'added' : 'deleted') : 'modified';
25
- principal.invalidateFile(filePath);
26
- unreferencedFiles.clear();
27
- const cachedUnusedFiles = collector.purge();
28
- switch (event) {
29
- case 'added':
30
- principal.addProjectPath(filePath);
31
- principal.deletedFiles.delete(filePath);
20
+ if (!workspace)
21
+ continue;
22
+ const principal = factory.getPrincipalByPackageName(workspace.pkgName);
23
+ if (!principal)
24
+ continue;
25
+ switch (type) {
26
+ case 'added':
27
+ added.add(filePath);
28
+ principal.addProjectPath(filePath);
29
+ principal.deletedFiles.delete(filePath);
30
+ debugLog(workspace.name, `Watcher: + ${relativePath}`);
31
+ break;
32
+ case 'deleted':
33
+ deleted.add(filePath);
34
+ analyzedFiles.delete(filePath);
35
+ principal.removeProjectPath(filePath);
36
+ debugLog(workspace.name, `Watcher: - ${relativePath}`);
37
+ break;
38
+ case 'modified':
39
+ modified.add(filePath);
40
+ debugLog(workspace.name, `Watcher: ± ${relativePath}`);
41
+ break;
42
+ }
43
+ principal.invalidateFile(filePath);
44
+ }
45
+ if (added.size === 0 && deleted.size === 0 && modified.size === 0)
46
+ return;
47
+ unreferencedFiles.clear();
48
+ const cachedUnusedFiles = collector.purge();
49
+ for (const filePath of added)
50
+ cachedUnusedFiles.add(filePath);
51
+ for (const filePath of deleted)
52
+ cachedUnusedFiles.delete(filePath);
53
+ const filePaths = factory.getPrincipals().flatMap(p => p.getUsedResolvedFiles());
54
+ if (added.size > 0 || deleted.size > 0) {
55
+ graph.clear();
56
+ for (const filePath of filePaths) {
57
+ const workspace = chief.findWorkspaceByFilePath(filePath);
58
+ if (workspace) {
59
+ const principal = factory.getPrincipalByPackageName(workspace.pkgName);
60
+ if (principal)
61
+ analyzeSourceFile(filePath, principal);
62
+ }
63
+ }
64
+ }
65
+ else {
66
+ for (const [filePath, file] of graph) {
67
+ if (filePaths.includes(filePath)) {
68
+ file.imported = undefined;
69
+ }
70
+ else {
71
+ graph.delete(filePath);
72
+ analyzedFiles.delete(filePath);
73
+ const workspace = chief.findWorkspaceByFilePath(filePath);
74
+ if (workspace) {
75
+ const principal = factory.getPrincipalByPackageName(workspace.pkgName);
76
+ if (principal?.projectPaths.has(filePath))
32
77
  cachedUnusedFiles.add(filePath);
33
- debugLog(workspace.name, `Watcher: + ${filename}`);
34
- break;
35
- case 'deleted':
36
- analyzedFiles.delete(filePath);
37
- principal.removeProjectPath(filePath);
38
- cachedUnusedFiles.delete(filePath);
39
- debugLog(workspace.name, `Watcher: - ${filename}`);
40
- break;
41
- case 'modified':
42
- debugLog(workspace.name, `Watcher: ± ${filename}`);
43
- break;
44
78
  }
45
- const filePaths = factory.getPrincipals().flatMap(p => p.getUsedResolvedFiles());
46
- if (event === 'added' || event === 'deleted') {
47
- graph.clear();
48
- for (const filePath of filePaths)
79
+ }
80
+ }
81
+ for (const filePath of filePaths) {
82
+ if (!graph.has(filePath)) {
83
+ const workspace = chief.findWorkspaceByFilePath(filePath);
84
+ if (workspace) {
85
+ const principal = factory.getPrincipalByPackageName(workspace.pkgName);
86
+ if (principal)
49
87
  analyzeSourceFile(filePath, principal);
50
88
  }
51
- else {
52
- for (const [filePath, file] of graph) {
53
- if (filePaths.includes(filePath)) {
54
- file.imported = undefined;
55
- }
56
- else {
57
- graph.delete(filePath);
58
- analyzedFiles.delete(filePath);
59
- if (principal.projectPaths.has(filePath))
60
- cachedUnusedFiles.add(filePath);
61
- }
62
- }
63
- for (const filePath of filePaths)
64
- if (!graph.has(filePath))
65
- analyzeSourceFile(filePath, principal);
66
- if (!cachedUnusedFiles.has(filePath))
89
+ }
90
+ }
91
+ for (const filePath of modified) {
92
+ if (!cachedUnusedFiles.has(filePath)) {
93
+ const workspace = chief.findWorkspaceByFilePath(filePath);
94
+ if (workspace) {
95
+ const principal = factory.getPrincipalByPackageName(workspace.pkgName);
96
+ if (principal)
67
97
  analyzeSourceFile(filePath, principal);
68
- for (const filePath of filePaths) {
69
- const file = graph.get(filePath);
70
- if (file?.internalImportCache)
71
- updateImportMap(file, file.internalImportCache, graph);
72
- }
73
98
  }
74
- await analyze();
75
- const unusedFiles = [...cachedUnusedFiles].filter(filePath => !analyzedFiles.has(filePath));
76
- collector.addFilesIssues(unusedFiles);
77
- collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
78
- await reportIssues(startTime);
79
99
  }
80
100
  }
101
+ for (const filePath of filePaths) {
102
+ const file = graph.get(filePath);
103
+ if (file?.internalImportCache)
104
+ updateImportMap(file, file.internalImportCache, graph);
105
+ }
106
+ }
107
+ await analyze();
108
+ const unusedFiles = [...cachedUnusedFiles].filter(filePath => !analyzedFiles.has(filePath));
109
+ collector.addFilesIssues(unusedFiles);
110
+ collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
111
+ for (const issue of collector.getRetainedIssues())
112
+ collector.addIssue(issue);
113
+ onUpdate({ issues: getIssues(), duration: performance.now() - startTime });
114
+ };
115
+ const listener = (eventType, filename) => {
116
+ debugLog('*', `(raw) ${eventType} ${filename}`);
117
+ if (typeof filename === 'string') {
118
+ const event = eventType === 'rename' ? (isFile(join(options.cwd, filename)) ? 'added' : 'deleted') : 'modified';
119
+ processBatch([[event, filename]]);
81
120
  }
82
121
  };
83
- await reportIssues();
122
+ onUpdate({ issues: getIssues() });
84
123
  return listener;
85
124
  };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.66.0";
1
+ export declare const version = "5.66.2";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.66.0';
1
+ export const version = '5.66.2';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.66.0",
3
+ "version": "5.66.2",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
package/schema.json CHANGED
@@ -98,6 +98,9 @@
98
98
  },
99
99
  "type": {
100
100
  "type": "boolean"
101
+ },
102
+ "variable": {
103
+ "type": "boolean"
101
104
  }
102
105
  }
103
106
  }