knip 2.38.3 → 2.38.5

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
@@ -277,7 +277,7 @@ Knip contains a growing list of plugins:
277
277
  - [ESLint][plugin-eslint]
278
278
  - [Gatsby][plugin-gatsby]
279
279
  - [GitHub Actions][plugin-github-actions]
280
- - [Graphql Codegen][plugin-graphql-codegen]
280
+ - [GraphQL Codegen][plugin-graphql-codegen]
281
281
  - [husky][plugin-husky]
282
282
  - [Jest][plugin-jest]
283
283
  - [Lefthook][plugin-lefthook]
@@ -1,5 +1,6 @@
1
1
  import { isGitIgnoredSync } from 'globby';
2
2
  import ts from 'typescript';
3
+ import { createCustomModuleResolver } from './typescript/resolveModuleNames.js';
3
4
  import { SourceFileManager } from './typescript/SourceFileManager.js';
4
5
  import type { SyncCompilers, AsyncCompilers } from './types/compilers.js';
5
6
  import type { ExportItem, ExportItemMember } from './types/exports.js';
@@ -21,7 +22,7 @@ export declare class ProjectPrincipal {
21
22
  backend: {
22
23
  fileManager: SourceFileManager;
23
24
  compilerHost: ts.CompilerHost;
24
- languageServiceHost: ts.LanguageServiceHost;
25
+ resolveModuleNames: ReturnType<typeof createCustomModuleResolver>;
25
26
  lsFindReferences: ts.LanguageService['findReferences'];
26
27
  program?: ts.Program;
27
28
  };
@@ -53,7 +54,7 @@ export declare class ProjectPrincipal {
53
54
  };
54
55
  scripts: Set<string>;
55
56
  };
