knip 2.19.11 → 2.20.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.
package/README.md CHANGED
@@ -482,6 +482,11 @@ Additionally, the `--strict` flag can be used to:
482
482
  - Ignore type-only imports (`import type {}`).
483
483
  - Verify each workspace is self-contained: have their own `dependencies` (and not use packages of ancestor workspaces).
484
484
 
485
+ ### Ignore `@internal` exports
486
+
487
+ In addition to the flags above, the `--ignore-internal` flag can be used to ignore exports tagged with `@internal`. This
488
+ can be useful in production mode, since `@internal` exports might be only imported from non-production code.
489
+
485
490
  ### Plugins
486
491
 
487
492
  Plugins also have this distinction. For instance, Next.js entry files for pages (`pages/**/*.tsx`) and Remix routes
@@ -630,6 +635,7 @@ for false positives, and how to handle them.
630
635
  -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)
631
636
  --production Analyze only production source files (e.g. no tests, devDependencies, exported types)
632
637
  --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)
638
+ --ignore-internal Ignore exports with tag @internal (JSDoc/TSDoc)
633
639
  --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)
634
640
  --no-gitignore Don't use .gitignore
635
641
  --include Report only provided issue type(s), can be comma-separated or repeated (1)
@@ -168,9 +168,9 @@ export class DependencyDeputy {
168
168
  return false;
169
169
  return referencedDependencies.has(typedPackageName);
170
170
  }
171
- const peerDependencies = this.getPeerDependenciesOf(workspaceName, dependency);
172
- peerDependencies.forEach(dep => (!peerDepRecs[dep] ? (peerDepRecs[dep] = 1) : peerDepRecs[dep]++));
173
- return !!peerDependencies.find(peerDependency => isReferencedDependency(peerDependency, true));
171
+ const peerDependenciesOf = this.getPeerDependenciesOf(workspaceName, dependency);
172
+ peerDependenciesOf.forEach(dep => (!peerDepRecs[dep] ? (peerDepRecs[dep] = 1) : peerDepRecs[dep]++));
173
+ return peerDependenciesOf.some(peerDependency => isReferencedDependency(peerDependency, true));
174
174
  };
175
175
  const isNotReferencedDependency = (dependency) => !isReferencedDependency(dependency);
176
176
  const pd = this.getProductionDependencies(workspaceName);
@@ -1,3 +1,4 @@
1
+ import { isGitIgnoredSync } from 'globby';
1
2
  import ts from 'typescript';
2
3
  import { SourceFileManager } from './typescript/SourceFileManager.js';
3
4
  import type { SyncCompilers, AsyncCompilers } from './types/compilers.js';
