knip 5.66.0 → 5.66.1

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 (41) 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 +2 -1
  10. package/dist/index.js +5 -1
  11. package/dist/plugins/nuxt/index.js +5 -1
  12. package/dist/reporters/util/util.d.ts +2 -2
  13. package/dist/reporters/util/util.js +2 -3
  14. package/dist/reporters/watch.d.ts +2 -2
  15. package/dist/reporters/watch.js +3 -3
  16. package/dist/schema/configuration.d.ts +1 -6
  17. package/dist/schema/configuration.js +3 -8
  18. package/dist/types/config.d.ts +1 -1
  19. package/dist/types/issues.d.ts +2 -10
  20. package/dist/types/issues.js +1 -11
  21. package/dist/typescript/ast-helpers.d.ts +3 -3
  22. package/dist/typescript/ast-helpers.js +11 -12
  23. package/dist/typescript/visitors/exports/exportDeclaration.js +4 -5
  24. package/dist/typescript/visitors/exports/exportKeyword.js +9 -10
  25. package/dist/typescript/visitors/exports/exportsAccessExpression.js +2 -3
  26. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +5 -6
  27. package/dist/util/Performance.d.ts +1 -1
  28. package/dist/util/Performance.js +2 -2
  29. package/dist/util/create-options.d.ts +7 -14
  30. package/dist/util/create-options.js +1 -1
  31. package/dist/util/get-included-issue-types.js +1 -4
  32. package/dist/util/get-referenced-inputs.d.ts +2 -2
  33. package/dist/util/get-referenced-inputs.js +5 -5
  34. package/dist/util/has-strictly-ns-references.d.ts +1 -1
  35. package/dist/util/string.js +5 -1
  36. package/dist/util/watch.d.ts +7 -3
  37. package/dist/util/watch.js +106 -67
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +1 -1
  41. package/schema.json +3 -0
@@ -644,13 +644,18 @@ export declare class ConfigurationChief {
644
644
  ignoreUnresolved: (string | RegExp)[];
645
645
  };