56
- resolveModule(specifier: string, filePath?: string): ts.ResolvedModuleFull | undefined;
57
+ resolveModule(specifier: string, filePath?: string): ts.ResolvedModule | undefined;
57
58
  getHasReferences(filePath: string, exportedItem: ExportItem): {
58
59
  external: boolean;
59
60
  internal: boolean;
@@ -5,6 +5,7 @@ import { IGNORED_FILE_EXTENSIONS } from './constants.js';
5
5
  import { getJSDocTags, getLineAndCharacterOfPosition, isInModuleBlock } from './typescript/ast-helpers.js';
6
6
  import { createHosts } from './typescript/createHosts.js';
7
7
  import { getImportsAndExports } from './typescript/getImportsAndExports.js';
8
+ import { createCustomModuleResolver } from './typescript/resolveModuleNames.js';
8
9
  import { SourceFileManager } from './typescript/SourceFileManager.js';
9
10
  import { isMaybePackageName, sanitizeSpecifier } from './util/modules.js';
10
11
  import { dirname, extname, isInNodeModules, join } from './util/path.js';
@@ -46,7 +47,7 @@ export class ProjectPrincipal {
46
47
  this.extensions = new Set([...DEFAULT_EXTENSIONS, ...syncCompilers.keys(), ...asyncCompilers.keys()]);
47
48
  this.syncCompilers = syncCompilers;
48
49
  this.asyncCompilers = asyncCompilers;
49
- const { fileManager, compilerHost, languageServiceHost } = createHosts({
50
+ const { fileManager, compilerHost, languageServiceHost, resolveModuleNames } = createHosts({
50
51
  cwd: this.cwd,
51
52
  compilerOptions: this.compilerOptions,
52
53
  entryPaths: this.entryPaths,
@@ -57,7 +58,7 @@ export class ProjectPrincipal {
57
58
  this.backend = {
58
59
  fileManager,
59
60
  compilerHost,
60
- languageServiceHost,
61
+ resolveModuleNames,
61
62
  lsFindReferences,
62
63
  };
63
64
  }
@@ -129,15 +130,14 @@ export class ProjectPrincipal {
129
130
  }
130
131
  else {
131
132
  const sanitizedSpecifier = sanitizeSpecifier(specifier);
132
- const ext = extname(sanitizedSpecifier);
133
- const hasIgnoredExtension = IGNORED_FILE_EXTENSIONS.includes(ext);
134
- if (!hasIgnoredExtension && isMaybePackageName(sanitizedSpecifier)) {
133
+ if (isMaybePackageName(sanitizedSpecifier)) {
135
134
  external.add(sanitizedSpecifier);
136
135
  }
137
136
  else {
138
137
  const isIgnored = this.isGitIgnored(join(dirname(filePath), sanitizedSpecifier));
139
138
  if (!isIgnored) {
140
139
  const ext = extname(sanitizedSpecifier);
140
+ const hasIgnoredExtension = IGNORED_FILE_EXTENSIONS.includes(ext);
141
141
  if (!ext || (ext !== '.json' && !hasIgnoredExtension)) {
142
142
  unresolvedImports.add(specifier);
143
143
  }
@@ -156,8 +156,7 @@ export class ProjectPrincipal {
156
156
  };
157
157
  }
158
158
  resolveModule(specifier, filePath = specifier) {
159
- const module = ts.resolveModuleName(specifier, filePath, this.compilerOptions, this.backend.languageServiceHost);
160
- return module?.resolvedModule;
159
+ return this.backend.resolveModuleNames([specifier], filePath)[0];
161
160
  }
162
161
  getHasReferences(filePath, exportedItem) {
163
162
  const hasReferences = { external: false, internal: false };
@@ -4,7 +4,9 @@ import { toBinary } from '../../util/protocols.js';
4
4
  import { tryResolveFilePath, tryResolveSpecifiers } from '../util.js';
5
5
  const withPositional = parsed => [parsed._[0], parsed.require].flat();
6
6
  const withoutPositional = parsed => [parsed.require].flat();
7
+ const withoutRequire = () => [];
7
8
  const argFilters = {
9
+ adb: withoutRequire,
8
10
  'babel-node': withPositional,
9
11
  esbuild: withPositional,
10
12
  execa: withPositional,
@@ -5,6 +5,7 @@ export declare const DEFAULT_EXTENSIONS: string[];
5
5
  export declare const GLOBAL_IGNORE_PATTERNS: string[];
6
6
  export declare const IGNORED_GLOBAL_BINARIES: string[];
7
7
  export declare const IGNORED_DEPENDENCIES: string[];
8
+ export declare const VIRTUAL_FILE_EXTENSIONS: string[];
8
9
  export declare const IGNORED_FILE_EXTENSIONS: string[];
9
10
  export declare const IGNORE_DEFINITELY_TYPED: string[];
10
11
  export declare const ISSUE_TYPES: IssueType[];
package/dist/constants.js CHANGED
@@ -32,9 +32,10 @@ export const IGNORED_GLOBAL_BINARIES = [
32
32
  'yarn',
33
33
  ];
34
34
  export const IGNORED_DEPENDENCIES = ['knip', 'typescript'];
35
+ export const VIRTUAL_FILE_EXTENSIONS = ['.css', '.html', '.svg'];
35
36
  export const IGNORED_FILE_EXTENSIONS = [
37
+ ...VIRTUAL_FILE_EXTENSIONS,
36
38
  '.avif',
37
- '.css',
38
39
  '.eot',
39
40
  '.gif',
40
41
  '.ico',
@@ -44,7 +45,6 @@ export const IGNORED_FILE_EXTENSIONS = [
44
45
  '.png',
45
46
  '.sass',
46
47
  '.scss',
47
- '.svg',
48
48
  '.sh',
49
49
  '.ttf',
50
50
  '.webp',
@@ -1,5 +1,5 @@
1
1
  import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
- export declare const NAME = "Graphql Codegen";
2
+ export declare const NAME = "GraphQL Codegen";
3
3
  export declare const ENABLERS: RegExp[];
4
4
  export declare const PACKAGE_JSON_PATH = "codegen";
5
5
  export declare const isEnabled: IsPluginEnabledCallback;
@@ -1,7 +1,7 @@
1
1
  import { timerify } from '../../util/Performance.js';
2
2
  import { hasDependency, load } from '../../util/plugin.js';
3
3
  import { isConfigurationOutput } from './types.js';
4
- export const NAME = 'Graphql Codegen';
4
+ export const NAME = 'GraphQL Codegen';
5
5
  export const ENABLERS = [/^@graphql-codegen\//];
6
6
  export const PACKAGE_JSON_PATH = 'codegen';
7
7
  export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
@@ -23,12 +23,10 @@ const findPluginDependencies = async (configFilePath, options) => {
23
23
  .map(presetName => `@graphql-codegen/${presetName}${presetName.endsWith('-preset') ? '' : '-preset'}`);
24
24
  const flatPlugins = generateSet
25
25
  .filter((config) => !isConfigurationOutput(config))
26
- .map(item => Object.keys(item))
27
- .flat()
26
+ .flatMap(item => Object.keys(item))
28
27
  .map(plugin => `@graphql-codegen/${plugin}`);
29
28
  const nestedPlugins = configurationOutput
30
- .map(configOutput => (configOutput.plugins ? configOutput.plugins : []))
31
- .flat()
29
+ .flatMap(configOutput => (configOutput.plugins ? configOutput.plugins : []))
32
30
  .map(plugin => `@graphql-codegen/${plugin}`);
33
31
  return [...presets, ...flatPlugins, ...nestedPlugins];
34
32
  };
@@ -1,9 +1,8 @@
1
- import { readFileSync } from 'fs';
2
1
  import { _getDependenciesFromScripts } from '../../binaries/index.js';
3
2
  import { getGitHookPaths } from '../../util/git.js';
4
3
  import { FAKE_PATH } from '../../util/loader.js';
5
4
  import { timerify } from '../../util/Performance.js';
6
- import { hasDependency } from '../../util/plugin.js';
5
+ import { hasDependency, loadFile } from '../../util/plugin.js';
7
6
  export const NAME = 'husky';
8
7
  export const ENABLERS = ['husky'];
9
8
  export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
@@ -13,7 +12,9 @@ const findHuskyDependencies = async (configFilePath, options) => {
13
12
  const { cwd, manifest, isProduction } = options;
14
13
  if (isProduction || configFilePath === FAKE_PATH)
15
14
  return [];
16
- const script = readFileSync(configFilePath);
15
+ const script = await loadFile(configFilePath);
16
+ if (!script)
17
+ return [];
17
18
  return _getDependenciesFromScripts(String(script), {
18
19
  cwd,
19
20
  manifest,
@@ -1,9 +1,8 @@
1
- import { readFileSync } from 'fs';
2
1
  import { _getDependenciesFromScripts } from '../../binaries/index.js';
3
2
  import { getGitHookPaths } from '../../util/git.js';
4
3
  import { getValuesByKeyDeep } from '../../util/object.js';
5
4
  import { timerify } from '../../util/Performance.js';
6
- import { hasDependency, load } from '../../util/plugin.js';
5
+ import { hasDependency, load, loadFile } from '../../util/plugin.js';
7
6
  import { fromBinary } from '../../util/protocols.js';
8
7
  export const NAME = 'Lefthook';
9
8
  export const ENABLERS = ['lefthook', '@arkweid/lefthook', '@evilmartians/lefthook'];
@@ -23,7 +22,9 @@ const findLefthookDependencies = async (configFilePath, options) => {
23
22
  const lefthook = process.env.CI ? ENABLERS.filter(dependency => dependencies.includes(dependency)) : [];
24
23
  return [...lefthook, ..._getDependenciesFromScripts(scripts, { cwd, manifest, knownGlobalsOnly: true })];
25
24
  }
26
- const script = readFileSync(configFilePath, 'utf8');
25
+ const script = await loadFile(configFilePath);
26
+ if (!script)
27
+ return [];
27
28
  const scriptDependencies = _getDependenciesFromScripts([script], { cwd, manifest, knownGlobalsOnly: false });
28
29
  const matches = scriptDependencies.find(dep => dependencies.includes(fromBinary(dep)));
29
30
  return matches ? [matches] : [];
@@ -11,5 +11,6 @@ export declare const createHosts: ({ cwd, compilerOptions, entryPaths, compilers
11
11
  fileManager: SourceFileManager;
12
12
  languageServiceHost: ts.LanguageServiceHost;
13
13
  compilerHost: ts.CompilerHost;
14
+ resolveModuleNames: (moduleNames: string[], containingFile: string) => (ts.ResolvedModule | undefined)[];
14
15
  };
15
16
  export {};
@@ -1,6 +1,7 @@
1
1
  import { EOL } from 'node:os';
2
2
  import path from 'node:path';
3
3
  import ts from 'typescript';
4
+ import { VIRTUAL_FILE_EXTENSIONS } from '../constants.js';
4
5
  import { createCustomModuleResolver } from './resolveModuleNames.js';
5
6
  import { SourceFileManager } from './SourceFileManager.js';
6
7
  import { createCustomSys } from './sys.js';
@@ -8,7 +9,7 @@ const libLocation = path.dirname(ts.getDefaultLibFilePath({}));
8
9
  const fileManager = new SourceFileManager();
9
10
  export const createHosts = ({ cwd, compilerOptions, entryPaths, compilers }) => {
10
11
  fileManager.installCompilers(compilers);
11
- const virtualFileExtensions = [...compilers[0].keys(), ...compilers[1].keys()];
12
+ const virtualFileExtensions = [...VIRTUAL_FILE_EXTENSIONS, ...compilers[0].keys(), ...compilers[1].keys()];
12
13
  const sys = createCustomSys(cwd, virtualFileExtensions);
13
14
  const resolveModuleNames = createCustomModuleResolver(sys, compilerOptions, virtualFileExtensions);
14
15
  const languageServiceHost = {
@@ -35,5 +36,5 @@ export const createHosts = ({ cwd, compilerOptions, entryPaths, compilers }) =>
35
36
  fileExists: languageServiceHost.fileExists,
36
37
  resolveModuleNames: languageServiceHost.resolveModuleNames,
37
38
  };
38
- return { fileManager, languageServiceHost, compilerHost };
39
+ return { fileManager, languageServiceHost, compilerHost, resolveModuleNames };
39
40
  };
@@ -1,11 +1,11 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import ts from 'typescript';
3
3
  import { sanitizeSpecifier } from '../util/modules.js';
4
- import { dirname, extname, isInternal, join } from '../util/path.js';
4
+ import { dirname, extname, isAbsolute, isInternal, join } from '../util/path.js';
5
5
  import { isDeclarationFileExtension } from './ast-helpers.js';
6
6
  import { ensureRealFilePath, isVirtualFilePath } from './utils.js';
7
7
  const simpleResolver = (name, containingFile) => {
8
- const resolvedFileName = join(dirname(containingFile), name);
8
+ const resolvedFileName = isAbsolute(name) ? name : join(dirname(containingFile), name);
9
9
  if (existsSync(resolvedFileName)) {
10
10
  return {
11
11
  resolvedFileName,
@@ -1,2 +1,3 @@
1
1
  export declare const FAKE_PATH = "__FAKE__";
2
2
  export declare const _load: (filePath: string) => Promise<any>;
3
+ export declare const _loadFile: (filePath: string) => Promise<string | undefined>;
@@ -25,10 +25,21 @@ const load = async (filePath) => {
25
25
  const imported = await import(fileUrl.href);
26
26
  return imported.default ?? imported;
27
27
  }
28
- return jiti(filePath);
28
+ return await jiti(filePath);
29
+ }
30
+ catch (error) {
31
+ throw new LoaderError(`Error loading ${filePath}`, { cause: error });
32
+ }
33
+ };
34
+ const loadFileAsync = async (filePath) => {
35
+ if (filePath === FAKE_PATH)
36
+ return;
37
+ try {
38
+ return await loadFile(filePath);
29
39
  }
30
40
  catch (error) {
31
41
  throw new LoaderError(`Error loading ${filePath}`, { cause: error });
32
42
  }
33
43
  };
34
44
  export const _load = timerify(load);
45
+ export const _loadFile = timerify(loadFileAsync);
@@ -1,3 +1,4 @@
1
+ export declare const isAbsolute: (path: string) => boolean;
1
2
  export declare const dirname: (path: string) => string;
2
3
  export declare const extname: (path: string) => string;
3
4
  export declare const join: (...paths: string[]) => string;
package/dist/util/path.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import parsedArgValues from './cli-arguments.js';
3
3
  const { directory } = parsedArgValues;
4
- const isAbsolute = path.isAbsolute;
4
+ export const isAbsolute = path.isAbsolute;
5
5
  export const dirname = path.posix.dirname;
6
6
  export const extname = path.posix.extname;
7
7
  export const join = path.posix.join;
@@ -1,4 +1,4 @@
1
- export { _load as load } from './loader.js';
1
+ export { _load as load, _loadFile as loadFile } from './loader.js';
2
2
  import type { RawPluginConfiguration } from '../types/config.js';
3
3
  export declare const toCamelCase: (name: string) => string;
4
4
  export declare const hasDependency: (dependencies: Set<string>, values: (string | RegExp)[]) => boolean;
@@ -1,4 +1,4 @@
1
- export { _load as load } from './loader.js';
1
+ export { _load as load, _loadFile as loadFile } from './loader.js';
2
2
  import { arrayify } from './array.js';
3
3
  export const toCamelCase = (name) => name.toLowerCase().replace(/(-[a-z])/g, group => group.toUpperCase().replace('-', ''));
4
4
  export const hasDependency = (dependencies, values) => values.some(value => {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.38.3";
1
+ export declare const version = "2.38.5";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.38.3';
1
+ export const version = '2.38.5';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.38.3",
3
+ "version": "2.38.5",
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",
@@ -46,13 +46,13 @@
46
46
  "@npmcli/map-workspaces": "^3.0.4",
47
47
  "@pkgjs/parseargs": "0.11.0",
48
48
  "@pnpm/logger": "5.0.0",
49
- "@pnpm/workspace.pkgs-graph": "2.0.9",
49
+ "@pnpm/workspace.pkgs-graph": "2.0.10",
50
50
  "@snyk/github-codeowners": "^1.1.0",
51
51
  "chalk": "^5.2.0",
52
52
  "easy-table": "^1.2.0",
53
53
  "fast-glob": "^3.2.12",
54
54
  "globby": "^13.1.3",
55
- "jiti": "^1.19.3",
55
+ "jiti": "1.21.0",
56
56
  "js-yaml": "^4.1.0",
57
57
  "micromatch": "^4.0.5",
58
58
  "minimist": "^1.2.8",
@@ -73,12 +73,12 @@
73
73
  "@types/js-yaml": "4.0.8",
74
74
  "@types/micromatch": "4.0.4",
75
75
  "@types/minimist": "1.2.4",
76
- "@types/node": "20.8.9",
76
+ "@types/node": "20.8.10",
77
77
  "@types/npmcli__map-workspaces": "3.0.3",
78
78
  "@types/pkgjs__parseargs": "0.10.2",
79
79
  "@types/webpack": "5.28.4",
80
- "@typescript-eslint/eslint-plugin": "6.9.0",
81
- "@typescript-eslint/parser": "6.9.0",
80
+ "@typescript-eslint/eslint-plugin": "6.9.1",
81
+ "@typescript-eslint/parser": "6.9.1",
82
82
  "c8": "8.0.1",
83
83
  "eslint": "8.52.0",
84
84
  "eslint-import-resolver-typescript": "3.6.1",