knip 5.71.0 → 5.72.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 (52) hide show
  1. package/dist/ConfigurationChief.d.ts +6 -0
  2. package/dist/ConsoleStreamer.js +1 -1
  3. package/dist/compilers/index.d.ts +10 -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/graph/analyze.js +19 -8
  8. package/dist/graph-explorer/explorer.d.ts +1 -1
  9. package/dist/graph-explorer/explorer.js +1 -1
  10. package/dist/graph-explorer/operations/{build-trace-tree.d.ts → build-exports-tree.d.ts} +4 -1
  11. package/dist/graph-explorer/operations/build-exports-tree.js +96 -0
  12. package/dist/graph-explorer/operations/is-referenced.js +4 -4
  13. package/dist/graph-explorer/utils.d.ts +1 -2
  14. package/dist/graph-explorer/utils.js +0 -15
  15. package/dist/graph-explorer/walk-down.d.ts +2 -1
  16. package/dist/graph-explorer/walk-down.js +7 -10
  17. package/dist/plugins/index.d.ts +1 -0
  18. package/dist/plugins/index.js +2 -0
  19. package/dist/plugins/rsbuild/index.js +8 -0
  20. package/dist/plugins/rsbuild/types.d.ts +1 -0
  21. package/dist/plugins/storybook/index.js +12 -4
  22. package/dist/plugins/storybook/types.d.ts +5 -0
  23. package/dist/plugins/svgo/index.js +1 -1
  24. package/dist/plugins/svgr/index.d.ts +3 -0
  25. package/dist/plugins/svgr/index.js +24 -0
  26. package/dist/plugins/svgr/types.d.ts +3 -0
  27. package/dist/plugins/svgr/types.js +1 -0
  28. package/dist/plugins/vite/index.js +4 -0
  29. package/dist/plugins/vitest/index.js +1 -1
  30. package/dist/schema/configuration.d.ts +10 -0
  31. package/dist/schema/plugins.d.ts +5 -0
  32. package/dist/schema/plugins.js +1 -0
  33. package/dist/types/PluginNames.d.ts +2 -2
  34. package/dist/types/PluginNames.js +1 -0
  35. package/dist/types/module-graph.d.ts +2 -3
  36. package/dist/typescript/ast-helpers.d.ts +1 -1
  37. package/dist/typescript/ast-helpers.js +0 -3
  38. package/dist/typescript/get-imports-and-exports.js +74 -11
  39. package/dist/typescript/resolve-module-names.js +5 -4
  40. package/dist/util/Performance.js +4 -2
  41. package/dist/util/create-options.d.ts +10 -0
  42. package/dist/util/create-options.js +7 -3
  43. package/dist/util/module-graph.js +0 -1
  44. package/dist/util/resolve.d.ts +3 -2
  45. package/dist/util/resolve.js +25 -2
  46. package/dist/util/trace.d.ts +2 -10
  47. package/dist/util/trace.js +42 -36
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/package.json +7 -7
  51. package/schema.json +4 -0
  52. package/dist/graph-explorer/operations/build-trace-tree.js +0 -51
@@ -481,6 +481,11 @@ export declare const pluginsSchema: z.ZodMiniObject<{
481
481
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
482
482
  project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
483
483
  }, z.core.$strip>]>;