646
646
  getConfigForWorkspace(workspaceName: string, extensions?: string[]): {
647
+ bun?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
648
+ node?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
649
+ pnpm?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
650
+ yarn?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
651
+ typescript?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
652
+ jest?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
647
653
  angular?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
648
654
  astro?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
649
655
  ava?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
650
656
  babel?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
651
657
  biome?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
652
658
  bumpp?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
653
- bun?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
654
659
  c8?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
655
660
  capacitor?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
656
661
  changelogen?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -679,7 +684,6 @@ export declare class ConfigurationChief {
679
684
  hardhat?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
680
685
  husky?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
681
686
  "i18next-parser"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
682
- jest?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
683
687
  karma?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
684
688
  ladle?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
685
689
  lefthook?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -696,7 +700,6 @@ export declare class ConfigurationChief {
696
700
  nest?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
697
701
  netlify?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
698
702
  next?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
699
- node?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
700
703
  "node-modules-inspector"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
701
704
  nodemon?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
702
705
  "npm-package-json-lint"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -709,7 +712,6 @@ export declare class ConfigurationChief {
709
712
  "playwright-ct"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
710
713
  "playwright-test"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
711
714
  plop?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
712
- pnpm?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
713
715
  postcss?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
714
716
  preconstruct?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
715
717
  prettier?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -744,7 +746,6 @@ export declare class ConfigurationChief {
744
746
  tsup?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
745
747
  tsx?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
746
748
  typedoc?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
747
- typescript?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
748
749
  unbuild?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
749
750
  unocss?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
750
751
  "vercel-og"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -757,7 +758,6 @@ export declare class ConfigurationChief {
757
758
  wireit?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
758
759
  wrangler?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
759
760
  xo?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
760
- yarn?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
761
761
  yorkie?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
762
762
  entry: string[];
763
763
  project: string[];
@@ -1,10 +1,11 @@
1
1
  import type { MainOptions } from './util/create-options.js';
2
2
  export declare class ConsoleStreamer {
3
3
  isEnabled: boolean;
4
+ isWatch: boolean;
4
5
  private lines;
5
6
  constructor(options: MainOptions);
6
7
  private clearLines;
7
- private resetLines;
8
+ private clearScreen;
8
9
  private update;
9
10
  cast(message: string | string[], sub?: string): void;
10
11
  clear(): void;
@@ -1,8 +1,10 @@
1
1
  export class ConsoleStreamer {
2
2
  isEnabled = false;
3
+ isWatch = false;
3
4
  lines = 0;
4
5
  constructor(options) {
5
- this.isEnabled = options.isShowProgress;
6
+ this.isEnabled = options.isShowProgress && !options.isDebug;
7
+ this.isWatch = options.isWatch;
6
8
  }
7
9
  clearLines(count) {
8
10
  if (count > 0) {
@@ -13,11 +15,11 @@ export class ConsoleStreamer {
13
15
  }
14
16
  process.stdout.cursorTo(0);
15
17
  }
16
- resetLines() {
17
- this.clearLines(this.lines);
18
+ clearScreen() {
19
+ process.stdout.write('\x1b[2J\x1b[1;1f');
18
20
  }
19
21
  update(messages) {
20
- this.resetLines();
22
+ this.clear();
21
23
  process.stdout.write(`${messages.join('\n')}\n`);
22
24
  this.lines = messages.length;
23
25
  }
@@ -32,6 +34,9 @@ export class ConsoleStreamer {
32
34
  clear() {
33
35
  if (!this.isEnabled)
34
36
  return;
35
- this.resetLines();
37
+ if (this.isWatch)
38
+ this.clearScreen();
39
+ else
40
+ this.clearLines(this.lines);
36
41
  }
37
42
  }
@@ -25,7 +25,7 @@ export declare class IssueCollector {
25
25
  unused: number;
26
26
  }): void;
27
27
  addFilesIssues(filePaths: string[]): void;
28
- addIssue(issue: Issue): Issue | undefined;
28
+ addIssue(issue: Issue): true | undefined;
29
29
  addConfigurationHint(issue: ConfigurationHint): void;
30
30
  addTagHint(issue: TagHint): void;
31
31
  purge(): import("./types/issues.js").IssueSet;
@@ -35,4 +35,7 @@ export declare class IssueCollector {
35
35
  tagHints: Set<TagHint>;
36
36
  configurationHints: Set<ConfigurationHint>;
37
37
  };
38
+ private retainedIssues;
39
+ retainIssue(issue: Issue): void;
40
+ getRetainedIssues(): Issue[];
38
41
  }
@@ -99,7 +99,7 @@ export class IssueCollector {
99
99
  issues[key][symbol] = issue;
100
100
  this.counters[issue.type]++;
101
101
  }
102
- return issue;
102
+ return true;
103
103
  }
104
104
  addConfigurationHint(issue) {
105
105
  const key = `${issue.workspaceName}::${issue.type}::${issue.identifier}`;
@@ -123,4 +123,11 @@ export class IssueCollector {
123
123
  configurationHints: new Set(this.configurationHints.values()),
124
124
  };
125
125
  }
126
+ retainedIssues = [];
127
+ retainIssue(issue) {
128
+ this.retainedIssues.push(issue);
129
+ }
130
+ getRetainedIssues() {
131
+ return this.retainedIssues;
132
+ }
126
133
  }
@@ -1166,10 +1166,10 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
1166
1166
  ignoreUnresolved?: (string | RegExp)[] | undefined;
1167
1167
  includeEntryExports?: boolean | undefined;
1168
1168
  }> | undefined;
1169
- include?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
1170
- exclude?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[] | undefined;
1169
+ include?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[] | undefined;
1170
+ exclude?: ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[] | undefined;
1171
1171
  $schema?: string | undefined;
1172
- rules?: Partial<Record<"files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers", "error" | "warn" | "off">> | undefined;
1172
+ rules?: Partial<Record<"files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates", "error" | "warn" | "off">> | undefined;
1173
1173
  entry?: string | string[] | undefined;
1174
1174
  project?: string | string[] | undefined;
1175
1175
  paths?: Record<string, string[]> | undefined;
@@ -1179,15 +1179,8 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
1179
1179
  ignoreDependencies?: (string | RegExp)[] | undefined;
1180
1180
  ignoreMembers?: (string | RegExp)[] | undefined;
1181
1181
  ignoreUnresolved?: (string | RegExp)[] | undefined;
1182
- ignoreExportsUsedInFile?: boolean | {
1183
- class?: boolean | undefined;
1184
- enum?: boolean | undefined;
1185
- function?: boolean | undefined;
1186
- interface?: boolean | undefined;
1187
- member?: boolean | undefined;
1188
- type?: boolean | undefined;
1189
- } | undefined;
1190
- ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "types" | "nsExports" | "nsTypes" | "duplicates" | "enumMembers" | "classMembers")[]> | undefined;
1182
+ ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
1183
+ ignoreIssues?: Record<string, ("files" | "dependencies" | "devDependencies" | "optionalPeerDependencies" | "unlisted" | "binaries" | "unresolved" | "exports" | "nsExports" | "types" | "nsTypes" | "enumMembers" | "classMembers" | "duplicates")[]> | undefined;
1191
1184
  ignoreWorkspaces?: string[] | undefined;
1192
1185
  includeEntryExports?: boolean | undefined;
1193
1186
  compilers?: Record<string, true | ((filename: string, contents: string) => string) | ((filename: string, contents: string) => Promise<string>)> | undefined;
@@ -1,4 +1,3 @@
1
- import type { IssueType } from './types/issues.js';
2
1
  export declare const ROOT_WORKSPACE_NAME = ".";
3
2
  export declare const IMPORT_STAR = "*";
4
3
  export declare const ANONYMOUS = "__anonymous";
@@ -16,8 +15,34 @@ export declare const IGNORED_DEPENDENCIES: Set<string>;
16
15
  export declare const IGNORED_RUNTIME_DEPENDENCIES: Set<string>;
17
16
  export declare const FOREIGN_FILE_EXTENSIONS: Set<string>;
18
17
  export declare const IGNORE_DEFINITELY_TYPED: Set<string>;
19
- export declare const ISSUE_TYPES: IssueType[];
20
- export declare const ISSUE_TYPE_TITLE: Record<IssueType, string>;
18
+ export declare const ISSUE_TYPES: readonly ["files", "dependencies", "devDependencies", "optionalPeerDependencies", "unlisted", "binaries", "unresolved", "exports", "nsExports", "types", "nsTypes", "enumMembers", "classMembers", "duplicates"];
19
+ export declare const ISSUE_TYPE_TITLE: {
20
+ readonly files: "Unused files";
21
+ readonly _files: "Unused files";
22
+ readonly dependencies: "Unused dependencies";
23
+ readonly devDependencies: "Unused devDependencies";
24
+ readonly optionalPeerDependencies: "Referenced optional peerDependencies";
25
+ readonly unlisted: "Unlisted dependencies";
26
+ readonly binaries: "Unlisted binaries";
27
+ readonly unresolved: "Unresolved imports";
28
+ readonly exports: "Unused exports";
29
+ readonly nsExports: "Exports in used namespace";
30
+ readonly types: "Unused exported types";
31
+ readonly nsTypes: "Exported types in used namespace";
32
+ readonly enumMembers: "Unused exported enum members";
33
+ readonly classMembers: "Unused exported class members";
34
+ readonly duplicates: "Duplicate exports";
35
+ };
36
+ export declare const SYMBOL_TYPE: {
37
+ readonly CLASS: "class";
38
+ readonly ENUM: "enum";
39
+ readonly FUNCTION: "function";
40
+ readonly INTERFACE: "interface";
41
+ readonly MEMBER: "member";
42
+ readonly TYPE: "type";
43
+ readonly UNKNOWN: "unknown";
44
+ readonly VARIABLE: "variable";
45
+ };
21
46
  export declare const FIX_FLAGS: {
22
47
  readonly NONE: 0;
23
48
  readonly OBJECT_BINDING: number;
package/dist/constants.js CHANGED
@@ -190,6 +190,16 @@ export const ISSUE_TYPE_TITLE = {
190
190
  classMembers: 'Unused exported class members',
191
191
  duplicates: 'Duplicate exports',
192
192
  };
193
+ export const SYMBOL_TYPE = {
194
+ CLASS: 'class',
195
+ ENUM: 'enum',
196
+ FUNCTION: 'function',
197
+ INTERFACE: 'interface',
198
+ MEMBER: 'member',
199
+ TYPE: 'type',
200
+ UNKNOWN: 'unknown',
201
+ VARIABLE: 'variable',
202
+ };
193
203
  export const FIX_FLAGS = {
194
204
  NONE: 0,
195
205
  OBJECT_BINDING: 1 << 0,
@@ -18,7 +18,8 @@ export async function build({ chief, collector, deputy, factory, isGitIgnored, s
18
18
  const enabledPluginsStore = new Map();
19
19
  const toSourceFilePath = getToSourcePathHandler(chief);
20
20
  const toSourceFilePaths = getToSourcePathsHandler(chief);
21
- const getReferencedInternalFilePath = getReferencedInputsHandler(collector, deputy, chief, isGitIgnored);
21
+ const addIssue = (issue) => collector.addIssue(issue) && options.isWatch && collector.retainIssue(issue);
22
+ const getReferencedInternalFilePath = getReferencedInputsHandler(deputy, chief, isGitIgnored, addIssue);
22
23
  for (const workspace of workspaces) {
23
24
  const { name, dir, manifestPath, manifestStr } = workspace;
24
25
  const manifest = chief.getManifestForWorkspace(name);
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { build } from './graph/build.js';
8
8
  import { IssueCollector } from './IssueCollector.js';
9
9
  import { IssueFixer } from './IssueFixer.js';
10
10
  import { PrincipalFactory } from './PrincipalFactory.js';
11
+ import watchReporter from './reporters/watch.js';
11
12
  import { debugLogArray, debugLogObject } from './util/debug.js';
12
13
  import { getGitIgnoredHandler } from './util/glob-core.js';
13
14
  import { getWatchHandler } from './util/watch.js';
@@ -52,6 +53,9 @@ export const main = async (options) => {
52
53
  });
53
54
  if (options.isWatch) {
54
55
  const isIgnored = (filePath) => filePath.startsWith(options.cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
56
+ const onUpdate = options.isWatch
57
+ ? ({ issues, duration }) => watchReporter(options, { issues, streamer, size: analyzedFiles.size, duration })
58
+ : () => { };
55
59
  const watchHandler = await getWatchHandler(options, {
56
60
  analyzedFiles,
57
61
  analyzeSourceFile,
@@ -61,7 +65,7 @@ export const main = async (options) => {
61
65
  factory,
62
66
  graph,
63
67
  isIgnored,
64
- streamer,
68
+ onUpdate,
65
69
  unreferencedFiles,
66
70
  });
67
71
  watch('.', { recursive: true }, watchHandler);
@@ -18,7 +18,11 @@ const production = [
18
18
  ];
19
19
  const setup = async () => {
20
20
  if (globalThis && !('defineNuxtConfig' in globalThis)) {
21
- Object.defineProperty(globalThis, 'defineNuxtConfig', { value: (id) => id });
21
+ Object.defineProperty(globalThis, 'defineNuxtConfig', {
22
+ value: (id) => id,
23
+ writable: true,
24
+ configurable: true,
25
+ });
22
26
  }
23
27
  };
24
28
  const resolveConfig = async (localConfig) => {
@@ -1,9 +1,9 @@
1
1
  import { ISSUE_TYPE_TITLE } from '../../constants.js';
2
- import { type Issue, type IssueSeverity, type IssueSymbol } from '../../types/issues.js';
2
+ import type { Issue, IssueSeverity, IssueSymbol } from '../../types/issues.js';
3
3
  import { Table } from '../../util/table.js';
4
4
  export declare const dim: import("picocolors/types.js").Formatter;
5
5
  export declare const bright: import("picocolors/types.js").Formatter;
6
- export declare const getIssueTypeTitle: (reportType: keyof typeof ISSUE_TYPE_TITLE) => string;
6
+ export declare const getIssueTypeTitle: (reportType: keyof typeof ISSUE_TYPE_TITLE) => "Unused files" | "Unused dependencies" | "Unused devDependencies" | "Referenced optional peerDependencies" | "Unlisted dependencies" | "Unlisted binaries" | "Unresolved imports" | "Unused exports" | "Exports in used namespace" | "Unused exported types" | "Exported types in used namespace" | "Unused exported enum members" | "Unused exported class members" | "Duplicate exports";
7
7
  export declare const getColoredTitle: (title: string, count: number) => string;
8
8
  export declare const getDimmedTitle: (title: string, count: number) => string;
9
9
  type LogIssueLine = {
@@ -1,6 +1,5 @@
1
1
  import picocolors from 'picocolors';
2
- import { ISSUE_TYPE_TITLE } from '../../constants.js';
3
- import { SymbolType } from '../../types/issues.js';
2
+ import { ISSUE_TYPE_TITLE, SYMBOL_TYPE } from '../../constants.js';
4
3
  import { relative } from '../../util/path.js';
5
4
  import { Table } from '../../util/table.js';
6
5
  const plain = (text) => text;
@@ -47,7 +46,7 @@ export const getTableForType = (issues, cwd, options = { isUseColors: true }) =>
47
46
  const symbol = issue.symbols ? issue.symbols.map(s => s.symbol).join(', ') : issue.symbol;
48
47
  table.cell('symbol', print(symbol), options.isUseColors ? highlightSymbol(issue) : () => symbol);
49
48
  table.cell('parentSymbol', issue.parentSymbol && print(issue.parentSymbol));
50
- table.cell('symbolType', issue.symbolType && issue.symbolType !== SymbolType.UNKNOWN && print(issue.symbolType));
49
+ table.cell('symbolType', issue.symbolType && issue.symbolType !== SYMBOL_TYPE.UNKNOWN && print(issue.symbolType));
51
50
  const pos = issue.line === undefined ? '' : `:${issue.line}${issue.col === undefined ? '' : `:${issue.col}`}`;
52
51
  const cell = issue.type === 'files' ? '' : `${relative(cwd, issue.filePath)}${pos}`;
53
52
  table.cell('filePath', print(cell));
@@ -4,8 +4,8 @@ import type { MainOptions } from '../util/create-options.js';
4
4
  interface WatchReporter {
5
5
  issues: Issues;
6
6
  streamer: ConsoleStreamer;
7
- startTime?: number;
7
+ duration?: number;
8
8
  size: number;
9
9
  }
10
- declare const _default: (options: MainOptions, { issues, streamer, startTime, size }: WatchReporter) => void;
10
+ declare const _default: (options: MainOptions, { issues, streamer, duration, size }: WatchReporter) => void;
11
11
  export default _default;
@@ -2,7 +2,7 @@ import picocolors from 'picocolors';
2
2
  import { perfObserver } from '../util/Performance.js';
3
3
  import { prettyMilliseconds } from '../util/string.js';
4
4
  import { getIssueTypeTitle, getTableForType } from './util/util.js';
5
- export default (options, { issues, streamer, startTime, size }) => {
5
+ export default (options, { issues, streamer, duration, size }) => {
6
6
  const reportMultipleGroups = Object.values(options.includedIssueTypes).filter(Boolean).length > 1;
7
7
  let totalIssues = 0;
8
8
  const lines = [];
@@ -22,8 +22,8 @@ export default (options, { issues, streamer, startTime, size }) => {
22
22
  }
23
23
  }
24
24
  const mem = perfObserver.getCurrentMemUsageInMb();
25
- const duration = perfObserver.getCurrentDurationInMs(startTime);
26
- const summary = `${size} files in ${prettyMilliseconds(duration)} (${mem}MB)`;
25
+ const ms = duration ?? perfObserver.getCurrentDurationInMs();
26
+ const summary = `${size} files in ${prettyMilliseconds(ms)} (${mem}MB)`;
27
27
  const messages = totalIssues === 0
28
28
  ? ['✂️ Excellent, Knip found no issues.', '', picocolors.gray(summary)]
29
29
  : [...lines, '', picocolors.gray(summary)];
@@ -1182,12 +1182,7 @@ export declare const knipConfigurationSchema: z.ZodMiniObject<{
1182
1182
  ignoreMembers: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniCustom<RegExp, RegExp>]>>>;
1183
1183
  ignoreUnresolved: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniCustom<RegExp, RegExp>]>>>;
1184
1184
  ignoreExportsUsedInFile: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniObject<{
1185
- class: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1186
- enum: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1187
- function: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1188
- interface: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1189
- member: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1190
- type: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1185
+ [k: string]: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
1191
1186
  }, z.core.$strict>]>>;
1192
1187
  ignoreIssues: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniUnion<readonly [z.ZodMiniLiteral<"files">, z.ZodMiniLiteral<"dependencies">, z.ZodMiniLiteral<"devDependencies">, z.ZodMiniLiteral<"optionalPeerDependencies">, z.ZodMiniLiteral<"unlisted">, z.ZodMiniLiteral<"binaries">, z.ZodMiniLiteral<"unresolved">, z.ZodMiniLiteral<"exports">, z.ZodMiniLiteral<"types">, z.ZodMiniLiteral<"nsExports">, z.ZodMiniLiteral<"nsTypes">, z.ZodMiniLiteral<"duplicates">, z.ZodMiniLiteral<"enumMembers">, z.ZodMiniLiteral<"classMembers">]>>>>;
1193
1188
  ignoreWorkspaces: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod/mini';
2
+ import { SYMBOL_TYPE } from '../constants.js';
2
3
  import { globSchema, pluginsSchema } from './plugins.js';
3
4
  const pathsSchema = z.record(z.string(), z.array(z.string()));
4
5
  const syncCompilerSchema = z.union([z.literal(true), z.custom()]);
@@ -23,14 +24,8 @@ const issueTypeSchema = z.union([
23
24
  z.literal('classMembers'),
24
25
  ]);
25
26
  const rulesSchema = z.partialRecord(issueTypeSchema, z.enum(['error', 'warn', 'off']));
26
- const ignoreExportsUsedInFileObjectSchema = z.strictObject({
27
- class: z.optional(z.boolean()),
28
- enum: z.optional(z.boolean()),
29
- function: z.optional(z.boolean()),
30
- interface: z.optional(z.boolean()),
31
- member: z.optional(z.boolean()),
32
- type: z.optional(z.boolean()),
33
- });
27
+ const ignorableSymbolTypes = Object.values(SYMBOL_TYPE).filter(type => type !== 'unknown');
28
+ const ignoreExportsUsedInFileObjectSchema = z.strictObject(Object.fromEntries(ignorableSymbolTypes.map(type => [type, z.optional(z.boolean())])));
34
29
  const ignoreExportsUsedInFileSchema = z.union([z.boolean(), ignoreExportsUsedInFileObjectSchema]);
35
30
  const ignoreIssuesSchema = z.record(z.string(), z.array(issueTypeSchema));
36
31
  const rootConfigurationSchema = z.object({
@@ -23,7 +23,7 @@ export type BinaryResolver = (binary: string, args: string[], options: BinaryRes
23
23
  export type RawConfiguration = z.infer<typeof knipConfigurationSchema>;
24
24
  export type RawPluginConfiguration = z.infer<typeof pluginSchema>;
25
25
  export type IgnorePatterns = (string | RegExp)[];
26
- type IgnorableExport = Exclude<SymbolType, SymbolType.UNKNOWN>;
26
+ type IgnorableExport = Exclude<SymbolType, 'unknown'>;
27
27
  export type IgnoreExportsUsedInFile = boolean | Partial<Record<IgnorableExport, boolean>>;
28
28
  export type IgnoreIssues = Record<string, IssueType[]>;
29
29
  export type GetImportsAndExportsOptions = {
@@ -1,13 +1,5 @@
1
- export declare enum SymbolType {
2
- VARIABLE = "variable",
3
- TYPE = "type",
4
- INTERFACE = "interface",
5
- ENUM = "enum",
6
- FUNCTION = "function",
7
- CLASS = "class",
8
- MEMBER = "member",
9
- UNKNOWN = "unknown"
10
- }
1
+ import type { SYMBOL_TYPE } from '../constants.js';
2
+ export type SymbolType = (typeof SYMBOL_TYPE)[keyof typeof SYMBOL_TYPE];
11
3
  export type IssueSymbol = {
12
4
  symbol: string;
13
5
  pos?: number;
@@ -1,11 +1 @@
1
- export var SymbolType;
2
- (function (SymbolType) {
3
- SymbolType["VARIABLE"] = "variable";
4
- SymbolType["TYPE"] = "type";
5
- SymbolType["INTERFACE"] = "interface";
6
- SymbolType["ENUM"] = "enum";
7
- SymbolType["FUNCTION"] = "function";
8
- SymbolType["CLASS"] = "class";
9
- SymbolType["MEMBER"] = "member";
10
- SymbolType["UNKNOWN"] = "unknown";
11
- })(SymbolType || (SymbolType = {}));
1
+ export {};
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import type { Fix } from '../types/exports.js';
3
- import { SymbolType } from '../types/issues.js';
3
+ import type { SymbolType } from '../types/issues.js';
4
4
  export declare function isDefaultImport(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration | ts.ExportDeclaration): boolean;
5
5
  export declare function isAccessExpression(node: ts.Node): node is ts.AccessExpression;
6
6
  export declare function isImportCall(node: ts.Node): node is ts.ImportCall;
@@ -12,14 +12,14 @@ export declare const getClassMember: (member: ts.MethodDeclaration | ts.Property
12
12
  node: ts.MethodDeclaration | ts.PropertyDeclaration;
13
13
  identifier: string;
14
14
  pos: number;
15
- type: SymbolType;
15
+ type: "member";
16
16
  fix: Fix;
17
17
  };
18
18
  export declare const getEnumMember: (member: ts.EnumMember, isFixTypes: boolean) => {
19
19
  node: ts.EnumMember;
20
20
  identifier: string;
21
21
  pos: number;
22
- type: SymbolType;
22
+ type: "member";
23
23
  fix: Fix;
24
24
  };
25
25
  export declare function stripQuotes(name: string): string;
@@ -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
  function isGetOrSetAccessorDeclaration(node) {
5
4
  return node.kind === ts.SyntaxKind.SetAccessor || node.kind === ts.SyntaxKind.GetAccessor;
6
5
  }
@@ -34,20 +33,20 @@ export function isPropertyAccessCall(node, identifier) {
34
33
  }
35
34
  export const getNodeType = (node) => {
36
35
  if (!node)
37
- return SymbolType.UNKNOWN;
36
+ return SYMBOL_TYPE.UNKNOWN;
38
37
  if (ts.isFunctionDeclaration(node))
39
- return SymbolType.FUNCTION;
38
+ return SYMBOL_TYPE.FUNCTION;
40
39
  if (ts.isClassDeclaration(node))
41
- return SymbolType.CLASS;
40
+ return SYMBOL_TYPE.CLASS;
42
41
  if (ts.isInterfaceDeclaration(node))
43
- return SymbolType.INTERFACE;
42
+ return SYMBOL_TYPE.INTERFACE;
44
43
  if (ts.isTypeAliasDeclaration(node))
45
- return SymbolType.TYPE;
44
+ return SYMBOL_TYPE.TYPE;
46
45
  if (ts.isEnumDeclaration(node))
47
- return SymbolType.ENUM;
46
+ return SYMBOL_TYPE.ENUM;
48
47
  if (ts.isVariableDeclaration(node))
49
- return SymbolType.VARIABLE;
50
- return SymbolType.UNKNOWN;
48
+ return SYMBOL_TYPE.VARIABLE;
49
+ return SYMBOL_TYPE.UNKNOWN;
51
50
  };
52
51
  export const isNonPrivatePropertyOrMethodDeclaration = (member) => (ts.isPropertyDeclaration(member) || ts.isMethodDeclaration(member) || isGetOrSetAccessorDeclaration(member)) &&
53
52
  !isPrivateMember(member);
@@ -55,14 +54,14 @@ export const getClassMember = (member, isFixTypes) => ({
55
54
  node: member,
56
55
  identifier: member.name.getText(),
57
56
  pos: member.name.getStart() + (ts.isComputedPropertyName(member.name) ? 1 : 0),
58
- type: SymbolType.MEMBER,
57
+ type: SYMBOL_TYPE.MEMBER,
59
58
  fix: isFixTypes ? [member.getStart(), member.getEnd(), FIX_FLAGS.NONE] : undefined,
60
59
  });
61
60
  export const getEnumMember = (member, isFixTypes) => ({
62
61
  node: member,
63
62
  identifier: stripQuotes(member.name.getText()),
64
63
  pos: member.name.getStart(),
65
- type: SymbolType.MEMBER,
64
+ type: SYMBOL_TYPE.MEMBER,
66
65
  fix: isFixTypes
67
66
  ? [member.getStart(), member.getEnd(), FIX_FLAGS.OBJECT_BINDING | FIX_FLAGS.WITH_NEWLINE]
68
67
  : undefined,
@@ -1,12 +1,11 @@
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 { isModule } from '../helpers.js';
5
4
  import { exportVisitor as visit } from '../index.js';
6
5
  export default visit(isModule, (node, { isFixExports, isFixTypes }) => {
7
6
  if (ts.isExportDeclaration(node)) {
8
7
  if (node.exportClause && ts.isNamedExports(node.exportClause)) {
9
- const nodeType = node.isTypeOnly ? SymbolType.TYPE : SymbolType.UNKNOWN;
8
+ const nodeType = node.isTypeOnly ? SYMBOL_TYPE.TYPE : SYMBOL_TYPE.UNKNOWN;
10
9
  const sourceFile = node.getSourceFile();
11
10
  const declarations = sourceFile.getNamedDeclarations?.();
12
11
  return node.exportClause.elements.map(element => {
@@ -14,8 +13,8 @@ export default visit(isModule, (node, { isFixExports, isFixTypes }) => {
14
13
  const propName = element.propertyName?.text;
15
14
  const symbol = declarations?.get(propName ?? identifier)?.[0]?.symbol;
16
15
  const pos = element.name.pos;
17
- const type = element.isTypeOnly ? SymbolType.TYPE : nodeType;
18
- const fix = (isFixExports && type !== SymbolType.TYPE) || (isFixTypes && type === SymbolType.TYPE)
16
+ const type = element.isTypeOnly ? SYMBOL_TYPE.TYPE : nodeType;
17
+ const fix = (isFixExports && type !== SYMBOL_TYPE.TYPE) || (isFixTypes && type === SYMBOL_TYPE.TYPE)
19
18
  ? [element.getStart(), element.getEnd(), FIX_FLAGS.OBJECT_BINDING | FIX_FLAGS.EMPTY_DECLARATION]
20
19
  : undefined;
21
20
  return { node: element, symbol, identifier, type, pos, fix };
@@ -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
  };
@@ -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.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.66.0';
1
+ export const version = '5.66.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.66.0",
3
+ "version": "5.66.1",
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
  }