knip 5.62.0 → 5.63.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 (134) hide show
  1. package/README.md +22 -24
  2. package/dist/CacheConsultant.d.ts +3 -9
  3. package/dist/CacheConsultant.js +5 -5
  4. package/dist/ConfigurationChief.d.ts +588 -38
  5. package/dist/ConfigurationChief.js +43 -124
  6. package/dist/ConsoleStreamer.d.ts +2 -3
  7. package/dist/ConsoleStreamer.js +2 -2
  8. package/dist/DependencyDeputy.d.ts +2 -6
  9. package/dist/IssueCollector.d.ts +4 -12
  10. package/dist/IssueCollector.js +10 -10
  11. package/dist/IssueFixer.d.ts +3 -14
  12. package/dist/IssueFixer.js +11 -21
  13. package/dist/PrincipalFactory.d.ts +3 -2
  14. package/dist/PrincipalFactory.js +11 -11
  15. package/dist/ProjectPrincipal.d.ts +5 -3
  16. package/dist/ProjectPrincipal.js +17 -11
  17. package/dist/WorkspaceWorker.d.ts +4 -9
  18. package/dist/WorkspaceWorker.js +8 -12
  19. package/dist/binaries/bash-parser.js +1 -1
  20. package/dist/binaries/fallback.js +4 -2
  21. package/dist/binaries/package-manager/pnpm.js +6 -1
  22. package/dist/cli.js +43 -60
  23. package/dist/compilers/index.d.ts +34 -4
  24. package/dist/graph/analyze.d.ts +3 -8
  25. package/dist/graph/analyze.js +24 -27
  26. package/dist/graph/build.d.ts +3 -17
  27. package/dist/graph/build.js +60 -47
  28. package/dist/index.d.ts +3 -6
  29. package/dist/index.js +23 -62
  30. package/dist/plugins/astro/index.d.ts +1 -0
  31. package/dist/plugins/astro/index.js +4 -0
  32. package/dist/plugins/index.d.ts +24 -1
  33. package/dist/plugins/index.js +6 -0
  34. package/dist/plugins/lefthook/index.js +2 -0
  35. package/dist/plugins/node-modules-inspector/index.d.ts +12 -0
  36. package/dist/plugins/node-modules-inspector/index.js +17 -0
  37. package/dist/plugins/nuxt/index.js +4 -3
  38. package/dist/plugins/nuxt/types.d.ts +3 -2
  39. package/dist/plugins/playwright/index.js +8 -1
  40. package/dist/plugins/playwright/types.d.ts +20 -14
  41. package/dist/plugins/pnpm/index.d.ts +7 -0
  42. package/dist/plugins/pnpm/index.js +8 -0
  43. package/dist/plugins/preconstruct/index.js +2 -1
  44. package/dist/plugins/react-router/index.js +18 -8
  45. package/dist/plugins/rsbuild/index.js +28 -2
  46. package/dist/plugins/rsbuild/types.d.ts +11 -0
  47. package/dist/plugins/rslib/index.d.ts +10 -0
  48. package/dist/plugins/rslib/index.js +15 -0
  49. package/dist/plugins/rslib/types.d.ts +1 -0
  50. package/dist/plugins/rspack/index.js +1 -1
  51. package/dist/plugins/typescript/index.d.ts +1 -1
  52. package/dist/plugins.js +3 -2
  53. package/dist/reporters/codeclimate.d.ts +1 -1
  54. package/dist/reporters/codeclimate.js +10 -10
  55. package/dist/reporters/codeowners.d.ts +1 -1
  56. package/dist/reporters/codeowners.js +5 -5
  57. package/dist/reporters/compact.d.ts +1 -1
  58. package/dist/reporters/compact.js +7 -7
  59. package/dist/reporters/disclosure.d.ts +1 -1
  60. package/dist/reporters/disclosure.js +2 -2
  61. package/dist/reporters/index.d.ts +6 -6
  62. package/dist/reporters/json.d.ts +1 -1
  63. package/dist/reporters/json.js +3 -3
  64. package/dist/reporters/markdown.d.ts +1 -1
  65. package/dist/reporters/markdown.js +4 -4
  66. package/dist/reporters/symbols.js +4 -2
  67. package/dist/reporters/util/configuration-hints.d.ts +1 -1
  68. package/dist/reporters/util/configuration-hints.js +58 -23
  69. package/dist/reporters/util/util.d.ts +2 -4
  70. package/dist/reporters/util/util.js +6 -6
  71. package/dist/reporters/watch.d.ts +3 -4
  72. package/dist/reporters/watch.js +5 -5
  73. package/dist/schema/configuration.d.ts +176 -8
  74. package/dist/schema/plugins.d.ts +69 -0
  75. package/dist/schema/plugins.js +3 -0
  76. package/dist/types/PluginNames.d.ts +2 -2
  77. package/dist/types/PluginNames.js +3 -0
  78. package/dist/types/config.d.ts +4 -10
  79. package/dist/types/entries.d.ts +3 -0
  80. package/dist/types/entries.js +1 -0
  81. package/dist/types/issues.d.ts +4 -3
  82. package/dist/types/{cli.d.ts → options.d.ts} +2 -2
  83. package/dist/types/options.js +1 -0
  84. package/dist/types/package-json.d.ts +5 -0
  85. package/dist/types/project.d.ts +1 -7
  86. package/dist/types/tsconfig-json.d.ts +14 -0
  87. package/dist/types/tsconfig-json.js +1 -0
  88. package/dist/typescript/ast-helpers.js +1 -1
  89. package/dist/typescript/get-imports-and-exports.d.ts +2 -2
  90. package/dist/typescript/get-imports-and-exports.js +9 -10
  91. package/dist/util/Performance.js +16 -6
  92. package/dist/util/cli-arguments.d.ts +1 -2
  93. package/dist/util/cli-arguments.js +3 -13
  94. package/dist/util/create-options.d.ts +1219 -0
  95. package/dist/util/create-options.js +112 -0
  96. package/dist/util/debug.js +3 -4
  97. package/dist/util/errors.d.ts +1 -1
  98. package/dist/util/file-entry-cache.js +3 -3
  99. package/dist/util/fs.d.ts +1 -1
  100. package/dist/util/get-included-issue-types.d.ts +9 -13
  101. package/dist/util/get-included-issue-types.js +10 -16
  102. package/dist/util/get-referenced-inputs.js +1 -1
  103. package/dist/util/glob-core.d.ts +1 -1
  104. package/dist/util/glob-core.js +8 -7
  105. package/dist/util/glob.d.ts +1 -0
  106. package/dist/util/glob.js +1 -1
  107. package/dist/util/input.d.ts +1 -1
  108. package/dist/util/input.js +1 -1
  109. package/dist/util/is-identifier-referenced.d.ts +1 -1
  110. package/dist/util/is-identifier-referenced.js +19 -19
  111. package/dist/util/load-config.d.ts +1 -0
  112. package/dist/util/load-config.js +24 -0
  113. package/dist/util/package-json.d.ts +2 -1
  114. package/dist/util/package-json.js +24 -12
  115. package/dist/util/parse-and-convert-gitignores.js +2 -0
  116. package/dist/util/path.d.ts +4 -4
  117. package/dist/util/path.js +5 -7
  118. package/dist/util/reporter.js +3 -3
  119. package/dist/util/require.js +1 -2
  120. package/dist/util/table.js +1 -3
  121. package/dist/util/tag.d.ts +1 -1
  122. package/dist/util/to-source-path.d.ts +1 -1
  123. package/dist/util/to-source-path.js +5 -5
  124. package/dist/util/trace.d.ts +6 -6
  125. package/dist/util/trace.js +18 -22
  126. package/dist/util/watch.d.ts +2 -5
  127. package/dist/util/watch.js +3 -3
  128. package/dist/version.d.ts +1 -1
  129. package/dist/version.js +1 -1
  130. package/package.json +10 -15
  131. package/schema.json +12 -0
  132. package/dist/util/unwrap-function.d.ts +0 -1
  133. package/dist/util/unwrap-function.js +0 -13
  134. /package/dist/{types/cli.js → plugins/rslib/types.js} +0 -0