@@ -11,6 +12,7 @@ export declare class ProjectPrincipal {
11
12
  entryPaths: Set<string>;
12
13
  projectPaths: Set<string>;
13
14
  skipExportsAnalysis: Set<string>;
15
+ isGitIgnored: ReturnType<typeof isGitIgnoredSync>;
14
16
  cwd: string;
15
17
  compilerOptions: ts.CompilerOptions;
16
18
  extensions: Set<string>;
@@ -7,7 +7,7 @@ import { createHosts } from './typescript/createHosts.js';
7
7
  import { getImportsAndExports } from './typescript/getImportsAndExports.js';
8
8
  import { SourceFileManager } from './typescript/SourceFileManager.js';
9
9
  import { isMaybePackageName } from './util/modules.js';
10
- import { extname, isInNodeModules, join } from './util/path.js';
10
+ import { dirname, extname, isInNodeModules, join } from './util/path.js';
11
11
  import { timerify } from './util/Performance.js';
12
12
  const baseCompilerOptions = {
13
13
  allowJs: true,
@@ -23,11 +23,11 @@ const baseCompilerOptions = {
23
23
  moduleResolution: ts.ModuleResolutionKind.NodeNext,
24
24
  };
25
25
  const tsCreateProgram = timerify(ts.createProgram);
26
- const isGitIgnored = isGitIgnoredSync();
27
26
  export class ProjectPrincipal {
28
27
  entryPaths = new Set();
29
28
  projectPaths = new Set();
30
29
  skipExportsAnalysis = new Set();
30
+ isGitIgnored;
31
31
  cwd;
32
32
  compilerOptions;
33
33
  extensions;
@@ -36,6 +36,7 @@ export class ProjectPrincipal {
36
36
  backend;
37
37
  constructor({ compilerOptions, cwd, compilers }) {
38
38
  this.cwd = cwd;
39
+ this.isGitIgnored = isGitIgnoredSync({ cwd });
39
40
  this.compilerOptions = {
40
41
  ...compilerOptions,
41
42
  ...baseCompilerOptions,
@@ -132,7 +133,7 @@ export class ProjectPrincipal {
132
133
  external.add(sanitizedSpecifier);
133
134
  }
134
135
  else {
135
- const isIgnored = isGitIgnored(join(filePath, sanitizedSpecifier));
136
+ const isIgnored = this.isGitIgnored(join(dirname(filePath), sanitizedSpecifier));
136
137
  if (!isIgnored) {
137
138
  const ext = extname(sanitizedSpecifier);
138
139
  if (!ext || (ext !== '.json' && !IGNORED_FILE_EXTENSIONS.includes(ext))) {
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import { cwd, resolve } from './util/path.js';
9
9
  import { Performance } from './util/Performance.js';
10
10
  import { version } from './version.js';
11
11
  import { main } from './index.js';
12
- const { debug: isDebug = false, help: isHelp, 'max-issues': maxIssues = '0', 'no-config-hints': noConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = false, 'include-entry-exports': isIncludeEntryExports = false, performance: isObservePerf = false, production: isProduction = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', strict: isStrict = false, tsConfig, version: isVersion, } = parsedArgValues;
12
+ const { debug: isDebug = false, help: isHelp, 'max-issues': maxIssues = '0', 'no-config-hints': noConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = false, 'ignore-internal': isIgnoreInternal = false, 'include-entry-exports': isIncludeEntryExports = false, performance: isObservePerf = false, production: isProduction = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', strict: isStrict = false, tsConfig, version: isVersion, } = parsedArgValues;
13
13
  if (isHelp) {
14
14
  console.log(helpText);
15
15
  process.exit(0);
@@ -27,8 +27,9 @@ const run = async () => {
27
27
  cwd,
28
28
  tsConfigFile: tsConfig,
29
29
  gitignore: !isNoGitIgnore,
30
- isStrict,
31
30
  isProduction,
31
+ isStrict,
32
+ isIgnoreInternal,
32
33
  isShowProgress,
33
34
  isIncludeEntryExports,
34
35
  });
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import { _require } from './util/require.js';
20
20
  import { loadTSConfig as loadCompilerOptions } from './util/tsconfig-loader.js';
21
21
  import { WorkspaceWorker } from './WorkspaceWorker.js';
22
22
  export const main = async (unresolvedConfiguration) => {
23
- const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isShowProgress, isIncludeEntryExports } = unresolvedConfiguration;
23
+ const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isIgnoreInternal, isShowProgress, isIncludeEntryExports, } = unresolvedConfiguration;
24
24
  debugLogObject('Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
25
25
  const chief = new ConfigurationChief({ cwd, isProduction });
26
26
  const deputy = new DependencyDeputy({ isStrict });
@@ -270,6 +270,8 @@ export const main = async (unresolvedConfiguration) => {
270
270
  const jsDocTags = principal.getJSDocTags(exportedItem);
271
271
  if (jsDocTags.includes('@public') || jsDocTags.includes('@beta'))
272
272
  continue;
273
+ if (isIgnoreInternal && jsDocTags.includes('@internal'))
274
+ continue;
273
275
  if (importedModule?.symbols.has(symbol)) {
274
276
  if (importedModule.isReExport && isExportedInEntryFile(importedModule))
275
277
  continue;
@@ -10,7 +10,7 @@ const findAvaDependencies = async (configFilePath, { cwd, manifest }) => {
10
10
  const config = configFilePath.endsWith('package.json') ? manifest.ava : await load(configFilePath);
11
11
  const requireArgs = (config?.require ?? []).map(require => `--require ${require}`);
12
12
  const otherArgs = config?.nodeArguments ?? [];
13
- const cmd = `node ${otherArgs.join(' ') + ' '}${requireArgs.join(' ')}`;
13
+ const cmd = `node ${otherArgs.join(' ')} ${requireArgs.join(' ')}`;
14
14
  return _getDependenciesFromScripts([cmd], {
15
15
  cwd,
16
16
  manifest,
@@ -1,4 +1,5 @@
1
1
  import { compact } from '../../util/array.js';
2
+ import { join } from '../../util/path.js';
2
3
  import { timerify } from '../../util/Performance.js';
3
4
  import { hasDependency, load } from '../../util/plugin.js';
4
5
  import { getEnvPackageName, getExternalReporters } from './helpers.js';
@@ -7,7 +8,7 @@ export const ENABLERS = ['vitest'];
7
8
  export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
8
9
  export const CONFIG_FILE_PATTERNS = ['vitest.config.ts'];
9
10
  export const ENTRY_FILE_PATTERNS = ['vite.config.ts'];
10
- const findVitestDependencies = async (configFilePath) => {
11
+ const findVitestDependencies = async (configFilePath, { cwd }) => {
11
12
  const config = await load(configFilePath);
12
13
  if (!config || !config.test)
13
14
  return [];
@@ -15,8 +16,8 @@ const findVitestDependencies = async (configFilePath) => {
15
16
  const environments = cfg.environment ? [getEnvPackageName(cfg.environment)] : [];
16
17
  const reporters = getExternalReporters(cfg.reporters);
17
18
  const coverage = cfg.coverage ? [`@vitest/coverage-${cfg.coverage.provider ?? 'v8'}`] : [];
18
- const setupFiles = cfg.setupFiles ? [cfg.setupFiles].flat() : [];
19
- const globalSetup = cfg.globalSetup ? [cfg.globalSetup].flat() : [];
19
+ const setupFiles = cfg.setupFiles ? [cfg.setupFiles].flat().map(filePath => join(cwd, filePath)) : [];
20
+ const globalSetup = cfg.globalSetup ? [cfg.globalSetup].flat().map(filePath => join(cwd, filePath)) : [];
20
21
  return compact([...environments, ...reporters, ...coverage, ...setupFiles, ...globalSetup]);
21
22
  };
22
23
  export const findDependencies = timerify(findVitestDependencies);
@@ -4,6 +4,7 @@ export interface CommandLineOptions {
4
4
  gitignore: boolean;
5
5
  isStrict: boolean;
6
6
  isProduction: boolean;
7
+ isIgnoreInternal: boolean;
7
8
  isShowProgress: boolean;
8
9
  isIncludeEntryExports: boolean;
9
10
  }
@@ -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 [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";
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 --ignore-internal Ignore exports with tag @internal (JSDoc/TSDoc)\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;
@@ -7,6 +7,7 @@ declare const _default: {
7
7
  exclude: string[] | undefined;
8
8
  exports: boolean | undefined;
9
9
  help: boolean | undefined;
10
+ 'ignore-internal': boolean | undefined;
10
11
  include: string[] | undefined;
11
12
  'include-entry-exports': boolean | undefined;
12
13
  'max-issues': string | undefined;
@@ -8,6 +8,7 @@ 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
+ --ignore-internal Ignore exports with tag @internal (JSDoc/TSDoc)
11
12
  --workspace [dir] Analyze a single workspace (default: analyze all configured workspaces)
12
13
  --no-gitignore Don't use .gitignore
13
14
  --include Report only provided issue type(s), can be comma-separated or repeated (1)
@@ -50,6 +51,7 @@ try {
50
51
  exclude: { type: 'string', multiple: true },
51
52
  exports: { type: 'boolean' },
52
53
  help: { type: 'boolean', short: 'h' },
54
+ 'ignore-internal': { type: 'boolean' },
53
55
  include: { type: 'string', multiple: true },
54
56
  'include-entry-exports': { type: 'boolean' },
55
57
  'max-issues': { type: 'string' },
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.19.11";
1
+ export declare const version = "2.20.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.19.11';
1
+ export const version = '2.20.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.19.11",
3
+ "version": "2.20.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",
@@ -18,7 +18,7 @@
18
18
  "types": "./dist/index.d.ts",
19
19
  "scripts": {
20
20
  "knip": "node ./dist/cli.js",
21
- "knip:production": "node ./dist/cli.js --production --strict",
21
+ "knip:production": "node ./dist/cli.js --production --strict --ignore-internal",
22
22
  "lint": "eslint scripts src tests",
23
23
  "lint:fix": "eslint scripts src tests --fix",
24
24
  "format": "prettier scripts src tests schema.json --with-node-modules --write --config .prettierrc",