knip 5.63.0 → 5.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/CacheConsultant.d.ts +3 -9
  2. package/dist/CacheConsultant.js +5 -5
  3. package/dist/ConfigurationChief.d.ts +597 -38
  4. package/dist/ConfigurationChief.js +33 -122
  5. package/dist/ConsoleStreamer.d.ts +2 -3
  6. package/dist/ConsoleStreamer.js +2 -2
  7. package/dist/DependencyDeputy.d.ts +2 -6
  8. package/dist/DependencyDeputy.js +3 -2
  9. package/dist/IssueCollector.d.ts +4 -12
  10. package/dist/IssueCollector.js +9 -9
  11. package/dist/IssueFixer.d.ts +3 -14
  12. package/dist/IssueFixer.js +14 -22
  13. package/dist/PrincipalFactory.d.ts +3 -2
  14. package/dist/PrincipalFactory.js +11 -11
  15. package/dist/ProjectPrincipal.d.ts +4 -3
  16. package/dist/ProjectPrincipal.js +8 -8
  17. package/dist/WorkspaceWorker.d.ts +4 -9
  18. package/dist/WorkspaceWorker.js +8 -12
  19. package/dist/binaries/bash-parser.d.ts +1 -0
  20. package/dist/binaries/bash-parser.js +4 -1
  21. package/dist/binaries/fallback.js +3 -2
  22. package/dist/binaries/package-manager/bun.js +1 -0
  23. package/dist/binaries/package-manager/pnpm.js +6 -1
  24. package/dist/binaries/plugins.js +3 -1
  25. package/dist/cli.js +43 -61
  26. package/dist/compilers/index.d.ts +34 -4
  27. package/dist/constants.js +2 -0
  28. package/dist/graph/analyze.d.ts +3 -8
  29. package/dist/graph/analyze.js +31 -31
  30. package/dist/graph/build.d.ts +3 -17
  31. package/dist/graph/build.js +49 -46
  32. package/dist/index.d.ts +3 -7
  33. package/dist/index.js +22 -62
  34. package/dist/plugins/angular/index.js +2 -3
  35. package/dist/plugins/bumpp/index.d.ts +8 -0
  36. package/dist/plugins/bumpp/index.js +11 -0
  37. package/dist/plugins/eslint/index.d.ts +7 -0
  38. package/dist/plugins/eslint/index.js +12 -0
  39. package/dist/plugins/glob/index.d.ts +0 -1
  40. package/dist/plugins/glob/index.js +0 -1
  41. package/dist/plugins/index.d.ts +24 -7
  42. package/dist/plugins/index.js +6 -0
  43. package/dist/plugins/karma/helpers.js +1 -1
  44. package/dist/plugins/node-modules-inspector/index.d.ts +0 -1
  45. package/dist/plugins/node-modules-inspector/index.js +0 -1
  46. package/dist/plugins/nuxt/index.js +10 -3
  47. package/dist/plugins/nuxt/types.d.ts +3 -2
  48. package/dist/plugins/oxlint/index.d.ts +0 -1
  49. package/dist/plugins/oxlint/index.js +0 -1
  50. package/dist/plugins/playwright/index.d.ts +0 -1
  51. package/dist/plugins/playwright/index.js +0 -1
  52. package/dist/plugins/playwright-test/index.d.ts +0 -1
  53. package/dist/plugins/playwright-test/index.js +0 -1
  54. package/dist/plugins/pnpm/index.d.ts +8 -0
  55. package/dist/plugins/pnpm/index.js +12 -0
  56. package/dist/plugins/prisma/index.d.ts +0 -1
  57. package/dist/plugins/prisma/index.js +0 -1
  58. package/dist/plugins/rsbuild/index.js +23 -6
  59. package/dist/plugins/rsbuild/types.d.ts +3 -0
  60. package/dist/plugins/rslib/index.js +1 -1
  61. package/dist/plugins/rstest/index.d.ts +10 -0
  62. package/dist/plugins/rstest/index.js +29 -0
  63. package/dist/plugins/rstest/types.d.ts +6 -0
  64. package/dist/plugins/ts-node/index.d.ts +0 -1
  65. package/dist/plugins/ts-node/index.js +0 -1
  66. package/dist/plugins.js +3 -2
  67. package/dist/reporters/codeclimate.d.ts +1 -1
  68. package/dist/reporters/codeclimate.js +10 -10
  69. package/dist/reporters/codeowners.d.ts +1 -1
  70. package/dist/reporters/codeowners.js +5 -5
  71. package/dist/reporters/compact.d.ts +1 -1
  72. package/dist/reporters/compact.js +7 -7
  73. package/dist/reporters/disclosure.d.ts +1 -1
  74. package/dist/reporters/disclosure.js +2 -2
  75. package/dist/reporters/githubActions.d.ts +3 -0
  76. package/dist/reporters/githubActions.js +94 -0
  77. package/dist/reporters/index.d.ts +7 -6
  78. package/dist/reporters/index.js +2 -0
  79. package/dist/reporters/json.d.ts +1 -1
  80. package/dist/reporters/json.js +4 -4
  81. package/dist/reporters/markdown.d.ts +1 -1
  82. package/dist/reporters/markdown.js +4 -4
  83. package/dist/reporters/symbols.js +1 -1
  84. package/dist/reporters/util/configuration-hints.d.ts +14 -2
  85. package/dist/reporters/util/configuration-hints.js +7 -7
  86. package/dist/reporters/util/util.d.ts +2 -2
  87. package/dist/reporters/util/util.js +4 -4
  88. package/dist/reporters/watch.d.ts +3 -4
  89. package/dist/reporters/watch.js +5 -5
  90. package/dist/schema/configuration.d.ts +176 -8
  91. package/dist/schema/plugins.d.ts +69 -0
  92. package/dist/schema/plugins.js +3 -0
  93. package/dist/types/PluginNames.d.ts +2 -2
  94. package/dist/types/PluginNames.js +3 -0
  95. package/dist/types/args.d.ts +2 -0
  96. package/dist/types/config.d.ts +4 -10
  97. package/dist/types/exports.d.ts +1 -1
  98. package/dist/types/imports.d.ts +1 -1
  99. package/dist/types/issues.d.ts +1 -2
  100. package/dist/types/module-graph.d.ts +5 -4
  101. package/dist/types/{cli.d.ts → options.d.ts} +2 -2
  102. package/dist/types/options.js +1 -0
  103. package/dist/types/package-json.d.ts +1 -0
  104. package/dist/types/project.d.ts +1 -7
  105. package/dist/typescript/SourceFile.d.ts +2 -2
  106. package/dist/typescript/ast-helpers.d.ts +4 -0
  107. package/dist/typescript/ast-helpers.js +29 -0
  108. package/dist/typescript/find-internal-references.js +10 -1
  109. package/dist/typescript/get-imports-and-exports.d.ts +2 -2
  110. package/dist/typescript/get-imports-and-exports.js +32 -23
  111. package/dist/typescript/visitors/dynamic-imports/importCall.js +6 -1
  112. package/dist/util/Performance.js +16 -6
  113. package/dist/util/cli-arguments.d.ts +3 -3
  114. package/dist/util/cli-arguments.js +4 -14
  115. package/dist/util/create-options.d.ts +1238 -0
  116. package/dist/util/create-options.js +112 -0
  117. package/dist/util/debug.js +3 -4
  118. package/dist/util/errors.d.ts +1 -1
  119. package/dist/util/file-entry-cache.js +3 -3
  120. package/dist/util/get-included-issue-types.d.ts +9 -13
  121. package/dist/util/get-included-issue-types.js +10 -16
  122. package/dist/util/get-referenced-inputs.js +1 -1
  123. package/dist/util/input.d.ts +1 -1
  124. package/dist/util/input.js +1 -1
  125. package/dist/util/is-identifier-referenced.d.ts +1 -1
  126. package/dist/util/is-identifier-referenced.js +2 -2
  127. package/dist/util/load-config.d.ts +2 -0
  128. package/dist/util/load-config.js +24 -0
  129. package/dist/util/modules.js +18 -7
  130. package/dist/util/path.d.ts +4 -4
  131. package/dist/util/path.js +5 -7
  132. package/dist/util/require.js +1 -2
  133. package/dist/util/tag.d.ts +1 -1
  134. package/dist/util/to-source-path.d.ts +1 -1
  135. package/dist/util/to-source-path.js +5 -5
  136. package/dist/util/trace.d.ts +6 -6
  137. package/dist/util/trace.js +18 -22
  138. package/dist/util/watch.d.ts +2 -5
  139. package/dist/util/watch.js +3 -3
  140. package/dist/version.d.ts +1 -1
  141. package/dist/version.js +1 -1
  142. package/package.json +4 -4
  143. package/schema.json +12 -0
  144. package/dist/util/unwrap-function.d.ts +0 -1
  145. package/dist/util/unwrap-function.js +0 -13
  146. /package/dist/{types/cli.js → plugins/rstest/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 || report.binaries;
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
@@ -177,16 +172,19 @@ export const analyze = async (options) => {
177
172
  }
178
173
  }
