knip 3.5.0 → 3.6.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 (53) hide show
  1. package/dist/ConfigurationChief.js +3 -2
  2. package/dist/ConfigurationValidator.d.ts +16 -16
  3. package/dist/ConfigurationValidator.js +5 -4
  4. package/dist/DependencyDeputy.d.ts +10 -8
  5. package/dist/DependencyDeputy.js +67 -25
  6. package/dist/IssueCollector.js +2 -5
  7. package/dist/ProjectPrincipal.js +5 -3
  8. package/dist/WorkspaceWorker.js +2 -2
  9. package/dist/constants.js +1 -0
  10. package/dist/index.js +24 -32
  11. package/dist/plugins/_template/index.js +2 -4
  12. package/dist/plugins/astro/index.js +1 -1
  13. package/dist/plugins/ava/index.js +4 -6
  14. package/dist/plugins/babel/index.js +2 -3
  15. package/dist/plugins/commitizen/index.js +2 -3
  16. package/dist/plugins/commitlint/index.js +2 -3
  17. package/dist/plugins/eslint/helpers.js +2 -2
  18. package/dist/plugins/eslint/index.js +2 -1
  19. package/dist/plugins/github-actions/index.js +2 -3
  20. package/dist/plugins/graphql-codegen/index.js +2 -4
  21. package/dist/plugins/husky/index.js +2 -3
  22. package/dist/plugins/jest/index.js +4 -4
  23. package/dist/plugins/lefthook/index.js +5 -5
  24. package/dist/plugins/lint-staged/index.js +4 -6
  25. package/dist/plugins/mocha/index.js +2 -3
  26. package/dist/plugins/node-test-runner/index.js +1 -5
  27. package/dist/plugins/npm-package-json-lint/index.js +2 -3
  28. package/dist/plugins/nx/index.js +2 -3
  29. package/dist/plugins/postcss/index.js +2 -3
  30. package/dist/plugins/prettier/index.js +2 -3
  31. package/dist/plugins/release-it/index.js +4 -6
  32. package/dist/plugins/remark/index.js +2 -3
  33. package/dist/plugins/semantic-release/index.js +2 -3
  34. package/dist/plugins/stylelint/index.js +2 -4
  35. package/dist/plugins/typedoc/index.js +3 -2
  36. package/dist/types/config.d.ts +2 -2
  37. package/dist/types/imports.d.ts +1 -1
  38. package/dist/types/issues.d.ts +1 -1
  39. package/dist/types/workspace.d.ts +2 -2
  40. package/dist/typescript/getImportsAndExports.js +5 -4
  41. package/dist/util/compilers.d.ts +4 -4
  42. package/dist/util/modules.d.ts +1 -1
  43. package/dist/util/modules.js +2 -2
  44. package/dist/util/path.d.ts +1 -0
  45. package/dist/util/path.js +1 -0
  46. package/dist/util/plugin.d.ts +1 -0
  47. package/dist/util/plugin.js +1 -0
  48. package/dist/util/regex.d.ts +4 -0
  49. package/dist/util/regex.js +4 -0
  50. package/dist/version.d.ts +1 -1
  51. package/dist/version.js +1 -1
  52. package/package.json +7 -7
  53. package/schema.json +4 -4
@@ -17,6 +17,7 @@ import { _load } from './util/loader.js';
17
17
  import { getKeysByValue } from './util/object.js';
18
18
  import { join, relative, toPosix } from './util/path.js';
19
19
  import { normalizePluginConfig, toCamelCase } from './util/plugin.js';
20
+ import { toRegexOrString } from './util/regex.js';
20
21
  import { _require } from './util/require.js';
21
22
  import { unwrapFunction } from './util/unwrap-function.js';
22
23
  import { byPathDepth } from './util/workspace.js';
@@ -131,9 +132,9 @@ export class ConfigurationChief {
131
132
  const include = rawConfig.include ?? defaultConfig.include;
132
133
  const exclude = rawConfig.exclude ?? defaultConfig.exclude;
133
134
  const ignore = arrayify(rawConfig.ignore ?? defaultConfig.ignore);
134
- const ignoreBinaries = rawConfig.ignoreBinaries ?? [];
135
+ const ignoreBinaries = (rawConfig.ignoreBinaries ?? []).map(toRegexOrString);
136
+ const ignoreDependencies = (rawConfig.ignoreDependencies ?? []).map(toRegexOrString);
135
137
  const ignoreExportsUsedInFile = rawConfig.ignoreExportsUsedInFile ?? false;
136
- const ignoreDependencies = rawConfig.ignoreDependencies ?? [];
137
138
  const ignoreWorkspaces = rawConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
138
139
  const isIncludeEntryExports = rawConfig.includeEntryExports ?? this.isIncludeEntryExports;
139
140
  const { syncCompilers, asyncCompilers } = rawConfig;
@@ -19,9 +19,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
19
19
  project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
20
20
  paths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
21
21
  ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
22
- ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
23
+ ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
23
24
  ignoreExportsUsedInFile: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodRecord<z.ZodUnion<[z.ZodLiteral<"class">, z.ZodLiteral<"enum">, z.ZodLiteral<"function">, z.ZodLiteral<"interface">, z.ZodLiteral<"member">, z.ZodLiteral<"type">]>, z.ZodBoolean>]>>;