484
+ svgr: z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
485
+ config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
486
+ entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
487
+ project: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
488
+ }, z.core.$strip>]>;
484
489
  syncpack: z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>, z.ZodMiniObject<{
485
490
  config: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
486
491
  entry: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
@@ -105,6 +105,7 @@ export const pluginsSchema = z.object({
105
105
  stylelint: pluginSchema,
106
106
  svelte: pluginSchema,
107
107
  svgo: pluginSchema,
108
+ svgr: pluginSchema,
108
109
  syncpack: pluginSchema,
109
110
  tailwind: pluginSchema,
110
111
  taskfile: pluginSchema,
@@ -1,2 +1,2 @@
1
- export type PluginName = 'angular' | 'astro' | 'astro-db' | 'ava' | 'babel' | 'biome' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'danger' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'mdx' | 'mdxlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'oxlint' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pnpm' | 'postcss' | 'preconstruct' | 'prettier' | 'prisma' | 'react-cosmos' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'svgo' | 'syncpack' | 'tailwind' | 'taskfile' | 'travis' | 'ts-node' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'vercel-og' | 'vike' | 'vite' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'xo' | 'yarn' | 'yorkie';
2
- export declare const pluginNames: readonly ["angular", "astro", "astro-db", "ava", "babel", "biome", "bumpp", "bun", "c8", "capacitor", "changelogen", "changelogithub", "changesets", "commitizen", "commitlint", "convex", "create-typescript-app", "cspell", "cucumber", "cypress", "danger", "dependency-cruiser", "docusaurus", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-action", "github-actions", "glob", "graphql-codegen", "hardhat", "husky", "i18next-parser", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "mdx", "mdxlint", "metro", "mocha", "moonrepo", "msw", "nano-staged", "nest", "netlify", "next", "node", "node-modules-inspector", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "oxlint", "playwright", "playwright-ct", "playwright-test", "plop", "pnpm", "postcss", "preconstruct", "prettier", "prisma", "react-cosmos", "react-router", "relay", "release-it", "remark", "remix", "rollup", "rsbuild", "rslib", "rspack", "rstest", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "sst", "starlight", "storybook", "stryker", "stylelint", "svelte", "svgo", "syncpack", "tailwind", "taskfile", "travis", "ts-node", "tsdown", "tsup", "tsx", "typedoc", "typescript", "unbuild", "unocss", "vercel-og", "vike", "vite", "vitest", "vue", "webdriver-io", "webpack", "wireit", "wrangler", "xo", "yarn", "yorkie"];
1
+ export type PluginName = 'angular' | 'astro' | 'astro-db' | 'ava' | 'babel' | 'biome' | 'bumpp' | 'bun' | 'c8' | 'capacitor' | 'changelogen' | 'changelogithub' | 'changesets' | 'commitizen' | 'commitlint' | 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress' | 'danger' | 'dependency-cruiser' | 'docusaurus' | 'dotenv' | 'drizzle' | 'eleventy' | 'eslint' | 'expo' | 'gatsby' | 'github-action' | 'github-actions' | 'glob' | 'graphql-codegen' | 'hardhat' | 'husky' | 'i18next-parser' | 'jest' | 'karma' | 'ladle' | 'lefthook' | 'lint-staged' | 'linthtml' | 'lockfile-lint' | 'lost-pixel' | 'markdownlint' | 'mdx' | 'mdxlint' | 'metro' | 'mocha' | 'moonrepo' | 'msw' | 'nano-staged' | 'nest' | 'netlify' | 'next' | 'node' | 'node-modules-inspector' | 'nodemon' | 'npm-package-json-lint' | 'nuxt' | 'nx' | 'nyc' | 'oclif' | 'oxlint' | 'playwright' | 'playwright-ct' | 'playwright-test' | 'plop' | 'pnpm' | 'postcss' | 'preconstruct' | 'prettier' | 'prisma' | 'react-cosmos' | 'react-router' | 'relay' | 'release-it' | 'remark' | 'remix' | 'rollup' | 'rsbuild' | 'rslib' | 'rspack' | 'rstest' | 'semantic-release' | 'sentry' | 'simple-git-hooks' | 'size-limit' | 'sst' | 'starlight' | 'storybook' | 'stryker' | 'stylelint' | 'svelte' | 'svgo' | 'svgr' | 'syncpack' | 'tailwind' | 'taskfile' | 'travis' | 'ts-node' | 'tsdown' | 'tsup' | 'tsx' | 'typedoc' | 'typescript' | 'unbuild' | 'unocss' | 'vercel-og' | 'vike' | 'vite' | 'vitest' | 'vue' | 'webdriver-io' | 'webpack' | 'wireit' | 'wrangler' | 'xo' | 'yarn' | 'yorkie';
2
+ export declare const pluginNames: readonly ["angular", "astro", "astro-db", "ava", "babel", "biome", "bumpp", "bun", "c8", "capacitor", "changelogen", "changelogithub", "changesets", "commitizen", "commitlint", "convex", "create-typescript-app", "cspell", "cucumber", "cypress", "danger", "dependency-cruiser", "docusaurus", "dotenv", "drizzle", "eleventy", "eslint", "expo", "gatsby", "github-action", "github-actions", "glob", "graphql-codegen", "hardhat", "husky", "i18next-parser", "jest", "karma", "ladle", "lefthook", "lint-staged", "linthtml", "lockfile-lint", "lost-pixel", "markdownlint", "mdx", "mdxlint", "metro", "mocha", "moonrepo", "msw", "nano-staged", "nest", "netlify", "next", "node", "node-modules-inspector", "nodemon", "npm-package-json-lint", "nuxt", "nx", "nyc", "oclif", "oxlint", "playwright", "playwright-ct", "playwright-test", "plop", "pnpm", "postcss", "preconstruct", "prettier", "prisma", "react-cosmos", "react-router", "relay", "release-it", "remark", "remix", "rollup", "rsbuild", "rslib", "rspack", "rstest", "semantic-release", "sentry", "simple-git-hooks", "size-limit", "sst", "starlight", "storybook", "stryker", "stylelint", "svelte", "svgo", "svgr", "syncpack", "tailwind", "taskfile", "travis", "ts-node", "tsdown", "tsup", "tsx", "typedoc", "typescript", "unbuild", "unocss", "vercel-og", "vike", "vite", "vitest", "vue", "webdriver-io", "webpack", "wireit", "wrangler", "xo", "yarn", "yorkie"];
@@ -94,6 +94,7 @@ export const pluginNames = [
94
94
  'stylelint',
95
95
  'svelte',
96
96
  'svgo',
97
+ 'svgr',
97
98
  'syncpack',
98
99
  'tailwind',
99
100
  'taskfile',
@@ -35,7 +35,7 @@ export interface Export extends SourceLocation {
35
35
  type: SymbolType;
36
36
  members: ExportMember[];
37
37
  jsDocTags: Tags;
38
- refs: [number, boolean];
38
+ self: [number, boolean];
39
39
  fixes: Fixes;
40
40
  symbol?: ts.Symbol;
41
41
  isReExport?: boolean;
@@ -46,7 +46,7 @@ export type ExportMember = {
46
46
  line: number;
47
47
  col: number;
48
48
  type: SymbolType;
49
- refs: [number, boolean];
49
+ self: [number, boolean];
50
50
  fix: Fix;
51
51
  symbol?: ts.Symbol;
52
52
  jsDocTags: Tags;
@@ -66,7 +66,6 @@ export type FileNode = {
66
66
  scripts: Set<string>;
67
67
  imported?: ImportMaps;
68
68
  internalImportCache?: ImportMap;
69
- traceRefs: References;
70
69
  };
71
70
  export type ModuleGraph = Map<FilePath, FileNode>;
72
71
  export {};
@@ -40,7 +40,7 @@ export declare const getLineAndCharacterOfPosition: (node: ts.Node, pos: number)
40
40
  col: number;
41
41
  pos: number;
42
42
  };
43
- export declare const getAccessMembers: (typeChecker: ts.TypeChecker, node: ts.Identifier) => string[];
43
+ export declare const getAccessMembers: (typeChecker: ts.TypeChecker, node: ts.Node) => string[];
44
44
  export declare const isDestructuring: (node: ts.Node) => boolean;
45
45
  export declare const getDestructuredNames: (name: ts.ObjectBindingPattern) => [string[], boolean];
46
46
  export declare const isConsiderReferencedNS: (node: ts.Identifier) => boolean;
@@ -198,13 +198,10 @@ export const getDestructuredNames = (name) => {
198
198
  return [members, hasSpread];
199
199
  };
200
200
  export const isConsiderReferencedNS = (node) => ts.isPropertyAssignment(node.parent) ||
201
- ts.isShorthandPropertyAssignment(node.parent) ||
202
201
  (ts.isCallExpression(node.parent) && node.parent.arguments.includes(node)) ||
203
202
  ts.isSpreadAssignment(node.parent) ||
204
203
  ts.isArrayLiteralExpression(node.parent) ||
205
204
  ts.isExportAssignment(node.parent) ||
206
- ts.isConditionalExpression(node.parent) ||
207
- (ts.isVariableDeclaration(node.parent) && node.parent.initializer === node) ||
208
205
  ts.isTypeQueryNode(node.parent.parent);
209
206
  export const isInOpaqueExpression = (node) => ts.isAwaitExpression(node.parent)
210
207
  ? isInOpaqueExpression(node.parent)
@@ -29,7 +29,7 @@ const createMember = (node, member, pos) => {
29
29
  line: line + 1,
30
30
  col: character + 1,
31
31
  fix: member.fix,
32
- refs: [0, false],
32
+ self: [0, false],
33
33
  jsDocTags: getJSDocTags(member.node),
34
34
  };
35
35
  };
@@ -42,19 +42,24 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
42
42
  const exports = new Map();
43
43
  const aliasedExports = new Map();
44
44
  const scripts = new Set();
45
- const traceRefs = new Set();
46
45
  const importedInternalSymbols = new Map();
46
+ const importAliases = new Map();
47
+ const addImportAlias = (aliasName, id, filePath) => {
48
+ const aliases = importAliases.get(aliasName);
49
+ if (aliases)
50
+ aliases.add({ id, filePath });
51
+ else
52
+ importAliases.set(aliasName, new Set([{ id, filePath }]));
53
+ };
47
54
  const referencedSymbolsInExport = new Set();
48
55
  const visitors = getVisitors(sourceFile);
49
56
  const addNsMemberRefs = (internalImport, namespace, member) => {
50
57
  if (typeof member === 'string') {
51
58
  internalImport.refs.add(`${namespace}.${member}`);
52
- traceRefs.add(`${namespace}.${member}`);
53
59
  }
54
60
  else {
55
61
  for (const m of member) {
56
62
  internalImport.refs.add(`${namespace}.${m}`);
57
- traceRefs.add(`${namespace}.${m}`);
58
63
  }
59
64
  }
60
65
  };
@@ -231,7 +236,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
231
236
  line: line + 1,
232
237
  col: character + 1,
233
238
  fixes: fix ? [fix] : [],
234
- refs: [0, false],
239
+ self: [0, false],
235
240
  isReExport,
236
241
  });
237
242
  }
@@ -285,13 +290,25 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
285
290
  if (ts.isIdentifier(node)) {
286
291
  const id = String(node.escapedText);
287
292
  const { symbol, filePath } = getImport(id, node);
293
+ if (importAliases.has(id) && isAccessExpression(node.parent)) {
294
+ const members = getAccessMembers(typeChecker, node);
295
+ for (const { id: aliasedId, filePath: aliasFilePath } of importAliases.get(id)) {
296
+ const aliasImports = internal.get(aliasFilePath);
297
+ if (aliasImports)
298
+ addNsMemberRefs(aliasImports, aliasedId, members);
299
+ }
300
+ }
288
301
  if (symbol) {
289
302
  if (filePath) {
290
303
  if (!isImportSpecifier(node)) {
291
304
  const imports = internal.get(filePath);
292
305
  if (imports) {
293
- traceRefs.add(id);
294
- if (isAccessExpression(node.parent)) {
306
+ const isPropName = ts.isPropertyAccessExpression(node.parent) && node.parent.name === node;
307
+ if (isPropName && isAccessExpression(node.parent.parent)) {
308
+ const members = getAccessMembers(typeChecker, node.parent);
309
+ addNsMemberRefs(imports, id, members);
310
+ }
311
+ else if (isAccessExpression(node.parent) && !isPropName) {
295
312
  if (isDestructuring(node.parent)) {
296
313
  if (ts.isPropertyAccessExpression(node.parent)) {
297
314
  const ns = String(symbol.escapedName);
@@ -318,6 +335,25 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
318
335
  else
319
336
  addNsMemberRefs(imports, id, members);
320
337
  }
338
+ else if (ts.isSpreadAssignment(node.parent)) {
339
+ const path = [];
340
+ let _node = node.parent;
341
+ while (_node && !ts.isVariableDeclaration(_node)) {
342
+ if (ts.isPropertyAssignment(_node) && ts.isIdentifier(_node.name))
343
+ path.unshift(_node.name.text);
344
+ _node = _node.parent;
345
+ }
346
+ if (_node && ts.isIdentifier(_node.name)) {
347
+ const varName = _node.name.text;
348
+ if (exports.has(varName)) {
349
+ addNsValue(imports.reExportedAs, id, [varName, ...path].join('.'), sourceFile.fileName);
350
+ }
351
+ else if (path.length === 0) {
352
+ addImportAlias(varName, id, filePath);
353
+ }
354
+ }
355
+ imports.refs.add(id);
356
+ }
321
357
  else {
322
358
  const typeRef = getTypeRef(node);
323
359
  if (typeRef) {
@@ -331,6 +367,34 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
331
367
  imports.refs.add(id);
332
368
  }
333
369
  }
370
+ else if (ts.isVariableDeclaration(node.parent) &&
371
+ node.parent.initializer === node &&
372
+ ts.isIdentifier(node.parent.name)) {
373
+ const aliasName = node.parent.name.text;
374
+ if (exports.has(aliasName)) {
375
+ addNsValue(imports.reExportedAs, id, aliasName, sourceFile.fileName);
376
+ }
377
+ else {
378
+ addImportAlias(aliasName, id, filePath);
379
+ imports.refs.add(id);
380
+ }
381
+ }
382
+ else if (ts.isConditionalExpression(node.parent) || ts.isBinaryExpression(node.parent)) {
383
+ let _node = node.parent;
384
+ while (_node && !ts.isVariableDeclaration(_node))
385
+ _node = _node.parent;
386
+ if (_node && ts.isIdentifier(_node.name))
387
+ addImportAlias(_node.name.text, id, filePath);
388
+ imports.refs.add(id);
389
+ }
390
+ else if (ts.isShorthandPropertyAssignment(node.parent)) {
391
+ let _node = node.parent;
392
+ while (_node && !ts.isVariableDeclaration(_node))
393
+ _node = _node.parent;
394
+ if (_node && ts.isIdentifier(_node.name))
395
+ addImportAlias(`${_node.name.text}.${id}`, id, filePath);
396
+ imports.refs.add(id);
397
+ }
334
398
  else if (imports.importedNs.has(id) && isConsiderReferencedNS(node)) {
335
399
  imports.refs.add(id);
336
400
  }
@@ -358,7 +422,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
358
422
  addImport(node, sourceFile);
359
423
  for (const item of exports.values()) {
360
424
  if (!isType(item) && item.symbol && referencedSymbolsInExport.has(item.symbol)) {
361
- item.refs = [1, true];
425
+ item.self = [1, true];
362
426
  }
363
427
  else {
364
428
  const isBindingElement = item.symbol?.valueDeclaration && ts.isBindingElement(item.symbol.valueDeclaration);
@@ -367,11 +431,11 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
367
431
  item.type !== 'unknown' &&
368
432
  ignoreExportsUsedInFile[item.type]) ||
369
433
  isBindingElement) {
370
- item.refs = findInternalReferences(item, sourceFile, typeChecker, referencedSymbolsInExport, isBindingElement);
434
+ item.self = findInternalReferences(item, sourceFile, typeChecker, referencedSymbolsInExport, isBindingElement);
371
435
  }
372
436
  }
373
437
  for (const member of item.members) {
374
- member.refs = findInternalReferences(member, sourceFile, typeChecker, referencedSymbolsInExport);
438
+ member.self = findInternalReferences(member, sourceFile, typeChecker, referencedSymbolsInExport);
375
439
  member.symbol = undefined;
376
440
  }
377
441
  item.symbol = undefined;
@@ -381,7 +445,6 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
381
445
  exports,
382
446
  duplicates: [...aliasedExports.values()],
383
447
  scripts,
384
- traceRefs,
385
448
  };
386
449
  };
387
450
  export const _getImportsAndExports = timerify(getImportsAndExports);
@@ -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);
@@ -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);
@@ -516,6 +516,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
516
516
  entry?: string | string[] | undefined;
517
517
  project?: string | string[] | undefined;
518
518
  } | undefined;
519
+ svgr?: string | boolean | string[] | {
520
+ config?: string | string[] | undefined;
521
+ entry?: string | string[] | undefined;
522
+ project?: string | string[] | undefined;
523
+ } | undefined;
519
524
  syncpack?: string | boolean | string[] | {
520
525
  config?: string | string[] | undefined;
521
526
  entry?: string | string[] | undefined;
@@ -1112,6 +1117,11 @@ export declare const createOptions: (options: CreateOptions) => Promise<{
1112
1117
  entry?: string | string[] | undefined;
1113
1118
  project?: string | string[] | undefined;
1114
1119
  } | undefined;
1120
+ svgr?: string | boolean | string[] | {
1121
+ config?: string | string[] | undefined;
1122
+ entry?: string | string[] | undefined;
1123
+ project?: string | string[] | undefined;
1124
+ } | undefined;
1115
1125
  syncpack?: string | boolean | string[] | {
1116
1126
  config?: string | string[] | undefined;
1117
1127
  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(),
@@ -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.72.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.71.0';
1
+ export const version = '5.72.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.71.0",
3
+ "version": "5.72.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
@@ -714,6 +714,10 @@
714
714
  "title": "svgo plugin configuration (https://knip.dev/reference/plugins/svgo)",
715
715
  "$ref": "#/definitions/plugin"
716
716
  },
717
+ "svgr": {
718
+ "title": "svgr plugin configuration (https://knip.dev/reference/plugins/svgr)",
719
+ "$ref": "#/definitions/plugin"
720
+ },
717
721
  "syncpack": {
718
722
  "title": "syncpack plugin configuration (https://knip.dev/reference/plugins/syncpack)",
719
723
  "$ref": "#/definitions/plugin"