knip 5.71.0 → 5.73.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 (64) hide show
  1. package/dist/ConfigurationChief.d.ts +18 -0
  2. package/dist/ConsoleStreamer.js +1 -1
  3. package/dist/compilers/index.d.ts +30 -0
  4. package/dist/compilers/index.js +3 -0
  5. package/dist/compilers/scss.d.ts +6 -0
  6. package/dist/compilers/scss.js +14 -0
  7. package/dist/constants.js +1 -0
  8. package/dist/graph/analyze.js +19 -8
  9. package/dist/graph-explorer/explorer.d.ts +1 -1
  10. package/dist/graph-explorer/explorer.js +1 -1
  11. package/dist/graph-explorer/operations/{build-trace-tree.d.ts → build-exports-tree.d.ts} +4 -1
  12. package/dist/graph-explorer/operations/build-exports-tree.js +96 -0
  13. package/dist/graph-explorer/operations/is-referenced.js +4 -4
  14. package/dist/graph-explorer/utils.d.ts +1 -2
  15. package/dist/graph-explorer/utils.js +0 -15
  16. package/dist/graph-explorer/walk-down.d.ts +2 -1
  17. package/dist/graph-explorer/walk-down.js +7 -10
  18. package/dist/plugins/index.d.ts +3 -0
  19. package/dist/plugins/index.js +6 -0
  20. package/dist/plugins/next/index.js +3 -5
  21. package/dist/plugins/next/resolveFromAST.d.ts +0 -1
  22. package/dist/plugins/next/resolveFromAST.js +1 -42
  23. package/dist/plugins/next-intl/index.d.ts +3 -0
  24. package/dist/plugins/next-intl/index.js +12 -0
  25. package/dist/plugins/next-mdx/index.d.ts +3 -0
  26. package/dist/plugins/next-mdx/index.js +21 -0
  27. package/dist/plugins/next-mdx/resolveFromAST.d.ts +2 -0
  28. package/dist/plugins/next-mdx/resolveFromAST.js +43 -0
  29. package/dist/plugins/rsbuild/index.js +8 -0
  30. package/dist/plugins/rsbuild/types.d.ts +1 -0
  31. package/dist/plugins/storybook/index.js +12 -4
  32. package/dist/plugins/storybook/types.d.ts +5 -0
  33. package/dist/plugins/svgo/index.js +1 -1
  34. package/dist/plugins/svgr/index.d.ts +3 -0
  35. package/dist/plugins/svgr/index.js +24 -0
  36. package/dist/plugins/svgr/types.d.ts +3 -0
  37. package/dist/plugins/svgr/types.js +1 -0
  38. package/dist/plugins/vite/index.js +4 -0
  39. package/dist/plugins/vitest/index.js +1 -1
  40. package/dist/schema/configuration.d.ts +30 -0
  41. package/dist/schema/plugins.d.ts +15 -0
  42. package/dist/schema/plugins.js +3 -0
  43. package/dist/types/PluginNames.d.ts +2 -2
  44. package/dist/types/PluginNames.js +3 -0
  45. package/dist/types/module-graph.d.ts +2 -3
  46. package/dist/typescript/ast-helpers.d.ts +1 -1
  47. package/dist/typescript/ast-helpers.js +0 -3
  48. package/dist/typescript/get-imports-and-exports.js +74 -11
  49. package/dist/typescript/resolve-module-names.js +5 -4
  50. package/dist/typescript/visitors/dynamic-imports/requireCall.js +2 -1
  51. package/dist/util/Performance.js +4 -2
  52. package/dist/util/create-options.d.ts +30 -0
  53. package/dist/util/create-options.js +7 -3
  54. package/dist/util/module-graph.js +0 -1
  55. package/dist/util/modules.js +8 -4
  56. package/dist/util/resolve.d.ts +3 -2
  57. package/dist/util/resolve.js +25 -2
  58. package/dist/util/trace.d.ts +2 -10
  59. package/dist/util/trace.js +42 -36
  60. package/dist/version.d.ts +1 -1
  61. package/dist/version.js +1 -1
  62. package/package.json +7 -7
  63. package/schema.json +12 -0
  64. package/dist/graph-explorer/operations/build-trace-tree.js +0 -51
