knip 0.0.0-angular.0 → 0.0.0-graph.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +21 -1
  2. package/dist/ConfigurationChief.d.ts +12 -4
  3. package/dist/ConfigurationChief.js +63 -27
  4. package/dist/ConfigurationValidator.d.ts +13 -0
  5. package/dist/ConfigurationValidator.js +1 -1
  6. package/dist/DependencyDeputy.d.ts +7 -5
  7. package/dist/DependencyDeputy.js +26 -13
  8. package/dist/PrincipalFactory.d.ts +3 -0
  9. package/dist/PrincipalFactory.js +10 -6
  10. package/dist/ProjectPrincipal.js +10 -5
  11. package/dist/WorkspaceWorker.d.ts +6 -4
  12. package/dist/WorkspaceWorker.js +7 -4
  13. package/dist/binaries/resolvers/index.d.ts +1 -0
  14. package/dist/binaries/resolvers/index.js +1 -0
  15. package/dist/binaries/resolvers/nx.d.ts +2 -0
  16. package/dist/binaries/resolvers/nx.js +9 -0
  17. package/dist/cli.js +2 -1
  18. package/dist/constants.js +1 -0
  19. package/dist/index.js +71 -59
  20. package/dist/manifest/index.d.ts +3 -2
  21. package/dist/manifest/index.js +11 -6
  22. package/dist/plugins/drizzle/index.d.ts +6 -0
  23. package/dist/plugins/drizzle/index.js +16 -0
  24. package/dist/plugins/drizzle/types.d.ts +3 -0
  25. package/dist/plugins/drizzle/types.js +1 -0
  26. package/dist/plugins/index.d.ts +2 -0
  27. package/dist/plugins/index.js +2 -0
  28. package/dist/plugins/jest/index.js +4 -1
  29. package/dist/plugins/next/index.js +12 -4
  30. package/dist/plugins/playwright-ct/index.d.ts +5 -0
  31. package/dist/plugins/playwright-ct/index.js +5 -0
  32. package/dist/plugins/storybook/index.js +1 -1
  33. package/dist/plugins/typescript/index.js +3 -7
  34. package/dist/plugins/vitest/index.js +13 -1
  35. package/dist/plugins/vitest/types.d.ts +1 -0
  36. package/dist/reporters/compact.js +1 -1
  37. package/dist/reporters/json.js +1 -1
  38. package/dist/types/config.d.ts +3 -2
  39. package/dist/types/config.js +1 -1
  40. package/dist/types/exports.d.ts +1 -1
  41. package/dist/types/issues.d.ts +1 -0
  42. package/dist/types/workspace.d.ts +1 -1
  43. package/dist/typescript/ast-helpers.d.ts +2 -2
  44. package/dist/typescript/ast-helpers.js +11 -3
  45. package/dist/typescript/getImportsAndExports.js +7 -6
  46. package/dist/typescript/resolveModuleNames.js +19 -1
  47. package/dist/typescript/visitors/imports/index.js +2 -2
  48. package/dist/typescript/visitors/imports/{requireResolveCall.js → propertyAccessCall.js} +2 -2
  49. package/dist/util/cli-arguments.d.ts +2 -1
  50. package/dist/util/cli-arguments.js +2 -0
  51. package/dist/util/modules.d.ts +1 -0
  52. package/dist/util/modules.js +1 -0
  53. package/dist/util/plugin.d.ts +6 -0
  54. package/dist/util/plugin.js +13 -0
  55. package/dist/util/tsconfig-loader.d.ts +4 -1
  56. package/dist/util/tsconfig-loader.js +4 -2
  57. package/dist/version.d.ts +1 -1
  58. package/dist/version.js +1 -1
  59. package/package.json +18 -16
  60. package/schema.json +8 -0
  61. /package/dist/typescript/visitors/imports/{requireResolveCall.d.ts → propertyAccessCall.d.ts} +0 -0
package/README.md CHANGED
@@ -253,6 +253,7 @@ Knip contains a growing list of plugins:
253
253
  - [commitlint][plugin-commitlint]
254
254
  - [cspell][plugin-cspell]
255
255
  - [Cypress][plugin-cypress]
256
+ - [Drizzle][plugin-drizzle]
256
257
  - [ESLint][plugin-eslint]
257
258
  - [Gatsby][plugin-gatsby]
258
259
  - [GitHub Actions][plugin-github-actions]
@@ -267,6 +268,7 @@ Knip contains a growing list of plugins:
267
268
  - [Nx][plugin-nx]
268
269
  - [nyc][plugin-nyc]
269
270
  - [Playwright][plugin-playwright]
271
+ - [Playwright for components][plugin-playwright-ct]
270
272
  - [PostCSS][plugin-postcss]
271
273
  - [Prettier][plugin-prettier]
272
274
  - [Release It][plugin-release-it]
@@ -321,6 +323,21 @@ has them at `e2e-tests/*.spec.ts`. Here's how to configure this:
321
323
  }
