knip 2.17.3 → 2.19.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 (39) hide show
  1. package/README.md +7 -4
  2. package/dist/ConfigurationChief.js +4 -0
  3. package/dist/DependencyDeputy.d.ts +1 -1
  4. package/dist/PrincipalFactory.js +1 -0
  5. package/dist/ProjectPrincipal.js +1 -0
  6. package/dist/WorkspaceWorker.d.ts +2 -2
  7. package/dist/constants.d.ts +1 -0
  8. package/dist/constants.js +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/issues/initializers.d.ts +1 -1
  11. package/dist/manifest/index.js +2 -1
  12. package/dist/plugins/babel/types.js +1 -1
  13. package/dist/plugins/eslint/helpers.d.ts +1 -0
  14. package/dist/plugins/eslint/helpers.js +6 -10
  15. package/dist/plugins/jest/index.js +19 -10
  16. package/dist/plugins/typescript/index.js +19 -3
  17. package/dist/plugins/vitest/index.js +1 -1
  18. package/dist/reporters/util.d.ts +1 -1
  19. package/dist/types/config.d.ts +1 -1
  20. package/dist/types/config.js +3 -1
  21. package/dist/types/exports.js +1 -1
  22. package/dist/typescript/SourceFile.d.ts +6 -0
  23. package/dist/typescript/SourceFile.js +1 -1
  24. package/dist/typescript/SourceFileManager.js +3 -2
  25. package/dist/typescript/getImportsAndExports.js +4 -0
  26. package/dist/typescript/visitors/exports/index.js +1 -0
  27. package/dist/typescript/visitors/helpers.d.ts +2 -1
  28. package/dist/typescript/visitors/helpers.js +7 -0
  29. package/dist/typescript/visitors/imports/index.js +1 -0
  30. package/dist/typescript/visitors/index.js +1 -0
  31. package/dist/typescript/visitors/scripts/index.js +1 -0
  32. package/dist/util/Performance.js +1 -1
  33. package/dist/util/cli-arguments.d.ts +1 -1
  34. package/dist/util/cli-arguments.js +2 -2
  35. package/dist/util/compilers.d.ts +2 -2
  36. package/dist/util/glob.js +4 -4
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/package.json +5 -5
package/README.md CHANGED
@@ -136,14 +136,14 @@ Using workspaces in a monorepo? Please see [workspaces][1] for more details abou
136
136
  -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)
137
137
  --production Analyze only production source files (e.g. no tests, devDependencies, exported types)
138
138
  --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)
139
- --workspace Analyze a single workspace (default: analyze all configured workspaces)
139
+ --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)
140
140
  --no-gitignore Don't use .gitignore
141
141
  --include Report only provided issue type(s), can be comma-separated or repeated (1)
142
142
  --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)
143
143
  --dependencies Shortcut for --include dependencies,unlisted,unresolved
144
144
  --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
145
145
  --include-entry-exports Include entry files when reporting unused exports
146
- -n, --no-progress Don't show dynamic progress updates (this is automatically enabled in CI environments)
146
+ -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
147
147
  --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
148
148
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
149
149
  --no-config-hints Suppress configuration hints
@@ -330,9 +330,10 @@ Knip supports workspaces as defined in three possible locations:
330
330
  - In the `workspaces` array in `package.json` (npm, Yarn, Lerna).
331
331
  - In the `workspaces.packages` array in `package.json` (legacy).
332
332
  - In the `packages` array in `pnpm-workspace.yaml` (pnpm).
333
+ - In the `workspaces` object in Knip configuration.
333
334
 
334
- Extra "workspaces" not configured as a workspace in the root `package.json` can be configured as well, Knip is happy to
335
- analyze unused dependencies and exports from any directory with a `package.json`.
335
+ The `workspaces` in Knip configuration not already defined in the root `package.json` or `pnpm-workspace.yaml` are
336
+ added. Knip requires a `package.json` file in each workspace directory.
336
337
 
337
338
  The `ignore`, `ignoreBinaries` and `ignoreDependencies` options are available inside workspace configurations.
338
339
 
@@ -342,6 +343,8 @@ Here's some example output when running Knip in a workspace:
342
343
 
343
344
  Use `--debug` to get more verbose output.
344
345
 
346
+ Use `--workspace [dir]` to analyze a single workspace (including its ancestors).
347
+
345
348
  ## Plugins
346
349
 