179
174
  if (file.imports?.external) {
180
- for (const specifier of file.imports.external) {
181
- const packageName = getPackageNameFromModuleSpecifier(specifier);
175
+ for (const extImport of file.imports.external) {
176
+ const packageName = getPackageNameFromModuleSpecifier(extImport.specifier);
182
177
  const isHandled = packageName && deputy.maybeAddReferencedExternalDependency(ws, packageName);
183
178
  if (!isHandled)
184
179
  collector.addIssue({
185
180
  type: 'unlisted',
186
181
  filePath,
187
182
  workspace: ws.name,
188
- symbol: packageName ?? specifier,
189
- specifier,
183
+ symbol: packageName ?? extImport.specifier,
184
+ specifier: extImport.specifier,
185
+ pos: extImport.pos,
186
+ line: extImport.line,
187
+ col: extImport.col,
190
188
  });
191
189
  }
192
190
  }
@@ -201,11 +199,11 @@ export const analyze = async (options) => {
201
199
  const unusedFiles = [...unreferencedFiles].filter(filePath => !analyzedFiles.has(filePath));
202
200
  collector.addFilesIssues(unusedFiles);
203
201
  collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
204
- if (isReportDependencies) {
202
+ if (options.isReportDependencies) {
205
203
  const { dependencyIssues, devDependencyIssues, optionalPeerDependencyIssues } = deputy.settleDependencyIssues();
206
204
  for (const issue of dependencyIssues)
207
205
  collector.addIssue(issue);
208
- if (!isProduction)
206
+ if (!options.isProduction)
209
207
  for (const issue of devDependencyIssues)
210
208
  collector.addIssue(issue);
211
209
  for (const issue of optionalPeerDependencyIssues)
@@ -219,6 +217,8 @@ export const analyze = async (options) => {
219
217
  for (const identifier of unusedIgnoredWorkspaces) {
220
218
  collector.addConfigurationHint({ type: 'ignoreWorkspaces', identifier });
221
219
  }
220
+ for (const hint of chief.getConfigurationHints())
221
+ collector.addConfigurationHint(hint);
222
222
  };
223
223
  await analyzeGraph();
224
224
  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>;
@@ -13,19 +13,26 @@ import { getPackageNameFromModuleSpecifier, isStartsLikePackageName, sanitizeSpe
13
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
38
  const { name, dir, ancestors, pkgName, manifestPath: filePath } = workspace;
@@ -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,8 +73,8 @@ 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)));
76
+ const sharedGlobOptions = { cwd: options.cwd, dir, gitignore: options.gitignore };
77
+ collector.addIgnorePatterns(ignore.map(pattern => join(options.cwd, pattern)));
75
78
  const entrySpecifiersFromManifest = getEntrySpecifiersFromManifest(manifest);
76
79
  for (const filePath of await toSourceFilePaths(entrySpecifiersFromManifest, dir, extensionGlobStr)) {
77
80
  inputs.add(toProductionEntry(filePath));
@@ -86,19 +89,13 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
86
89
  }
87
90
  for (const dep of getManifestImportDependencies(manifest))
88
91
  deputy.addReferencedDependency(name, dep);
89
- const principal = factory.createPrincipal({
90
- cwd: dir,
92
+ const principal = factory.createPrincipal(options, {
93
+ dir,
91
94
  isFile,
92
95
  compilerOptions,
93
96
  compilers,
94
97
  pkgName,
95
- isIsolateWorkspaces,
96
- isSkipLibs,
97
- isWatch,
98
98
  toSourceFilePath,
99
- isCache,
100
- cacheLocation,
101
- isProduction,
102
99
  });
103
100
  principal.addPaths(config.paths, dir);
104
101
  const inputsFromPlugins = await worker.runPlugins();
@@ -152,7 +149,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
152
149
  productionPatternsSkipExports.add(resolvedFilePath);
153
150
  }
154
151
  else if (isDeferResolveEntry(input)) {
155
- if (!isProduction || !input.optional)
152
+ if (!options.isProduction || !input.optional)
156
153
  entryPatternsSkipExports.add(resolvedFilePath);
157
154
  }
158
155
  else {
@@ -161,7 +158,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
161
158
  }
162
159
  }
163
160
  }
164
- if (isProduction) {
161
+ if (options.isProduction) {
165
162
  const negatedEntryPatterns = [...entryPatterns, ...entryPatternsSkipExports].map(negate);
166
163
  {
167
164
  const label = 'entry paths';
@@ -238,8 +235,8 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
238
235
  principal.addProjectPath(projectPath);
239
236
  }
240
237
  }
241
- if (chief.resolvedConfigFilePath) {
242
- principal.addEntryPath(chief.resolvedConfigFilePath, { skipExportsAnalysis: true });
238
+ if (options.configFilePath) {
239
+ factory.getPrincipals().at(0)?.addEntryPath(options.configFilePath, { skipExportsAnalysis: true });
243
240
  }
244
241
  worker.onDispose();
245
242
  }
@@ -255,28 +252,28 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
255
252
  if (workspace)
256
253
  return factory.getPrincipalByPackageName(workspace.pkgName);
257
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
+ };
258
262
  const analyzeSourceFile = (filePath, principal) => {
259
- if (!isWatch && analyzedFiles.has(filePath))
263
+ if (!options.isWatch && analyzedFiles.has(filePath))
260
264
  return;
261
265
  analyzedFiles.add(filePath);
262
266
  const workspace = chief.findWorkspaceByFilePath(filePath);
263
267
  if (workspace) {
264
- const file = principal.analyzeSourceFile(filePath, {
265
- skipTypeOnly: isStrict,
266
- isFixExports,
267
- isFixTypes,
268
- ignoreExportsUsedInFile: chief.config.ignoreExportsUsedInFile,
269
- isReportClassMembers,
270
- tags,
271
- });
272
- const _unresolved = new Set();
268
+ const file = principal.analyzeSourceFile(filePath, analyzeOpts, chief.config.ignoreExportsUsedInFile);
269
+ const unresolvedImports = new Set();
273
270
  for (const unresolvedImport of file.imports.unresolved) {
274
271
  const { specifier } = unresolvedImport;
275
272
  if (specifier.startsWith('http'))
276
273
  continue;
277
274
  const sanitizedSpecifier = sanitizeSpecifier(specifier);
278
275
  if (isStartsLikePackageName(sanitizedSpecifier)) {
279
- file.imports.external.add(sanitizedSpecifier);
276
+ file.imports.external.add({ ...unresolvedImport, specifier: sanitizedSpecifier });
280
277
  }
281
278
  else {
282
279
  const isIgnored = isGitIgnored(join(dirname(filePath), sanitizedSpecifier));
@@ -284,7 +281,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
284
281
  const ext = extname(sanitizedSpecifier);
285
282
  const hasIgnoredExtension = FOREIGN_FILE_EXTENSIONS.has(ext);
286
283
  if (!ext || (ext !== '.json' && !hasIgnoredExtension))
287
- _unresolved.add(unresolvedImport);
284
+ unresolvedImports.add(unresolvedImport);
288
285
  }
289
286
  }
290
287
  }
@@ -293,10 +290,10 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
293
290
  if (!isIgnored)
294
291
  principal.addEntryPath(filePath, { skipExportsAnalysis: true });
295
292
  }
296
- for (const [specifier, specifierFilePath] of file.imports.specifiers) {
297
- const packageName = getPackageNameFromModuleSpecifier(specifier);
293
+ for (const [import_, specifierFilePath] of file.imports.specifiers) {
294
+ const packageName = getPackageNameFromModuleSpecifier(import_.specifier);
298
295
  if (packageName && isInternalWorkspace(packageName)) {
299
- file.imports.external.add(packageName);
296
+ file.imports.external.add({ ...import_, specifier: packageName });
300
297
  const principal = getPrincipalByFilePath(specifierFilePath);
301
298
  if (principal && !isGitIgnored(specifierFilePath)) {
302
299
  principal.addNonEntryPath(specifierFilePath);
@@ -307,8 +304,14 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
307
304
  const dependencies = deputy.getDependencies(workspace.name);
308
305
  const manifestScriptNames = new Set(Object.keys(chief.getManifestForWorkspace(workspace.name)?.scripts ?? {}));
309
306
  const dir = dirname(filePath);
310
- const options = { cwd: dir, rootCwd: cwd, containingFilePath: filePath, dependencies, manifestScriptNames };
311
- 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);
312
315
  for (const input of inputs) {
313
316
  input.containingFilePath ??= filePath;
314
317
  input.dir ??= dir;
@@ -318,7 +321,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
318
321
  }
319
322
  }
320
323
  const node = getOrCreateFileNode(graph, filePath);
321
- file.imports.unresolved = _unresolved;
324
+ file.imports.unresolved = unresolvedImports;
322
325
  Object.assign(node, file);
323
326
  updateImportMap(node, file.imports.internal, graph);
324
327
  node.internalImportCache = file.imports.internal;
@@ -334,7 +337,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
334
337
  streamer.cast('Running async compilers');
335
338
  await principal.runAsyncCompilers();
336
339
  }
337
- streamer.cast('Analyzing source files', toRelative(principal.cwd));
340
+ streamer.cast('Analyzing source files', toRelative(principal.cwd, options.cwd));
338
341
  let size = principal.entryPaths.size;
339
342
  let round = 0;
340
343
  do {
@@ -350,16 +353,16 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
350
353
  for (const filePath of principal.entryPaths)
351
354
  entryPaths.add(filePath);
352
355
  principal.reconcileCache(graph);
353
- if (isIsolateWorkspaces || (isSkipLibs && !isWatch)) {
354
- factory.deletePrincipal(principal);
356
+ if (options.isIsolateWorkspaces || (options.isSkipLibs && !options.isWatch)) {
357
+ factory.deletePrincipal(principal, options.cwd);
355
358
  principals[i] = undefined;
356
359
  }
357
360
  perfObserver.addMemoryMark(factory.getPrincipalCount());
358
361
  }
359
- if (!isWatch && isSkipLibs && !isIsolateWorkspaces) {
362
+ if (!options.isWatch && options.isSkipLibs && !options.isIsolateWorkspaces) {
360
363
  for (const principal of principals) {
361
364
  if (principal)
362
- factory.deletePrincipal(principal);
365
+ factory.deletePrincipal(principal, options.cwd);
363
366
  }
364
367
  principals.length = 0;
365
368
  }
package/dist/index.d.ts CHANGED
@@ -1,14 +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[];
13
- configFilePath: string | undefined;
9
+ includedWorkspaceDirs: string[];
14
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,39 +45,30 @@ 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
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);
@@ -114,17 +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,
128
- configFilePath: chief.resolvedConfigFilePath,
88
+ includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
129
89
  };
130
90
  };
@@ -8,7 +8,6 @@ const enablers = ['@angular/cli'];
8
8
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
9
9
  const config = ['angular.json'];
10
10
  const resolveConfig = async (config, options) => {
11
- const { cwd, configFilePath } = options;
12
11
  if (!config?.projects)
13
12
  return [];
14
13
  const inputs = new Set();
@@ -22,7 +21,7 @@ const resolveConfig = async (config, options) => {
22
21
  inputs.add(toDependency(packageName));
23
22
  if (opts) {
24
23
  if ('tsConfig' in opts && typeof opts.tsConfig === 'string') {
25
- inputs.add(toConfig('typescript', opts.tsConfig, { containingFilePath: configFilePath }));
24
+ inputs.add(toConfig('typescript', opts.tsConfig));
26
25
  }
27
26
  }
28
27
  const defaultEntriesByOption = opts ? entriesByOption(opts) : new Map();
@@ -31,7 +30,7 @@ const resolveConfig = async (config, options) => {
31
30
  const isBuildTarget = targetName === BUILD_TARGET_NAME;
32
31
  const maybeExternal = (option) => option === 'polyfills';
33
32
  const toInput = (specifier, opts) => {
34
- const normalizedPath = join(cwd, specifier);
33
+ const normalizedPath = join(options.cwd, specifier);
35
34
  if (opts.maybeExternal && !isInternal(specifier) && !existsSync(normalizedPath)) {
36
35
  return toDeferResolve(specifier);
37
36
  }
@@ -0,0 +1,8 @@
1
+ import type { IsPluginEnabled } from '../../types/config.js';
2
+ declare const _default: {
3
+ title: string;
4
+ enablers: string[];
5
+ isEnabled: IsPluginEnabled;
6
+ entry: string[];
7
+ };
8
+ export default _default;