@@ -5,7 +5,7 @@ import { DEFAULT_EXTENSIONS } from '../constants.js';
5
5
  import { sanitizeSpecifier } from '../util/modules.js';
6
6
  import { timerify } from '../util/Performance.js';
7
7
  import { dirname, extname, isAbsolute, isInNodeModules, join } from '../util/path.js';
8
- import { _createSyncResolver, _resolveSync } from '../util/resolve.js';
8
+ import { _createSyncModuleResolver, _resolveModuleSync } from '../util/resolve.js';
9
9
  import { isDeclarationFileExtension } from './ast-helpers.js';
10
10
  const resolutionCache = new Map();
11
11
  const fileExists = (name, containingFile) => {
@@ -19,10 +19,11 @@ const fileExists = (name, containingFile) => {
19
19
  };
20
20
  }
21
21
  };
22
+ const tsResolveModuleName = timerify(ts.resolveModuleName);
22
23
  export function createCustomModuleResolver(compilerOptions, customCompilerExtensions, toSourceFilePath, useCache = true, isSkipLibs = true) {
23
24
  const customCompilerExtensionsSet = new Set(customCompilerExtensions);
24
25
  const extensions = [...DEFAULT_EXTENSIONS, ...customCompilerExtensions];
25
- const resolveSync = customCompilerExtensionsSet.size === 0 ? _resolveSync : _createSyncResolver(extensions);
26
+ const resolveSync = customCompilerExtensionsSet.size === 0 ? _resolveModuleSync : _createSyncModuleResolver(extensions);
26
27
  const virtualDeclarationFiles = new Map();
27
28
  const tsSys = {
28
29
  ...ts.sys,
@@ -57,7 +58,7 @@ export function createCustomModuleResolver(compilerOptions, customCompilerExtens
57
58
  const sanitizedSpecifier = sanitizeSpecifier(name);
58
59
  if (isBuiltin(sanitizedSpecifier))
59
60
  return undefined;
60
- const resolvedFileName = isSkipLibs && resolveSync(sanitizedSpecifier, dirname(containingFile));
61
+ const resolvedFileName = isSkipLibs && resolveSync(sanitizedSpecifier, containingFile);
61
62
  if (resolvedFileName) {
62
63
  const ext = extname(resolvedFileName);
63
64
  if (!customCompilerExtensionsSet.has(ext)) {
@@ -78,7 +79,7 @@ export function createCustomModuleResolver(compilerOptions, customCompilerExtens
78
79
  resolvedUsingTsExtension: false,
79
80
  };
80
81
  }
81
- const tsResolvedModule = ts.resolveModuleName(sanitizedSpecifier, containingFile, compilerOptions, tsSys).resolvedModule;
82
+ const tsResolvedModule = tsResolveModuleName(sanitizedSpecifier, containingFile, compilerOptions, tsSys).resolvedModule;
82
83
  if (tsResolvedModule) {
83
84
  if (isDeclarationFileExtension(tsResolvedModule.extension)) {
84
85
  const srcFilePath = toSourceFilePath(tsResolvedModule.resolvedFileName);
@@ -1,12 +1,13 @@
1
1
  import ts from 'typescript';
2
2
  import { IMPORT_MODIFIERS, IMPORT_STAR } from '../../../constants.js';
3
3
  import { findAncestor, findDescendants, isModuleExportsAccess, isRequireCall, isTopLevel } from '../../ast-helpers.js';
4
+ import { isNotJS } from '../helpers.js';
4
5
  import { importVisitor as visit } from '../index.js';
5
6
  export default visit(() => true, node => {
6
7
  if (isRequireCall(node)) {
7
8
  if (ts.isStringLiteralLike(node.arguments[0])) {
8
9
  const specifier = node.arguments[0].text;
9
- const modifiers = IMPORT_MODIFIERS.NONE;
10
+ const modifiers = isNotJS(node.getSourceFile()) ? IMPORT_MODIFIERS.ENTRY : IMPORT_MODIFIERS.NONE;
10
11
  if (specifier) {
11
12
  const propertyAccessExpression = findAncestor(node, _node => {
12
13
  if (ts.isExpressionStatement(_node) || ts.isCallExpression(_node))
@@ -8,7 +8,7 @@ const { values } = parseArgs({
8
8
  strict: false,
9
9
  options: {
10
10
  performance: { type: 'boolean' },
11
- 'performance-fn': { type: 'string' },
11
+ 'performance-fn': { type: 'string', multiple: true },
12
12
  memory: { type: 'boolean' },
13
13
  'memory-realtime': { type: 'boolean' },
14
14
  },
@@ -20,7 +20,7 @@ const isMemoryUsageEnabled = !!values.memory || isMemoryRealtime;
20
20
  export const timerify = (fn, name = fn.name) => {
21
21
  if (!isTimerifyFunctions)
22
22
  return fn;
23
- if (timerifyOnlyFnName && name !== timerifyOnlyFnName)
23
+ if (timerifyOnlyFnName && !timerifyOnlyFnName.includes(name))
24
24
  return fn;
25
25
  return performance.timerify(Object.defineProperty(fn, 'name', { get: () => name }));
26
26
  };
@@ -123,10 +123,12 @@ class Performance {
123
123
  }
124
124
  getMemoryUsageTable() {
125
125
  const table = new Table({ header: true });
126
+ let i = 0;
126
127
  for (const entry of this.memEntries) {
127
128
  if (!entry.detail)
128
129
  continue;
129
130
  table.row();
131
+ table.cell('#', String(i++));
130
132
  table.cell('heapUsed', inMB(entry.detail.heapUsed), twoFixed);
131
133
  table.cell('heapTotal', inMB(entry.detail.heapTotal), twoFixed);
132
134
  table.cell('freemem', inMB(entry.detail.freemem), twoFixed);
@@ -316,6 +316,16 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
316
316
  entry?: string | string[] | undefined;
317
317
  project?: string | string[] | undefined;
318
318
  } | undefined;
319
+ 'next-intl'?: string | boolean | string[] | {
320
+ config?: string | string[] | undefined;
321
+ entry?: string | string[] | undefined;
322
+ project?: string | string[] | undefined;
323
+ } | undefined;
324
+ 'next-mdx'?: string | boolean | string[] | {
325
+ config?: string | string[] | undefined;
326
+ entry?: string | string[] | undefined;
327
+ project?: string | string[] | undefined;
328
+ } | undefined;
319
329
  node?: string | boolean | string[] | {
320
330
  config?: string | string[] | undefined;
321
331
  entry?: string | string[] | undefined;
@@ -516,6 +526,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
516
526
  entry?: string | string[] | undefined;
517
527
  project?: string | string[] | undefined;
518
528
  } | undefined;
529
+ svgr?: string | boolean | string[] | {
530
+ config?: string | string[] | undefined;
531
+ entry?: string | string[] | undefined;
532
+ project?: string | string[] | undefined;
533
+ } | undefined;
519
534
  syncpack?: string | boolean | string[] | {
520
535
  config?: string | string[] | undefined;
521
536
  entry?: string | string[] | undefined;
@@ -912,6 +927,16 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
912
927
  entry?: string | string[] | undefined;
913
928
  project?: string | string[] | undefined;
914
929
  } | undefined;
930
+ 'next-intl'?: string | boolean | string[] | {
931
+ config?: string | string[] | undefined;
932
+ entry?: string | string[] | undefined;
933
+ project?: string | string[] | undefined;
934
+ } | undefined;
935
+ 'next-mdx'?: string | boolean | string[] | {
936
+ config?: string | string[] | undefined;
937
+ entry?: string | string[] | undefined;
938
+ project?: string | string[] | undefined;
939
+ } | undefined;
915
940
  node?: string | boolean | string[] | {
916
941
  config?: string | string[] | undefined;
917
942
  entry?: string | string[] | undefined;
@@ -1112,6 +1137,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1112
1137
  entry?: string | string[] | undefined;
1113
1138
  project?: string | string[] | undefined;
1114
1139
  } | undefined;
1140
+ svgr?: string | boolean | string[] | {
1141
+ config?: string | string[] | undefined;
1142
+ entry?: string | string[] | undefined;
1143
+ project?: string | string[] | undefined;
1144
+ } | undefined;
1115
1145
  syncpack?: string | boolean | string[] | {
1116
1146
  config?: string | string[] | undefined;
1117
1147
  entry?: string | string[] | undefined;
@@ -45,6 +45,8 @@ export const createOptions = async (options) => {
45
45
  : []);
46
46
  const isStrict = options.isStrict ?? parsedCLIArgs.strict ?? false;
47
47
  const isProduction = options.isProduction ?? parsedCLIArgs.production ?? isStrict;
48
+ const isDebug = parsedCLIArgs.debug ?? false;
49
+ const isTrace = Boolean(parsedCLIArgs.trace ?? parsedCLIArgs['trace-file'] ?? parsedCLIArgs['trace-export']);
48
50
  const rules = { ...defaultRules, ...parsedConfig.rules };
49
51
  const excludesFromRules = getKeysByValue(rules, 'off');
50
52
  const includedIssueTypes = getIncludedIssueTypes({
@@ -82,7 +84,7 @@ export const createOptions = async (options) => {
82
84
  gitignore: parsedCLIArgs['no-gitignore'] ? false : (options.gitignore ?? true),
83
85
  includedIssueTypes,
84
86
  isCache: parsedCLIArgs.cache ?? false,
85
- isDebug: parsedCLIArgs.debug ?? false,
87
+ isDebug,
86
88
  isDisableConfigHints: parsedCLIArgs['no-config-hints'] || isProduction || Boolean(parsedCLIArgs.workspace),
87
89
  isFix: parsedCLIArgs.fix ?? options.isFix ?? isFixFiles ?? fixTypes.length > 0,
88
90
  isFixCatalog: fixTypes.length === 0 || fixTypes.includes('catalog'),
@@ -101,13 +103,15 @@ export const createOptions = async (options) => {
101
103
  includedIssueTypes.binaries,
102
104
  isReportTypes: includedIssueTypes.types || includedIssueTypes.nsTypes || includedIssueTypes.enumMembers,
103
105
  isReportValues: includedIssueTypes.exports || includedIssueTypes.nsExports || isReportClassMembers,
104
- isShowProgress: parsedCLIArgs['no-progress'] !== true &&
106
+ isShowProgress: !isDebug &&
107
+ !isTrace &&
108
+ parsedCLIArgs['no-progress'] !== true &&
105
109
  options.isShowProgress !== false &&
106
110
  process.stdout.isTTY &&
107
111
  typeof process.stdout.cursorTo === 'function',
108
112
  isSkipLibs: !(isIncludeLibs || includedIssueTypes.classMembers),
109
113
  isStrict,
110
- isTrace: Boolean(parsedCLIArgs.trace ?? parsedCLIArgs['trace-file'] ?? parsedCLIArgs['trace-export']),
114
+ isTrace,
111
115
  isTreatConfigHintsAsErrors: parsedCLIArgs['treat-config-hints-as-errors'] ?? parsedConfig.treatConfigHintsAsErrors ?? false,
112
116
  isWatch: parsedCLIArgs.watch ?? options.isWatch ?? false,
113
117
  maxShowIssues: parsedCLIArgs['max-show-issues'] ? Number(parsedCLIArgs['max-show-issues']) : undefined,
@@ -40,7 +40,6 @@ const createFileNode = () => ({
40
40
  exports: new Map(),
41
41
  duplicates: new Set(),
42
42
  scripts: new Set(),
43
- traceRefs: new Set(),
44
43
  });
45
44
  export const createImports = () => ({
46
45
  refs: new Set(),
@@ -45,13 +45,17 @@ const CHAR_COLON = 58;
45
45
  const CHAR_HASH = 35;
46
46
  const CHAR_QUESTION = 63;
47
47
  export const sanitizeSpecifier = (specifier) => {
48
- if (isBuiltin(specifier) || isAbsolute(specifier) || specifier.startsWith(PROTOCOL_VIRTUAL))
48
+ if (isBuiltin(specifier) ||
49
+ isAbsolute(specifier) ||
50
+ specifier.charCodeAt(0) === CHAR_COLON ||
51
+ specifier.startsWith(PROTOCOL_VIRTUAL)) {
49
52
  return specifier;
53
+ }
50
54
  const len = specifier.length;
51
55
  let start = 0;
52
56
  let end = len;
53
57
  let colon = -1;
54
- let sawSlash = false;
58
+ let hasSlash = false;
55
59
  for (let i = 0; i < len; i++) {
56
60
  const ch = specifier.charCodeAt(i);
57
61
  if (i === start && (ch === CHAR_EXCLAMATION || ch === CHAR_DASH)) {
@@ -59,9 +63,9 @@ export const sanitizeSpecifier = (specifier) => {
59
63
  continue;
60
64
  }
61
65
  if (ch === CHAR_SLASH && colon === -1) {
62
- sawSlash = true;
66
+ hasSlash = true;
63
67
  }
64
- if (colon === -1 && ch === CHAR_COLON && !sawSlash) {
68
+ if (colon === -1 && ch === CHAR_COLON && !hasSlash) {
65
69
  colon = i;
66
70
  }
67
71
  if (ch === CHAR_EXCLAMATION || ch === CHAR_QUESTION || (ch === CHAR_HASH && i > start)) {
@@ -1,4 +1,5 @@
1
- declare const createSyncResolver: (extensions: string[]) => (specifier: string, baseDir: string) => string | undefined;
1
+ declare const createSyncModuleResolver: (extensions: string[]) => (specifier: string, basePath: string) => string | undefined;
2
+ export declare const _resolveModuleSync: (specifier: string, basePath: string) => string | undefined;
3
+ export declare const _createSyncModuleResolver: typeof createSyncModuleResolver;
2
4
  export declare const _resolveSync: (specifier: string, baseDir: string) => string | undefined;
3
- export declare const _createSyncResolver: typeof createSyncResolver;
4
5
  export {};
@@ -2,6 +2,30 @@ import { ResolverFactory } from 'oxc-resolver';
2
2
  import { DEFAULT_EXTENSIONS } from '../constants.js';
3
3
  import { timerify } from './Performance.js';
4
4
  import { toPosix } from './path.js';
5
+ const createSyncModuleResolver = (extensions) => {
6
+ const resolver = new ResolverFactory({
7
+ tsconfig: 'auto',
8
+ extensions,
9
+ extensionAlias: {
10
+ '.js': ['.js', '.ts'],
11
+ '.jsx': ['.jsx', '.tsx'],
12
+ '.mjs': ['.mjs', '.mts'],
13
+ '.cjs': ['.cjs', '.cts'],
14
+ },
15
+ conditionNames: ['require', 'import', 'node', 'default'],
16
+ });
17
+ return function resolveSync(specifier, basePath) {
18
+ try {
19
+ const resolved = resolver.resolveFileSync(basePath, specifier);
20
+ if (resolved?.path)
21
+ return toPosix(resolved.path);
22
+ }
23
+ catch (_error) { }
24
+ };
25
+ };
26
+ const resolveModuleSync = createSyncModuleResolver([...DEFAULT_EXTENSIONS, '.json', '.jsonc']);
27
+ export const _resolveModuleSync = timerify(resolveModuleSync);
28
+ export const _createSyncModuleResolver = extensions => timerify(createSyncModuleResolver(extensions));
5
29
  const createSyncResolver = (extensions) => {
6
30
  const resolver = new ResolverFactory({
7
31
  extensions,
@@ -16,6 +40,5 @@ const createSyncResolver = (extensions) => {
16
40
  catch (_error) { }
17
41
  };
18
42
  };
19
- const resolveSync = createSyncResolver([...DEFAULT_EXTENSIONS, '.json', '.jsonc']);
43
+ const resolveSync = createSyncResolver(DEFAULT_EXTENSIONS);
20
44
  export const _resolveSync = timerify(resolveSync);
21
- export const _createSyncResolver = extensions => timerify(createSyncResolver(extensions));
@@ -1,10 +1,2 @@
1
- import type { MainOptions } from './create-options.js';
2
- type ExplorerTraceNode = {
3
- filePath: string;
4
- identifier?: string;
5
- hasRef: boolean;
6
- isEntry: boolean;
7
- children: ExplorerTraceNode[];
8
- };
9
- export declare const printTraceNode: (node: ExplorerTraceNode, options: MainOptions) => void;
10
- export {};
1
+ import type { TreeNode } from '../graph-explorer/operations/build-exports-tree.js';
2
+ export declare const formatTrace: (node: TreeNode, toRelative: (path: string) => string, isReferenced: boolean) => string;
@@ -1,39 +1,45 @@
1
- import picocolors from 'picocolors';
2
- import { toRelative } from './path.js';
3
- const IS_ENTRY = ' ◯';
4
- const HAS_REF = ' ✓';
5
- const HAS_NO_REF = ' x';
6
- const getPadding = (level, levels) => {
7
- let padding = '';
8
- for (let i = 0; i < level; i++)
9
- padding += levels.has(i) ? `${picocolors.dim('│')} ` : ' ';
10
- return padding;
11
- };
12
- const renderExplorerTrace = (node, options, level = 0, levels = new Set()) => {
13
- let index = 0;
14
- const size = node.children.length;
15
- const padding = getPadding(level, levels);
16
- for (const child of node.children) {
17
- const isLast = ++index === size;
18
- const hasRef = child.hasRef === true;
19
- const rel = toRelative(child.filePath, options.cwd);
20
- const file = hasRef ? rel : picocolors.dim(rel);
21
- const suffix = hasRef ? HAS_REF : '';
22
- const text = `${padding}${picocolors.dim(isLast ? '└─' : '├─')} ${file}${suffix}`;
23
- console.log(text);
24
- if (child.children.length > 0) {
25
- if (!isLast)
26
- levels.add(level);
27
- if (isLast)
28
- levels.delete(level);
29
- renderExplorerTrace(child, options, level + 1, levels);
1
+ import pc from 'picocolors';
2
+ export const formatTrace = (node, toRelative, isReferenced) => {
3
+ const lines = [];
4
+ const file = pc.white;
5
+ const id = pc.cyanBright;
6
+ const ref = pc.cyanBright;
7
+ const via = pc.dim;
8
+ const ok = pc.green;
9
+ const fail = pc.red;
10
+ const dim = pc.dim;
11
+ const entryMarker = node.isEntry ? dim(' ◯') : '';
12
+ lines.push(`${file(toRelative(node.filePath))}${dim(':')}${id(node.identifier)}${entryMarker}`);
13
+ const formatVia = (child) => {
14
+ if (!child.via)
15
+ return id(child.identifier);
16
+ const parts = child.identifier.split('.');
17
+ const name = parts[0];
18
+ const rest = parts.slice(1).join('.');
19
+ const nameDisplay = child.originalId ? `${id(child.originalId)}${dim(' → ')}${id(name)}` : id(name);
20
+ return `${via(child.via)}${dim('[')}${nameDisplay}${rest ? `${dim('.')}${id(rest)}` : ''}${dim(']')}`;
21
+ };
22
+ const formatChild = (child, prefix, isLast) => {
23
+ const connector = isLast ? '└── ' : '├── ';
24
+ const childPrefix = isLast ? ' ' : '│ ';
25
+ const entryMarker = child.isEntry ? dim(' ◯') : '';
26
+ const isLeaf = child.children.length === 0;
27
+ const leafMarker = isLeaf && !child.via?.startsWith('reExport') ? (isReferenced ? ok(' ✓') : fail(' ✗')) : '';
28
+ lines.push(`${dim(prefix)}${dim(connector)}${file(toRelative(child.filePath))}${dim(':')}${formatVia(child)}${entryMarker}${leafMarker}`);
29
+ if (child.refs.length > 0) {
30
+ const refsPrefix = isLeaf ? ' ' : '│';
31
+ lines.push(`${dim(prefix)}${dim(childPrefix)}${dim(refsPrefix)} ${dim('refs: [')}${child.refs.map(r => ref(r)).join(dim(', '))}${dim(']')}`);
32
+ }
33
+ for (let i = 0; i < child.children.length; i++) {
34
+ formatChild(child.children[i], prefix + childPrefix, i === child.children.length - 1);
30
35
  }
36
+ };
37
+ for (let i = 0; i < node.children.length; i++) {
38
+ formatChild(node.children[i], '', i === node.children.length - 1);
31
39
  }
32
- };
33
- export const printTraceNode = (node, options) => {
34
- const suffix = (node.isEntry ? IS_ENTRY : '') + (node.children.length === 0 ? HAS_NO_REF : '');
35
- const header = `${toRelative(node.filePath, options.cwd)}${node.identifier ? `:${node.identifier}` : ''}${suffix}`;
36
- console.log(header);
37
- renderExplorerTrace(node, options);
38
- console.log();
40
+ if (node.children.length === 0) {
41
+ const leafMarker = isReferenced ? ok(' ✓') : fail(' ✗');
42
+ lines.push(`${dim('└── (no imports found)')}${leafMarker}`);
43
+ }
44
+ return lines.join('\n');
39
45
  };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.71.0";
1
+ export declare const version = "5.73.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.71.0';
1
+ export const version = '5.73.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.71.0",
3
+ "version": "5.73.0",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "test": "node scripts/run-test.ts",
40
40
  "test:node": "tsx --test test/*.test.ts test/**/*.test.ts",
41
41
  "test:bun": "bun test test/*.test.ts test/**/*.test.ts",
42
- "test:smoke": "glob -c \"tsx --test\" \"test/*.test.ts\" && glob -c \"tsx --test\" \"test/{plugins,util}/*.test.ts\"",
42
+ "test:smoke": "glob-bin -c \"tsx --test\" \"test/*.test.ts\" && glob-bin -c \"tsx --test\" \"test/{plugins,util}/*.test.ts\"",
43
43
  "test:bun:smoke": "bun test test/*.test.ts test/{plugins,util}/*.test.ts",
44
44
  "watch": "npm link && tsc --watch",
45
45
  "prebuild": "pnpm run generate-plugin-defs && node rmdir.js dist",
@@ -63,7 +63,7 @@
63
63
  "jiti": "^2.6.0",
64
64
  "js-yaml": "^4.1.1",
65
65
  "minimist": "^1.2.8",
66
- "oxc-resolver": "^11.13.2",
66
+ "oxc-resolver": "^11.15.0",
67
67
  "picocolors": "^1.1.1",
68
68
  "picomatch": "^4.0.1",
69
69
  "smol-toml": "^1.5.2",
@@ -77,14 +77,14 @@
77
77
  "devDependencies": {
78
78
  "@jest/types": "^29.6.3",
79
79
  "@release-it/bumper": "^7.0.5",
80
- "@types/bun": "1.2.22",
80
+ "@types/bun": "^1.3.3",
81
81
  "@types/js-yaml": "^4.0.9",
82
82
  "@types/minimist": "^1.2.5",
83
- "@types/picomatch": "3.0.1",
83
+ "@types/picomatch": "^4.0.1",
84
84
  "@types/webpack": "^5.28.5",
85
- "@wdio/types": "^9.16.2",
85
+ "@wdio/types": "^9.20.0",
86
86
  "codeclimate-types": "^0.3.1",
87
- "glob": "^11.0.2",
87
+ "glob-bin": "^1.0.0",
88
88
  "release-it": "^19.0.5",
89
89
  "tsx": "^4.20.3",
90
90
  "typescript": "^5.5.2"
package/schema.json CHANGED
@@ -554,6 +554,14 @@
554
554
  "title": "Next.js plugin configuration (https://knip.dev/reference/plugins/main)",
555
555
  "$ref": "#/definitions/plugin"
556
556
  },
557
+ "next-intl": {
558
+ "title": "next-intl plugin configuration (https://knip.dev/reference/plugins/next-intl)",
559
+ "$ref": "#/definitions/plugin"
560
+ },
561
+ "next-mdx": {
562
+ "title": "next-mdx plugin configuration (https://knip.dev/reference/plugins/next-mdx)",
563
+ "$ref": "#/definitions/plugin"
564
+ },
557
565
  "node": {
558
566
  "title": "node plugin configuration (https://knip.dev/reference/plugins/node)",
559
567
  "$ref": "#/definitions/plugin"
@@ -714,6 +722,10 @@
714
722
  "title": "svgo plugin configuration (https://knip.dev/reference/plugins/svgo)",
715
723
  "$ref": "#/definitions/plugin"
716
724
  },
725
+ "svgr": {
726
+ "title": "svgr plugin configuration (https://knip.dev/reference/plugins/svgr)",
727
+ "$ref": "#/definitions/plugin"
728
+ },
717
729
  "syncpack": {
718
730
  "title": "syncpack plugin configuration (https://knip.dev/reference/plugins/syncpack)",
719
731
  "$ref": "#/definitions/plugin"
@@ -1,51 +0,0 @@
1
- import { CONTINUE } from '../constants.js';
2
- import { walkDown } from '../walk-down.js';
3
- export const buildExportsTree = (graph, entryPaths, options) => {
4
- const traces = [];
5
- const processFile = (filePath, file) => {
6
- for (const exportId of options.identifier ? [options.identifier] : file.exports.keys()) {
7
- if (!options.identifier || file.exports.has(exportId)) {
8
- const trace = buildExportTree(graph, entryPaths, filePath, exportId);
9
- if (trace)
10
- traces.push(trace);
11
- }
12
- }
13
- };
14
- if (options.filePath) {
15
- const file = graph.get(options.filePath);
16
- if (file)
17
- processFile(options.filePath, file);
18
- }
19
- else {
20
- for (const [filePath, file] of graph)
21
- processFile(filePath, file);
22
- }
23
- return traces;
24
- };
25
- const buildExportTree = (graph, entryPaths, filePath, identifier) => {
26
- const rootNode = {
27
- filePath,
28
- identifier,
29
- hasRef: false,
30
- isEntry: entryPaths.has(filePath),
31
- children: [],
32
- };
33
- const nodeMap = new Map();
34
- nodeMap.set(`${filePath}:${identifier}`, rootNode);
35
- walkDown(graph, filePath, identifier, (sourceFile, sourceId, importingFile, id, isEntry, isReExport) => {
36
- const key = `${importingFile}:${id}`;
37
- const childNode = nodeMap.get(key) ?? {
38
- filePath: importingFile,
39
- identifier: id,
40
- hasRef: !isReExport && Boolean(graph.get(importingFile)?.traceRefs?.has(id)),
41
- isEntry,
42
- children: [],
43
- };
44
- nodeMap.set(key, childNode);
45
- const parentKey = `${sourceFile}:${sourceId}`;
46
- const parentNode = nodeMap.get(parentKey) ?? rootNode;
47
- parentNode.children.push(childNode);
48
- return CONTINUE;
49
- }, entryPaths);
50
- return rootNode;
51
- };