24
- ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
25
25
  ignoreWorkspaces: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
26
26
  includeEntryExports: z.ZodOptional<z.ZodBoolean>;
27
27
  compilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodString>, z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodPromise<z.ZodString>>]>>>;
@@ -33,8 +33,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
33
33
  project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
34
34
  paths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
35
35
  ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
36
- ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
37
- ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
36
+ ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
37
+ ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
38
38
  includeEntryExports: z.ZodOptional<z.ZodBoolean>;
39
39
  astro: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
40
40
  config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
@@ -613,8 +613,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
613
613
  project?: string | string[] | undefined;
614
614
  paths?: Record<string, string[]> | undefined;
615
615
  ignore?: string | string[] | undefined;
616
- ignoreBinaries?: string[] | undefined;
617
- ignoreDependencies?: string[] | undefined;
616
+ ignoreBinaries?: (string | RegExp)[] | undefined;
617
+ ignoreDependencies?: (string | RegExp)[] | undefined;
618
618
  includeEntryExports?: boolean | undefined;
619
619
  astro?: string | boolean | string[] | {
620
620
  config?: string | string[] | undefined;
@@ -841,8 +841,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
841
841
  project?: string | string[] | undefined;
842
842
  paths?: Record<string, string[]> | undefined;
843
843
  ignore?: string | string[] | undefined;
844
- ignoreBinaries?: string[] | undefined;
845
- ignoreDependencies?: string[] | undefined;
844
+ ignoreBinaries?: (string | RegExp)[] | undefined;
845
+ ignoreDependencies?: (string | RegExp)[] | undefined;
846
846
  includeEntryExports?: boolean | undefined;
847
847
  astro?: string | boolean | string[] | {
848
848
  config?: string | string[] | undefined;
@@ -1644,9 +1644,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
1644
1644
  project?: string | string[] | undefined;
1645
1645
  paths?: Record<string, string[]> | undefined;
1646
1646
  ignore?: string | string[] | undefined;
1647
- ignoreBinaries?: string[] | undefined;
1647
+ ignoreBinaries?: (string | RegExp)[] | undefined;
1648
+ ignoreDependencies?: (string | RegExp)[] | undefined;
1648
1649
  ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
1649
- ignoreDependencies?: string[] | undefined;
1650
1650
  ignoreWorkspaces?: string[] | undefined;
1651
1651
  includeEntryExports?: boolean | undefined;
1652
1652
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
@@ -1658,8 +1658,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
1658
1658
  project?: string | string[] | undefined;
1659
1659
  paths?: Record<string, string[]> | undefined;
1660
1660
  ignore?: string | string[] | undefined;
1661
- ignoreBinaries?: string[] | undefined;
1662
- ignoreDependencies?: string[] | undefined;
1661
+ ignoreBinaries?: (string | RegExp)[] | undefined;
1662
+ ignoreDependencies?: (string | RegExp)[] | undefined;
1663
1663
  includeEntryExports?: boolean | undefined;
1664
1664
  astro?: string | boolean | string[] | {
1665
1665
  config?: string | string[] | undefined;
@@ -2109,9 +2109,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
2109
2109
  project?: string | string[] | undefined;
2110
2110
  paths?: Record<string, string[]> | undefined;
2111
2111
  ignore?: string | string[] | undefined;
2112
- ignoreBinaries?: string[] | undefined;
2112
+ ignoreBinaries?: (string | RegExp)[] | undefined;
2113
+ ignoreDependencies?: (string | RegExp)[] | undefined;
2113
2114
  ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
2114
- ignoreDependencies?: string[] | undefined;
2115
2115
  ignoreWorkspaces?: string[] | undefined;
2116
2116
  includeEntryExports?: boolean | undefined;
2117
2117
  compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
@@ -2123,8 +2123,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
2123
2123
  project?: string | string[] | undefined;
2124
2124
  paths?: Record<string, string[]> | undefined;
2125
2125
  ignore?: string | string[] | undefined;
2126
- ignoreBinaries?: string[] | undefined;
2127
- ignoreDependencies?: string[] | undefined;
2126
+ ignoreBinaries?: (string | RegExp)[] | undefined;
2127
+ ignoreDependencies?: (string | RegExp)[] | undefined;
2128
2128
  includeEntryExports?: boolean | undefined;
2129
2129
  astro?: string | boolean | string[] | {
2130
2130
  config?: string | string[] | undefined;
@@ -5,6 +5,7 @@ const syncCompilerSchema = z.function().args(z.string()).returns(z.string());
5
5
  const asyncCompilerSchema = z.function().args(z.string()).returns(z.promise(z.string()));
6
6
  const compilerSchema = z.union([syncCompilerSchema, asyncCompilerSchema]);
7
7
  const compilersSchema = z.record(z.string(), compilerSchema);
8
+ const stringOrRegexSchema = z.array(z.union([z.string(), z.instanceof(RegExp)]));
8
9
  const issueTypeSchema = z.union([
9
10
  z.literal('files'),
10
11
  z.literal('dependencies'),
@@ -38,9 +39,9 @@ const rootConfigurationSchema = z.object({
38
39
  project: globSchema.optional(),
39
40
  paths: pathsSchema.optional(),
40
41
  ignore: globSchema.optional(),
41
- ignoreBinaries: z.array(z.string()).optional(),
42
+ ignoreBinaries: stringOrRegexSchema.optional(),
43
+ ignoreDependencies: stringOrRegexSchema.optional(),
42
44
  ignoreExportsUsedInFile: ignoreExportsUsedInFileSchema.optional(),
43
- ignoreDependencies: z.array(z.string()).optional(),
44
45
  ignoreWorkspaces: z.array(z.string()).optional(),
45
46
  includeEntryExports: z.boolean().optional(),
46
47
  compilers: compilersSchema.optional(),
@@ -111,8 +112,8 @@ const baseWorkspaceConfigurationSchema = z.object({
111
112
  project: globSchema.optional(),
112
113
  paths: pathsSchema.optional(),
113
114
  ignore: globSchema.optional(),
114
- ignoreBinaries: z.array(z.string()).optional(),
115
- ignoreDependencies: z.array(z.string()).optional(),
115
+ ignoreBinaries: stringOrRegexSchema.optional(),
116
+ ignoreDependencies: stringOrRegexSchema.optional(),
116
117
  includeEntryExports: z.boolean().optional(),
117
118
  });
118
119
  const workspaceConfigurationSchema = baseWorkspaceConfigurationSchema.merge(pluginsSchema.partial());
@@ -4,9 +4,11 @@ import type { ConfigurationHints, Issue } from './types/issues.js';
4
4
  import type { WorkspaceManifests, HostDependencies, InstalledBinaries } from './types/workspace.js';
5
5
  import type { PackageJson } from '@npmcli/package-json';
6
6
  type Options = {
7
+ isProduction: boolean;
7
8
  isStrict: boolean;
8
9
  };
9
10
  export declare class DependencyDeputy {
11
+ isProduction: boolean;
10
12
  isStrict: boolean;
11
13
  _manifests: WorkspaceManifests;
12
14
  referencedDependencies: Map<string, Set<string>>;
@@ -14,18 +16,18 @@ export declare class DependencyDeputy {
14
16
  hostDependencies: Map<string, HostDependencies>;
15
17
  installedBinaries: Map<string, InstalledBinaries>;
16
18
  hasTypesIncluded: Map<string, Set<string>>;
17
- ignoreBinaries: string[];
18
- ignoreDependencies: string[];
19
- constructor({ isStrict }: Options);
19
+ ignoreBinaries: (string | RegExp)[];
20
+ ignoreDependencies: (string | RegExp)[];
21
+ constructor({ isProduction, isStrict }: Options);
20
22
  addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries, }: {
21
23
  name: string;
22
24
  dir: string;
23
25
  manifestPath: string;
24
26
  manifest: PackageJson;
25
- ignoreDependencies: string[];
26
- ignoreBinaries: string[];
27
+ ignoreDependencies: (string | RegExp)[];
28
+ ignoreBinaries: (string | RegExp)[];
27
29
  }): void;
28
- addIgnored(ignoreBinaries: string[], ignoreDependencies: string[]): void;
30
+ addIgnored(ignoreBinaries: (string | RegExp)[], ignoreDependencies: (string | RegExp)[]): void;
29
31
  getWorkspaceManifest(workspaceName: string): {
30
32
  workspaceDir: string;
31
33
  manifestPath: string;
@@ -36,8 +38,8 @@ export declare class DependencyDeputy {
36
38
  optionalDependencies: string[];
37
39
  devDependencies: string[];
38
40
  allDependencies: string[];
39
- ignoreDependencies: string[];
40
- ignoreBinaries: string[];
41
+ ignoreDependencies: (string | RegExp)[];
42
+ ignoreBinaries: (string | RegExp)[];
41
43
  } | undefined;
42
44
  getProductionDependencies(workspaceName: string): string[];
43
45
  getDevDependencies(workspaceName: string): string[];
@@ -1,7 +1,9 @@
1
1
  import { isBuiltin } from 'node:module';
2
2
  import { IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_GLOBAL_BINARIES, ROOT_WORKSPACE_NAME, } from './constants.js';
3
3
  import { isDefinitelyTyped, getDefinitelyTypedFor, getPackageFromDefinitelyTyped } from './util/modules.js';
4
+ import { hasMatch, hasMatchInArray, hasMatchInSet } from './util/regex.js';
4
5
  export class DependencyDeputy {
6
+ isProduction;
5
7
  isStrict;
6
8
  _manifests = new Map();
7
9
  referencedDependencies;
@@ -11,7 +13,8 @@ export class DependencyDeputy {
11
13
  hasTypesIncluded;
12
14
  ignoreBinaries = [];
13
15
  ignoreDependencies = [];
14
- constructor({ isStrict }) {
16
+ constructor({ isProduction, isStrict }) {
17
+ this.isProduction = isProduction;
15
18
  this.isStrict = isStrict;
16
19
  this.referencedDependencies = new Map();
17
20
  this.referencedBinaries = new Map();
@@ -122,9 +125,9 @@ export class DependencyDeputy {
122
125
  else {
123
126
  this.addReferencedDependency(workspace.name, packageName);
124
127
  }
125
- if (this.getWorkspaceManifest(workspace.name)?.ignoreDependencies.includes(packageName))
128
+ if (hasMatch(this.getWorkspaceManifest(workspace.name)?.ignoreDependencies, packageName))
126
129
  return true;
127
- if (this.ignoreDependencies.includes(packageName))
130
+ if (hasMatch(this.ignoreDependencies, packageName))
128
131
  return true;
129
132
  return false;
130
133
  }
@@ -143,9 +146,9 @@ export class DependencyDeputy {
143
146
  }
144
147
  }
145
148
  }
146
- if (this.getWorkspaceManifest(workspace.name)?.ignoreBinaries.includes(binaryName))
149
+ if (hasMatch(this.getWorkspaceManifest(workspace.name)?.ignoreBinaries, binaryName))
147
150
  return true;
148
- if (this.ignoreBinaries.includes(binaryName))
151
+ if (hasMatch(this.ignoreBinaries, binaryName))
149
152
  return true;
150
153
  return false;
151
154
  }
@@ -166,12 +169,14 @@ export class DependencyDeputy {
166
169
  const hasTypesIncluded = this.getHasTypesIncluded(workspaceName);
167
170
  const ignoreBins = [...IGNORED_GLOBAL_BINARIES, ...this.ignoreBinaries, ...ignoreBinaries];
168
171
  const ignoreDeps = [...IGNORED_DEPENDENCIES, ...this.ignoreDependencies, ...ignoreDependencies];
169
- const isNotIgnoredDependency = (packageName) => !ignoreDeps.includes(packageName);
172
+ const isNotIgnoredDependency = (packageName) => !hasMatch(ignoreDeps, packageName);
170
173
  const isNotIgnoredBinary = (packageName) => {
171
174
  if (installedBinaries?.has(packageName)) {
172
175
  const binaryNames = installedBinaries.get(packageName);
173
176
  if (binaryNames) {
174
- if (ignoreBins.some(ignoredBinary => binaryNames.has(ignoredBinary)))
177
+ if (ignoreBins.some(binaryName => typeof binaryName === 'string'
178
+ ? binaryNames.has(binaryName)
179
+ : [...binaryNames].some(n => binaryName.test(n))))
175
180
  return false;
176
181
  }
177
182
  }
@@ -225,30 +230,56 @@ export class DependencyDeputy {
225
230
  }
226
231
  getConfigurationHints() {
227
232
  const configurationHints = new Set();
228
- const rootIgnoreBinaries = Object.fromEntries(this.ignoreBinaries.map(key => [key, 0]));
229
- const rootIgnoreDependencies = Object.fromEntries(this.ignoreDependencies.map(key => [key, 0]));
233
+ const rootIgnoreBinaries = new Map(this.ignoreBinaries.map(key => [key, 0]));
234
+ const rootIgnoreDependencies = new Map(this.ignoreDependencies.map(key => [key, 0]));
230
235
  for (const [workspaceName, { ignoreDependencies, ignoreBinaries }] of this._manifests.entries()) {
231
236
  const referencedDependencies = this.referencedDependencies.get(workspaceName);
232
237
  const referencedBinaries = this.referencedBinaries.get(workspaceName);
233
238
  const installedBinaries = this.getInstalledBinaries(workspaceName);
234
- referencedDependencies?.forEach(pkg => pkg in rootIgnoreDependencies && rootIgnoreDependencies[pkg]++);
235
- referencedBinaries?.forEach(binaryName => binaryName in rootIgnoreBinaries && rootIgnoreBinaries[binaryName]++);
239
+ referencedDependencies?.forEach(pkg => {
240
+ for (const key of rootIgnoreDependencies.keys()) {
241
+ if ((typeof key === 'string' && key === pkg) || (key instanceof RegExp && key.test(pkg))) {
242
+ rootIgnoreDependencies.set(key, rootIgnoreDependencies.get(key) + 1);
243
+ return;
244
+ }
245
+ }
246
+ });
247
+ referencedBinaries?.forEach(binaryName => {
248
+ for (const key of rootIgnoreBinaries.keys()) {
249
+ if ((typeof key === 'string' && key === binaryName) || (key instanceof RegExp && key.test(binaryName))) {
250
+ rootIgnoreBinaries.set(key, rootIgnoreBinaries.get(key) + 1);
251
+ return;
252
+ }
253
+ }
254
+ });
236
255
  const dependencies = [
237
256
  ...this.getProductionDependencies(workspaceName),
238
257
  ...this.getDevDependencies(workspaceName),
239
258
  ];
240
259
  const peerDependencies = this.getPeerDependencies(workspaceName);
241
- const isReferencedDep = (name) => referencedDependencies?.has(name) && dependencies.includes(name);
242
- const isReferencedBin = (name) => referencedBinaries?.has(name) && installedBinaries?.has(name);
243
260
  ignoreDependencies
244
- .filter(packageName => IGNORED_DEPENDENCIES.includes(packageName) ||
245
- (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreDependencies.includes(packageName)) ||
246
- (!peerDependencies.includes(packageName) && isReferencedDep(packageName)))
247
- .forEach(identifier => configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' }));
261
+ .filter(packageName => {
262
+ if (hasMatchInArray(IGNORED_DEPENDENCIES, packageName))
263
+ return true;
264
+ if (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreDependencies.includes(packageName))
265
+ return true;
266
+ const isReferenced = hasMatchInSet(referencedDependencies, packageName);
267
+ const isListed = hasMatchInArray(dependencies, packageName) && !hasMatchInArray(peerDependencies, packageName);
268
+ return isListed && isReferenced;
269
+ })
270
+ .forEach(identifier => {
271
+ configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
272
+ });
248
273
  ignoreBinaries
249
- .filter(binaryName => IGNORED_GLOBAL_BINARIES.includes(binaryName) ||
250
- (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreBinaries.includes(binaryName)) ||
251
- isReferencedBin(binaryName))
274
+ .filter(binaryName => {
275
+ if (hasMatchInArray(IGNORED_GLOBAL_BINARIES, binaryName))
276
+ return true;
277
+ if (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreBinaries.includes(binaryName))
278
+ return true;
279
+ const isReferenced = hasMatchInSet(referencedBinaries, binaryName);
280
+ const isInstalled = hasMatchInArray(Array.from(installedBinaries?.keys() ?? []), binaryName);
281
+ return isReferenced && isInstalled;
282
+ })
252
283
  .forEach(identifier => configurationHints.add({ workspaceName, identifier, type: 'ignoreBinaries' }));
253
284
  }
254
285
  const installedBinaries = this.getInstalledBinaries(ROOT_WORKSPACE_NAME);
@@ -257,12 +288,23 @@ export class DependencyDeputy {
257
288
  ...this.getDevDependencies(ROOT_WORKSPACE_NAME),
258
289
  ];
259
290
  const peerDependencies = this.getPeerDependencies(ROOT_WORKSPACE_NAME);
260
- Object.keys(rootIgnoreBinaries)
261
- .filter(key => IGNORED_GLOBAL_BINARIES.includes(key) || (rootIgnoreBinaries[key] !== 0 && installedBinaries?.has(key)))
291
+ Array.from(rootIgnoreBinaries.keys())
292
+ .filter(binaryName => {
293
+ if (hasMatchInArray(IGNORED_GLOBAL_BINARIES, binaryName))
294
+ return true;
295
+ const isReferenced = rootIgnoreBinaries.get(binaryName) !== 0;
296
+ const isInstalled = hasMatchInArray(Array.from(installedBinaries?.keys() ?? []), binaryName);
297
+ return (isReferenced && isInstalled) || (!this.isProduction && !isReferenced && !isInstalled);
298
+ })
262
299
  .forEach(identifier => configurationHints.add({ workspaceName: ROOT_WORKSPACE_NAME, identifier, type: 'ignoreBinaries' }));
263
- Object.keys(rootIgnoreDependencies)
264
- .filter(key => IGNORED_DEPENDENCIES.includes(key) ||
265
- (rootIgnoreDependencies[key] === 0 && !peerDependencies.includes(key) && !dependencies.includes(key)))
300
+ Array.from(rootIgnoreDependencies.keys())
301
+ .filter(packageName => {
302
+ if (hasMatchInArray(IGNORED_DEPENDENCIES, packageName))
303
+ return true;
304
+ const isReferenced = rootIgnoreDependencies.get(packageName) !== 0;
305
+ const isListed = hasMatchInArray(dependencies, packageName) && !hasMatchInArray(peerDependencies, packageName);
306
+ return (isReferenced && isListed) || (!this.isProduction && !isReferenced && !isListed);
307
+ })
266
308
  .forEach(identifier => configurationHints.add({ workspaceName: ROOT_WORKSPACE_NAME, identifier, type: 'ignoreDependencies' }));
267
309
  return { configurationHints };
268
310
  }
@@ -1,9 +1,6 @@
1
1
  import { initIssues, initCounters } from './issues/initializers.js';
2
2
  import { relative } from './util/path.js';
3
- function objectInSet(set, obj) {
4
- const objJSON = JSON.stringify(obj);
5
- return Array.from(set).some(item => JSON.stringify(item) === objJSON);
6
- }
3
+ const hasHint = (hints, hint) => Array.from(hints).some(item => item.identifier === hint.identifier && item.type === hint.type && item.workspaceName === hint.workspaceName);
7
4
  export class IssueCollector {
8
5
  cwd;
9
6
  rules;
@@ -44,7 +41,7 @@ export class IssueCollector {
44
41
  }
45
42
  }
46
43
  addConfigurationHint(issue) {
47
- if (!objectInSet(this.configurationHints, issue)) {
44
+ if (!hasHint(this.configurationHints, issue)) {
48
45
  this.configurationHints.add(issue);
49
46
  }
50
47
  }
@@ -7,7 +7,8 @@ import { getImportsAndExports } from './typescript/getImportsAndExports.js';
7
7
  import { createCustomModuleResolver } from './typescript/resolveModuleNames.js';
8
8
  import { SourceFileManager } from './typescript/SourceFileManager.js';
9
9
  import { compact } from './util/array.js';
10
- import { isMaybePackageName, sanitizeSpecifier } from './util/modules.js';
10
+ import { debugLog } from './util/debug.js';
11
+ import { isStartsLikePackageName, sanitizeSpecifier } from './util/modules.js';
11
12
  import { dirname, extname, isInNodeModules, join } from './util/path.js';
12
13
  import { timerify } from './util/Performance.js';
13
14
  const baseCompilerOptions = {
@@ -145,7 +146,7 @@ export class ProjectPrincipal {
145
146
  }
146
147
  else {
147
148
  const sanitizedSpecifier = sanitizeSpecifier(specifier);
148
- if (isMaybePackageName(sanitizedSpecifier)) {
149
+ if (isStartsLikePackageName(sanitizedSpecifier)) {
149
150
  external.add(sanitizedSpecifier);
150
151
  }
151
152
  else {
@@ -210,7 +211,8 @@ export class ProjectPrincipal {
210
211
  try {
211
212
  return this.backend.lsFindReferences(filePath, pos) ?? [];
212
213
  }
213
- catch {
214
+ catch (error) {
215
+ debugLog('*', String(error));
214
216
  return [];
215
217
  }
216
218
  }
@@ -4,7 +4,7 @@ import { debugLogArray, debugLogObject } from './util/debug.js';
4
4
  import { _pureGlob, negate, hasProductionSuffix, hasNoProductionSuffix, prependDirToPattern } from './util/glob.js';
5
5
  import { FAKE_PATH } from './util/loader.js';
6
6
  import { get, getKeysByValue } from './util/object.js';
7
- import { join, toPosix } from './util/path.js';
7
+ import { basename, join, toPosix } from './util/path.js';
8
8
  import { fromEntryPattern, fromProductionEntryPattern, isEntryPattern, isProductionEntryPattern, } from './util/protocols.js';
9
9
  const nullConfig = { config: null, entry: null, project: null };
10
10
  export class WorkspaceWorker {
@@ -183,7 +183,7 @@ export class WorkspaceWorker {
183
183
  continue;
184
184
  const patterns = this.getConfigurationFilePatterns(pluginName);
185
185
  const allConfigFilePaths = await _pureGlob({ patterns, cwd, ignore, gitignore: false });
186
- const configFilePaths = allConfigFilePaths.filter(filePath => !filePath.endsWith('package.json') ||
186
+ const configFilePaths = allConfigFilePaths.filter(filePath => basename(filePath) !== 'package.json' ||
187
187
  get(this.manifest, 'PACKAGE_JSON_PATH' in plugin ? plugin.PACKAGE_JSON_PATH : pluginName));
188
188
  debugLogArray([name, plugin.NAME], 'config file paths', configFilePaths);
189
189
  if (configFilePaths.length === 0)
package/dist/constants.js CHANGED
@@ -33,6 +33,7 @@ export const IGNORED_GLOBAL_BINARIES = [
33
33
  'test',
34
34
  'true',
35
35
  'yarn',
36
+ 'xargs',
36
37
  ];
37
38
  export const IGNORED_DEPENDENCIES = ['knip', 'typescript'];
38
39
  export const DUMMY_VIRTUAL_FILE_EXTENSIONS = new Set(['.html', '.jpeg', '.jpg', '.png', '.svg', '.webp']);
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ export const main = async (unresolvedConfiguration) => {
19
19
  const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isShowProgress, isIncludeEntryExports, isIsolateWorkspaces, } = unresolvedConfiguration;
20
20
  debugLogObject('*', 'Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
21
21
  const chief = new ConfigurationChief({ cwd, isProduction, isStrict, isIncludeEntryExports });
22
- const deputy = new DependencyDeputy({ isStrict });
22
+ const deputy = new DependencyDeputy({ isProduction, isStrict });
23
23
  const factory = new PrincipalFactory();
24
24
  const streamer = new ConsoleStreamer({ isEnabled: isShowProgress });
25
25
  const isGitIgnored = gitignore ? isGitIgnoredSync({ cwd }) : () => false;
@@ -214,15 +214,14 @@ export const main = async (unresolvedConfiguration) => {
214
214
  }
215
215
  else {
216
216
  const importedModule = importedSymbols.get(specifierFilePath);
217
- for (const identifier of importItems.symbols) {
217
+ for (const identifier of importItems.symbols)
218
218
  importedModule.symbols.add(identifier);
219
- }
219
+ if (importItems.hasStar)
220
+ importedModule.hasStar = true;
220
221
  if (importItems.isReExport) {
221
- importedModule.isReExport = importItems.isReExport;
222
+ importedModule.isReExport = true;
222
223
  importedModule.isReExportedBy.add(filePath);
223
224
  }
224
- if (importItems.isStar)
225
- importedModule.isStar = importItems.isStar;
226
225
  }
227
226
  }
228
227
  duplicate.forEach(symbols => {
@@ -299,16 +298,17 @@ export const main = async (unresolvedConfiguration) => {
299
298
  const workspace = chief.findWorkspaceByFilePath(filePath);
300
299
  const principal = workspace && factory.getPrincipalByPackageName(workspace.pkgName);
301
300
  if (principal) {
302
- if (!workspace.config.isIncludeEntryExports && principal.entryPaths.has(filePath))
301
+ const { isIncludeEntryExports } = workspace.config;
302
+ if (!isIncludeEntryExports && principal.entryPaths.has(filePath))
303
303
  continue;
304
- const importingModule = importedSymbols.get(filePath);
304
+ const importsForExport = importedSymbols.get(filePath);
305
305
  for (const [symbol, exportedItem] of exportItems.entries()) {
306
306
  if (exportedItem.jsDocTags.has('@public') || exportedItem.jsDocTags.has('@beta'))
307
307
  continue;
308
308
  if (isProduction && exportedItem.jsDocTags.has('@internal'))
309
309
  continue;
310
- if (importingModule && isSymbolImported(symbol, importingModule)) {
311
- if (importingModule.isReExport && isExportedInEntryFile(principal, importingModule))
310
+ if (importsForExport && isSymbolImported(symbol, importsForExport)) {
311
+ if (importsForExport.isReExport && isExportedInEntryFile(principal, importsForExport))
312
312
  continue;
313
313
  if (report.enumMembers && exportedItem.type === 'enum' && exportedItem.members) {
314
314
  principal.findUnusedMembers(filePath, exportedItem.members).forEach(member => {
@@ -334,28 +334,20 @@ export const main = async (unresolvedConfiguration) => {
334
334
  }
335
335
  continue;
336
336
  }
337
- const isStar = Boolean(importingModule?.isStar);
338
- const isReExportedByEntryFile = !workspace.config.isIncludeEntryExports && isStar && isExportedInEntryFile(principal, importingModule);
339
- if (!isReExportedByEntryFile && !isExportedItemReferenced(principal, exportedItem, filePath)) {
340
- if (['enum', 'type', 'interface'].includes(exportedItem.type)) {
341
- const type = isStar ? 'nsTypes' : 'types';
342
- collector.addIssue({
343
- type,
344
- filePath,
345
- symbol,
346
- symbolType: exportedItem.type,
347
- ...principal.getPos(exportedItem.node, exportedItem.pos),
348
- });
349
- }
350
- else {
351
- const type = isStar ? 'nsExports' : 'exports';
352
- collector.addIssue({
353
- type,
354
- filePath,
355
- symbol,
356
- ...principal.getPos(exportedItem.node, exportedItem.pos),
357
- });
358
- }
337
+ const hasNsImport = Boolean(importsForExport?.hasStar);
338
+ const isReExport = !isIncludeEntryExports && hasNsImport && isExportedInEntryFile(principal, importsForExport);
339
+ const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
340
+ if (hasNsImport && ((!report.nsTypes && isType) || (!report.nsExports && !isType)))
341
+ continue;
342
+ if (!isReExport && !isExportedItemReferenced(principal, exportedItem, filePath)) {
343
+ const type = isType ? (hasNsImport ? 'nsTypes' : 'types') : hasNsImport ? 'nsExports' : 'exports';
344
+ collector.addIssue({
345
+ type,
346
+ filePath,
347
+ symbol,
348
+ symbolType: exportedItem.type,
349
+ ...principal.getPos(exportedItem.node, exportedItem.pos),
350
+ });
359
351
  }
360
352
  }
361
353
  }
@@ -1,3 +1,4 @@
1
+ import { basename } from '../../util/path.js';
1
2
  import { timerify } from '../../util/Performance.js';
2
3
  import { hasDependency, load } from '../../util/plugin.js';
3
4
  import { toEntryPattern, toProductionEntryPattern } from '../../util/protocols.js';
@@ -10,10 +11,7 @@ export const PRODUCTION_ENTRY_FILE_PATTERNS = [];
10
11
  export const PROJECT_FILE_PATTERNS = [];
11
12
  const findPluginDependencies = async (configFilePath, options) => {
12
13
  const { manifest, config, isProduction } = options;
13
- const localConfig = configFilePath.endsWith('package.json')
14
- ?
15
- manifest.plugin
16
- : await load(configFilePath);
14
+ const localConfig = basename(configFilePath) === 'package.json' ? manifest.plugin : await load(configFilePath);
17
15
  if (!localConfig)
18
16
  return [];
19
17
  const entryPatterns = (config?.entry ?? localConfig.entryPathsOrPatterns ?? ENTRY_FILE_PATTERNS).map(toEntryPattern);
@@ -12,7 +12,7 @@ export const findDependencies = async (configFilePath, options) => {
12
12
  : [...ENTRY_FILE_PATTERNS.map(toEntryPattern), ...PRODUCTION_ENTRY_FILE_PATTERNS.map(toProductionEntryPattern)];
13
13
  if (!isProduction &&
14
14
  manifest.scripts &&
15
- Object.values(manifest.scripts).some(script => /astro (--.+ )?check/.test(script))) {
15
+ Object.values(manifest.scripts).some(script => /(?<=^|\s)astro(\s|\s.+\s)check(?=\s|$)/.test(script))) {
16
16
  dependencies.push('@astrojs/check');
17
17
  }
18
18
  return dependencies;
@@ -1,6 +1,6 @@
1
- import { _getDependenciesFromScripts } from '../../binaries/index.js';
1
+ import { basename } from '../../util/path.js';
2
2
  import { timerify } from '../../util/Performance.js';
3
- import { hasDependency, load } from '../../util/plugin.js';
3
+ import { getDependenciesFromScripts, hasDependency, load } from '../../util/plugin.js';
4
4
  import { toEntryPattern } from '../../util/protocols.js';
5
5
  export const NAME = 'Ava';
6
6
  export const ENABLERS = ['ava'];
@@ -20,9 +20,7 @@ export const ENTRY_FILE_PATTERNS = [
20
20
  ];
21
21
  const findAvaDependencies = async (configFilePath, options) => {
22
22
  const { cwd, manifest, isProduction, config } = options;
23
- let localConfig = configFilePath.endsWith('package.json')
24
- ? manifest.ava
25
- : await load(configFilePath);
23
+ let localConfig = basename(configFilePath) === 'package.json' ? manifest.ava : await load(configFilePath);
26
24
  if (typeof localConfig === 'function')
27
25
  localConfig = localConfig();
28
26
  const entryPatterns = (config.entry ?? localConfig?.files ?? ENTRY_FILE_PATTERNS).map(toEntryPattern);
@@ -31,7 +29,7 @@ const findAvaDependencies = async (configFilePath, options) => {
31
29
  const nodeArgs = localConfig.nodeArguments ?? [];
32
30
  const requireArgs = (localConfig.require ?? []).map(require => `--require ${require}`);
33
31
  const fakeCommand = `node ${nodeArgs.join(' ')} ${requireArgs.join(' ')}`;
34
- const dependencies = _getDependenciesFromScripts([fakeCommand], {
32
+ const dependencies = getDependenciesFromScripts([fakeCommand], {
35
33
  cwd,
36
34
  manifest,
37
35
  knownGlobalsOnly: true,
@@ -1,4 +1,5 @@
1
1
  import { compact } from '../../util/array.js';
2
+ import { basename } from '../../util/path.js';
2
3
  import { timerify } from '../../util/Performance.js';
3
4
  import { hasDependency, load } from '../../util/plugin.js';
4
5
  import { resolveName, api } from './helpers.js';
@@ -21,9 +22,7 @@ export const getDependenciesFromConfig = (config) => {
21
22
  const findBabelDependencies = async (configFilePath, { manifest, isProduction }) => {
22
23
  if (isProduction)
23
24
  return [];
24
- let localConfig = configFilePath.endsWith('package.json')
25
- ? manifest.babel
26
- : await load(configFilePath);
25
+ let localConfig = basename(configFilePath) === 'package.json' ? manifest.babel : await load(configFilePath);
27
26
  if (typeof localConfig === 'function')
28
27
  localConfig = localConfig(api);
29
28
  if (!localConfig)
@@ -1,3 +1,4 @@
1
+ import { basename } from '../../util/path.js';
1
2
  import { timerify } from '../../util/Performance.js';
2
3
  import { hasDependency, load } from '../../util/plugin.js';
3
4
  export const NAME = 'Commitizen';
@@ -8,9 +9,7 @@ export const CONFIG_FILE_PATTERNS = ['.czrc', '.cz.json', 'package.json'];
8
9
  const findPluginDependencies = async (configFilePath, { manifest, isProduction }) => {
9
10
  if (isProduction)
10
11
  return [];
11
- const localConfig = configFilePath.endsWith('package.json')
12
- ? manifest.config?.commitizen
13
- : await load(configFilePath);
12
+ const localConfig = basename(configFilePath) === 'package.json' ? manifest.config?.commitizen : await load(configFilePath);
14
13
  if (!localConfig)
15
14
  return [];
16
15
  return localConfig.path ? [localConfig.path] : [];
@@ -1,3 +1,4 @@
1
+ import { basename } from '../../util/path.js';
1
2
  import { timerify } from '../../util/Performance.js';
2
3
  import { hasDependency, load } from '../../util/plugin.js';
3
4
  export const NAME = 'commitlint';
@@ -12,9 +13,7 @@ export const CONFIG_FILE_PATTERNS = [
12
13
  const findCommitLintDependencies = async (configFilePath, { manifest, isProduction }) => {
13
14
  if (isProduction)
14
15
  return [];
15
- const localConfig = configFilePath.endsWith('package.json')
16
- ? manifest.commitlint
17
- : await load(configFilePath);
16
+ const localConfig = basename(configFilePath) === 'package.json' ? manifest.commitlint : await load(configFilePath);
18
17
  if (!localConfig)
19
18
  return [];
20
19
  return localConfig.extends ? [localConfig.extends].flat() : [];