347
350
  Plugins tell Knip where to look for configuration and entry files, and if necessary have a custom dependency finder.
@@ -1,3 +1,4 @@
1
+ import { existsSync } from 'node:fs';
1
2
  import mapWorkspaces from '@npmcli/map-workspaces';
2
3
  import micromatch from 'micromatch';
3
4
  import { ConfigurationValidator } from './ConfigurationValidator.js';
@@ -214,6 +215,9 @@ export class ConfigurationChief {
214
215
  return [ROOT_WORKSPACE_NAME, ...this.manifestWorkspaces.keys(), ...this.additionalWorkspaceNames].filter(name => !micromatch.isMatch(name, this.ignoredWorkspacePatterns));
215
216
  }
216
217
  getEnabledWorkspaces() {
218
+ if (workspaceArg && !existsSync(workspaceArg)) {
219
+ throw new ConfigurationError(`Directory does not exist: ${workspaceArg}`);
220
+ }
217
221
  const workspaceNames = workspaceArg
218
222
  ? this.enabledWorkspaceNames.filter(name => name === workspaceArg)
219
223
  : this.enabledWorkspaceNames;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="npmcli__package-json" />
2
- import { Workspace } from './ConfigurationChief.js';
2
+ import type { Workspace } from './ConfigurationChief.js';
3
3
  import type { ConfigurationHints, Issue } from './types/issues.js';
4
4
  import type { WorkspaceManifests } from './types/workspace.js';
5
5
  import type { PeerDependencies, InstalledBinaries } from './types/workspace.js';
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript';
1
2
  import { ProjectPrincipal } from './ProjectPrincipal.js';
2
3
  import { toAbsolute } from './util/path.js';
3
4
  const mergePaths = (cwd, compilerOptions, paths = {}) => {
@@ -4,6 +4,7 @@ import { IGNORED_FILE_EXTENSIONS } from './constants.js';
4
4
  import { isInModuleBlock } from './typescript/ast-helpers.js';
5
5
  import { createHosts } from './typescript/createHosts.js';
6
6
  import { getImportsAndExports } from './typescript/getImportsAndExports.js';
7
+ import { SourceFileManager } from './typescript/SourceFileManager.js';
7
8
  import { isMaybePackageName } from './util/modules.js';
8
9
  import { extname, isInNodeModules } from './util/path.js';
9
10
  import { timerify } from './util/Performance.js';
@@ -1,6 +1,6 @@
1
- import { PackageJsonWithPlugins } from './types/plugins.js';
2
- import { InstalledBinaries, PeerDependencies } from './types/workspace.js';
3
1
  import type { Configuration, PluginName, WorkspaceConfiguration } from './types/config.js';
2
+ import type { PackageJsonWithPlugins } from './types/plugins.js';
3
+ import type { InstalledBinaries, PeerDependencies } from './types/workspace.js';
4
4
  type WorkspaceManagerOptions = {
5
5
  name: string;
6
6
  dir: string;
@@ -3,6 +3,7 @@ export declare const ROOT_WORKSPACE_NAME = ".";
3
3
  export declare const KNIP_CONFIG_LOCATIONS: string[];
4
4
  export declare const DEFAULT_EXTENSIONS: string[];
5
5
  export declare const TEST_FILE_PATTERNS: string[];
6
+ export declare const GLOBAL_IGNORE_PATTERNS: string[];
6
7
  export declare const IGNORED_GLOBAL_BINARIES: string[];
7
8
  export declare const IGNORED_DEPENDENCIES: string[];
8
9
  export declare const IGNORED_FILE_EXTENSIONS: string[];
package/dist/constants.js CHANGED
@@ -5,6 +5,7 @@ export const TEST_FILE_PATTERNS = [
5
5
  '**/*{.,-}{test,spec}.{js,jsx,ts,tsx,mjs,cjs}',
6
6
  '**/{test,__tests__}/**/*.{js,jsx,ts,tsx,mjs,cjs}',
7
7
  ];
8
+ export const GLOBAL_IGNORE_PATTERNS = ['**/node_modules/**', '.yarn'];
8
9
  export const IGNORED_GLOBAL_BINARIES = [
9
10
  'bash',
10
11
  'bun',
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { ROOT_WORKSPACE_NAME } from './constants.js';
7
7
  import { DependencyDeputy } from './DependencyDeputy.js';
8
8
  import { IssueCollector } from './IssueCollector.js';
9
9
  import { PrincipalFactory } from './PrincipalFactory.js';
10
+ import { ProjectPrincipal } from './ProjectPrincipal.js';
10
11
  import { compact } from './util/array.js';
11
12
  import { debugLogObject, debugLogArray, debugLog } from './util/debug.js';
12
13
  import { LoaderError } from './util/errors.js';
@@ -1,4 +1,4 @@
1
- import { Issues, Counters, Rules } from '../types/issues.js';
1
+ import type { Issues, Counters, Rules } from '../types/issues.js';
2
2
  export declare const initIssues: () => Issues;
3
3
  export declare const initCounters: () => Counters;
4
4
  export declare const defaultRules: Rules;
@@ -20,7 +20,8 @@ const findManifestDependencies = async ({ manifest, isProduction, isStrict, dir,
20
20
  for (const packageName of packageNames) {
21
21
  const manifest = await getPackageManifest({ dir, packageName, cwd });
22
22
  if (manifest) {
23
- const binaries = typeof manifest.bin === 'string' ? [packageName] : Object.keys(manifest.bin ?? {});
23
+ const binaryName = packageName.replace(/^@[^/]+\//, '');
24
+ const binaries = typeof manifest.bin === 'string' ? [binaryName] : Object.keys(manifest.bin ?? {});
24
25
  binaries.forEach(binaryName => {
25
26
  if (installedBinaries.has(binaryName)) {
26
27
  installedBinaries.get(binaryName)?.add(packageName);
@@ -1 +1 @@
1
- export {};
1
+ import { api } from './helpers.js';
@@ -9,4 +9,5 @@ type GetDependenciesDeep = (configFilePath: string, dependencies: Set<string>, o
9
9
  manifest: Manifest;
10
10
  }) => Promise<Set<string>>;
11
11
  export declare const getDependenciesDeep: GetDependenciesDeep;
12
+ export declare const resolveExtendsSpecifier: (specifier: string) => string | undefined;
12
13
  export {};
@@ -56,21 +56,17 @@ const resolvePackageName = (namespace, pluginName) => {
56
56
  : `${namespace}-${pluginName}`;
57
57
  };
58
58
  const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
59
- const resolveExtendsSpecifier = (specifier) => {
59
+ export const resolveExtendsSpecifier = (specifier) => {
60
60
  if (isInternal(specifier))
61
61
  return;
62
62
  if (/\/eslint-(config|plugin)/.test(specifier))
63
63
  return specifier;
64
- const strippedSpecifier = specifier
65
- .replace(/(^plugin:|:.+$)/, '')
66
- .replace(/\/(eslint-)?(recommended.*|stylistic.*|strict.*|all)$/, '');
67
- if (/eslint-(config|plugin)-/.test(strippedSpecifier))
68
- return strippedSpecifier;
69
- const packageName = getPackageNameFromModuleSpecifier(strippedSpecifier);
70
- if (!packageName)
71
- return;
72
- if (packageName === 'eslint')
64
+ const noProtocolSpecifier = specifier.replace(/(^plugin:|:.+$)/, '');
65
+ if (noProtocolSpecifier.startsWith('@typescript-eslint/'))
66
+ return '@typescript-eslint/eslint-plugin';
67
+ if (noProtocolSpecifier === 'eslint')
73
68
  return;
69
+ const packageName = getPackageNameFromModuleSpecifier(noProtocolSpecifier) ?? noProtocolSpecifier;
74
70
  return resolvePackageName(specifier.startsWith('plugin:') ? 'eslint-plugin' : 'eslint-config', packageName);
75
71
  };
76
72
  const getDependenciesFromSettings = (settings = {}) => {
@@ -17,16 +17,12 @@ const resolveExtensibleConfig = async (configFilePath) => {
17
17
  }
18
18
  return config;
19
19
  };
20
- const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
21
- let config = configFilePath.endsWith('package.json')
22
- ? manifest.jest
23
- : await resolveExtensibleConfig(configFilePath);
24
- if (typeof config === 'function')
25
- config = await config();
26
- if (!config)
27
- return [];
28
- const replaceRootDir = (name) => name.includes('<rootDir>') ? join(cwd, name.replace(/^.*<rootDir>/, '')) : name;
20
+ const resolveDependencies = (config) => {
29
21
  const presets = (config.preset ? [config.preset] : []).map(preset => isInternal(preset) ? preset : join(preset, 'jest-preset'));
22
+ const projects = Array.isArray(config.projects)
23
+ ? config.projects.map(config => (typeof config === 'string' ? config : resolveDependencies(config))).flat()
24
+ : [];
25
+ const runner = config.runner ? [config.runner] : [];
30
26
  const environments = config.testEnvironment === 'jsdom' ? ['jest-environment-jsdom'] : [];
31
27
  const resolvers = config.resolver ? [config.resolver] : [];
32
28
  const reporters = config.reporters
@@ -45,6 +41,8 @@ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
45
41
  : []).filter(value => !/\$[0-9]/.test(value));
46
42
  return [
47
43
  ...presets,
44
+ ...projects,
45
+ ...runner,
48
46
  ...environments,
49
47
  ...resolvers,
50
48
  ...reporters,
@@ -53,6 +51,17 @@ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
53
51
  ...setupFilesAfterEnv,
54
52
  ...transform,
55
53
  ...moduleNameMapper,
56
- ].map(replaceRootDir);
54
+ ];
55
+ };
56
+ const findJestDependencies = async (configFilePath, { cwd, manifest }) => {
57
+ let config = configFilePath.endsWith('package.json')
58
+ ? manifest.jest
59
+ : await resolveExtensibleConfig(configFilePath);
60
+ if (typeof config === 'function')
61
+ config = await config();
62
+ if (!config)
63
+ return [];
64
+ const replaceRootDir = (name) => name.includes('<rootDir>') ? join(cwd, name.replace(/^.*<rootDir>/, '')) : name;
65
+ return resolveDependencies(config).map(replaceRootDir);
57
66
  };
58
67
  export const findDependencies = timerify(findJestDependencies);
@@ -1,18 +1,34 @@
1
1
  import { compact } from '../../util/array.js';
2
- import { isInternal } from '../../util/path.js';
2
+ import { dirname, isInternal, toAbsolute } from '../../util/path.js';
3
3
  import { timerify } from '../../util/Performance.js';
4
4
  import { hasDependency, load } from '../../util/plugin.js';
5
5
  export const NAME = 'TypeScript';
6
6
  export const ENABLERS = ['typescript'];
7
7
  export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
8
8
  export const CONFIG_FILE_PATTERNS = ['tsconfig.json'];
9
- const findTypeScriptDependencies = async (configFilePath) => {
9
+ const resolveExtensibleConfig = async (configFilePath) => {
10
10
  const config = await load(configFilePath);
11
+ if (config?.extends) {
12
+ if (isInternal(config.extends)) {
13
+ const presetConfigPath = toAbsolute(config.extends, dirname(configFilePath));
14
+ const presetConfig = await resolveExtensibleConfig(presetConfigPath);
15
+ Object.assign(config, presetConfig);
16
+ }
17
+ }
18
+ return config;
19
+ };
20
+ const findTypeScriptDependencies = async (configFilePath) => {
21
+ const config = await resolveExtensibleConfig(configFilePath);
11
22
  if (!config)
12
23
  return [];
13
24
  const extend = config.extends ? [config.extends].flat().filter(extend => !isInternal(extend)) : [];
14
25
  const plugins = compact(config.compilerOptions?.plugins?.map(plugin => plugin.name) ?? []);
15
26
  const importHelpers = config.compilerOptions?.importHelpers ? ['tslib'] : [];
16
- return [...extend, ...plugins, ...importHelpers];
27
+ const jsx = config.compilerOptions?.jsxImportSource
28
+ ? [config.compilerOptions.jsxImportSource]
29
+ : config.compilerOptions?.jsx
30
+ ? ['react']
31
+ : [];
32
+ return [...extend, ...plugins, ...importHelpers, ...jsx];
17
33
  };
18
34
  export const findDependencies = timerify(findTypeScriptDependencies);
@@ -14,7 +14,7 @@ const findVitestDependencies = async (configFilePath) => {
14
14
  const cfg = config.test;
15
15
  const environments = cfg.environment ? [getEnvPackageName(cfg.environment)] : [];
16
16
  const reporters = getExternalReporters(cfg.reporters);
17
- const coverage = cfg.coverage?.provider ? [`@vitest/coverage-${cfg.coverage.provider}`] : [];
17
+ const coverage = cfg.coverage ? [`@vitest/coverage-${cfg.coverage.provider ?? "v8"}`] : [];
18
18
  const setupFiles = cfg.setupFiles ? [cfg.setupFiles].flat() : [];
19
19
  const globalSetup = cfg.globalSetup ? [cfg.globalSetup].flat() : [];
20
20
  return compact([...environments, ...reporters, ...coverage, ...setupFiles, ...globalSetup]);
@@ -1,5 +1,5 @@
1
1
  import { ISSUE_TYPE_TITLE } from '../constants.js';
2
- import { IssueSeverity } from '../types/issues.js';
2
+ import type { IssueSeverity } from '../types/issues.js';
3
3
  export declare const identity: (text: string) => string;
4
4
  export declare const getTitle: (reportType: keyof typeof ISSUE_TYPE_TITLE) => string;
5
5
  export declare const logTitle: (title: string, count: number) => void;
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { ConfigurationValidator } from '../ConfigurationValidator.js';
3
3
  import * as Plugins from '../plugins/index.js';
4
- import { Rules } from './issues.js';
4
+ import type { Rules } from './issues.js';
5
5
  import type { SyncCompilers, AsyncCompilers } from '../types/compilers.js';
6
6
  export type RawConfiguration = z.infer<typeof ConfigurationValidator>;
7
7
  type NormalizedGlob = string[];
@@ -1 +1,3 @@
1
- export {};
1
+ import { z } from 'zod';
2
+ import { ConfigurationValidator } from '../ConfigurationValidator.js';
3
+ import * as Plugins from '../plugins/index.js';
@@ -1 +1 @@
1
- export {};
1
+ import ts from 'typescript';
@@ -3,10 +3,16 @@ type SymbolTable = Map<string, ts.Symbol>;
3
3
  type SymbolWithExports = ts.Symbol & {
4
4
  exports?: SymbolTable;
5
5
  };
6
+ type PragmaMap = {
7
+ arguments: {
8
+ factory: string;
9
+ };
10
+ };
6
11
  export interface BoundSourceFile extends ts.SourceFile {
7
12
  symbol?: SymbolWithExports;
8
13
  resolvedModules?: ts.ModeAwareCache<ts.ResolvedModuleWithFailedLookupLocations>;
9
14
  locals?: SymbolTable;
10
15
  scriptKind?: ts.ScriptKind;
16
+ pragmas?: Map<string, PragmaMap | PragmaMap[]>;
11
17
  }
12
18
  export {};
@@ -1 +1 @@
1
- export {};
1
+ import ts from 'typescript';
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import { debugLog } from '../util/debug.js';
3
- import { extname } from '../util/path.js';
3
+ import { extname, isInternal } from '../util/path.js';
4
4
  export class SourceFileManager {
5
5
  sourceFileCache = new Map();
6
6
  snapshotCache = new Map();
@@ -11,7 +11,8 @@ export class SourceFileManager {
11
11
  this.asyncCompilers = compilers[1];
12
12
  }
13
13
  createSourceFile(filePath, contents) {
14
- const sourceFile = ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true);
14
+ const setParentNodes = isInternal(filePath);
15
+ const sourceFile = ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, setParentNodes);
15
16
  this.sourceFileCache.set(filePath, sourceFile);
16
17
  return sourceFile;
17
18
  }
@@ -5,6 +5,7 @@ import { isMaybePackageName } from '../util/modules.js';
5
5
  import { isInNodeModules } from '../util/path.js';
6
6
  import { isDeclarationFileExtension, isAccessExpression, getAccessExpressionName } from './ast-helpers.js';
7
7
  import getExportVisitors from './visitors/exports/index.js';
8
+ import { getJSXImplicitImportBase } from './visitors/helpers.js';
8
9
  import getImportVisitors from './visitors/imports/index.js';
9
10
  import getScriptVisitors from './visitors/scripts/index.js';
10
11
  const getVisitors = (sourceFile) => ({
@@ -20,6 +21,9 @@ export const getImportsAndExports = (sourceFile, options) => {
20
21
  const aliasedExports = {};
21
22
  const scripts = new Set();
22
23
  const importedInternalSymbols = new Map();
24
+ const jsxImport = getJSXImplicitImportBase(sourceFile);
25
+ if (jsxImport)
26
+ externalImports.add(jsxImport);
23
27
  const visitors = getVisitors(sourceFile);
24
28
  const addInternalImport = (options) => {
25
29
  const { identifier, specifier, symbol, filePath, isReExport } = options;
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript';
1
2
  import exportAssignment from './exportAssignment.js';
2
3
  import exportDeclaration from './exportDeclaration.js';
3
4
  import exportKeyword from './exportKeyword.js';
@@ -1,3 +1,4 @@
1
- import { BoundSourceFile } from '../SourceFile.js';
1
+ import type { BoundSourceFile } from '../SourceFile.js';
2
2
  export declare const isNotJS: (sourceFile: BoundSourceFile) => boolean;
3
3
  export declare const isJS: (sourceFile: BoundSourceFile) => boolean;
4
+ export declare function getJSXImplicitImportBase(sourceFile: BoundSourceFile): string | undefined;
@@ -1,3 +1,10 @@
1
1
  import ts from 'typescript';
2
2
  export const isNotJS = (sourceFile) => sourceFile.scriptKind !== ts.ScriptKind.JS && sourceFile.scriptKind !== ts.ScriptKind.JSX;
3
3
  export const isJS = (sourceFile) => sourceFile.scriptKind === ts.ScriptKind.JS || sourceFile.scriptKind === ts.ScriptKind.JSX;
4
+ export function getJSXImplicitImportBase(sourceFile) {
5
+ const jsxImportSourcePragmas = sourceFile.pragmas?.get('jsximportsource');
6
+ const jsxImportSourcePragma = Array.isArray(jsxImportSourcePragmas)
7
+ ? jsxImportSourcePragmas[jsxImportSourcePragmas.length - 1]
8
+ : jsxImportSourcePragmas;
9
+ return jsxImportSourcePragma?.arguments.factory;
10
+ }
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript';
1
2
  import importCall from './importCall.js';
2
3
  import importDeclaration from './importDeclaration.js';
3
4
  import importEqualsDeclaration from './importEqualsDeclaration.js';
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript';
1
2
  export const importVisitor = (fileCondition, visitorFn) => sourceFile => {
2
3
  if (fileCondition(sourceFile)) {
3
4
  return (node, options) => visitorFn(node, options);
@@ -1,3 +1,4 @@
1
+ import ts from 'typescript';
1
2
  import execa from './execa.js';
2
3
  import zx from './zx.js';
3
4
  const visitors = [execa, zx];
@@ -1,4 +1,4 @@
1
- import { performance, PerformanceObserver } from 'node:perf_hooks';
1
+ import { performance, PerformanceObserver, PerformanceEntry } from 'node:perf_hooks';
2
2
  import EasyTable from 'easy-table';
3
3
  import Summary from 'summary';
4
4
  import parsedArgValues from './cli-arguments.js';
@@ -1,4 +1,4 @@
1
- export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n --workspace Analyze a single workspace (default: analyze all configured workspaces)\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --include-entry-exports Include entry files when reporting unused exports\n -n, --no-progress Don't show dynamic progress updates (this is automatically enabled in CI environments)\n --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-config-hints Suppress configuration hints\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --debug-file-filter Filter for files in debug output (regex as string)\n --performance Measure count and running time of expensive functions and display stats table\n -h, --help Print this help text\n -V, --version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --debug --debug-file-filter '(specific|particular)-module'\n\nMore documentation and bug reports: https://github.com/webpro/knip";
1
+ export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --include-entry-exports Include entry files when reporting unused exports\n -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)\n --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-config-hints Suppress configuration hints\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --debug-file-filter Filter for files in debug output (regex as string)\n --performance Measure count and running time of expensive functions and display stats table\n -h, --help Print this help text\n -V, --version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --debug --debug-file-filter '(specific|particular)-module'\n\nMore documentation and bug reports: https://github.com/webpro/knip";
2
2
  declare const _default: {
3
3
  config: string | undefined;
4
4
  debug: boolean | undefined;
@@ -8,14 +8,14 @@ Options:
8
8
  -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)
9
9
  --production Analyze only production source files (e.g. no tests, devDependencies, exported types)
10
10
  --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)
11
- --workspace Analyze a single workspace (default: analyze all configured workspaces)
11
+ --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)
12
12
  --no-gitignore Don't use .gitignore
13
13
  --include Report only provided issue type(s), can be comma-separated or repeated (1)
14
14
  --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)
15
15
  --dependencies Shortcut for --include dependencies,unlisted,unresolved
16
16
  --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
17
17
  --include-entry-exports Include entry files when reporting unused exports
18
- -n, --no-progress Don't show dynamic progress updates (this is automatically enabled in CI environments)
18
+ -n, --no-progress Don't show dynamic progress updates (automatically enabled in CI environments)
19
19
  --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
20
20
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
21
21
  --no-config-hints Suppress configuration hints
@@ -1,5 +1,5 @@
1
- import { AsyncCompilerFn, SyncCompilerFn } from '../types/compilers.js';
2
- import { RawConfiguration } from '../types/config.js';
1
+ import type { AsyncCompilerFn, SyncCompilerFn } from '../types/compilers.js';
2
+ import type { RawConfiguration } from '../types/config.js';
3
3
  export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
4
4
  syncCompilers: Record<string, SyncCompilerFn>;
5
5
  asyncCompilers: Record<string, AsyncCompilerFn>;
package/dist/util/glob.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fg from 'fast-glob';
2
2
  import { globby } from 'globby';
3
- import { ROOT_WORKSPACE_NAME } from '../constants.js';
3
+ import { GLOBAL_IGNORE_PATTERNS, ROOT_WORKSPACE_NAME } from '../constants.js';
4
4
  import { compact } from './array.js';
5
5
  import { debugLogObject } from './debug.js';
6
6
  import { join, relative } from './path.js';
@@ -23,7 +23,7 @@ const glob = async ({ cwd, workingDir = cwd, patterns, ignore = [], gitignore =
23
23
  const globPatterns = compact([patterns].flat().map(prepend).map(removeProductionSuffix)).sort(negatedLast);
24
24
  if (globPatterns[0].startsWith('!'))
25
25
  return [];
26
- const ignorePatterns = compact([...ignore, '**/node_modules/**']);
26
+ const ignorePatterns = compact([...ignore, ...GLOBAL_IGNORE_PATTERNS]);
27
27
  debugLogObject(`Globbing (${relativePath || ROOT_WORKSPACE_NAME})`, { cwd, globPatterns, ignorePatterns });
28
28
  return globby(globPatterns, {
29
29
  cwd,
@@ -38,13 +38,13 @@ const pureGlob = async ({ cwd, patterns, ignore = [], gitignore = true }) => {
38
38
  return [];
39
39
  return globby(patterns, {
40
40
  cwd,
41
- ignore: [...ignore, '**/node_modules/**'],
41
+ ignore: [...ignore, ...GLOBAL_IGNORE_PATTERNS],
42
42
  gitignore,
43
43
  absolute: true,
44
44
  });
45
45
  };
46
46
  const firstGlob = async ({ cwd, patterns }) => {
47
- const stream = fg.stream(patterns.map(removeProductionSuffix), { cwd, ignore: ['**/node_modules/**'] });
47
+ const stream = fg.stream(patterns.map(removeProductionSuffix), { cwd, ignore: GLOBAL_IGNORE_PATTERNS });
48
48
  for await (const entry of stream) {
49
49
  return entry;
50
50
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.17.3";
1
+ export declare const version = "2.19.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.17.3';
1
+ export const version = '2.19.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.17.3",
3
+ "version": "2.19.0",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",
@@ -65,12 +65,12 @@
65
65
  "@npmcli/package-json": "4.0.1",
66
66
  "@release-it/bumper": "5.1.0",
67
67
  "@swc/cli": "0.1.62",
68
- "@swc/core": "1.3.73",
69
- "@types/eslint": "8.44.1",
68
+ "@swc/core": "1.3.74",
69
+ "@types/eslint": "8.44.2",
70
70
  "@types/js-yaml": "4.0.5",
71
71
  "@types/micromatch": "4.0.2",
72
72
  "@types/minimist": "1.2.2",
73
- "@types/node": "20.4.5",
73
+ "@types/node": "20.4.7",
74
74
  "@types/npmcli__map-workspaces": "3.0.1",
75
75
  "@types/webpack": "5.28.1",
76
76
  "@typescript-eslint/eslint-plugin": "6.2.1",
@@ -80,7 +80,7 @@
80
80
  "eslint-import-resolver-typescript": "3.5.5",
81
81
  "eslint-plugin-import": "2.28.0",
82
82
  "eslint-plugin-n": "16.0.1",
83
- "prettier": "3.0.0",
83
+ "prettier": "3.0.1",
84
84
  "release-it": "16.1.3",
85
85
  "remark-cli": "11.0.0",
86
86
  "remark-preset-webpro": "0.0.3",