@@ -4,16 +4,10 @@ import { getPackageNameFromModuleSpecifier } from '../util/modules.js';
4
4
  import { findMatch } from '../util/regex.js';
5
5
  import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.js';
6
6
  import { createAndPrintTrace, printTrace } from '../util/trace.js';
7
- export const analyze = async (options) => {
8
- const { analyzedFiles, chief, collector, deputy, entryPaths, factory, fixer, graph, isFix, isIncludeLibs, isProduction, report, streamer, tags, unreferencedFiles, } = options;
9
- const isReportDependencies = report.dependencies || report.unlisted || report.unresolved;
10
- const isReportValues = report.exports || report.nsExports || report.classMembers;
11
- const isReportTypes = report.types || report.nsTypes || report.enumMembers;
12
- const isReportClassMembers = report.classMembers;
13
- const isSkipLibs = !(isIncludeLibs || isReportClassMembers);
14
- const shouldIgnore = getShouldIgnoreHandler(isProduction);
15
- const shouldIgnoreTags = getShouldIgnoreTagHandler(tags);
16
- const isIdentifierReferenced = getIsIdentifierReferencedHandler(graph, entryPaths);
7
+ export const analyze = async ({ analyzedFiles, chief, collector, deputy, entryPaths, factory, fixer, graph, streamer, unreferencedFiles, options, }) => {
8
+ const shouldIgnore = getShouldIgnoreHandler(options.isProduction);
9
+ const shouldIgnoreTags = getShouldIgnoreTagHandler(options.tags);
10
+ const isIdentifierReferenced = getIsIdentifierReferencedHandler(graph, entryPaths, options.isTrace);
17
11
  const ignoreExportsUsedInFile = chief.config.ignoreExportsUsedInFile;
18
12
  const isExportedItemReferenced = (exportedItem) => exportedItem.refs[1] ||
19
13
  (exportedItem.refs[0] > 0 &&
@@ -21,7 +15,7 @@ export const analyze = async (options) => {
21
15
  ? exportedItem.type !== 'unknown' && !!ignoreExportsUsedInFile[exportedItem.type]
22
16
  : ignoreExportsUsedInFile));
23
17
  const analyzeGraph = async () => {
24
- if (isReportValues || isReportTypes) {
18
+ if (options.isReportValues || options.isReportTypes) {
25
19
  streamer.cast('Connecting the dots');
26
20
  for (const [filePath, file] of graph.entries()) {
27
21
  const exportItems = file.exports;
@@ -33,7 +27,7 @@ export const analyze = async (options) => {
33
27
  const principal = factory.getPrincipalByPackageName(workspace.pkgName);
34
28
  const isEntry = entryPaths.has(filePath);
35
29
  if (!isIncludeEntryExports && isEntry) {
36
- createAndPrintTrace(filePath, { isEntry });
30
+ createAndPrintTrace(filePath, options, { isEntry });
37
31
  continue;
38
32
  }
39
33
  const importsForExport = file.imported;
@@ -45,7 +39,7 @@ export const analyze = async (options) => {
45
39
  const { isReferenced, reExportingEntryFile, traceNode } = isIdentifierReferenced(filePath, identifier, isIncludeEntryExports);
46
40
  if ((isReferenced || exportedItem.refs[1]) && isIgnored) {
47
41
  for (const tagName of exportedItem.jsDocTags) {
48
- if (tags[1].includes(tagName.replace(/^@/, ''))) {
42
+ if (options.tags[1].includes(tagName.replace(/^@/, ''))) {
49
43
  collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
50
44
  }
51
45
  }
@@ -54,7 +48,7 @@ export const analyze = async (options) => {
54
48
  continue;
55
49
  if (reExportingEntryFile) {
56
50
  if (!isIncludeEntryExports) {
57
- createAndPrintTrace(filePath, { identifier, isEntry, hasRef: isReferenced });
51
+ createAndPrintTrace(filePath, options, { identifier, isEntry, hasRef: isReferenced });
58
52
  continue;
59
53
  }
60
54
  const reExportedItem = graph.get(reExportingEntryFile)?.exports.get(identifier);
@@ -62,10 +56,10 @@ export const analyze = async (options) => {
62
56
  continue;
63
57
  }
64
58
  if (traceNode)
65
- printTrace(traceNode, filePath, identifier);
59
+ printTrace(traceNode, filePath, options, identifier);
66
60
  if (isReferenced) {
67
- if (report.enumMembers && exportedItem.type === 'enum') {
68
- if (!report.nsTypes && importsForExport.refs.has(identifier))
61
+ if (options.includedIssueTypes.enumMembers && exportedItem.type === 'enum') {
62
+ if (!options.includedIssueTypes.nsTypes && importsForExport.refs.has(identifier))
69
63
  continue;
70
64
  if (hasStrictlyEnumReferences(importsForExport, identifier))
71
65
  continue;
@@ -91,12 +85,12 @@ export const analyze = async (options) => {
91
85
  line: member.line,
92
86
  col: member.col,
93
87
  });
94
- if (isFix && isIssueAdded && member.fix)
88
+ if (options.isFix && isIssueAdded && member.fix)
95
89
  fixer.addUnusedTypeNode(filePath, [member.fix]);
96
90
  }
97
91
  else if (isIgnored) {
98
92
  for (const tagName of exportedItem.jsDocTags) {
99
- if (tags[1].includes(tagName.replace(/^@/, ''))) {
93
+ if (options.tags[1].includes(tagName.replace(/^@/, ''))) {
100
94
  collector.addTagHint({ type: 'tag', filePath, identifier: id, tagName });
101
95
  }
102
96
  }
@@ -104,13 +98,13 @@ export const analyze = async (options) => {
104
98
  }
105
99
  }
106
100
  }
107
- if (principal && isReportClassMembers && exportedItem.type === 'class') {
101
+ if (principal && options.isReportClassMembers && exportedItem.type === 'class') {
108
102
  const members = exportedItem.members.filter(member => !(findMatch(workspace.ignoreMembers, member.identifier) || shouldIgnore(member.jsDocTags)));
109
103
  for (const member of principal.findUnusedMembers(filePath, members)) {
110
104
  if (shouldIgnoreTags(member.jsDocTags)) {
111
105
  const identifier = `${exportedItem.identifier}.${member.identifier}`;
112
106
  for (const tagName of exportedItem.jsDocTags) {
113
- if (tags[1].includes(tagName.replace(/^@/, ''))) {
107
+ if (options.tags[1].includes(tagName.replace(/^@/, ''))) {
114
108
  collector.addTagHint({ type: 'tag', filePath, identifier, tagName });
115
109
  }
116
110
  }
@@ -126,7 +120,7 @@ export const analyze = async (options) => {
126
120
  line: member.line,
127
121
  col: member.col,
128
122
  });
129
- if (isFix && isIssueAdded && member.fix)
123
+ if (options.isFix && isIssueAdded && member.fix)
130
124
  fixer.addUnusedTypeNode(filePath, [member.fix]);
131
125
  }
132
126
  }
@@ -135,12 +129,13 @@ export const analyze = async (options) => {
135
129
  }
136
130
  const [hasStrictlyNsRefs, namespace] = hasStrictlyNsReferences(graph, importsForExport, identifier);
137
131
  const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
138
- if (hasStrictlyNsRefs && ((!report.nsTypes && isType) || !(report.nsExports || isType)))
132
+ if (hasStrictlyNsRefs &&
133
+ ((!options.includedIssueTypes.nsTypes && isType) || !(options.includedIssueTypes.nsExports || isType)))
139
134
  continue;
140
135
  if (!isExportedItemReferenced(exportedItem)) {
141
136
  if (isIgnored)
142
137
  continue;
143
- if (!isSkipLibs && principal?.hasExternalReferences(filePath, exportedItem))
138
+ if (!options.isSkipLibs && principal?.hasExternalReferences(filePath, exportedItem))
144
139
  continue;
145
140
  const type = getType(hasStrictlyNsRefs, isType);
146
141
  const isIssueAdded = collector.addIssue({
@@ -154,7 +149,7 @@ export const analyze = async (options) => {
154
149
  line: exportedItem.line,
155
150
  col: exportedItem.col,
156
151
  });
157
- if (isFix && isIssueAdded) {
152
+ if (options.isFix && isIssueAdded) {
158
153
  if (isType)
159
154
  fixer.addUnusedTypeNode(filePath, exportedItem.fixes);
160
155
  else
@@ -201,11 +196,11 @@ export const analyze = async (options) => {
201
196
  const unusedFiles = [...unreferencedFiles].filter(filePath => !analyzedFiles.has(filePath));
202
197
  collector.addFilesIssues(unusedFiles);
203
198
  collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
204
- if (isReportDependencies) {
199
+ if (options.isReportDependencies) {
205
200
  const { dependencyIssues, devDependencyIssues, optionalPeerDependencyIssues } = deputy.settleDependencyIssues();
206
201
  for (const issue of dependencyIssues)
207
202
  collector.addIssue(issue);
208
- if (!isProduction)
203
+ if (!options.isProduction)
209
204
  for (const issue of devDependencyIssues)
210
205
  collector.addIssue(issue);
211
206
  for (const issue of optionalPeerDependencyIssues)
@@ -219,6 +214,8 @@ export const analyze = async (options) => {
219
214
  for (const identifier of unusedIgnoredWorkspaces) {
220
215
  collector.addConfigurationHint({ type: 'ignoreWorkspaces', identifier });
221
216
  }
217
+ for (const hint of chief.getConfigurationHints())
218
+ collector.addConfigurationHint(hint);
222
219
  };
223
220
  await analyzeGraph();
224
221
  return analyzeGraph;
@@ -4,33 +4,19 @@ import type { DependencyDeputy } from '../DependencyDeputy.js';
4
4
  import type { IssueCollector } from '../IssueCollector.js';
5
5
  import type { PrincipalFactory } from '../PrincipalFactory.js';
6
6
  import type { ProjectPrincipal } from '../ProjectPrincipal.js';
7
- import type { Tags } from '../types/cli.js';
8
- import type { Report } from '../types/issues.js';
9
7
  import type { ModuleGraph } from '../types/module-graph.js';
8
+ import type { MainOptions } from '../util/create-options.js';
10
9
  interface BuildOptions {
11
- cacheLocation: string;
12
10
  chief: ConfigurationChief;
13
11
  collector: IssueCollector;
14
- cwd: string;
15
12
  deputy: DependencyDeputy;
16
13
  factory: PrincipalFactory;
17
- gitignore: boolean;
18
- isCache: boolean;
19
- isFixExports: boolean;
20
- isFixTypes: boolean;
21
14
  isGitIgnored: (path: string) => boolean;
22
- isIsolateWorkspaces: boolean;
23
- isProduction: boolean;
24
- isSkipLibs: boolean;
25
- isStrict: boolean;
26
- isWatch: boolean;
27
- report: Report;
28
15
  streamer: ConsoleStreamer;
29
- tags: Tags;
30
- tsConfigFile?: string;
31
16
  workspaces: Workspace[];
17
+ options: MainOptions;
32
18
  }
33
- export declare function build({ cacheLocation, chief, collector, cwd, deputy, factory, gitignore, isCache, isFixExports, isFixTypes, isGitIgnored, isIsolateWorkspaces, isProduction, isSkipLibs, isStrict, isWatch, report, streamer, tags, tsConfigFile, workspaces, }: BuildOptions): Promise<{
19
+ export declare function build({ chief, collector, deputy, factory, isGitIgnored, streamer, workspaces, options, }: BuildOptions): Promise<{
34
20
  graph: ModuleGraph;
35
21
  entryPaths: Set<string>;
36
22
  analyzedFiles: Set<string>;
@@ -5,30 +5,37 @@ import { DEFAULT_EXTENSIONS, FOREIGN_FILE_EXTENSIONS } from '../constants.js';
5
5
  import { perfObserver } from '../util/Performance.js';
6
6
  import { debugLog, debugLogArray } from '../util/debug.js';
7
7
  import { getReferencedInputsHandler } from '../util/get-referenced-inputs.js';
8
- import { _glob, negate } from '../util/glob.js';
8
+ import { _glob, _syncGlob, negate } from '../util/glob.js';
9
9
  import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
10
10
  import { loadTSConfig } from '../util/load-tsconfig.js';
11
11
  import { getOrCreateFileNode, updateImportMap } from '../util/module-graph.js';
12
12
  import { getPackageNameFromModuleSpecifier, isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
13
- import { getEntryPathsFromManifest } from '../util/package-json.js';
13
+ import { getEntrySpecifiersFromManifest, getManifestImportDependencies } from '../util/package-json.js';
14
14
  import { dirname, extname, isAbsolute, join, relative, toRelative } from '../util/path.js';
15
15
  import { augmentWorkspace, getToSourcePathHandler, getToSourcePathsHandler } from '../util/to-source-path.js';
16
- export async function build({ cacheLocation, chief, collector, cwd, deputy, factory, gitignore, isCache, isFixExports, isFixTypes, isGitIgnored, isIsolateWorkspaces, isProduction, isSkipLibs, isStrict, isWatch, report, streamer, tags, tsConfigFile, workspaces, }) {
16
+ export async function build({ chief, collector, deputy, factory, isGitIgnored, streamer, workspaces, options, }) {
17
17
  const configFilesMap = new Map();
18
18
  const enabledPluginsStore = new Map();
19
19
  const toSourceFilePath = getToSourcePathHandler(chief);
20
20
  const toSourceFilePaths = getToSourcePathsHandler(chief);
21
21
  const getReferencedInternalFilePath = getReferencedInputsHandler(collector, deputy, chief, isGitIgnored);
22
- const isReportClassMembers = report.classMembers;
23
22
  for (const workspace of workspaces) {
24
23
  const { name, dir, manifestPath, manifestStr } = workspace;
25
24
  const manifest = chief.getManifestForWorkspace(name);
26
25
  if (!manifest)
27
26
  continue;
28
- deputy.addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ...chief.getIgnores(name) });
27
+ deputy.addWorkspace({
28
+ name,
29
+ cwd: options.cwd,
30
+ dir,
31
+ manifestPath,
32
+ manifestStr,
33
+ manifest,
34
+ ...chief.getIgnores(name),
35
+ });
29
36
  }
30
37
  for (const workspace of workspaces) {
31
- const { name, dir, ancestors, pkgName } = workspace;
38
+ const { name, dir, ancestors, pkgName, manifestPath: filePath } = workspace;
32
39
  streamer.cast('Analyzing workspace', name);
33
40
  const manifest = chief.getManifestForWorkspace(name);
34
41
  if (!manifest)
@@ -38,29 +45,25 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
38
45
  const extensions = getCompilerExtensions(compilers);
39
46
  const extensionGlobStr = `.{${[...DEFAULT_EXTENSIONS, ...extensions].map(ext => ext.slice(1)).join(',')}}`;
40
47
  const config = chief.getConfigForWorkspace(name, extensions);
41
- const tsConfigFilePath = join(dir, tsConfigFile ?? 'tsconfig.json');
48
+ const tsConfigFilePath = join(dir, options.tsConfigFile ?? 'tsconfig.json');
42
49
  const { isFile, compilerOptions, definitionPaths } = await loadTSConfig(tsConfigFilePath);
43
50
  if (isFile)
44
51
  augmentWorkspace(workspace, dir, compilerOptions);
45
52
  const worker = new WorkspaceWorker({
46
53
  name,
47
54
  dir,
48
- cwd,
49
55
  config,
50
56
  manifest,
51
57
  dependencies,
52
58
  getReferencedInternalFilePath: (input) => getReferencedInternalFilePath(input, workspace),
53
59
  findWorkspaceByFilePath: chief.findWorkspaceByFilePath.bind(chief),
54
- isProduction,
55
- isStrict,
56
60
  rootIgnore: chief.config.ignore,
57
61
  negatedWorkspacePatterns: chief.getNegatedWorkspacePatterns(name),
58
62
  ignoredWorkspacePatterns: chief.getIgnoredWorkspacesFor(name),
59
63
  enabledPluginsInAncestors: ancestors.flatMap(ancestor => enabledPluginsStore.get(ancestor) ?? []),
60
64
  getSourceFile: (filePath) => principal.backend.fileManager.getSourceFile(filePath),
61
- isCache,
62
- cacheLocation,
63
65
  configFilesMap,
66
+ options,
64
67
  });
65
68
  await worker.init();
66
69
  const inputs = new Set();
@@ -70,25 +73,29 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
70
73
  inputs.add(toProductionEntry(id, { containingFilePath: tsConfigFilePath }));
71
74
  }
72
75
  const ignore = worker.getIgnorePatterns();
73
- const sharedGlobOptions = { cwd, dir, gitignore };
74
- collector.addIgnorePatterns(ignore.map(pattern => join(cwd, pattern)));
75
- const entryPathsFromManifest = getEntryPathsFromManifest(manifest);
76
- for (const filePath of await toSourceFilePaths(entryPathsFromManifest, dir, extensionGlobStr)) {
76
+ const sharedGlobOptions = { cwd: options.cwd, dir, gitignore: options.gitignore };
77
+ collector.addIgnorePatterns(ignore.map(pattern => join(options.cwd, pattern)));
78
+ const entrySpecifiersFromManifest = getEntrySpecifiersFromManifest(manifest);
79
+ for (const filePath of await toSourceFilePaths(entrySpecifiersFromManifest, dir, extensionGlobStr)) {
77
80
  inputs.add(toProductionEntry(filePath));
78
81
  }
79
- const principal = factory.createPrincipal({
80
- cwd: dir,
82
+ for (const identifier of entrySpecifiersFromManifest) {
83
+ if (!identifier.startsWith('!') && !isGitIgnored(join(dir, identifier))) {
84
+ const files = _syncGlob({ patterns: [identifier], cwd: dir });
85
+ if (files.length === 0) {
86
+ collector.addConfigurationHint({ type: 'package-entry', filePath, identifier, workspaceName: name });
87
+ }
88
+ }
89
+ }
90
+ for (const dep of getManifestImportDependencies(manifest))
91
+ deputy.addReferencedDependency(name, dep);
92
+ const principal = factory.createPrincipal(options, {
93
+ dir,
81
94
  isFile,
82
95
  compilerOptions,
83
96
  compilers,
84
97
  pkgName,
85
- isIsolateWorkspaces,
86
- isSkipLibs,
87
- isWatch,
88
98
  toSourceFilePath,
89
- isCache,
90
- cacheLocation,
91
- isProduction,
92
99
  });
93
100
  principal.addPaths(config.paths, dir);
94
101
  const inputsFromPlugins = await worker.runPlugins();
@@ -142,7 +149,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
142
149
  productionPatternsSkipExports.add(resolvedFilePath);
143
150
  }
144
151
  else if (isDeferResolveEntry(input)) {
145
- if (!isProduction || !input.optional)
152
+ if (!options.isProduction || !input.optional)
146
153
  entryPatternsSkipExports.add(resolvedFilePath);
147
154
  }
148
155
  else {
@@ -151,7 +158,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
151
158
  }
152
159
  }
153
160
  }
154
- if (isProduction) {
161
+ if (options.isProduction) {
155
162
  const negatedEntryPatterns = [...entryPatterns, ...entryPatternsSkipExports].map(negate);
156
163
  {
157
164
  const label = 'entry paths';
@@ -160,7 +167,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
160
167
  principal.addEntryPaths(workspaceEntryPaths);
161
168
  }
162
169
  {
163
- const label = 'production entry paths from plugins (skip exports analysis)';
170
+ const label = 'production entry paths from plugins (ignore exports)';
164
171
  const patterns = Array.from(productionPatternsSkipExports);
165
172
  const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
166
173
  principal.addEntryPaths(pluginWorkspaceEntryPaths, { skipExportsAnalysis: true });
@@ -181,7 +188,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
181
188
  }
182
189
  else {
183
190
  {
184
- const label = 'entry paths from plugins (skip exports analysis)';
191
+ const label = 'entry paths from plugins (ignore exports)';
185
192
  const patterns = worker.getPluginEntryFilePatterns([
186
193
  ...entryPatternsSkipExports,
187
194
  ...productionPatternsSkipExports,
@@ -212,7 +219,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
212
219
  principal.addProjectPath(projectPath);
213
220
  }
214
221
  {
215
- const label = 'plugin configuration paths (skip exports analysis)';
222
+ const label = 'plugin configuration paths (ignore exports)';
216
223
  const patterns = worker.getPluginConfigPatterns();
217
224
  const configurationEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
218
225
  principal.addEntryPaths(configurationEntryPaths, { skipExportsAnalysis: true });
@@ -228,8 +235,8 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
228
235
  principal.addProjectPath(projectPath);
229
236
  }
230
237
  }
231
- if (chief.resolvedConfigFilePath) {
232
- principal.addEntryPath(chief.resolvedConfigFilePath, { skipExportsAnalysis: true });
238
+ if (options.configFilePath) {
239
+ factory.getPrincipals().at(0)?.addEntryPath(options.configFilePath, { skipExportsAnalysis: true });
233
240
  }
234
241
  worker.onDispose();
235
242
  }
@@ -245,20 +252,20 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
245
252
  if (workspace)
246
253
  return factory.getPrincipalByPackageName(workspace.pkgName);
247
254
  };
255
+ const analyzeOpts = {
256
+ isFixExports: options.isFixUnusedExports,
257
+ isFixTypes: options.isFixUnusedTypes,
258
+ isReportClassMembers: options.isReportClassMembers,
259
+ skipTypeOnly: options.isStrict,
260
+ tags: options.tags,
261
+ };
248
262
  const analyzeSourceFile = (filePath, principal) => {
249
- if (!isWatch && analyzedFiles.has(filePath))
263
+ if (!options.isWatch && analyzedFiles.has(filePath))
250
264
  return;
251
265
  analyzedFiles.add(filePath);
252
266
  const workspace = chief.findWorkspaceByFilePath(filePath);
253
267
  if (workspace) {
254
- const file = principal.analyzeSourceFile(filePath, {
255
- skipTypeOnly: isStrict,
256
- isFixExports,
257
- isFixTypes,
258
- ignoreExportsUsedInFile: chief.config.ignoreExportsUsedInFile,
259
- isReportClassMembers,
260
- tags,
261
- });
268
+ const file = principal.analyzeSourceFile(filePath, analyzeOpts, chief.config.ignoreExportsUsedInFile);
262
269
  const _unresolved = new Set();
263
270
  for (const unresolvedImport of file.imports.unresolved) {
264
271
  const { specifier } = unresolvedImport;
@@ -297,8 +304,14 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
297
304
  const dependencies = deputy.getDependencies(workspace.name);
298
305
  const manifestScriptNames = new Set(Object.keys(chief.getManifestForWorkspace(workspace.name)?.scripts ?? {}));
299
306
  const dir = dirname(filePath);
300
- const options = { cwd: dir, rootCwd: cwd, containingFilePath: filePath, dependencies, manifestScriptNames };
301
- const inputs = _getInputsFromScripts(file.scripts, options);
307
+ const opts = {
308
+ cwd: dir,
309
+ rootCwd: options.cwd,
310
+ containingFilePath: filePath,
311
+ dependencies,
312
+ manifestScriptNames,
313
+ };
314
+ const inputs = _getInputsFromScripts(file.scripts, opts);
302
315
  for (const input of inputs) {
303
316
  input.containingFilePath ??= filePath;
304
317
  input.dir ??= dir;
@@ -324,7 +337,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
324
337
  streamer.cast('Running async compilers');
325
338
  await principal.runAsyncCompilers();
326
339
  }
327
- streamer.cast('Analyzing source files', toRelative(principal.cwd));
340
+ streamer.cast('Analyzing source files', toRelative(principal.cwd, options.cwd));
328
341
  let size = principal.entryPaths.size;
329
342
  let round = 0;
330
343
  do {
@@ -340,16 +353,16 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
340
353
  for (const filePath of principal.entryPaths)
341
354
  entryPaths.add(filePath);
342
355
  principal.reconcileCache(graph);
343
- if (isIsolateWorkspaces || (isSkipLibs && !isWatch)) {
344
- factory.deletePrincipal(principal);
356
+ if (options.isIsolateWorkspaces || (options.isSkipLibs && !options.isWatch)) {
357
+ factory.deletePrincipal(principal, options.cwd);
345
358
  principals[i] = undefined;
346
359
  }
347
360
  perfObserver.addMemoryMark(factory.getPrincipalCount());
348
361
  }
349
- if (!isWatch && isSkipLibs && !isIsolateWorkspaces) {
362
+ if (!options.isWatch && options.isSkipLibs && !options.isIsolateWorkspaces) {
350
363
  for (const principal of principals) {
351
364
  if (principal)
352
- factory.deletePrincipal(principal);
365
+ factory.deletePrincipal(principal, options.cwd);
353
366
  }
354
367
  principals.length = 0;
355
368
  }
package/dist/index.d.ts CHANGED
@@ -1,13 +1,10 @@
1
- import type { CommandLineOptions } from './types/cli.js';
1
+ import type { MainOptions } from './util/create-options.js';
2
2
  export type { RawConfiguration as KnipConfig } from './types/config.js';
3
3
  export type { Preprocessor, Reporter, ReporterOptions } from './types/issues.js';
4
- export declare const main: (unresolvedConfiguration: CommandLineOptions) => Promise<{
5
- report: import("./types/issues.js").Report;
4
+ export declare const main: (options: MainOptions) => Promise<{
6
5
  issues: import("./types/issues.js").Issues;
7
6
  counters: import("./types/issues.js").Counters;
8
- rules: import("./types/issues.js").Rules;
9
7
  tagHints: Set<import("./types/issues.js").TagHint>;
10
8
  configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
11
- isTreatConfigHintsAsErrors: boolean;
12
- includedWorkspaces: import("./ConfigurationChief.js").Workspace[];
9
+ includedWorkspaceDirs: string[];
13
10
  }>;
package/dist/index.js CHANGED
@@ -11,57 +11,30 @@ import { build } from './graph/build.js';
11
11
  import { debugLogArray, debugLogObject } from './util/debug.js';
12
12
  import { getGitIgnoredHandler } from './util/glob-core.js';
13
13
  import { getWatchHandler } from './util/watch.js';
14
- export const main = async (unresolvedConfiguration) => {
15
- const { cacheLocation, cwd, excludedIssueTypes, fixTypes, gitignore, includedIssueTypes, isCache, isDebug, isDependenciesShorthand, isExportsShorthand, isFilesShorthand, isFix, isFormat, isIncludeEntryExports, isIncludeLibs, isIsolateWorkspaces, isProduction, isRemoveFiles, isShowProgress, isStrict, isWatch, tags, tsConfigFile, workspace, } = unresolvedConfiguration;
16
- debugLogObject('*', 'Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
17
- const chief = new ConfigurationChief({ cwd, isProduction, isStrict, isIncludeEntryExports, workspace });
18
- const deputy = new DependencyDeputy({ isProduction, isStrict });
14
+ export const main = async (options) => {
15
+ const { cwd } = options;
16
+ debugLogObject('*', 'Unresolved configuration', options);
17
+ debugLogObject('*', 'Included issue types', options.includedIssueTypes);
18
+ const chief = new ConfigurationChief(options);
19
+ const deputy = new DependencyDeputy(options);
19
20
  const factory = new PrincipalFactory();
20
- const streamer = new ConsoleStreamer({ isEnabled: isShowProgress });
21
+ const streamer = new ConsoleStreamer(options);
22
+ const fixer = new IssueFixer(options);
23
+ const collector = new IssueCollector(options);
21
24
  streamer.cast('Reading workspace configuration');
22
- await chief.init();
23
- const workspaces = chief.getWorkspaces();
24
- const report = chief.getIncludedIssueTypes({
25
- includedIssueTypes,
26
- excludedIssueTypes,
27
- isDependenciesShorthand,
28
- isExportsShorthand,
29
- isFilesShorthand,
30
- });
31
- const rules = chief.getRules();
32
- const filters = chief.getFilters();
33
- const finalTags = tags[0].length > 0 || tags[1].length > 0 ? tags : chief.getTags();
34
- const fixer = new IssueFixer({ isEnabled: isFix, cwd, fixTypes, isRemoveFiles });
35
- debugLogObject('*', 'Included issue types', report);
36
- const isReportClassMembers = report.classMembers;
37
- const isSkipLibs = !(isIncludeLibs || isReportClassMembers);
38
- const collector = new IssueCollector({ cwd, rules, filters });
39
- const o = () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors }));
25
+ const workspaces = await chief.getWorkspaces();
26
+ const isGitIgnored = await getGitIgnoredHandler(options);
40
27
  debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
41
- debugLogObject('*', 'Included workspace configs', o);
42
- const isGitIgnored = await getGitIgnoredHandler({ cwd, gitignore });
28
+ debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
43
29
  const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
44
- cacheLocation,
45
30
  chief,
46
31
  collector,
47
- cwd,
48
32
  deputy,
49
33
  factory,
50
- gitignore,
51
- isCache,
52
- isFixExports: fixer.isEnabled && fixer.isFixUnusedExports,
53
- isFixTypes: fixer.isEnabled && fixer.isFixUnusedTypes,
54
34
  isGitIgnored,
55
- isIsolateWorkspaces,
56
- isProduction,
57
- isSkipLibs,
58
- isStrict,
59
- isWatch,
60
- report,
61
35
  streamer,
62
- tags: finalTags,
63
- tsConfigFile,
64
36
  workspaces,
37
+ options,
65
38
  });
66
39
  const reAnalyze = await analyze({
67
40
  analyzedFiles,
@@ -72,41 +45,32 @@ export const main = async (unresolvedConfiguration) => {
72
45
  factory,
73
46
  fixer,
74
47
  graph,
75
- isFix,
76
- isIncludeLibs,
77
- isProduction,
78
- report,
79
48
  streamer,
80
- tags: finalTags,
81
49
  unreferencedFiles,
50
+ options,
82
51
  });
83
- const { issues, counters, tagHints, configurationHints } = collector.getIssues();
84
- for (const hint of chief.getConfigurationHints())
85
- collector.addConfigurationHint(hint);
86
- if (isWatch) {
87
- const isIgnored = (filePath) => filePath.startsWith(cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
88
- const watchHandler = await getWatchHandler({
52
+ if (options.isWatch) {
53
+ const isIgnored = (filePath) => filePath.startsWith(options.cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
54
+ const watchHandler = await getWatchHandler(options, {
89
55
  analyzedFiles,
90
56
  analyzeSourceFile,
91
57
  chief,
92
58
  collector,
93
59
  analyze: reAnalyze,
94
- cwd,
95
60
  factory,
96
61
  graph,
97
- isDebug,
98
62
  isIgnored,
99
- report,
100
63
  streamer,
101
64
  unreferencedFiles,
102
65
  });
103
66
  watch('.', { recursive: true }, watchHandler);
104
67
  }
105
- if (isFix) {
68
+ const { issues, counters, tagHints, configurationHints } = collector.getIssues();
69
+ if (options.isFix) {
106
70
  const touchedFiles = await fixer.fixIssues(issues);
107
- if (isFormat) {
71
+ if (options.isFormat) {
108
72
  const report = await formatly(Array.from(touchedFiles), { cwd });
109
- if (report.ran && report.result.code === 0) {
73
+ if (report.ran && report.result && (report.result.runner === 'virtual' || report.result.code === 0)) {
110
74
  debugLogArray('*', `Formatted files using ${report.formatter.name} (${report.formatter.runner})`, touchedFiles);
111
75
  }
112
76
  else {
@@ -114,16 +78,13 @@ export const main = async (unresolvedConfiguration) => {
114
78
  }
115
79
  }
116
80
  }
117
- if (!isWatch)
81
+ if (!options.isWatch)
118
82
  streamer.clear();
119
83
  return {
120
- report,
121
84
  issues,
122
85
  counters,
123
- rules,
124
86
  tagHints,
125
87
  configurationHints,
126
- isTreatConfigHintsAsErrors: chief.config.isTreatConfigHintsAsErrors,
127
- includedWorkspaces: chief.includedWorkspaces,
88
+ includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
128
89
  };
129
90
  };
@@ -9,5 +9,6 @@ declare const _default: {
9
9
  production: string[];
10
10
  resolveFromAST: ResolveFromAST;
11
11
  resolve: Resolve;
12
+ project: string[];
12
13
  };
13
14
  export default _default;
@@ -6,8 +6,11 @@ const enablers = ['astro'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
7
  export const config = ['astro.config.{js,cjs,mjs,ts,mts}'];
8
8
  const entry = ['src/content/config.ts', 'src/content.config.ts'];
9
+ const project = ['src/**/*'];
9
10
  const production = [
10
11
  'src/pages/**/*.{astro,mdx,js,ts}',
12
+ '!src/pages/**/_*',
13
+ '!src/pages/**/_*/**',
11
14
  'src/content/**/*.mdx',
12
15
  'src/middleware.{js,ts}',
13
16
  'src/actions/index.{js,ts}',
@@ -39,4 +42,5 @@ export default {
39
42
  production,
40
43
  resolveFromAST,
41
44
  resolve,
45
+ project,
42
46
  };