knip 5.76.1 → 5.76.3

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.
@@ -6,13 +6,14 @@ import type { MainOptions } from './util/create-options.js';
6
6
  export declare class DependencyDeputy {
7
7
  isProduction: boolean;
8
8
  isStrict: boolean;
9
+ isReportDependencies: boolean;
9
10
  _manifests: WorkspaceManifests;
10
11
  referencedDependencies: Map<string, Set<string>>;
11
12
  referencedBinaries: Map<string, Set<string>>;
12
13
  hostDependencies: Map<string, HostDependencies>;
13
14
  installedBinaries: Map<string, InstalledBinaries>;
14
15
  hasTypesIncluded: Map<string, Set<string>>;
15
- constructor({ isProduction, isStrict }: MainOptions);
16
+ constructor({ isProduction, isStrict, isReportDependencies }: MainOptions);
16
17
  addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }: {
17
18
  name: string;
18
19
  cwd: string;
@@ -8,15 +8,17 @@ const filterIsProduction = (id, isProduction) => typeof id === 'string' ? (isPro
8
8
  export class DependencyDeputy {
9
9
  isProduction;
10
10
  isStrict;
11
+ isReportDependencies;
11
12
  _manifests = new Map();
12
13
  referencedDependencies;
13
14
  referencedBinaries;
14
15
  hostDependencies;
15
16
  installedBinaries;
16
17
  hasTypesIncluded;
17
- constructor({ isProduction, isStrict }) {
18
+ constructor({ isProduction, isStrict, isReportDependencies }) {
18
19
  this.isProduction = isProduction;
19
20
  this.isStrict = isStrict;
21
+ this.isReportDependencies = isReportDependencies;
20
22
  this.referencedDependencies = new Map();
21
23
  this.referencedBinaries = new Map();
22
24
  this.hostDependencies = new Map();
@@ -39,14 +41,16 @@ export class DependencyDeputy {
39
41
  ...(this.isStrict ? peerDependencies : []),
40
42
  ...(this.isProduction ? [] : devDependencies),
41
43
  ];
42
- const { hostDependencies, installedBinaries, hasTypesIncluded } = getDependencyMetaData({
43
- packageNames,
44
- dir,
45
- cwd,
46
- });
47
- this.setHostDependencies(name, hostDependencies);
48
- this.setInstalledBinaries(name, installedBinaries);
49
- this.setHasTypesIncluded(name, hasTypesIncluded);
44
+ if (this.isReportDependencies) {
45
+ const { hostDependencies, installedBinaries, hasTypesIncluded } = getDependencyMetaData({
46
+ packageNames,
47
+ dir,
48
+ cwd,
49
+ });
50
+ this.setHostDependencies(name, hostDependencies);
51
+ this.setInstalledBinaries(name, installedBinaries);
52
+ this.setHasTypesIncluded(name, hasTypesIncluded);
53
+ }
50
54
  const ignoreDependencies = id.flatMap(id => filterIsProduction(id, this.isProduction)).map(toRegexOrString);
51
55
  const ignoreBinaries = ib.flatMap(ib => filterIsProduction(ib, this.isProduction)).map(toRegexOrString);
52
56
  const ignoreUnresolved = iu.map(toRegexOrString);
@@ -124,6 +128,8 @@ export class DependencyDeputy {
124
128
  return manifest.optionalPeerDependencies;
125
129
  }
126
130
  maybeAddReferencedExternalDependency(workspace, packageName) {
131
+ if (!this.isReportDependencies)
132
+ return true;
127
133
  if (isBuiltin(packageName))
128
134
  return true;
129
135
  if (IGNORED_RUNTIME_DEPENDENCIES.has(packageName))
@@ -145,6 +151,8 @@ export class DependencyDeputy {
145
151
  return false;
146
152
  }
147
153
  maybeAddReferencedBinary(workspace, binaryName) {
154
+ if (!this.isReportDependencies)
155
+ return new Set();
148
156
  if (IGNORED_GLOBAL_BINARIES.has(binaryName))
149
157
  return new Set();
150
158
  this.addReferencedBinary(workspace.name, binaryName);
@@ -13,6 +13,7 @@ type WorkspaceManagerOptions = {
13
13
  config: WorkspaceConfiguration;
14
14
  manifest: PackageJson;
15
15
  dependencies: DependencySet;
16
+ rootManifest: PackageJson | undefined;
16
17
  handleInput: HandleInput;
17
18
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
18
19
  getSourceFile: GetSourceFile;
@@ -32,6 +33,7 @@ export declare class WorkspaceWorker {
32
33
  dir: string;
33
34
  config: WorkspaceConfiguration;
34
35
  manifest: PackageJson;
36
+ rootManifest: PackageJson | undefined;
35
37
  dependencies: DependencySet;
36
38
  handleInput: HandleInput;
37
39
  findWorkspaceByFilePath: (filePath: string) => Workspace | undefined;
@@ -44,7 +46,7 @@ export declare class WorkspaceWorker {
44
46
  enabledPluginsInAncestors: string[];
45
47
  cache: CacheConsultant<CacheItem>;
46
48
  configFilesMap: Map<string, Map<PluginName, Set<string>>>;
47
- constructor({ name, dir, config, manifest, dependencies, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getSourceFile, configFilesMap, options, }: WorkspaceManagerOptions);
49
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getSourceFile, configFilesMap, options, }: WorkspaceManagerOptions);
48
50
  init(): Promise<void>;
49
51
  private determineEnabledPlugins;
50
52
  private getConfigForPlugin;
@@ -21,6 +21,7 @@ export class WorkspaceWorker {
21
21
  dir;
22
22
  config;
23
23
  manifest;
24
+ rootManifest;
24
25
  dependencies;
25
26
  handleInput;
26
27
  findWorkspaceByFilePath;
@@ -33,11 +34,12 @@ export class WorkspaceWorker {
33
34
  enabledPluginsInAncestors;
34
35
  cache;
35
36
  configFilesMap;
36
- constructor({ name, dir, config, manifest, dependencies, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getSourceFile, configFilesMap, options, }) {
37
+ constructor({ name, dir, config, manifest, dependencies, rootManifest, negatedWorkspacePatterns, ignoredWorkspacePatterns, enabledPluginsInAncestors, handleInput, findWorkspaceByFilePath, getSourceFile, configFilesMap, options, }) {
37
38
  this.name = name;
38
39
  this.dir = dir;
39
40
  this.config = config;
40
41
  this.manifest = manifest;
42
+ this.rootManifest = rootManifest;
41
43
  this.dependencies = dependencies;
42
44
  this.negatedWorkspacePatterns = negatedWorkspacePatterns;
43
45
  this.ignoredWorkspacePatterns = ignoredWorkspacePatterns;
@@ -158,7 +160,8 @@ export class WorkspaceWorker {
158
160
  const isProduction = this.options.isProduction;
159
161
  const knownBinsOnly = false;
160
162
  const manifestScriptNames = new Set(Object.keys(manifest.scripts ?? {}));
161
- const baseOptions = { manifestScriptNames, cwd, rootCwd, containingFilePath, knownBinsOnly };
163
+ const rootManifest = this.rootManifest;
164
+ const baseOptions = { manifestScriptNames, rootManifest, cwd, rootCwd, containingFilePath, knownBinsOnly };
162
165
  const baseScriptOptions = { ...baseOptions, manifest, isProduction, enabledPlugins: this.enabledPlugins };
163
166
  const [productionScripts, developmentScripts] = getFilteredScripts(manifest.scripts ?? {});
164
167
  const inputsFromManifest = _getInputsFromScripts(Object.values(developmentScripts), baseOptions);
@@ -1,7 +1,7 @@
1
1
  import parseArgs from 'minimist';
2
- import { isFile } from '../../util/fs.js';
3
2
  import { toEntry } from '../../util/input.js';
4
3
  import { isAbsolute, join } from '../../util/path.js';
4
+ import { _resolveSync } from '../../util/resolve.js';
5
5
  import { resolveX } from './bunx.js';
6
6
  const commands = [
7
7
  'add',
@@ -46,9 +46,12 @@ export const resolve = (_binary, args, options) => {
46
46
  if (command !== 'run' && commands.includes(command))
47
47
  return [];
48
48
  const filePath = command === 'run' ? script : command;
49
- const absFilePath = isAbsolute(filePath) ? filePath : join(cwd, filePath);
50
- if (isFile(absFilePath))
51
- return [toEntry(absFilePath)];
49
+ if (!filePath)
50
+ return [];
51
+ const _cwd = parsed.cwd ? join(cwd, parsed.cwd) : cwd;
52
+ const resolved = _resolveSync(isAbsolute(filePath) ? filePath : join(_cwd, filePath), _cwd);
53
+ if (resolved)
54
+ return [toEntry(resolved)];
52
55
  const dir = parsed.cwd ? join(cwd, parsed.cwd) : undefined;
53
56
  const opts = dir ? { cwd: dir } : {};
54
57
  return command === 'run' ? [] : fromArgs(args, opts);
@@ -1,17 +1,20 @@
1
1
  import parseArgs from 'minimist';
2
- import { toDependency } from '../../util/input.js';
2
+ import { toBinary, toDependency } from '../../util/input.js';
3
3
  import { stripVersionFromSpecifier } from '../../util/modules.js';
4
+ import { isInternal } from '../../util/path.js';
4
5
  import { argsFrom } from '../util.js';
5
6
  export const resolveX = (args, options) => {
6
7
  const { fromArgs } = options;
7
- const parsed = parseArgs(args);
8
+ const parsed = parseArgs(args, { boolean: ['bun'] });
8
9
  const packageSpecifier = parsed._[0];
9
10
  const specifier = packageSpecifier ? stripVersionFromSpecifier(packageSpecifier) : '';
10
11
  const packages = parsed.package && !parsed.yes ? [parsed.package].flat().map(stripVersionFromSpecifier) : [];
11
12
  const command = parsed['shell-mode'] ? fromArgs([parsed['shell-mode']]) : [];
12
13
  const restArgs = argsFrom(args, packageSpecifier);
13
- const dependency = specifier ? [toDependency(specifier, { optional: true })] : [];
14
- return [...dependency, ...packages.map(id => toDependency(id)), ...command, ...fromArgs(restArgs).slice(1)];
14
+ const isBinary = specifier && !packageSpecifier.includes('@') && !isInternal(specifier);
15
+ const dependency = isBinary ? toBinary(specifier, { optional: true }) : toDependency(specifier, { optional: true });
16
+ const specifiers = specifier ? [dependency] : [];
17
+ return [...specifiers, ...packages.map(id => toDependency(id)), ...command, ...fromArgs(restArgs).slice(1)];
15
18
  };
16
19
  export const resolve = (_binary, args, options) => {
17
20
  return resolveX(args, options);
@@ -1,7 +1,12 @@
1
1
  import parseArgs from 'minimist';
2
2
  export const resolve = (_binary, args, options) => {
3
- const { fromArgs } = options;
4
- const parsed = parseArgs(args);
5
- const [command] = parsed._;
6
- return command !== 'exec' ? [] : fromArgs(parsed._.slice(1));
3
+ const { fromArgs, manifestScriptNames } = options;
4
+ const parsed = parseArgs(args, { '--': true });
5
+ const [command, script] = parsed._;
6
+ const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--']) : [];
7
+ if (command === 'exec')
8
+ return _childArgs;
9
+ if (command === 'run' && manifestScriptNames.has(script))
10
+ return _childArgs;
11
+ return [];
7
12
  };
@@ -64,6 +64,7 @@ export const resolve = (_binary, args, options) => {
64
64
  const parsed = parseArgs(args, {
65
65
  boolean: ['recursive', 'silent', 'shell-mode'],
66
66
  alias: { recursive: 'r', silent: 's', 'shell-mode': 'c', filter: 'F' },
67
+ '--': true,
67
68
  });
68
69
  const [command] = parsed._;
69
70
  if (command === 'dlx') {
@@ -73,9 +74,12 @@ export const resolve = (_binary, args, options) => {
73
74
  const { manifestScriptNames, fromArgs } = options;
74
75
  if (parsed.filter && !parsed.recursive)
75
76
  return [];
76
- if (manifestScriptNames.has(command) || commands.includes(command))
77
- return [];
78
- if (command === 'exec')
79
- return fromArgs(parsed._.slice(1));
77
+ const childInputs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--']) : [];
78
+ if (command === 'exec') {
79
+ return childInputs.length > 0 ? childInputs : fromArgs(parsed._.slice(1));
80
+ }
81
+ const isScript = manifestScriptNames.has(command);
82
+ if (isScript || commands.includes(command))
83
+ return childInputs;
80
84
  return command ? [toBinary(command)] : [];
81
85
  };
@@ -50,18 +50,19 @@ const resolveDlx = (args, options) => {
50
50
  };
51
51
  export const resolve = (_binary, args, options) => {
52
52
  const { manifestScriptNames, fromArgs, cwd, rootCwd } = options;
53
- const parsed = parseArgs(args, { boolean: ['top-level'], string: ['cwd'] });
53
+ const parsed = parseArgs(args, { boolean: ['top-level'], string: ['cwd'], '--': true });
54
54
  const dir = parsed['top-level'] ? rootCwd : parsed.cwd ? join(cwd, parsed.cwd) : undefined;
55
55
  const [command, binary] = parsed._;
56
56
  if (!command && !binary)
57
57
  return [];
58
+ const _childArgs = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--']) : [];
58
59
  if (command === 'run') {
59
60
  if (manifestScriptNames.has(binary))
60
- return [];
61
+ return _childArgs;
61
62
  const bin = toBinary(binary, { optional: true });
62
63
  if (dir)
63
64
  Object.assign(bin, { dir });
64
- return [bin];
65
+ return [bin, ..._childArgs];
65
66
  }
66
67
  if (command === 'node')
67
68
  return fromArgs(parsed._);
@@ -70,7 +71,7 @@ export const resolve = (_binary, args, options) => {
70
71
  return resolveDlx(argsForDlx, options);
71
72
  }
72
73
  if ((!dir && manifestScriptNames.has(command)) || commands.includes(command))
73
- return [];
74
+ return _childArgs;
74
75
  const opts = dir ? { cwd: dir } : {};
75
76
  return fromArgs(argsFrom(args, command === 'exec' ? binary : command), opts);
76
77
  };
package/dist/cli.js CHANGED
@@ -30,7 +30,7 @@ const run = async () => {
30
30
  console.log(version);
31
31
  process.exit(0);
32
32
  }
33
- const { issues, counters, tagHints, configurationHints, includedWorkspaceDirs } = await main(options);
33
+ const { issues, counters, tagHints, configurationHints, includedWorkspaceDirs, enabledPlugins } = await main(options);
34
34
  if (options.isWatch || options.isTrace)
35
35
  return;
36
36
  const initialData = {
@@ -39,6 +39,7 @@ const run = async () => {
39
39
  counters,
40
40
  tagHints,
41
41
  configurationHints,
42
+ enabledPlugins,
42
43
  includedWorkspaceDirs,
43
44
  cwd: options.cwd,
44
45
  configFilePath: options.configFilePath,
@@ -199,8 +199,11 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
199
199
  }
200
200
  }
201
201
  }
202
- const unusedFiles = [...unreferencedFiles].filter(filePath => !analyzedFiles.has(filePath));
203
- collector.addFilesIssues(unusedFiles);
202
+ const unusedFiles = options.isReportFiles
203
+ ? [...unreferencedFiles].filter(filePath => !analyzedFiles.has(filePath))
204
+ : [];
205
+ if (options.isReportFiles)
206
+ collector.addFilesIssues(unusedFiles);
204
207
  collector.addFileCounts({ processed: analyzedFiles.size, unused: unusedFiles.length });
205
208
  if (options.isReportDependencies) {
206
209
  const { dependencyIssues, devDependencyIssues, optionalPeerDependencyIssues } = deputy.settleDependencyIssues();
@@ -24,5 +24,6 @@ export declare function build({ chief, collector, counselor, deputy, factory, is
24
24
  analyzedFiles: Set<string>;
25
25
  unreferencedFiles: Set<string>;
26
26
  analyzeSourceFile: (filePath: string, principal: ProjectPrincipal) => void;
27
+ enabledPluginsStore: Map<string, string[]>;
27
28
  }>;
28
29
  export {};
@@ -20,8 +20,9 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
20
20
  const toModuleSourceFilePath = getModuleSourcePathHandler(chief);
21
21
  const toSourceFilePaths = getToSourcePathsHandler(chief);
22
22
  const addIssue = (issue) => collector.addIssue(issue) && options.isWatch && collector.retainIssue(issue);
23
- const externalRefsFromInputs = new Map();
23
+ const externalRefsFromInputs = options.isSession ? new Map() : undefined;
24
24
  const handleInput = createInputHandler(deputy, chief, isGitIgnored, addIssue, externalRefsFromInputs, options);
25
+ const rootManifest = chief.getManifestForWorkspace('.');
25
26
  for (const workspace of workspaces) {
26
27
  const { name, dir, manifestPath, manifestStr } = workspace;
27
28
  const manifest = chief.getManifestForWorkspace(name);
@@ -62,6 +63,7 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
62
63
  config,
63
64
  manifest,
64
65
  dependencies,
66
+ rootManifest,
65
67
  handleInput: (input) => handleInput(input, workspace),
66
68
  findWorkspaceByFilePath: chief.findWorkspaceByFilePath.bind(chief),
67
69
  negatedWorkspacePatterns: chief.getNegatedWorkspacePatterns(name),
@@ -255,6 +257,7 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
255
257
  isFixExports: options.isFixUnusedExports,
256
258
  isFixTypes: options.isFixUnusedTypes,
257
259
  isReportClassMembers: options.isReportClassMembers,
260
+ isReportExports: options.isReportExports,
258
261
  skipTypeOnly: options.isStrict,
259
262
  tags: options.tags,
260
263
  };
@@ -316,6 +319,7 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
316
319
  containingFilePath: filePath,
317
320
  dependencies,
318
321
  manifestScriptNames,
322
+ rootManifest,
319
323
  };
320
324
  const inputs = _getInputsFromScripts(file.scripts, opts);
321
325
  for (const input of inputs) {
@@ -327,7 +331,7 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
327
331
  }
328
332
  }
329
333
  file.imports.unresolved = unresolvedImports;
330
- const pluginRefs = externalRefsFromInputs.get(filePath);
334
+ const pluginRefs = externalRefsFromInputs?.get(filePath);
331
335
  if (pluginRefs)
332
336
  for (const ref of pluginRefs)
333
337
  file.imports.externalRefs.add(ref);
@@ -385,11 +389,13 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
385
389
  }
386
390
  principals.length = 0;
387
391
  }
388
- for (const [filePath, refs] of externalRefsFromInputs) {
389
- if (!graph.has(filePath))
390
- graph.set(filePath, createFileNode());
391
- for (const ref of refs)
392
- graph.get(filePath).imports.externalRefs.add(ref);
392
+ if (externalRefsFromInputs) {
393
+ for (const [filePath, refs] of externalRefsFromInputs) {
394
+ if (!graph.has(filePath))
395
+ graph.set(filePath, createFileNode());
396
+ for (const ref of refs)
397
+ graph.get(filePath).imports.externalRefs.add(ref);
398
+ }
393
399
  }
394
400
  return {
395
401
  graph,
@@ -397,5 +403,6 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
397
403
  analyzedFiles,
398
404
  unreferencedFiles,
399
405
  analyzeSourceFile,
406
+ enabledPluginsStore,
400
407
  };
401
408
  }
package/dist/index.d.ts CHANGED
@@ -5,4 +5,7 @@ export declare const main: (options: MainOptions) => Promise<{
5
5
  tagHints: Set<import("./types/issues.js").TagHint>;
6
6
  configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
7
7
  includedWorkspaceDirs: string[];
8
+ enabledPlugins: {
9
+ [k: string]: string[];
10
+ };
8
11
  }>;
@@ -2,17 +2,16 @@ import parseArgs from 'minimist';
2
2
  import { toEntry } from '../../util/input.js';
3
3
  const title = 'Bun';
4
4
  const enablers = ['bun'];
5
- const isEnabled = () => true;
6
- const config = ['package.json'];
7
- const packageJsonPath = (id) => id;
8
- const resolveConfig = localConfig => {
9
- const scripts = localConfig.scripts;
10
- if (scripts) {
11
- const testScripts = Object.keys(scripts).filter(script => /(?<=^|\s)bun test/.test(scripts[script]));
12
- for (const script of testScripts) {
13
- const parsed = parseArgs(scripts[script].split(' '));
5
+ const hasBunTest = (scripts) => scripts && Object.values(scripts).some(script => /(?<=^|\s)bun test/.test(script));
6
+ const isEnabled = ({ manifest }) => !!hasBunTest(manifest.scripts);
7
+ const patterns = ['**/*.{test,spec}.{js,jsx,ts,tsx}', '**/*_{test,spec}.{js,jsx,ts,tsx}'];
8
+ const resolve = (options) => {
9
+ const scripts = { ...options.rootManifest?.scripts, ...options.manifest.scripts };
10
+ for (const script of Object.values(scripts)) {
11
+ if (/(?<=^|\s)bun test/.test(script)) {
12
+ const parsed = parseArgs(script.split(' '));
14
13
  if (parsed._.filter(id => id !== 'bun' && id !== 'test').length === 0) {
15
- return ['**/*.{test,spec}.{js,jsx,ts,tsx}', '**/*_{test,spec}.{js,jsx,ts,tsx}'].map(toEntry);
14
+ return patterns.map(toEntry);
16
15
  }
17
16
  }
18
17
  }
@@ -22,8 +21,6 @@ const plugin = {
22
21
  title,
23
22
  enablers,
24
23
  isEnabled,
25
- config,
26
- packageJsonPath,
27
- resolveConfig,
24
+ resolve,
28
25
  };
29
26
  export default plugin;
@@ -1,19 +1,18 @@
1
1
  import { toEntry, toProductionEntry } from '../../util/input.js';
2
2
  const title = 'Node.js';
3
3
  const isEnabled = () => true;
4
- const config = ['package.json'];
5
- const packageJsonPath = (id) => id;
6
- const resolveConfig = localConfig => {
7
- const scripts = localConfig.scripts;
8
- const entries = [toProductionEntry('server.js')];
9
- if (scripts && Object.values(scripts).some(script => /(?<=^|\s)node\s(.*)--test/.test(script))) {
10
- const patterns = [
11
- '**/*{.,-,_}test.{cjs,mjs,js,cts,mts,ts}',
12
- '**/test-*.{cjs,mjs,js,cts,mts,ts}',
13
- '**/test.{cjs,mjs,js,cts,mts,ts}',
14
- '**/test/**/*.{cjs,mjs,js,cts,mts,ts}',
15
- ];
16
- entries.push(...patterns.map(id => toEntry(id)));
4
+ const patterns = [
5
+ '**/*{.,-,_}test.{cjs,mjs,js,cts,mts,ts}',
6
+ '**/test-*.{cjs,mjs,js,cts,mts,ts}',
7
+ '**/test.{cjs,mjs,js,cts,mts,ts}',
8
+ '**/test/**/*.{cjs,mjs,js,cts,mts,ts}',
9
+ ];
10
+ const hasNodeTest = (scripts) => scripts && Object.values(scripts).some(script => /(?<=^|\s)node\s(.*)--test/.test(script));
11
+ const entry = ['server.js'];
12
+ const resolve = (options) => {
13
+ const entries = entry.map(id => toProductionEntry(id));
14
+ if (hasNodeTest(options.manifest.scripts) || hasNodeTest(options.rootManifest?.scripts)) {
15
+ entries.push(...patterns.map(toEntry));
17
16
  }
18
17
  return entries;
19
18
  };
@@ -39,9 +38,8 @@ const args = {
39
38
  const plugin = {
40
39
  title,
41
40
  isEnabled,
42
- packageJsonPath,
43
- config,
44
- resolveConfig,
41
+ entry,
42
+ resolve,
45
43
  args,
46
44
  };
47
45
  export default plugin;
@@ -1,3 +1,6 @@
1
1
  import type { Plugin } from '../../types/config.js';
2
+ export declare const docs: {
3
+ note: string;
4
+ };
2
5
  declare const plugin: Plugin;
3
6
  export default plugin;
@@ -51,6 +51,9 @@ const resolveConfig = async (localConfig, options) => {
51
51
  const args = {
52
52
  fromArgs: (parsed) => (parsed._[0] === 'exec' ? parsed._.slice(1) : []),
53
53
  };
54
+ export const docs = {
55
+ note: `Also see [integrated monorepos](/features/integrated-monorepos) and the note regarding internal workspace dependencies.`,
56
+ };
54
57
  const plugin = {
55
58
  title,
56
59
  enablers,
@@ -19,4 +19,4 @@ export declare const finalizeConfigurationHints: (results: Results, options: {
19
19
  cwd: string;
20
20
  configFilePath?: string;
21
21
  }) => ProcessedHint[];
22
- export declare const printConfigurationHints: ({ cwd, counters, issues, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaceDirs, configFilePath, }: ReporterOptions) => void;
22
+ export declare const printConfigurationHints: ({ cwd, counters, issues, tagHints, configurationHints, enabledPlugins, isTreatConfigHintsAsErrors, includedWorkspaceDirs, configFilePath, }: ReporterOptions) => void;
@@ -102,8 +102,8 @@ export const finalizeConfigurationHints = (results, options) => {
102
102
  return row;
103
103
  }));
104
104
  };
105
- export const printConfigurationHints = ({ cwd, counters, issues, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaceDirs, configFilePath, }) => {
106
- const rows = finalizeConfigurationHints({ issues, counters, configurationHints, tagHints, includedWorkspaceDirs }, { cwd, configFilePath });
105
+ export const printConfigurationHints = ({ cwd, counters, issues, tagHints, configurationHints, enabledPlugins, isTreatConfigHintsAsErrors, includedWorkspaceDirs, configFilePath, }) => {
106
+ const rows = finalizeConfigurationHints({ issues, counters, configurationHints, tagHints, includedWorkspaceDirs, enabledPlugins }, { cwd, configFilePath });
107
107
  if (rows.length > 0) {
108
108
  const getTitle = isTreatConfigHintsAsErrors ? getColoredTitle : getDimmedTitle;
109
109
  console.log(getTitle('Configuration hints', configurationHints.size));
package/dist/run.d.ts CHANGED
@@ -8,6 +8,9 @@ export declare const run: (options: MainOptions) => Promise<{
8
8
  tagHints: Set<import("./types/issues.js").TagHint>;
9
9
  configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
10
10
  includedWorkspaceDirs: string[];
11
+ enabledPlugins: {
12
+ [k: string]: string[];
13
+ };
11
14
  };
12
15
  session: {
13
16
  listener: import("fs").WatchListener<string | Buffer<ArrayBufferLike>>;
package/dist/run.js CHANGED
@@ -29,7 +29,7 @@ export const run = async (options) => {
29
29
  collector.setIgnoreIssues(chief.config.ignoreIssues);
30
30
  debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
31
31
  debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
32
- const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
32
+ const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile, enabledPluginsStore } = await build({
33
33
  chief,
34
34
  collector,
35
35
  counselor,
@@ -100,6 +100,7 @@ export const run = async (options) => {
100
100
  tagHints,
101
101
  configurationHints,
102
102
  includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
103
+ enabledPlugins: Object.fromEntries(enabledPluginsStore),
103
104
  },
104
105
  session,
105
106
  streamer,
@@ -33,6 +33,7 @@ export type GetImportsAndExportsOptions = {
33
33
  isFixExports: boolean;
34
34
  isFixTypes: boolean;
35
35
  isReportClassMembers: boolean;
36
+ isReportExports: boolean;
36
37
  tags: Tags;
37
38
  };
38
39
  export interface Configuration {
@@ -72,6 +73,7 @@ interface BaseOptions {
72
73
  rootCwd: string;
73
74
  cwd: string;
74
75
  manifestScriptNames: Set<string>;
76
+ rootManifest: PackageJson | undefined;
75
77
  }
76
78
  type IsPluginEnabledOptions = {
77
79
  cwd: string;
@@ -55,6 +55,7 @@ export type ReporterOptions = {
55
55
  counters: Counters;
56
56
  tagHints: TagHints;
57
57
  configurationHints: Set<ConfigurationHint>;
58
+ enabledPlugins: Record<string, string[]>;
58
59
  isDisableConfigHints: boolean;
59
60
  isTreatConfigHintsAsErrors: boolean;
60
61
  cwd: string;
@@ -2,4 +2,4 @@ import ts from 'typescript';
2
2
  import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile } from '../types/config.js';
3
3
  import type { FileNode } from '../types/module-graph.js';
4
4
  import type { BoundSourceFile } from './SourceFile.js';
5
- export declare const _getImportsAndExports: (sourceFile: BoundSourceFile, resolveModule: (specifier: string) => ts.ResolvedModuleFull | undefined, typeChecker: ts.TypeChecker, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile, skipExports: boolean) => FileNode;
5
+ export declare const _getImportsAndExports: (sourceFile: BoundSourceFile, resolveModule: (specifier: string) => ts.ResolvedModuleFull | undefined, typeChecker: ts.TypeChecker, options: GetImportsAndExportsOptions, ignoreExportsUsedInFile: IgnoreExportsUsedInFile, skipExportsForFile: boolean) => FileNode;
@@ -34,7 +34,8 @@ const createMember = (node, member, pos) => {
34
34
  flags: member.flags,
35
35
  };
36
36
  };
37
- const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, ignoreExportsUsedInFile, skipExports) => {
37
+ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, ignoreExportsUsedInFile, skipExportsForFile) => {
38
+ const skipExports = skipExportsForFile || !options.isReportExports;
38
39
  const internal = new Map();
39
40
  const external = new Set();
40
41
  const unresolved = new Set();
@@ -197,8 +198,6 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
197
198
  }
198
199
  };
199
200
  const addExport = ({ node, symbol, identifier, type, pos, members, fix }) => {
200
- if (skipExports)
201
- return;
202
201
  let isReExport = Boolean(node.parent?.parent && ts.isExportDeclaration(node.parent.parent) && node.parent.parent.moduleSpecifier);
203
202
  if (symbol) {
204
203
  const importedSymbolFilePath = importedInternalSymbols.get(symbol);
@@ -266,9 +265,11 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
266
265
  const result = visitor(node, options);
267
266
  result && (Array.isArray(result) ? result.forEach(addImportWithNode) : addImportWithNode(result));
268
267
  }
269
- for (const visitor of visitors.export) {
270
- const result = visitor(node, options);
271
- result && (Array.isArray(result) ? result.forEach(addExport) : addExport(result));
268
+ if (!skipExports) {
269
+ for (const visitor of visitors.export) {
270
+ const result = visitor(node, options);
271
+ result && (Array.isArray(result) ? result.forEach(addExport) : addExport(result));
272
+ }
272
273
  }
273
274
  if (ts.isImportEqualsDeclaration(node) &&
274
275
  ts.isQualifiedName(node.moduleReference) &&
@@ -5,4 +5,4 @@ import type { ExternalRef } from '../types/module-graph.js';
5
5
  import type { MainOptions } from './create-options.js';
6
6
  import { type Input } from './input.js';
7
7
  export type ExternalRefsFromInputs = Map<string, Set<ExternalRef>>;
8
- export declare const createInputHandler: (deputy: DependencyDeputy, chief: ConfigurationChief, isGitIgnored: (filePath: string) => boolean, addIssue: (issue: Issue) => void, externalRefs: ExternalRefsFromInputs, options: MainOptions) => (input: Input, workspace: Workspace) => string | undefined;
8
+ export declare const createInputHandler: (deputy: DependencyDeputy, chief: ConfigurationChief, isGitIgnored: (filePath: string) => boolean, addIssue: (issue: Issue) => void, externalRefs: ExternalRefsFromInputs | undefined, options: MainOptions) => (input: Input, workspace: Workspace) => string | undefined;
@@ -21,8 +21,10 @@ export const createInputHandler = (deputy, chief, isGitIgnored, addIssue, extern
21
21
  const inputWorkspace = getWorkspaceFor(input, chief, workspace);
22
22
  const dependencies = deputy.maybeAddReferencedBinary(inputWorkspace, binaryName);
23
23
  if (dependencies) {
24
- for (const dependency of dependencies) {
25
- addExternalRef(externalRefs, containingFilePath, { specifier: dependency, identifier: binaryName });
24
+ if (externalRefs) {
25
+ for (const dependency of dependencies) {
26
+ addExternalRef(externalRefs, containingFilePath, { specifier: dependency, identifier: binaryName });
27
+ }
26
28
  }
27
29
  return;
28
30
  }
@@ -44,7 +46,7 @@ export const createInputHandler = (deputy, chief, isGitIgnored, addIssue, extern
44
46
  const inputWorkspace = getWorkspaceFor(input, chief, workspace);
45
47
  if (inputWorkspace) {
46
48
  const isHandled = deputy.maybeAddReferencedExternalDependency(inputWorkspace, packageName);
47
- if (!isWorkspace) {
49
+ if (externalRefs && !isWorkspace) {
48
50
  addExternalRef(externalRefs, containingFilePath, { specifier: packageName, identifier: undefined });
49
51
  }
50
52
  if (isWorkspace || isDependency(input)) {
@@ -31,6 +31,8 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
31
31
  isProduction: boolean;
32
32
  isReportClassMembers: boolean;
33
33
  isReportDependencies: boolean;
34
+ isReportExports: boolean;
35
+ isReportFiles: boolean;
34
36
  isReportTypes: boolean;
35
37
  isReportValues: boolean;
36
38
  isSession: boolean;
@@ -101,6 +101,14 @@ export const createOptions = async (options) => {
101
101
  includedIssueTypes.unlisted ||
102
102
  includedIssueTypes.unresolved ||
103
103
  includedIssueTypes.binaries,
104
+ isReportExports: includedIssueTypes.exports ||
105
+ includedIssueTypes.types ||
106
+ includedIssueTypes.nsExports ||
107
+ includedIssueTypes.nsTypes ||
108
+ includedIssueTypes.enumMembers ||
109
+ includedIssueTypes.duplicates ||
110
+ isReportClassMembers,
111
+ isReportFiles: includedIssueTypes.files,
104
112
  isReportTypes: includedIssueTypes.types || includedIssueTypes.nsTypes || includedIssueTypes.enumMembers,
105
113
  isReportValues: includedIssueTypes.exports || includedIssueTypes.nsExports || isReportClassMembers,
106
114
  isSession: options.isSession ?? false,
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.76.1";
1
+ export declare const version = "5.76.3";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.76.1';
1
+ export const version = '5.76.3';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.76.1",
3
+ "version": "5.76.3",
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": {