knip 2.1.2 → 2.2.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 (116) hide show
  1. package/dist/{configuration-chief.js → ConfigurationChief.js} +39 -38
  2. package/dist/{dependency-deputy.d.ts → DependencyDeputy.d.ts} +4 -2
  3. package/dist/{dependency-deputy.js → DependencyDeputy.js} +29 -10
  4. package/dist/{principal-factory.d.ts → PrincipalFactory.d.ts} +1 -1
  5. package/dist/{principal-factory.js → PrincipalFactory.js} +1 -1
  6. package/dist/{project-principal.d.ts → ProjectPrincipal.d.ts} +7 -4
  7. package/dist/{project-principal.js → ProjectPrincipal.js} +6 -4
  8. package/dist/{workspace-worker.d.ts → WorkspaceWorker.d.ts} +1 -1
  9. package/dist/{workspace-worker.js → WorkspaceWorker.js} +0 -2
  10. package/dist/binaries/index.d.ts +2 -2
  11. package/dist/binaries/index.js +12 -16
  12. package/dist/binaries/resolvers/fallback.js +8 -4
  13. package/dist/binaries/resolvers/npx.js +3 -1
  14. package/dist/binaries/types.d.ts +1 -5
  15. package/dist/cli.js +1 -1
  16. package/dist/index.js +56 -46
  17. package/dist/manifest/index.d.ts +1 -3
  18. package/dist/manifest/index.js +11 -25
  19. package/dist/plugins/_template/index.js +1 -1
  20. package/dist/plugins/ava/index.js +4 -6
  21. package/dist/plugins/babel/index.js +1 -1
  22. package/dist/plugins/capacitor/index.js +1 -1
  23. package/dist/plugins/changesets/index.js +1 -1
  24. package/dist/plugins/commitizen/index.js +1 -1
  25. package/dist/plugins/commitlint/index.js +1 -1
  26. package/dist/plugins/cspell/index.js +1 -1
  27. package/dist/plugins/eslint/index.js +1 -1
  28. package/dist/plugins/gatsby/index.js +1 -1
  29. package/dist/plugins/github-actions/index.js +4 -6
  30. package/dist/plugins/husky/index.js +4 -6
  31. package/dist/plugins/jest/index.js +1 -1
  32. package/dist/plugins/lefthook/index.js +4 -6
  33. package/dist/plugins/lint-staged/index.js +7 -7
  34. package/dist/plugins/markdownlint/index.js +1 -1
  35. package/dist/plugins/mocha/index.js +1 -1
  36. package/dist/plugins/npm-package-json-lint/index.js +1 -1
  37. package/dist/plugins/nx/index.js +4 -4
  38. package/dist/plugins/nyc/index.js +1 -1
  39. package/dist/plugins/postcss/index.js +1 -1
  40. package/dist/plugins/prettier/index.js +1 -1
  41. package/dist/plugins/release-it/index.js +4 -4
  42. package/dist/plugins/remark/index.js +1 -1
  43. package/dist/plugins/semantic-release/index.js +1 -1
  44. package/dist/plugins/storybook/index.js +1 -1
  45. package/dist/plugins/stryker/index.js +1 -1
  46. package/dist/plugins/tailwind/index.js +1 -1
  47. package/dist/plugins/typedoc/index.js +1 -1
  48. package/dist/plugins/typescript/index.js +1 -1
  49. package/dist/plugins/vitest/index.js +1 -1
  50. package/dist/plugins/webpack/index.js +1 -1
  51. package/dist/types/config.d.ts +1 -1
  52. package/dist/types/{ast.d.ts → exports.d.ts} +0 -10
  53. package/dist/types/imports.d.ts +13 -0
  54. package/dist/types/imports.js +1 -0
  55. package/dist/types/plugins.d.ts +1 -2
  56. package/dist/types/workspace.d.ts +1 -0
  57. package/dist/typescript/SourceFile.d.ts +1 -0
  58. package/dist/typescript/getImportsAndExports.d.ts +28 -0
  59. package/dist/typescript/getImportsAndExports.js +157 -0
  60. package/dist/typescript/visitors/exports/exportAssignment.d.ts +3 -0
  61. package/dist/typescript/visitors/exports/exportAssignment.js +8 -0
  62. package/dist/typescript/visitors/exports/exportDeclaration.d.ts +3 -0
  63. package/dist/typescript/visitors/exports/exportDeclaration.js +13 -0
  64. package/dist/typescript/visitors/exports/exportKeyword.d.ts +3 -0
  65. package/dist/typescript/visitors/exports/exportKeyword.js +77 -0
  66. package/dist/typescript/visitors/exports/index.d.ts +3 -0
  67. package/dist/typescript/visitors/exports/index.js +6 -0
  68. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.d.ts +3 -0
  69. package/dist/typescript/visitors/exports/moduleExportsAccessExpression.js +31 -0
  70. package/dist/typescript/visitors/helpers.d.ts +3 -0
  71. package/dist/typescript/visitors/helpers.js +3 -0
  72. package/dist/typescript/visitors/imports/importCall.d.ts +3 -0
  73. package/dist/typescript/visitors/imports/importCall.js +38 -0
  74. package/dist/typescript/visitors/imports/importDeclaration.d.ts +3 -0
  75. package/dist/typescript/visitors/imports/importDeclaration.js +32 -0
  76. package/dist/typescript/visitors/imports/importEqualsDeclaration.d.ts +3 -0
  77. package/dist/typescript/visitors/imports/importEqualsDeclaration.js +11 -0
  78. package/dist/typescript/visitors/imports/index.d.ts +3 -0
  79. package/dist/typescript/visitors/imports/index.js +17 -0
  80. package/dist/typescript/visitors/imports/jsDocType.d.ts +3 -0
  81. package/dist/typescript/visitors/imports/jsDocType.js +11 -0
  82. package/dist/typescript/visitors/imports/reExportDeclaration.d.ts +3 -0
  83. package/dist/typescript/visitors/imports/reExportDeclaration.js +21 -0
  84. package/dist/typescript/visitors/imports/requireCall.d.ts +3 -0
  85. package/dist/typescript/visitors/imports/requireCall.js +46 -0
  86. package/dist/typescript/visitors/imports/requireResolveCall.d.ts +3 -0
  87. package/dist/typescript/visitors/imports/requireResolveCall.js +14 -0
  88. package/dist/typescript/visitors/index.d.ts +10 -0
  89. package/dist/typescript/visitors/index.js +15 -0
  90. package/dist/typescript/visitors/scripts/index.d.ts +3 -0
  91. package/dist/typescript/visitors/scripts/index.js +3 -0
  92. package/dist/typescript/visitors/scripts/zx.d.ts +3 -0
  93. package/dist/typescript/visitors/scripts/zx.js +8 -0
  94. package/dist/util/array.d.ts +0 -1
  95. package/dist/util/array.js +0 -7
  96. package/dist/util/compilers.d.ts +5 -4
  97. package/dist/util/compilers.js +1 -3
  98. package/dist/util/glob.js +1 -1
  99. package/dist/util/loader.js +1 -1
  100. package/dist/util/plugin.js +1 -1
  101. package/dist/util/require.js +1 -1
  102. package/dist/version.d.ts +1 -1
  103. package/dist/version.js +1 -1
  104. package/package.json +4 -4
  105. package/dist/typescript/ast-walker.d.ts +0 -16
  106. package/dist/typescript/ast-walker.js +0 -364
  107. package/dist/{configuration-chief.d.ts → ConfigurationChief.d.ts} +0 -0
  108. package/dist/{configuration-validator.d.ts → ConfigurationValidator.d.ts} +6 -6
  109. /package/dist/{configuration-validator.js → ConfigurationValidator.js} +0 -0
  110. /package/dist/{console-streamer.d.ts → ConsoleStreamer.d.ts} +0 -0
  111. /package/dist/{console-streamer.js → ConsoleStreamer.js} +0 -0
  112. /package/dist/{issue-collector.d.ts → IssueCollector.d.ts} +0 -0
  113. /package/dist/{issue-collector.js → IssueCollector.js} +0 -0
  114. /package/dist/types/{ast.js → exports.js} +0 -0
  115. /package/dist/util/{performance.d.ts → Performance.d.ts} +0 -0
  116. /package/dist/util/{performance.js → Performance.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  import mapWorkspaces from '@npmcli/map-workspaces';
2
2
  import micromatch from 'micromatch';
3
- import { ConfigurationValidator } from './configuration-validator.js';
3
+ import { ConfigurationValidator } from './ConfigurationValidator.js';
4
4
  import { ROOT_WORKSPACE_NAME, DEFAULT_EXTENSIONS, KNIP_CONFIG_LOCATIONS } from './constants.js';
5
5
  import * as plugins from './plugins/index.js';
6
6
  import { arrayify, compact } from './util/array.js';
@@ -88,7 +88,7 @@ export class ConfigurationChief {
88
88
  return [this.config.syncCompilers, this.config.asyncCompilers];
89
89
  }
90
90
  normalize(rawLocalConfig) {
91
- const workspaces = rawLocalConfig.workspaces ?? {
91
+ const initialWorkspaces = rawLocalConfig.workspaces ?? {
92
92
  [ROOT_WORKSPACE_NAME]: {
93
93
  ...rawLocalConfig,
94
94
  },
@@ -102,6 +102,42 @@ export class ConfigurationChief {
102
102
  const { syncCompilers, asyncCompilers } = rawLocalConfig;
103
103
  const extensions = [...Object.keys(syncCompilers ?? {}), ...Object.keys(asyncCompilers ?? {})];
104
104
  const defaultWorkspaceConfig = getDefaultWorkspaceConfig(extensions);
105
+ const workspaces = Object.entries(initialWorkspaces)
106
+ .filter(([workspaceName]) => !ignoreWorkspaces.includes(workspaceName))
107
+ .reduce((workspaces, workspace) => {
108
+ const [workspaceName, workspaceConfig] = workspace;
109
+ const entry = workspaceConfig.entry ? arrayify(workspaceConfig.entry) : defaultWorkspaceConfig.entry;
110
+ const project = workspaceConfig.project ? arrayify(workspaceConfig.project) : defaultWorkspaceConfig.project;
111
+ const paths = workspaceConfig.paths ?? defaultWorkspaceConfig.paths;
112
+ workspaces[workspaceName] = {
113
+ entry,
114
+ project,
115
+ paths,
116
+ ignore: arrayify(workspaceConfig.ignore),
117
+ ignoreBinaries: compact([...ignoreBinaries, ...arrayify(workspaceConfig.ignoreBinaries)]),
118
+ ignoreDependencies: compact([...ignoreDependencies, ...arrayify(workspaceConfig.ignoreDependencies)]),
119
+ };
120
+ for (const [name, pluginConfig] of Object.entries(workspaceConfig)) {
121
+ const pluginName = toCamelCase(name);
122
+ if (PLUGIN_NAMES.includes(pluginName)) {
123
+ if (pluginConfig === false) {
124
+ workspaces[workspaceName][pluginName] = false;
125
+ }
126
+ else {
127
+ const isObject = typeof pluginConfig !== 'string' && !Array.isArray(pluginConfig);
128
+ const config = isObject ? arrayify(pluginConfig.config) : pluginConfig ? arrayify(pluginConfig) : null;
129
+ const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : null;
130
+ const project = isObject && 'project' in pluginConfig ? arrayify(pluginConfig.project) : entry;
131
+ workspaces[workspaceName][pluginName] = {
132
+ config,
133
+ entry,
134
+ project,
135
+ };
136
+ }
137
+ }
138
+ }
139
+ return workspaces;
140
+ }, {});
105
141
  return {
106
142
  include,
107
143
  exclude,
@@ -109,42 +145,7 @@ export class ConfigurationChief {
109
145
  ignoreWorkspaces,
110
146
  syncCompilers: new Map(Object.entries(syncCompilers ?? {})),
111
147
  asyncCompilers: new Map(Object.entries(asyncCompilers ?? {})),
112
- workspaces: Object.entries(workspaces)
113
- .filter(([workspaceName]) => !ignoreWorkspaces.includes(workspaceName))
114
- .reduce((workspaces, workspace) => {
115
- const [workspaceName, workspaceConfig] = workspace;
116
- const entry = workspaceConfig.entry ? arrayify(workspaceConfig.entry) : defaultWorkspaceConfig.entry;
117
- const project = workspaceConfig.project ? arrayify(workspaceConfig.project) : defaultWorkspaceConfig.project;
118
- const paths = workspaceConfig.paths ?? defaultWorkspaceConfig.paths;
119
- workspaces[workspaceName] = {
120
- entry,
121
- project,
122
- paths,
123
- ignore: arrayify(workspaceConfig.ignore),
124
- ignoreBinaries: compact([...ignoreBinaries, ...arrayify(workspaceConfig.ignoreBinaries)]),
125
- ignoreDependencies: compact([...ignoreDependencies, ...arrayify(workspaceConfig.ignoreDependencies)]),
126
- };
127
- for (const [name, pluginConfig] of Object.entries(workspaceConfig)) {
128
- const pluginName = toCamelCase(name);
129
- if (PLUGIN_NAMES.includes(pluginName)) {
130
- if (pluginConfig === false) {
131
- workspaces[workspaceName][pluginName] = false;
132
- }
133
- else {
134
- const isObject = typeof pluginConfig !== 'string' && !Array.isArray(pluginConfig);
135
- const config = isObject ? arrayify(pluginConfig.config) : pluginConfig ? arrayify(pluginConfig) : null;
136
- const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : null;
137
- const project = isObject && 'project' in pluginConfig ? arrayify(pluginConfig.project) : entry;
138
- workspaces[workspaceName][pluginName] = {
139
- config,
140
- entry,
141
- project,
142
- };
143
- }
144
- }
145
- }
146
- return workspaces;
147
- }, {}),
148
+ workspaces,
148
149
  };
149
150
  }
150
151
  async setWorkspaces() {
@@ -1,4 +1,4 @@
1
- import { Workspace } from './configuration-chief.js';
1
+ import { Workspace } from './ConfigurationChief.js';
2
2
  import type { Issue } from './types/issues.js';
3
3
  import type { WorkspaceManifests } from './types/workspace.js';
4
4
  import type { PeerDependencies, InstalledBinaries } from './types/workspace.js';
@@ -13,12 +13,13 @@ export declare class DependencyDeputy {
13
13
  peerDependencies: Map<string, PeerDependencies>;
14
14
  installedBinaries: Map<string, InstalledBinaries>;
15
15
  constructor({ isStrict }: Options);
16
- addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, }: {
16
+ addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries, }: {
17
17
  name: string;
18
18
  dir: string;
19
19
  manifestPath: string;
20
20
  manifest: PackageJson;
21
21
  ignoreDependencies: string[];
22
+ ignoreBinaries: string[];
22
23
  }): void;
23
24
  getWorkspaceManifest(workspaceName: string): {
24
25
  workspaceDir: string;
@@ -30,6 +31,7 @@ export declare class DependencyDeputy {
30
31
  devDependencies: string[];
31
32
  allDependencies: string[];
32
33
  ignoreDependencies: string[];
34
+ ignoreBinaries: string[];
33
35
  } | undefined;
34
36
  getProductionDependencies(workspaceName: string): string[];
35
37
  getDevDependencies(workspaceName: string): string[];
@@ -1,5 +1,5 @@
1
1
  import { isBuiltin } from 'node:module';
2
- import { IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES } from './constants.js';
2
+ import { IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_GLOBAL_BINARIES } from './constants.js';
3
3
  import { isDefinitelyTyped, getDefinitelyTypedFor, getPackageFromDefinitelyTyped } from './util/modules.js';
4
4
  export class DependencyDeputy {
5
5
  isStrict;
@@ -13,7 +13,7 @@ export class DependencyDeputy {
13
13
  this.peerDependencies = new Map();
14
14
  this.installedBinaries = new Map();
15
15
  }
16
- addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, }) {
16
+ addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries, }) {
17
17
  const scripts = Object.values(manifest.scripts ?? {});
18
18
  const dependencies = Object.keys(manifest.dependencies ?? {});
19
19
  const peerDependencies = Object.keys(manifest.peerDependencies ?? {});
@@ -24,6 +24,7 @@ export class DependencyDeputy {
24
24
  workspaceDir: dir,
25
25
  manifestPath,
26
26
  ignoreDependencies,
27
+ ignoreBinaries,
27
28
  scripts,
28
29
  dependencies,
29
30
  peerDependencies,
@@ -80,6 +81,10 @@ export class DependencyDeputy {
80
81
  closestWorkspaceNameForTypes && this.addReferencedDependency(closestWorkspaceNameForTypes, typesPackageName);
81
82
  return true;
82
83
  }
84
+ if (IGNORED_GLOBAL_BINARIES.includes(packageName))
85
+ return true;
86
+ if (this.getWorkspaceManifest(workspace.name)?.ignoreBinaries.includes(packageName))
87
+ return true;
83
88
  for (const name of workspaceNames) {
84
89
  const binaries = this.getInstalledBinaries(name);
85
90
  if (binaries?.has(packageName)) {
@@ -102,9 +107,21 @@ export class DependencyDeputy {
102
107
  settleDependencyIssues() {
103
108
  const dependencyIssues = [];
104
109
  const devDependencyIssues = [];
105
- for (const [workspaceName, { manifestPath, ignoreDependencies }] of this._manifests.entries()) {
110
+ for (const [workspaceName, { manifestPath, ignoreDependencies, ignoreBinaries }] of this._manifests.entries()) {
106
111
  const referencedDependencies = this.referencedDependencies.get(workspaceName);
107
- const isUnreferencedDependency = (dependency) => {
112
+ const installedBinaries = this.getInstalledBinaries(workspaceName);
113
+ const ignoreBins = [...IGNORED_GLOBAL_BINARIES, ...ignoreBinaries];
114
+ const ignoreDeps = [...IGNORED_DEPENDENCIES, ...ignoreDependencies];
115
+ const isNotIgnoredDependency = (packageName) => !ignoreDeps.includes(packageName);
116
+ const isNotIgnoredBinary = (packageName) => {
117
+ if (installedBinaries?.has(packageName)) {
118
+ const binaryNames = installedBinaries.get(packageName);
119
+ if (binaryNames && ignoreBins.some(ignoredBinary => binaryNames.has(ignoredBinary)))
120
+ return false;
121
+ }
122
+ return true;
123
+ };
124
+ const isNotReferencedDependency = (dependency) => {
108
125
  if (referencedDependencies?.has(dependency))
109
126
  return false;
110
127
  const [scope, typedDependency] = dependency.split('/');
@@ -114,23 +131,25 @@ export class DependencyDeputy {
114
131
  return false;
115
132
  const peerDependencies = this.getPeerDependencies(workspaceName, typedPackageName);
116
133
  if (peerDependencies.length) {
117
- return !peerDependencies.find(peerDependency => !isUnreferencedDependency(peerDependency));
134
+ return !peerDependencies.find(peerDependency => !isNotReferencedDependency(peerDependency));
118
135
  }
119
136
  return !referencedDependencies?.has(typedPackageName);
120
137
  }
121
138
  if (!referencedDependencies?.has(dependency)) {
122
139
  const peerDependencies = this.getPeerDependencies(workspaceName, dependency);
123
- return !peerDependencies.find(peerDependency => !isUnreferencedDependency(peerDependency));
140
+ return !peerDependencies.find(peerDependency => !isNotReferencedDependency(peerDependency));
124
141
  }
125
142
  return false;
126
143
  };
127
144
  this.getProductionDependencies(workspaceName)
128
- .filter(symbol => !IGNORED_DEPENDENCIES.includes(symbol) && !ignoreDependencies.includes(symbol))
129
- .filter(isUnreferencedDependency)
145
+ .filter(isNotIgnoredDependency)
146
+ .filter(isNotIgnoredBinary)
147
+ .filter(isNotReferencedDependency)
130
148
  .forEach(symbol => dependencyIssues.push({ type: 'dependencies', filePath: manifestPath, symbol }));
131
149
  this.getDevDependencies(workspaceName)
132
- .filter(symbol => !IGNORED_DEPENDENCIES.includes(symbol) && !ignoreDependencies.includes(symbol))
133
- .filter(isUnreferencedDependency)
150
+ .filter(isNotIgnoredDependency)
151
+ .filter(isNotIgnoredBinary)
152
+ .filter(isNotReferencedDependency)
134
153
  .forEach(symbol => devDependencyIssues.push({ type: 'devDependencies', filePath: manifestPath, symbol }));
135
154
  }
136
155
  return { dependencyIssues, devDependencyIssues };
@@ -1,5 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { ProjectPrincipal } from './project-principal.js';
2
+ import { ProjectPrincipal } from './ProjectPrincipal.js';
3
3
  import type { SyncCompilers, AsyncCompilers } from './types/compilers.js';
4
4
  import type { Report } from './types/issues.js';
5
5
  type Paths = ts.CompilerOptions['paths'];
@@ -1,4 +1,4 @@
1
- import { ProjectPrincipal } from './project-principal.js';
1
+ import { ProjectPrincipal } from './ProjectPrincipal.js';
2
2
  import { join, isAbsolute } from './util/path.js';
3
3
  const mergePaths = (cwd, compilerOptions, paths = {}) => {
4
4
  const overridePaths = Object.keys(paths).reduce((overridePaths, key) => {
@@ -1,7 +1,7 @@
1
1
  import ts from 'typescript';
2
2
  import { SourceFileManager } from './typescript/SourceFileManager.js';
3
- import type { ExportItem, ExportItemMember } from './types/ast.js';
4
3
  import type { SyncCompilers, AsyncCompilers } from './types/compilers.js';
4
+ import type { ExportItem, ExportItemMember } from './types/exports.js';
5
5
  import type { Report } from './types/issues.js';
6
6
  type ProjectPrincipalOptions = {
7
7
  compilerOptions: ts.CompilerOptions;
@@ -39,12 +39,15 @@ export declare class ProjectPrincipal {
39
39
  getUnreferencedFiles(): string[];
40
40
  analyzeSourceFile(filePath: string): {
41
41
  imports: {
42
- internal: import("./types/ast.js").Imports;
42
+ internal: import("./types/imports.js").Imports;
43
43
  unresolved: Set<string>;
44
44
  external: Set<string>;
45
45
  };
46
- exports: import("./types/ast.js").ExportItems;
47
- duplicateExports: string[][];
46
+ exports: {
47
+ exported: import("./types/exports.js").ExportItems;
48
+ duplicate: string[][];
49
+ };
50
+ scripts: Set<string>;
48
51
  };
49
52
  private resolveModule;
50
53
  hasExternalReferences(filePath: string, exportedItem: ExportItem): boolean;
@@ -1,10 +1,10 @@
1
1
  import ts from 'typescript';
2
2
  import { DEFAULT_EXTENSIONS } from './constants.js';
3
3
  import { IGNORED_FILE_EXTENSIONS } from './constants.js';
4
- import { getImportsAndExports } from './typescript/ast-walker.js';
5
4
  import { createHosts } from './typescript/createHosts.js';
5
+ import { getImportsAndExports } from './typescript/getImportsAndExports.js';
6
6
  import { extname, isInNodeModules } from './util/path.js';
7
- import { timerify } from './util/performance.js';
7
+ import { timerify } from './util/Performance.js';
8
8
  const baseCompilerOptions = {
9
9
  allowJs: true,
10
10
  jsx: ts.JsxEmit.Preserve,
@@ -109,7 +109,7 @@ export class ProjectPrincipal {
109
109
  throw new Error(`Unable to find ${filePath}`);
110
110
  const skipTypeOnly = !this.isReportTypes;
111
111
  const skipExports = this.skipExportsAnalysis.has(filePath);
112
- const { imports, exports, duplicateExports } = getImportsAndExports(sourceFile, { skipTypeOnly, skipExports });
112
+ const { imports, exports, scripts } = getImportsAndExports(sourceFile, { skipTypeOnly, skipExports });
113
113
  const { internal, unresolved, external } = imports;
114
114
  const unresolvedImports = new Set();
115
115
  unresolved.forEach(specifier => {
@@ -144,7 +144,7 @@ export class ProjectPrincipal {
144
144
  external,
145
145
  },
146
146
  exports,
147
- duplicateExports,
147
+ scripts,
148
148
  };
149
149
  }
150
150
  resolveModule(specifier, filePath = specifier) {
@@ -159,6 +159,8 @@ export class ProjectPrincipal {
159
159
  findUnusedMembers(filePath, members) {
160
160
  return members
161
161
  .filter(member => {
162
+ if (this.isPublicExport(member))
163
+ return false;
162
164
  const referencedSymbols = this.findReferences(filePath, member.node);
163
165
  const files = referencedSymbols
164
166
  .flatMap(refs => refs.references)
@@ -50,7 +50,7 @@ export declare class WorkspaceWorker {
50
50
  peerDependencies: PeerDependencies;
51
51
  installedBinaries: InstalledBinaries;
52
52
  referencedDependencies: ReferencedDependencies;
53
- enabledPlugins: ("typescript" | "ava" | "babel" | "capacitor" | "changesets" | "commitizen" | "commitlint" | "cspell" | "cypress" | "eslint" | "gatsby" | "husky" | "jest" | "lefthook" | "markdownlint" | "mocha" | "next" | "nx" | "nyc" | "playwright" | "postcss" | "prettier" | "remark" | "remix" | "rollup" | "sentry" | "storybook" | "stryker" | "tailwind" | "typedoc" | "vite" | "vitest" | "webpack" | "githubActions" | "lintStaged" | "npmPackageJsonLint" | "releaseIt" | "semanticRelease" | "svelte")[];
53
+ enabledPlugins: ("ava" | "babel" | "capacitor" | "changesets" | "commitizen" | "commitlint" | "cspell" | "cypress" | "eslint" | "gatsby" | "husky" | "jest" | "lefthook" | "markdownlint" | "mocha" | "next" | "nx" | "nyc" | "playwright" | "postcss" | "prettier" | "remark" | "remix" | "rollup" | "sentry" | "storybook" | "stryker" | "tailwind" | "typedoc" | "typescript" | "vite" | "vitest" | "webpack" | "githubActions" | "lintStaged" | "npmPackageJsonLint" | "releaseIt" | "semanticRelease" | "svelte")[];
54
54
  }>;
55
55
  }
56
56
  export {};
@@ -58,7 +58,6 @@ export class WorkspaceWorker {
58
58
  }
59
59
  async initReferencedDependencies() {
60
60
  const { dependencies, peerDependencies, installedBinaries } = await npm.findDependencies({
61
- config: this.config,
62
61
  manifest: this.manifest,
63
62
  isProduction: this.isProduction,
64
63
  isStrict: this.isStrict,
@@ -218,7 +217,6 @@ export class WorkspaceWorker {
218
217
  cwd,
219
218
  manifest: this.manifest,
220
219
  config: pluginConfig,
221
- workspaceConfig: this.config,
222
220
  isProduction: this.isProduction,
223
221
  });
224
222
  dependencies.forEach(specifier => {
@@ -1,2 +1,2 @@
1
- import type { GetReferencesFromScripts } from './types.js';
2
- export declare const _getReferencesFromScripts: GetReferencesFromScripts;
1
+ import type { GetDependenciesFromScripts } from './types.js';
2
+ export declare const _getDependenciesFromScripts: GetDependenciesFromScripts;
@@ -1,23 +1,19 @@
1
- import { IGNORED_GLOBAL_BINARIES } from '../constants.js';
2
1
  import { compact } from '../util/array.js';
3
- import { partition } from '../util/array.js';
4
2
  import { getPackageNameFromModuleSpecifier, stripBinary } from '../util/modules.js';
5
3
  import { isInternal } from '../util/path.js';
6
- import { timerify } from '../util/performance.js';
4
+ import { timerify } from '../util/Performance.js';
7
5
  import { getBinariesFromScript } from './bash-parser.js';
8
6
  const defaultCwd = process.cwd();
9
- const getReferencesFromScripts = (npmScripts, options = {}) => {
10
- const { cwd = defaultCwd, manifest = {}, ignore = [], knownGlobalsOnly = false } = options;
11
- const scripts = [npmScripts].flat();
7
+ const getDependenciesFromScripts = (npmScripts, options = {}) => {
8
+ const { cwd = defaultCwd, manifest = {}, knownGlobalsOnly = false } = options;
9
+ const scripts = typeof npmScripts === 'string' ? [npmScripts] : [...npmScripts];
12
10
  const results = scripts.flatMap(script => getBinariesFromScript(script, { cwd, manifest, knownGlobalsOnly }));
13
- const [entryFiles, binaries] = partition(compact(results), isInternal);
14
- return {
15
- entryFiles,
16
- binaries: binaries
17
- .map(stripBinary)
18
- .map(getPackageNameFromModuleSpecifier)
19
- .filter(binaryName => !binaryName.startsWith('.'))
20
- .filter(binaryName => !IGNORED_GLOBAL_BINARIES.includes(binaryName) && !ignore.includes(binaryName)),
21
- };
11
+ return compact(results.map(identifier => {
12
+ if (isInternal(identifier))
13
+ return identifier;
14
+ const packageName = getPackageNameFromModuleSpecifier(stripBinary(identifier));
15
+ if (!packageName.startsWith('.'))
16
+ return packageName;
17
+ }));
22
18
  };
23
- export const _getReferencesFromScripts = timerify(getReferencesFromScripts);
19
+ export const _getDependenciesFromScripts = timerify(getDependenciesFromScripts);
@@ -1,14 +1,18 @@
1
1
  import parseArgs from 'minimist';
2
2
  import { compact } from '../../util/array.js';
3
3
  import { tryResolveFilePaths } from './util.js';
4
+ const withPositional = parsed => [parsed._[0], parsed.require].flat();
5
+ const withoutPositional = parsed => [parsed.require].flat();
4
6
  const argFilters = {
5
- 'babel-node': parsed => [parsed._[0], parsed.require].flat(),
6
- 'ts-node': parsed => [parsed._[0], parsed.require].flat(),
7
+ 'babel-node': withPositional,
8
+ nodemon: withPositional,
9
+ 'ts-node': withPositional,
10
+ zx: withPositional,
7
11
  tsx: parsed => parsed._.filter(p => p !== 'watch'),
8
- default: parsed => [parsed.require].flat(),
12
+ default: withoutPositional,
9
13
  };
10
14
  export const resolve = (binary, args, { cwd }) => {
11
- const parsed = parseArgs(args, { string: ['r'], alias: { require: ['r', 'loader'] } });
15
+ const parsed = parseArgs(args, { string: ['r'], alias: { require: ['r', 'loader'] }, boolean: ['quiet', 'verbose'] });
12
16
  const argFilter = argFilters[binary] ?? argFilters.default;
13
17
  const filteredArgs = compact(argFilter(parsed));
14
18
  return [binary, ...tryResolveFilePaths(cwd, filteredArgs)];
@@ -1,5 +1,7 @@
1
1
  import parseArgs from 'minimist';
2
2
  export const resolve = (binary, args, { fromArgs }) => {
3
3
  const parsed = parseArgs(args, { '--': true, stopEarly: true, boolean: ['yes', 'no'], alias: { yes: 'y', no: 'n' } });
4
- return [...(parsed.yes ? [] : fromArgs(parsed._)), ...(parsed['--'] ? fromArgs(parsed['--']) : [])];
4
+ const left = fromArgs(parsed._);
5
+ const right = parsed['--'] ? fromArgs(parsed['--']) : [];
6
+ return [...(parsed.yes ? left.slice(1) : left), ...right];
5
7
  };
@@ -2,13 +2,9 @@ import type { PackageJson } from 'type-fest';
2
2
  type Options = {
3
3
  cwd?: string;
4
4
  manifest?: PackageJson;
5
- ignore?: string[];
6
5
  knownGlobalsOnly?: boolean;
7
6
  };
8
- export type GetReferencesFromScripts = (npmScripts: string | string[], options?: Options) => {
9
- entryFiles: string[];
10
- binaries: string[];
11
- };
7
+ export type GetDependenciesFromScripts = (npmScripts: string | string[] | Set<string>, options?: Options) => string[];
12
8
  type FromArgs = (args: string[]) => string[];
13
9
  export type Resolver = (binary: string, args: string[], options: {
14
10
  cwd: string;
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import parsedArgs, { helpText } from './util/cli-arguments.js';
6
6
  import { isKnownError, ConfigurationError } from './util/errors.js';
7
7
  import { _load } from './util/loader.js';
8
8
  import { cwd, resolve } from './util/path.js';
9
- import { Performance } from './util/performance.js';
9
+ import { Performance } from './util/Performance.js';
10
10
  import { version } from './version.js';
11
11
  import { main } from './index.js';
12
12
  const { debug: isDebug = false, help: isHelp, 'max-issues': maxIssues = '0', 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = false, performance: isObservePerf = false, production: isProduction = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', strict: isStrict = false, tsConfig, version: isVersion, } = parsedArgs.values;
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
- import { ConfigurationChief } from './configuration-chief.js';
2
- import { ConsoleStreamer } from './console-streamer.js';
1
+ import { _getDependenciesFromScripts } from './binaries/index.js';
2
+ import { ConfigurationChief } from './ConfigurationChief.js';
3
+ import { ConsoleStreamer } from './ConsoleStreamer.js';
3
4
  import { ROOT_WORKSPACE_NAME } from './constants.js';
4
- import { DependencyDeputy } from './dependency-deputy.js';
5
- import { IssueCollector } from './issue-collector.js';
6
- import { PrincipalFactory } from './principal-factory.js';
5
+ import { DependencyDeputy } from './DependencyDeputy.js';
6
+ import { IssueCollector } from './IssueCollector.js';
7
+ import { PrincipalFactory } from './PrincipalFactory.js';
7
8
  import { compact } from './util/array.js';
8
9
  import { debugLogObject, debugLogArray, debugLog } from './util/debug.js';
9
10
  import { LoaderError } from './util/errors.js';
@@ -14,7 +15,7 @@ import { dirname, isInNodeModules, join, isInternal, isAbsolute } from './util/p
14
15
  import { _resolveSpecifier, _tryResolve } from './util/require.js';
15
16
  import { _require } from './util/require.js';
16
17
  import { loadTSConfig as loadCompilerOptions } from './util/tsconfig-loader.js';
17
- import { WorkspaceWorker } from './workspace-worker.js';
18
+ import { WorkspaceWorker } from './WorkspaceWorker.js';
18
19
  export const main = async (unresolvedConfiguration) => {
19
20
  const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isShowProgress } = unresolvedConfiguration;
20
21
  debugLogObject('Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
@@ -29,17 +30,55 @@ export const main = async (unresolvedConfiguration) => {
29
30
  const workspaces = chief.getEnabledWorkspaces();
30
31
  const report = chief.getIssueTypesToReport();
31
32
  debugLogObject('Included workspaces', workspaces);
33
+ const handleReferencedDependency = ({ specifier, containingFilePath, principal, workspace, }) => {
34
+ if (isInternal(specifier)) {
35
+ const absSpecifier = isAbsolute(specifier) ? specifier : join(dirname(containingFilePath), specifier);
36
+ const filePath = _tryResolve(absSpecifier, containingFilePath);
37
+ if (filePath) {
38
+ principal.addEntryPath(filePath);
39
+ }
40
+ else {
41
+ collector.addIssue({ type: 'unresolved', filePath: containingFilePath, symbol: specifier });
42
+ }
43
+ }
44
+ else {
45
+ if (isInNodeModules(specifier)) {
46
+ const packageName = getPackageNameFromFilePath(specifier);
47
+ const isHandled = deputy.maybeAddReferencedExternalDependency(workspace, packageName);
48
+ if (!isHandled)
49
+ collector.addIssue({ type: 'unlisted', filePath: containingFilePath, symbol: specifier });
50
+ }
51
+ else {
52
+ const packageName = getPackageNameFromModuleSpecifier(specifier);
53
+ const isHandled = deputy.maybeAddReferencedExternalDependency(workspace, packageName);
54
+ if (!isHandled)
55
+ collector.addIssue({ type: 'unlisted', filePath: containingFilePath, symbol: specifier });
56
+ if (specifier !== packageName) {
57
+ const otherWorkspace = chief.findWorkspaceByPackageName(packageName);
58
+ if (otherWorkspace) {
59
+ const filePath = _resolveSpecifier(otherWorkspace.dir, specifier);
60
+ if (filePath) {
61
+ principal.addEntryPath(filePath);
62
+ }
63
+ else {
64
+ collector.addIssue({ type: 'unresolved', filePath: containingFilePath, symbol: specifier });
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ };
32
71
  const enabledPluginsStore = new Map();
33
72
  for (const workspace of workspaces) {
34
73
  const { name, dir, config, ancestors } = workspace;
35
- const { paths, ignoreDependencies } = config;
74
+ const { paths, ignoreDependencies, ignoreBinaries } = config;
36
75
  const isRoot = name === ROOT_WORKSPACE_NAME;
37
76
  streamer.cast(`Analyzing workspace (${name})...`);
38
77
  const manifestPath = isRoot ? chief.manifestPath : findFile(dir, 'package.json');
39
78
  const manifest = isRoot ? chief.manifest : manifestPath && _require(manifestPath);
40
79
  if (!manifestPath || !manifest)
41
80
  throw new LoaderError(`Unable to load package.json for ${name}`);
42
- deputy.addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies });
81
+ deputy.addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries });
43
82
  const compilerOptions = await loadCompilerOptions(join(dir, tsConfigFile ?? 'tsconfig.json'));
44
83
  const principal = factory.getPrincipal({ cwd: dir, report: report, paths, compilerOptions, compilers });
45
84
  const worker = new WorkspaceWorker({
@@ -122,40 +161,7 @@ export const main = async (unresolvedConfiguration) => {
122
161
  deputy.setInstalledBinaries(name, installedBinaries);
123
162
  enabledPluginsStore.set(name, enabledPlugins);
124
163
  referencedDependencies.forEach(([containingFilePath, specifier]) => {
125
- if (isInternal(specifier)) {
126
- const absSpecifier = isAbsolute(specifier) ? specifier : join(dirname(containingFilePath), specifier);
127
- const filePath = _tryResolve(absSpecifier, containingFilePath);
128
- if (filePath) {
129
- principal.addEntryPath(filePath);
130
- }
131
- else {
132
- collector.addIssue({ type: 'unresolved', filePath: containingFilePath, symbol: specifier });
133
- }
134
- }
135
- else {
136
- if (isInNodeModules(specifier)) {
137
- const packageName = getPackageNameFromFilePath(specifier);
138
- const isHandled = deputy.maybeAddReferencedExternalDependency(workspace, packageName);
139
- if (!isHandled)
140
- collector.addIssue({ type: 'unlisted', filePath: containingFilePath, symbol: specifier });
141
- }
142
- else {
143
- const packageName = getPackageNameFromModuleSpecifier(specifier);
144
- const isHandled = deputy.maybeAddReferencedExternalDependency(workspace, packageName);
145
- if (!isHandled)
146
- collector.addIssue({ type: 'unlisted', filePath: containingFilePath, symbol: specifier });
147
- const otherWorkspace = chief.findWorkspaceByPackageName(packageName);
148
- if (otherWorkspace && specifier !== packageName) {
149
- const filePath = _resolveSpecifier(otherWorkspace.dir, specifier);
150
- if (filePath) {
151
- principal.addEntryPath(filePath);
152
- }
153
- else {
154
- collector.addIssue({ type: 'unresolved', filePath: containingFilePath, symbol: specifier });
155
- }
156
- }
157
- }
158
- }
164
+ handleReferencedDependency({ specifier, containingFilePath, principal, workspace });
159
165
  });
160
166
  }
161
167
  const principals = factory.getPrincipals();
@@ -167,10 +173,11 @@ export const main = async (unresolvedConfiguration) => {
167
173
  collector.counters.processed++;
168
174
  const workspace = chief.findWorkspaceByFilePath(filePath);
169
175
  if (workspace) {
170
- const { imports, exports, duplicateExports } = principal.analyzeSourceFile(filePath);
176
+ const { imports, exports, scripts } = principal.analyzeSourceFile(filePath);
171
177
  const { internal, external, unresolved } = imports;
172
- if (exports.size > 0)
173
- exportedSymbols.set(filePath, exports);
178
+ const { exported, duplicate } = exports;
179
+ if (exported.size > 0)
180
+ exportedSymbols.set(filePath, exported);
174
181
  for (const [specifierFilePath, importItems] of internal.entries()) {
175
182
  const packageName = getPackageNameFromModuleSpecifier(importItems.specifier);
176
183
  const importedWorkspace = chief.findWorkspaceByPackageName(packageName);
@@ -196,7 +203,7 @@ export const main = async (unresolvedConfiguration) => {
196
203
  }
197
204
  }
198
205
  }
199
- duplicateExports.forEach(symbols => {
206
+ duplicate.forEach(symbols => {
200
207
  const symbol = symbols.join('|');
201
208
  collector.addIssue({ type: 'duplicates', filePath, symbol, symbols });
202
209
  });
@@ -209,6 +216,9 @@ export const main = async (unresolvedConfiguration) => {
209
216
  unresolved.forEach(moduleSpecifier => {
210
217
  collector.addIssue({ type: 'unresolved', filePath, symbol: moduleSpecifier });
211
218
  });
219
+ _getDependenciesFromScripts(scripts, { cwd: dirname(filePath) }).forEach(specifier => {
220
+ handleReferencedDependency({ specifier, containingFilePath: filePath, principal, workspace });
221
+ });
212
222
  }
213
223
  };
214
224
  const isExportedInEntryFile = (importedModule) => {
@@ -1,15 +1,13 @@
1
- import type { WorkspaceConfiguration } from '../types/config.js';
2
1
  import type { InstalledBinaries, PeerDependencies } from '../types/workspace.js';
3
2
  import type { PackageJson } from 'type-fest';
4
3
  type Options = {
5
- config: WorkspaceConfiguration;
6
4
  manifest: PackageJson;
7
5
  isProduction: boolean;
8
6
  isStrict: boolean;
9
7
  dir: string;
10
8
  cwd: string;
11
9
  };
12
- export declare const findDependencies: ({ config, manifest, isProduction, isStrict, dir, cwd }: Options) => Promise<{
10
+ export declare const findDependencies: ({ manifest, isProduction, isStrict, dir, cwd }: Options) => Promise<{
13
11
  dependencies: string[];
14
12
  peerDependencies: PeerDependencies;
15
13
  installedBinaries: InstalledBinaries;