322
324
  ```
323
325
 
326
+ When overriding any plugin's configuration, the options object is fully replaced. Look at the plugin's page to find the
327
+ default configuration and use that as a basis. Here's another example to override the test file pattern for Vitest:
328
+
329
+ ```json
330
+ {
331
+ "vitest": {
332
+ "config": ["vitest.config.ts"],
333
+ "entry": ["**/*.vitest.ts"]
334
+ }
335
+ }
336
+ ```
337
+
338
+ This plugin configuration can be set on root and workspace level. If set on root level, it can be disabled on workspace
339
+ level by setting it to `false` there.
340
+
324
341
  #### Multi-project repositories
325
342
 
326
343
  Some repositories have a single `package.json`, but consist of multiple projects with configuration files across the
@@ -663,6 +680,7 @@ Knip takes the following JSDoc/TSDoc tags into account:
663
680
  --include-entry-exports Include entry files when reporting unused exports
664
681
  -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
665
682
  --preprocessor Preprocess the results before providing it to the reporter(s), can be repeated
683
+ --preprocessor-options Pass extra options to the preprocessor (as JSON string, see --reporter-options example)
666
684
  --reporter Select reporter: symbols, compact, codeowners, json, can be repeated (default: symbols)
667
685
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
668
686
  --no-config-hints Suppress configuration hints
@@ -800,7 +818,7 @@ Special thanks to the wonderful people who have contributed to this project:
800
818
  [7]: #jsdoc-tags
801
819
  [8]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
802
820
  [9]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
803
- [10]: https://discord.gg/ya5yktTq
821
+ [10]: https://discord.gg/r5uXTtbTpc
804
822
  [11]: https://twitter.com/webprolific
805
823
  [12]: https://fosstodon.org/@webpro
806
824
  [13]: https://github.com/webpro/knip/issues
@@ -873,6 +891,7 @@ Special thanks to the wonderful people who have contributed to this project:
873
891
  [plugin-commitlint]: ./src/plugins/commitlint
874
892
  [plugin-cspell]: ./src/plugins/cspell
875
893
  [plugin-cypress]: ./src/plugins/cypress
894
+ [plugin-drizzle]: ./src/plugins/drizzle
876
895
  [plugin-eslint]: ./src/plugins/eslint
877
896
  [plugin-gatsby]: ./src/plugins/gatsby
878
897
  [plugin-github-actions]: ./src/plugins/github-actions
@@ -887,6 +906,7 @@ Special thanks to the wonderful people who have contributed to this project:
887
906
  [plugin-nx]: ./src/plugins/nx
888
907
  [plugin-nyc]: ./src/plugins/nyc
889
908
  [plugin-playwright]: ./src/plugins/playwright
909
+ [plugin-playwright-ct]: ./src/plugins/playwright-ct
890
910
  [plugin-postcss]: ./src/plugins/postcss
891
911
  [plugin-prettier]: ./src/plugins/prettier
892
912
  [plugin-release-it]: ./src/plugins/release-it
@@ -1,29 +1,36 @@
1
- /// <reference types="npmcli__package-json" />
1
+ import { createPkgGraph } from '@pnpm/workspace.pkgs-graph';
2
2
  import type { SyncCompilers, AsyncCompilers } from './types/compilers.js';
3
3
  import type { Configuration, WorkspaceConfiguration } from './types/config.js';
4
- import type { PackageJson } from '@npmcli/package-json';
4
+ import type { PackageJsonWithPlugins } from './types/plugins.js';
5
5
  type ConfigurationManagerOptions = {
6
6
  cwd: string;
7
7
  isProduction: boolean;
8
8
  };
9
9
  export type Workspace = {
10
10
  name: string;
11
- pkgName?: string;
11
+ pkgName: string;
12
12
  dir: string;
13
13
  ancestors: string[];
14
14
  config: WorkspaceConfiguration;
15
+ manifestPath: string;
16
+ manifest: PackageJsonWithPlugins;
15
17
  };
16
18
  export declare class ConfigurationChief {
17
19
  cwd: string;
18
20
  isProduction: boolean;
19
21
  config: Configuration;
20
22
  manifestPath?: string;
21
- manifest?: PackageJson;
23
+ manifest?: PackageJsonWithPlugins;
22
24
  ignoredWorkspacePatterns: string[];
23
25
  manifestWorkspaces: Map<string, string>;
24
26
  additionalWorkspaceNames: Set<string>;
25
27
  availableWorkspaceNames: string[];
26
28
  availableWorkspaceDirs: string[];
29
+ availableWorkspaceManifests: {
30
+ dir: string;
31
+ manifest: PackageJsonWithPlugins;
32
+ }[];
33
+ workspacesGraph: ReturnType<typeof createPkgGraph> | undefined;
27
34
  enabledWorkspaces: Workspace[];
28
35
  localWorkspaces: Set<string>;
29
36
  resolvedConfigFilePath?: string;
@@ -38,6 +45,7 @@ export declare class ConfigurationChief {
38
45
  private getManifestWorkspaces;
39
46
  private getAdditionalWorkspaceNames;
40
47
  private getAvailableWorkspaceNames;
48
+ private getAvailableWorkspaceManifests;
41
49
  private getEnabledWorkspaces;
42
50
  getWorkspaces(): Workspace[];
43
51
  private getDescendentWorkspaces;
@@ -1,5 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import mapWorkspaces from '@npmcli/map-workspaces';
3
+ import { createPkgGraph } from '@pnpm/workspace.pkgs-graph';
3
4
  import micromatch from 'micromatch';
4
5
  import { ConfigurationValidator } from './ConfigurationValidator.js';
5
6
  import { ROOT_WORKSPACE_NAME, DEFAULT_EXTENSIONS, KNIP_CONFIG_LOCATIONS } from './constants.js';
@@ -8,14 +9,15 @@ import * as plugins from './plugins/index.js';
8
9
  import { arrayify, compact } from './util/array.js';
9
10
  import parsedArgValues from './util/cli-arguments.js';
10
11
  import { partitionCompilers } from './util/compilers.js';
11
- import { ConfigurationError } from './util/errors.js';
12
+ import { ConfigurationError, LoaderError } from './util/errors.js';
12
13
  import { findFile, loadJSON } from './util/fs.js';
13
14
  import { getIncludedIssueTypes } from './util/get-included-issue-types.js';
14
15
  import { _dirGlob } from './util/glob.js';
15
16
  import { _load } from './util/loader.js';
16
17
  import { getKeysByValue } from './util/object.js';
17
18
  import { join, relative, toPosix } from './util/path.js';
18
- import { toCamelCase } from './util/plugin.js';
19
+ import { normalizePluginConfig, toCamelCase } from './util/plugin.js';
20
+ import { _require } from './util/require.js';
19
21
  import { byPathDepth } from './util/workspace.js';
20
22
  const { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [], dependencies = false, exports = false, } = parsedArgValues;
21
23
  const workspaceArg = rawWorkspaceArg ? toPosix(rawWorkspaceArg).replace(/^\.\//, '').replace(/\/$/, '') : undefined;
@@ -57,6 +59,8 @@ export class ConfigurationChief {
57
59
  additionalWorkspaceNames = new Set();
58
60
  availableWorkspaceNames = [];
59
61
  availableWorkspaceDirs = [];
62
+ availableWorkspaceManifests = [];
63
+ workspacesGraph;
60
64
  enabledWorkspaces = [];
61
65
  localWorkspaces = new Set();
62
66
  resolvedConfigFilePath;
@@ -116,6 +120,13 @@ export class ConfigurationChief {
116
120
  const { syncCompilers, asyncCompilers } = rawLocalConfig;
117
121
  const extensions = [...Object.keys(syncCompilers ?? {}), ...Object.keys(asyncCompilers ?? {})];
118
122
  const defaultWorkspaceConfig = getDefaultWorkspaceConfig(extensions);
123
+ const rootPluginConfigs = {};
124
+ for (const [name, pluginConfig] of Object.entries(rawLocalConfig)) {
125
+ const pluginName = toCamelCase(name);
126
+ if (PLUGIN_NAMES.includes(pluginName)) {
127
+ rootPluginConfigs[pluginName] = normalizePluginConfig(pluginConfig);
128
+ }
129
+ }
119
130
  const workspaces = Object.entries(initialWorkspaces)
120
131
  .filter(([workspaceName]) => !ignoreWorkspaces.includes(workspaceName))
121
132
  .reduce((workspaces, workspace) => {
@@ -131,23 +142,15 @@ export class ConfigurationChief {
131
142
  ignoreBinaries: arrayify(workspaceConfig.ignoreBinaries),
132
143
  ignoreDependencies: arrayify(workspaceConfig.ignoreDependencies),
133
144
  };
145
+ for (const [name, pluginConfig] of Object.entries(rootPluginConfigs)) {
146
+ const pluginName = toCamelCase(name);
147
+ if (pluginConfig)
148
+ workspaces[workspaceName][pluginName] = pluginConfig;
149
+ }
134
150
  for (const [name, pluginConfig] of Object.entries(workspaceConfig)) {
135
151
  const pluginName = toCamelCase(name);
136
152
  if (PLUGIN_NAMES.includes(pluginName)) {
137
- if (pluginConfig === false) {
138
- workspaces[workspaceName][pluginName] = false;
139
- }
140
- else {
141
- const isObject = typeof pluginConfig !== 'string' && !Array.isArray(pluginConfig);
142
- const config = isObject ? arrayify(pluginConfig.config) : pluginConfig ? arrayify(pluginConfig) : null;
143
- const entry = isObject && 'entry' in pluginConfig ? arrayify(pluginConfig.entry) : null;
144
- const project = isObject && 'project' in pluginConfig ? arrayify(pluginConfig.project) : entry;
145
- workspaces[workspaceName][pluginName] = {
146
- config,
147
- entry,
148
- project,
149
- };
150
- }
153
+ workspaces[workspaceName][pluginName] = normalizePluginConfig(pluginConfig);
151
154
  }
152
155
  }
153
156
  return workspaces;
@@ -175,6 +178,8 @@ export class ConfigurationChief {
175
178
  .sort(byPathDepth)
176
179
  .reverse()
177
180
  .map(dir => join(this.cwd, dir));
181
+ this.availableWorkspaceManifests = this.getAvailableWorkspaceManifests(this.availableWorkspaceDirs);
182
+ this.workspacesGraph = createPkgGraph(this.availableWorkspaceManifests);
178
183
  this.enabledWorkspaces = this.getEnabledWorkspaces();
179
184
  this.localWorkspaces = new Set(compact(this.enabledWorkspaces.map(w => w.pkgName)));
180
185
  }
@@ -214,6 +219,14 @@ export class ConfigurationChief {
214
219
  getAvailableWorkspaceNames() {
215
220
  return [ROOT_WORKSPACE_NAME, ...this.manifestWorkspaces.keys(), ...this.additionalWorkspaceNames].filter(name => !micromatch.isMatch(name, this.ignoredWorkspacePatterns));
216
221
  }
222
+ getAvailableWorkspaceManifests(availableWorkspaceDirs) {
223
+ return availableWorkspaceDirs.map(dir => {
224
+ const manifest = _require(join(dir, 'package.json'));
225
+ if (!manifest)
226
+ throw new LoaderError(`Unable to load package.json for ${dir}`);
227
+ return { dir, manifest };
228
+ });
229
+ }
217
230
  getEnabledWorkspaces() {
218
231
  if (workspaceArg && !existsSync(workspaceArg)) {
219
232
  throw new ConfigurationError(`Directory does not exist: ${workspaceArg}`);
@@ -226,18 +239,41 @@ export class ConfigurationChief {
226
239
  return ancestors;
227
240
  };
228
241
  const workspaceNames = workspaceArg
229
- ? [
230
- ...this.availableWorkspaceNames.reduce(getAncestors(workspaceArg), []),
231
- ...this.availableWorkspaceNames.filter(name => name === workspaceArg),
232
- ]
242
+ ? [...this.availableWorkspaceNames.reduce(getAncestors(workspaceArg), []), workspaceArg]
233
243
  : this.availableWorkspaceNames;
234
- return workspaceNames.sort(byPathDepth).map((name) => ({
235
- name,
236
- pkgName: this.manifestWorkspaces.get(name) ?? this.manifest?.name,
237
- dir: join(this.cwd, name),
238
- config: this.getConfigForWorkspace(name),
239
- ancestors: this.availableWorkspaceNames.reduce(getAncestors(name), []),
240
- }));
244
+ const graph = this.workspacesGraph?.graph;
245
+ const ws = new Set();
246
+ if (graph && workspaceArg) {
247
+ const seen = new Set();
248
+ const workspaceDirsWithDependants = new Set(workspaceNames.map(name => join(this.cwd, name)));
249
+ const addDependents = (dir) => {
250
+ seen.add(dir);
251
+ const deps = graph[dir]?.dependencies ?? [];
252
+ if (deps.length > 0 && Array.from(workspaceDirsWithDependants).some(dir => deps.includes(dir))) {
253
+ workspaceDirsWithDependants.add(dir);
254
+ deps.filter(dir => !seen.has(dir)).forEach(addDependents);
255
+ }
256
+ };
257
+ this.availableWorkspaceNames.map(name => join(this.cwd, name)).forEach(addDependents);
258
+ workspaceDirsWithDependants.forEach(dir => ws.add(relative(this.cwd, dir) || ROOT_WORKSPACE_NAME));
259
+ }
260
+ else {
261
+ workspaceNames.forEach(name => ws.add(name));
262
+ }
263
+ return Array.from(ws)
264
+ .sort(byPathDepth)
265
+ .map((name) => {
266
+ const dir = join(this.cwd, name);
267
+ return {
268
+ name,
269
+ pkgName: this.manifestWorkspaces.get(name) ?? this.manifest?.name ?? `NOT_FOUND_${name}`,
270
+ dir,
271
+ config: this.getConfigForWorkspace(name),
272
+ ancestors: this.availableWorkspaceNames.reduce(getAncestors(name), []),
273
+ manifestPath: join(dir, 'package.json'),
274
+ manifest: this.availableWorkspaceManifests?.find(item => item.dir === dir)?.manifest ?? {},
275
+ };
276
+ });
241
277
  }
242
278
  getWorkspaces() {
243
279
  return this.enabledWorkspaces;
@@ -1,4 +1,17 @@
1
1
  import { z } from 'zod';
2
+ export declare const pluginSchema: z.ZodUnion<[z.ZodLiteral<false>, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
3
+ config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
4
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
5
+ project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ config?: string | string[] | undefined;
8
+ entry?: string | string[] | undefined;
9
+ project?: string | string[] | undefined;
10
+ }, {
11
+ config?: string | string[] | undefined;
12
+ entry?: string | string[] | undefined;
13
+ project?: string | string[] | undefined;
14
+ }>]>;
2
15
  export declare const ConfigurationValidator: z.ZodObject<{
3
16
  exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
4
17
  rules: z.ZodOptional<z.ZodRecord<z.ZodUnion<[z.ZodLiteral<"files">, z.ZodLiteral<"dependencies">, z.ZodLiteral<"devDependencies">, z.ZodLiteral<"unlisted">, z.ZodLiteral<"binaries">, z.ZodLiteral<"unresolved">, z.ZodLiteral<"exports">, z.ZodLiteral<"types">, z.ZodLiteral<"nsExports">, z.ZodLiteral<"nsTypes">, z.ZodLiteral<"duplicates">, z.ZodLiteral<"enumMembers">, z.ZodLiteral<"classMembers">]>, z.ZodEnum<["error", "warn", "off"]>>>;
@@ -50,7 +50,7 @@ const reportConfigSchema = z.object({
50
50
  include: z.array(z.string()).optional(),
51
51
  exclude: z.array(z.string()).optional(),
52
52
  });
53
- const pluginSchema = z.union([
53
+ export const pluginSchema = z.union([
54
54
  z.literal(false),
55
55
  globSchema,
56
56
  z.object({
@@ -1,8 +1,7 @@
1
1
  /// <reference types="npmcli__package-json" />
2
2
  import type { Workspace } from './ConfigurationChief.js';
3
3
  import type { ConfigurationHints, Issue } from './types/issues.js';
4
- import type { WorkspaceManifests } from './types/workspace.js';
5
- import type { PeerDependencies, InstalledBinaries } from './types/workspace.js';
4
+ import type { WorkspaceManifests, HostDependencies, InstalledBinaries } from './types/workspace.js';
6
5
  import type { PackageJson } from '@npmcli/package-json';
7
6
  type Options = {
8
7
  isStrict: boolean;
@@ -12,8 +11,9 @@ export declare class DependencyDeputy {
12
11
  _manifests: WorkspaceManifests;
13
12
  referencedDependencies: Map<string, Set<string>>;
14
13
  referencedBinaries: Map<string, Set<string>>;
15
- peerDependencies: Map<string, PeerDependencies>;
14
+ hostDependencies: Map<string, HostDependencies>;
16
15
  installedBinaries: Map<string, InstalledBinaries>;
16
+ hasTypesIncluded: Map<string, Set<string>>;
17
17
  ignoreBinaries: string[];
18
18
  ignoreDependencies: string[];
19
19
  constructor({ isStrict }: Options);
@@ -43,10 +43,12 @@ export declare class DependencyDeputy {
43
43
  getDevDependencies(workspaceName: string): string[];
44
44
  setInstalledBinaries(workspaceName: string, installedBinaries: Map<string, Set<string>>): void;
45
45
  getInstalledBinaries(workspaceName: string): InstalledBinaries | undefined;
46
+ setHasTypesIncluded(workspaceName: string, hasTypesIncluded: Set<string>): void;
47
+ getHasTypesIncluded(workspaceName: string): InstalledBinaries | undefined;
46
48
  addReferencedDependency(workspaceName: string, packageName: string): void;
47
49
  addReferencedBinary(workspaceName: string, binaryName: string): void;
48
- addPeerDependencies(workspaceName: string, peerDependencies: Map<string, Set<string>>): void;
49
- getPeerDependenciesOf(workspaceName: string, dependency: string): string[];
50
+ addHostDependencies(workspaceName: string, hostDependencies: HostDependencies): void;
51
+ getHostDependenciesFor(workspaceName: string, dependency: string): string[];
50
52
  getPeerDependencies(workspaceName: string): string[];
51
53
  getOptionalPeerDependencies(workspaceName: string): string[];
52
54
  maybeAddReferencedExternalDependency(workspace: Workspace, packageName: string): boolean;
@@ -6,16 +6,18 @@ export class DependencyDeputy {
6
6
  _manifests = new Map();
7
7
  referencedDependencies;
8
8
  referencedBinaries;
9
- peerDependencies;
9
+ hostDependencies;
10
10
  installedBinaries;
11
+ hasTypesIncluded;
11
12
  ignoreBinaries = [];
12
13
  ignoreDependencies = [];
13
14
  constructor({ isStrict }) {
14
15
  this.isStrict = isStrict;
15
16
  this.referencedDependencies = new Map();
16
17
  this.referencedBinaries = new Map();
17
- this.peerDependencies = new Map();
18
+ this.hostDependencies = new Map();
18
19
  this.installedBinaries = new Map();
20
+ this.hasTypesIncluded = new Map();
19
21
  }
20
22
  addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries, }) {
21
23
  const scripts = Object.values(manifest.scripts ?? {});
@@ -67,6 +69,12 @@ export class DependencyDeputy {
67
69
  getInstalledBinaries(workspaceName) {
68
70
  return this.installedBinaries.get(workspaceName);
69
71
  }
72
+ setHasTypesIncluded(workspaceName, hasTypesIncluded) {
73
+ this.hasTypesIncluded.set(workspaceName, hasTypesIncluded);
74
+ }
75
+ getHasTypesIncluded(workspaceName) {
76
+ return this.installedBinaries.get(workspaceName);
77
+ }
70
78
  addReferencedDependency(workspaceName, packageName) {
71
79
  if (!this.referencedDependencies.has(workspaceName)) {
72
80
  this.referencedDependencies.set(workspaceName, new Set());
@@ -79,11 +87,11 @@ export class DependencyDeputy {
79
87
  }
80
88
  this.referencedBinaries.get(workspaceName)?.add(binaryName);
81
89
  }
82
- addPeerDependencies(workspaceName, peerDependencies) {
83
- this.peerDependencies.set(workspaceName, peerDependencies);
90
+ addHostDependencies(workspaceName, hostDependencies) {
91
+ this.hostDependencies.set(workspaceName, hostDependencies);
84
92
  }
85
- getPeerDependenciesOf(workspaceName, dependency) {
86
- return Array.from(this.peerDependencies.get(workspaceName)?.get(dependency) ?? []);
93
+ getHostDependenciesFor(workspaceName, dependency) {
94
+ return Array.from(this.hostDependencies.get(workspaceName)?.get(dependency) ?? []);
87
95
  }
88
96
  getPeerDependencies(workspaceName) {
89
97
  const manifest = this._manifests.get(workspaceName);
@@ -155,6 +163,7 @@ export class DependencyDeputy {
155
163
  for (const [workspaceName, { manifestPath, ignoreDependencies, ignoreBinaries }] of this._manifests.entries()) {
156
164
  const referencedDependencies = this.referencedDependencies.get(workspaceName);
157
165
  const installedBinaries = this.getInstalledBinaries(workspaceName);
166
+ const hasTypesIncluded = this.getHasTypesIncluded(workspaceName);
158
167
  const ignoreBins = [...IGNORED_GLOBAL_BINARIES, ...this.ignoreBinaries, ...ignoreBinaries];
159
168
  const ignoreDeps = [...IGNORED_DEPENDENCIES, ...this.ignoreDependencies, ...ignoreDependencies];
160
169
  const isNotIgnoredDependency = (packageName) => !ignoreDeps.includes(packageName);
@@ -176,20 +185,24 @@ export class DependencyDeputy {
176
185
  return false;
177
186
  const [scope, typedDependency] = dependency.split('/');
178
187
  if (scope === '@types') {
188
+ if (hasTypesIncluded?.has(typedDependency))
189
+ return false;
179
190
  const typedPackageName = getPackageFromDefinitelyTyped(typedDependency);
180
191
  if (IGNORE_DEFINITELY_TYPED.includes(typedPackageName))
181
192
  return true;
182
- const peerDependencies = this.getPeerDependenciesOf(workspaceName, typedPackageName);
183
- if (peerDependencies.length) {
184
- return !!peerDependencies.find(peerDependency => isReferencedDependency(peerDependency, true));
185
- }
193
+ const hostDependencies = [
194
+ ...this.getHostDependenciesFor(workspaceName, dependency),
195
+ ...this.getHostDependenciesFor(workspaceName, typedPackageName),
196
+ ];
197
+ if (hostDependencies.length)
198
+ return !!hostDependencies.find(host => isReferencedDependency(host, true));
186
199
  if (!referencedDependencies)
187
200
  return false;
188
201
  return referencedDependencies.has(typedPackageName);
189
202
  }
190
- const peerDependenciesOf = this.getPeerDependenciesOf(workspaceName, dependency);
191
- peerDependenciesOf.forEach(dep => (!peerDepRecs[dep] ? (peerDepRecs[dep] = 1) : peerDepRecs[dep]++));
192
- return peerDependenciesOf.some(peerDependency => isReferencedDependency(peerDependency, true));
203
+ const hostDependencies = this.getHostDependenciesFor(workspaceName, dependency);
204
+ hostDependencies.forEach(dep => (!peerDepRecs[dep] ? (peerDepRecs[dep] = 1) : peerDepRecs[dep]++));
205
+ return hostDependencies.some(peerDependency => isReferencedDependency(peerDependency, true));
193
206
  };
194
207
  const isNotReferencedDependency = (dependency) => !isReferencedDependency(dependency);
195
208
  const pd = this.getProductionDependencies(workspaceName);
@@ -6,6 +6,7 @@ type Principal = {
6
6
  principal: ProjectPrincipal;
7
7
  cwds: Set<string>;
8
8
  pathKeys: Set<string>;
9
+ pkgNames: Set<string>;
9
10
  };
10
11
  type Principals = Set<Principal>;
11
12
  type Options = {
@@ -13,6 +14,7 @@ type Options = {
13
14
  compilerOptions: ts.CompilerOptions;
14
15
  paths: Paths;
15
16
  compilers: [SyncCompilers, AsyncCompilers];
17
+ pkgName: string;
16
18
  };
17
19
  export declare class PrincipalFactory {
18
20
  principals: Principals;
@@ -21,5 +23,6 @@ export declare class PrincipalFactory {
21
23
  private linkPrincipal;
22
24
  private addNewPrincipal;
23
25
  getPrincipals(): ProjectPrincipal[];
26
+ getPrincipalByPackageName(packageName: string): ProjectPrincipal | undefined;
24
27
  }
25
28
  export {};
@@ -12,11 +12,11 @@ const mergePaths = (cwd, compilerOptions, paths = {}) => {
12
12
  export class PrincipalFactory {
13
13
  principals = new Set();
14
14
  getPrincipal(options) {
15
- const { cwd, compilerOptions, paths } = options;
15
+ const { cwd, compilerOptions, paths, pkgName } = options;
16
16
  options.compilerOptions = mergePaths(cwd, compilerOptions, paths);
17
17
  const principal = this.findReusablePrincipal(compilerOptions);
18
18
  if (principal) {
19
- this.linkPrincipal(principal, cwd, compilerOptions);
19
+ this.linkPrincipal(principal, cwd, compilerOptions, pkgName);
20
20
  return principal.principal;
21
21
  }
22
22
  else {
@@ -35,22 +35,26 @@ export class PrincipalFactory {
35
35
  });
36
36
  return principal;
37
37
  }
38
- linkPrincipal(principal, cwd, compilerOptions) {
38
+ linkPrincipal(principal, cwd, compilerOptions, pkgName) {
39
39
  const { pathsBasePath, paths } = compilerOptions;
40
40
  if (pathsBasePath)
41
41
  principal.principal.compilerOptions.pathsBasePath = pathsBasePath;
42
42
  Object.keys(paths ?? {}).forEach(p => principal.pathKeys.add(p));
43
43
  principal.principal.compilerOptions.paths = { ...principal.principal.compilerOptions.paths, ...paths };
44
44
  principal.cwds.add(cwd);
45
+ principal.pkgNames.add(pkgName);
45
46
  }
46
47
  addNewPrincipal(options) {
47
- const { cwd, compilerOptions } = options;
48
+ const { cwd, compilerOptions, pkgName } = options;
48
49
  const pathKeys = new Set(Object.keys(compilerOptions?.paths ?? {}));
49
50
  const principal = new ProjectPrincipal(options);
50
- this.principals.add({ principal, cwds: new Set([cwd]), pathKeys });
51
+ this.principals.add({ principal, cwds: new Set([cwd]), pathKeys, pkgNames: new Set([pkgName]) });
51
52
  return principal;
52
53
  }
53
54
  getPrincipals() {
54
- return Array.from(this.principals).map(p => p.principal);
55
+ return Array.from(this.principals, p => p.principal).reverse();
56
+ }
57
+ getPrincipalByPackageName(packageName) {
58
+ return Array.from(this.principals).find(principal => principal.pkgNames.has(packageName))?.principal;
55
59
  }
56
60
  }
@@ -6,7 +6,7 @@ import { getJSDocTags, isInModuleBlock } from './typescript/ast-helpers.js';
6
6
  import { createHosts } from './typescript/createHosts.js';
7
7
  import { getImportsAndExports } from './typescript/getImportsAndExports.js';
8
8
  import { SourceFileManager } from './typescript/SourceFileManager.js';
9
- import { isMaybePackageName } from './util/modules.js';
9
+ import { isMaybePackageName, sanitizeSpecifier } from './util/modules.js';
10
10
  import { dirname, extname, isInNodeModules, join } from './util/path.js';
11
11
  import { timerify } from './util/Performance.js';
12
12
  const baseCompilerOptions = {
@@ -107,7 +107,7 @@ export class ProjectPrincipal {
107
107
  return Array.from(this.projectPaths).filter(filePath => !sourceFiles.has(filePath));
108
108
  }
109
109
  analyzeSourceFile(filePath, { skipTypeOnly }) {
110
- const sourceFile = this.backend.program?.getSourceFile(filePath);
110
+ const sourceFile = this.backend.fileManager.getSourceFile(filePath);
111
111
  if (!sourceFile)
112
112
  throw new Error(`Unable to find ${filePath}`);
113
113
  const skipExports = this.skipExportsAnalysis.has(filePath);
@@ -128,7 +128,7 @@ export class ProjectPrincipal {
128
128
  }
129
129
  }
130
130
  else {
131
- const sanitizedSpecifier = specifier.replace(/^([?!|-]+)?([^!?]+).*/, '$2');
131
+ const sanitizedSpecifier = sanitizeSpecifier(specifier);
132
132
  if (isMaybePackageName(sanitizedSpecifier)) {
133
133
  external.add(sanitizedSpecifier);
134
134
  }
@@ -178,7 +178,7 @@ export class ProjectPrincipal {
178
178
  findUnusedMembers(filePath, members) {
179
179
  return members
180
180
  .filter(member => {
181
- if (getJSDocTags(member.node).includes('@public'))
181
+ if (getJSDocTags(member.node).has('@public'))
182
182
  return false;
183
183
  const referencedSymbols = this.findReferences(filePath, member.pos);
184
184
  const files = referencedSymbols
@@ -192,6 +192,11 @@ export class ProjectPrincipal {
192
192
  .map(member => member.identifier);
193
193
  }
194
194
  findReferences(filePath, pos) {
195
- return this.backend.lsFindReferences(filePath, pos) ?? [];
195
+ try {
196
+ return this.backend.lsFindReferences(filePath, pos) ?? [];
197
+ }
198
+ catch {
199
+ return [];
200
+ }
196
201
  }
197
202
  }
@@ -1,6 +1,6 @@
1
1
  import type { Configuration, PluginName, WorkspaceConfiguration } from './types/config.js';
2
2
  import type { PackageJsonWithPlugins } from './types/plugins.js';
3
- import type { InstalledBinaries, PeerDependencies } from './types/workspace.js';
3
+ import type { InstalledBinaries, HostDependencies } from './types/workspace.js';
4
4
  type WorkspaceManagerOptions = {
5
5
  name: string;
6
6
  dir: string;
@@ -28,8 +28,9 @@ export declare class WorkspaceWorker {
28
28
  enabled: Record<PluginName, boolean>;
29
29
  enabledPlugins: PluginName[];
30
30
  referencedDependencies: ReferencedDependencies;
31
- peerDependencies: PeerDependencies;
31
+ hostDependencies: HostDependencies;
32
32
  installedBinaries: InstalledBinaries;
33
+ hasTypesIncluded: Set<string>;
33
34
  constructor({ name, dir, cwd, config, manifest, isProduction, isStrict, rootIgnore, negatedWorkspacePatterns, enabledPluginsInAncestors, }: WorkspaceManagerOptions);
34
35
  init(): Promise<void>;
35
36
  private setEnabledPlugins;
@@ -47,10 +48,11 @@ export declare class WorkspaceWorker {
47
48
  getIgnorePatterns(): string[];
48
49
  private findDependenciesByPlugins;
49
50
  findAllDependencies(): Promise<{
50
- peerDependencies: PeerDependencies;
51
+ hostDependencies: HostDependencies;
51
52
  installedBinaries: InstalledBinaries;
52
53
  referencedDependencies: ReferencedDependencies;
53
- enabledPlugins: ("angular" | "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" | "stylelint" | "tailwind" | "typedoc" | "typescript" | "vite" | "vitest" | "webpack" | "githubActions" | "lintStaged" | "npmPackageJsonLint" | "releaseIt" | "semanticRelease" | "svelte")[];
54
+ hasTypesIncluded: Set<string>;
55
+ enabledPlugins: ("angular" | "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" | "stylelint" | "tailwind" | "typedoc" | "typescript" | "vite" | "vitest" | "webpack" | "drizzle" | "githubActions" | "lintStaged" | "npmPackageJsonLint" | "playwrightCt" | "releaseIt" | "semanticRelease" | "svelte")[];
54
56
  }>;
55
57
  }
56
58
  export {};
@@ -20,8 +20,9 @@ export class WorkspaceWorker {
20
20
  enabled;
21
21
  enabledPlugins = [];
22
22
  referencedDependencies = new Set();
23
- peerDependencies = new Map();
23
+ hostDependencies = new Map();
24
24
  installedBinaries = new Map();
25
+ hasTypesIncluded = new Set();
25
26
  constructor({ name, dir, cwd, config, manifest, isProduction, isStrict, rootIgnore, negatedWorkspacePatterns, enabledPluginsInAncestors, }) {
26
27
  this.name = name;
27
28
  this.dir = dir;
@@ -59,7 +60,7 @@ export class WorkspaceWorker {
59
60
  debugLogObject(`Enabled plugins (${this.name})`, enabledPluginNames);
60
61
  }
61
62
  async initReferencedDependencies() {
62
- const { dependencies, peerDependencies, installedBinaries } = await npm.findDependencies({
63
+ const { dependencies, hostDependencies, installedBinaries, hasTypesIncluded } = await npm.findDependencies({
63
64
  manifest: this.manifest,
64
65
  isProduction: this.isProduction,
65
66
  isStrict: this.isStrict,
@@ -68,8 +69,9 @@ export class WorkspaceWorker {
68
69
  });
69
70
  const filePath = join(this.dir, 'package.json');
70
71
  dependencies.forEach(dependency => this.referencedDependencies.add([filePath, dependency]));
71
- this.peerDependencies = peerDependencies;
72
+ this.hostDependencies = hostDependencies;
72
73
  this.installedBinaries = installedBinaries;
74
+ this.hasTypesIncluded = hasTypesIncluded;
73
75
  }
74
76
  getConfigForPlugin(pluginName) {
75
77
  return this.config[pluginName] ?? { config: null, entry: null, project: null };
@@ -235,9 +237,10 @@ export class WorkspaceWorker {
235
237
  async findAllDependencies() {
236
238
  await this.findDependenciesByPlugins();
237
239
  return {
238
- peerDependencies: this.peerDependencies,
240
+ hostDependencies: this.hostDependencies,
239
241
  installedBinaries: this.installedBinaries,
240
242
  referencedDependencies: this.referencedDependencies,
243
+ hasTypesIncluded: this.hasTypesIncluded,
241
244
  enabledPlugins: this.enabledPlugins,
242
245
  };
243
246
  }
@@ -3,6 +3,7 @@ export * as dotenv from './dotenv.js';
3
3
  export * as node from './node.js';
4
4
  export * as nodemon from './nodemon.js';
5
5
  export * as npx from './npx.js';
6
+ export * as nx from './nx.js';
6
7
  export * as pnpm from './pnpm.js';
7
8
  export * as rollup from './rollup.js';
8
9
  export * as yarn from './yarn.js';
@@ -3,6 +3,7 @@ export * as dotenv from './dotenv.js';
3
3
  export * as node from './node.js';
4
4
  export * as nodemon from './nodemon.js';
5
5
  export * as npx from './npx.js';
6
+ export * as nx from './nx.js';
6
7
  export * as pnpm from './pnpm.js';
7
8
  export * as rollup from './rollup.js';
8
9
  export * as yarn from './yarn.js';
@@ -0,0 +1,2 @@
1
+ import type { Resolver } from '../types.js';
2
+ export declare const resolve: Resolver;