knip 5.70.2 → 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 (86) hide show
  1. package/dist/ConfigurationChief.d.ts +6 -0
  2. package/dist/ConsoleStreamer.js +1 -1
  3. package/dist/DependencyDeputy.js +2 -2
  4. package/dist/ProjectPrincipal.js +1 -1
  5. package/dist/WorkspaceWorker.js +1 -1
  6. package/dist/binaries/bash-parser.js +14 -1
  7. package/dist/compilers/index.d.ts +10 -0
  8. package/dist/compilers/index.js +4 -1
  9. package/dist/compilers/scss.d.ts +6 -0
  10. package/dist/compilers/scss.js +14 -0
  11. package/dist/constants.js +1 -0
  12. package/dist/graph/analyze.js +38 -22
  13. package/dist/graph-explorer/constants.d.ts +2 -0
  14. package/dist/graph-explorer/constants.js +2 -0
  15. package/dist/graph-explorer/explorer.d.ts +11 -0
  16. package/dist/graph-explorer/explorer.js +10 -0
  17. package/dist/graph-explorer/operations/build-exports-tree.d.ts +15 -0
  18. package/dist/graph-explorer/operations/build-exports-tree.js +96 -0
  19. package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
  20. package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
  21. package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
  22. package/dist/graph-explorer/operations/is-referenced.js +89 -0
  23. package/dist/graph-explorer/utils.d.ts +3 -0
  24. package/dist/graph-explorer/utils.js +13 -0
  25. package/dist/graph-explorer/visitors.d.ts +12 -0
  26. package/dist/graph-explorer/visitors.js +30 -0
  27. package/dist/graph-explorer/walk-down.d.ts +5 -0
  28. package/dist/graph-explorer/walk-down.js +116 -0
  29. package/dist/index.js +2 -98
  30. package/dist/plugins/angular/index.js +3 -3
  31. package/dist/plugins/index.d.ts +1 -0
  32. package/dist/plugins/index.js +2 -0
  33. package/dist/plugins/next/index.js +4 -3
  34. package/dist/plugins/next/resolveFromAST.d.ts +1 -0
  35. package/dist/plugins/next/resolveFromAST.js +42 -1
  36. package/dist/plugins/rsbuild/index.js +8 -0
  37. package/dist/plugins/rsbuild/types.d.ts +1 -0
  38. package/dist/plugins/storybook/index.js +12 -4
  39. package/dist/plugins/storybook/types.d.ts +5 -0
  40. package/dist/plugins/svgo/index.js +1 -1
  41. package/dist/plugins/svgr/index.d.ts +3 -0
  42. package/dist/plugins/svgr/index.js +24 -0
  43. package/dist/plugins/svgr/types.d.ts +3 -0
  44. package/dist/plugins/svgr/types.js +1 -0
  45. package/dist/plugins/vite/helpers.js +1 -1
  46. package/dist/plugins/vite/index.js +4 -0
  47. package/dist/plugins/vitest/index.js +1 -1
  48. package/dist/reporters/codeclimate.js +3 -7
  49. package/dist/reporters/util/util.d.ts +2 -1
  50. package/dist/reporters/util/util.js +1 -0
  51. package/dist/reporters/watch.js +1 -1
  52. package/dist/run.d.ts +25 -0
  53. package/dist/run.js +107 -0
  54. package/dist/schema/configuration.d.ts +10 -0
  55. package/dist/schema/plugins.d.ts +5 -0
  56. package/dist/schema/plugins.js +1 -0
  57. package/dist/types/PluginNames.d.ts +2 -2
  58. package/dist/types/PluginNames.js +1 -0
  59. package/dist/types/issues.d.ts +4 -4
  60. package/dist/types/module-graph.d.ts +11 -13
  61. package/dist/typescript/ast-helpers.d.ts +5 -1
  62. package/dist/typescript/ast-helpers.js +47 -2
  63. package/dist/typescript/get-imports-and-exports.js +78 -12
  64. package/dist/typescript/resolve-module-names.js +5 -4
  65. package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
  66. package/dist/util/Performance.js +4 -2
  67. package/dist/util/create-options.d.ts +10 -0
  68. package/dist/util/create-options.js +8 -4
  69. package/dist/util/file-entry-cache.js +1 -1
  70. package/dist/util/graph-sequencer.js +1 -1
  71. package/dist/util/module-graph.js +7 -8
  72. package/dist/util/resolve.d.ts +3 -2
  73. package/dist/util/resolve.js +25 -2
  74. package/dist/util/trace.d.ts +2 -20
  75. package/dist/util/trace.js +41 -66
  76. package/dist/util/watch.d.ts +19 -3
  77. package/dist/util/watch.js +28 -17
  78. package/dist/version.d.ts +1 -1
  79. package/dist/version.js +1 -1
  80. package/package.json +7 -7
  81. package/schema.json +4 -0
  82. package/vendor/bash-parser/index.d.ts +6 -1
  83. package/dist/util/has-strictly-ns-references.d.ts +0 -4
  84. package/dist/util/has-strictly-ns-references.js +0 -103
  85. package/dist/util/is-identifier-referenced.d.ts +0 -9
  86. package/dist/util/is-identifier-referenced.js +0 -145
@@ -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
  };
@@ -190,9 +195,11 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
190
195
  const addExport = ({ node, symbol, identifier, type, pos, members = [], fix }) => {
191
196
  if (skipExports)
192
197
  return;
198
+ let isReExport = Boolean(node.parent?.parent && ts.isExportDeclaration(node.parent.parent) && node.parent.parent.moduleSpecifier);
193
199
  if (symbol) {
194
200
  const importedSymbolFilePath = importedInternalSymbols.get(symbol);
195
201
  if (importedSymbolFilePath) {
202
+ isReExport = true;
196
203
  const importId = String(symbol.escapedName);
197
204
  const internalImport = internal.get(importedSymbolFilePath);
198
205
  if (internalImport) {
@@ -215,7 +222,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
215
222
  const members = [...(item.members ?? []), ...exportMembers];
216
223
  const tags = new Set([...(item.jsDocTags ?? []), ...jsDocTags]);
217
224
  const fixes = fix ? [...(item.fixes ?? []), fix] : item.fixes;
218
- exports.set(identifier, { ...item, members, jsDocTags: tags, fixes });
225
+ exports.set(identifier, { ...item, members, jsDocTags: tags, fixes, isReExport });
219
226
  }
220
227
  else {
221
228
  const { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(pos);
@@ -229,7 +236,8 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
229
236
  line: line + 1,
230
237
  col: character + 1,
231
238
  fixes: fix ? [fix] : [],
232
- refs: [0, false],
239
+ self: [0, false],
240
+ isReExport,
233
241
  });
234
242
  }
235
243
  if (!jsDocTags.has(ALIAS_TAG)) {
@@ -282,13 +290,25 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
282
290
  if (ts.isIdentifier(node)) {
283
291
  const id = String(node.escapedText);
284
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
+ }
285
301
  if (symbol) {
286
302
  if (filePath) {
287
303
  if (!isImportSpecifier(node)) {
288
304
  const imports = internal.get(filePath);
289
305
  if (imports) {
290
- traceRefs.add(id);
291
- 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) {
292
312
  if (isDestructuring(node.parent)) {
293
313
  if (ts.isPropertyAccessExpression(node.parent)) {
294
314
  const ns = String(symbol.escapedName);
@@ -315,6 +335,25 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
315
335
  else
316
336
  addNsMemberRefs(imports, id, members);
317
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
+ }
318
357
  else {
319
358
  const typeRef = getTypeRef(node);
320
359
  if (typeRef) {
@@ -328,6 +367,34 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
328
367
  imports.refs.add(id);
329
368
  }
330
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
+ }
331
398
  else if (imports.importedNs.has(id) && isConsiderReferencedNS(node)) {
332
399
  imports.refs.add(id);
333
400
  }
@@ -355,7 +422,7 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
355
422
  addImport(node, sourceFile);
356
423
  for (const item of exports.values()) {
357
424
  if (!isType(item) && item.symbol && referencedSymbolsInExport.has(item.symbol)) {
358
- item.refs = [1, true];
425
+ item.self = [1, true];
359
426
  }
360
427
  else {
361
428
  const isBindingElement = item.symbol?.valueDeclaration && ts.isBindingElement(item.symbol.valueDeclaration);
@@ -364,11 +431,11 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
364
431
  item.type !== 'unknown' &&
365
432
  ignoreExportsUsedInFile[item.type]) ||
366
433
  isBindingElement) {
367
- item.refs = findInternalReferences(item, sourceFile, typeChecker, referencedSymbolsInExport, isBindingElement);
434
+ item.self = findInternalReferences(item, sourceFile, typeChecker, referencedSymbolsInExport, isBindingElement);
368
435
  }
369
436
  }
370
437
  for (const member of item.members) {
371
- member.refs = findInternalReferences(member, sourceFile, typeChecker, referencedSymbolsInExport);
438
+ member.self = findInternalReferences(member, sourceFile, typeChecker, referencedSymbolsInExport);
372
439
  member.symbol = undefined;
373
440
  }
374
441
  item.symbol = undefined;
@@ -378,7 +445,6 @@ const getImportsAndExports = (sourceFile, resolveModule, typeChecker, options, i
378
445
  exports,
379
446
  duplicates: [...aliasedExports.values()],
380
447
  scripts,
381
- traceRefs,
382
448
  };
383
449
  };
384
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);
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import { IMPORT_MODIFIERS } from '../../../constants.js';
3
- import { findAncestor, findDescendants, getAccessedIdentifiers, isAccessExpression, isImportCall, isInOpaqueExpression, isTopLevel, stripQuotes, } from '../../ast-helpers.js';
3
+ import { findAncestor, findDescendants, getAccessedIdentifiers, getThenBindings, isAccessExpression, isImportCall, isInOpaqueExpression, isTopLevel, stripQuotes, } from '../../ast-helpers.js';
4
4
  import { importVisitor as visit } from '../index.js';
5
5
  const getSymbol = (node, isTopLevel) => (isTopLevel ? node.symbol : undefined);
6
6
  export default visit(() => true, node => {
@@ -20,24 +20,10 @@ export default visit(() => true, node => {
20
20
  const pos = accessExpression.name.pos;
21
21
  if (identifier === 'then') {
22
22
  const callExpression = node.parent.parent;
23
- if (ts.isCallExpression(callExpression) && ts.isFunctionLike(callExpression.arguments[0])) {
24
- const arg = callExpression.arguments[0].parameters[0];
25
- if (arg && ts.isIdentifier(arg.name)) {
26
- const argName = arg.name.escapedText;
27
- const accessExpressions = findDescendants(callExpression.arguments[0].body, ts.isPropertyAccessExpression).filter(binding => binding.expression.getText() === argName);
28
- if (accessExpressions.length > 0) {
29
- return accessExpressions.map(binding => {
30
- const identifier = String(binding.name.escapedText);
31
- return { identifier, specifier, pos, modifiers };
32
- });
33
- }
34
- }
35
- else if (arg && ts.isObjectBindingPattern(arg.name)) {
36
- return arg.name.elements.map(element => {
37
- const identifier = (element.propertyName ?? element.name).getText();
38
- const alias = element.propertyName ? element.name.getText() : undefined;
39
- return { identifier, alias, specifier, pos: element.pos, modifiers };
40
- });
23
+ if (ts.isCallExpression(callExpression)) {
24
+ const accessed = getThenBindings(callExpression);
25
+ if (accessed && accessed.length > 0) {
26
+ return accessed.map(acc => ({ ...acc, specifier, modifiers }));
41
27
  }
42
28
  }
43
29
  return { identifier: 'default', specifier, pos, modifiers };
@@ -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,
@@ -115,7 +119,7 @@ export const createOptions = async (options) => {
115
119
  rules,
116
120
  tags,
117
121
  traceExport: parsedCLIArgs['trace-export'],
118
- traceFile: parsedCLIArgs['trace-file'],
122
+ traceFile: parsedCLIArgs['trace-file'] ? toAbsolute(parsedCLIArgs['trace-file'], cwd) : undefined,
119
123
  tsConfigFile: parsedCLIArgs.tsConfig,
120
124
  workspace: options.workspace ?? parsedCLIArgs.workspace,
121
125
  workspaces,
@@ -86,7 +86,7 @@ export class FileEntryCache {
86
86
  }
87
87
  reconcile() {
88
88
  this.removeNotFoundFiles();
89
- for (const [entryName, cacheEntry] of this.normalizedEntries.entries()) {
89
+ for (const [entryName, cacheEntry] of this.normalizedEntries) {
90
90
  try {
91
91
  const meta = this._getMetaForFileUsingMtimeAndSize(cacheEntry);
92
92
  this.cache.set(entryName, meta);
@@ -6,7 +6,7 @@ export function graphSequencer(graph, includedNodes = [...graph.keys()]) {
6
6
  const nodes = new Set(includedNodes);
7
7
  const visited = new Set();
8
8
  const outDegree = new Map();
9
- for (const [from, edges] of graph.entries()) {
9
+ for (const [from, edges] of graph) {
10
10
  outDegree.set(from, 0);
11
11
  for (const to of edges) {
12
12
  if (nodes.has(from) && nodes.has(to)) {
@@ -2,21 +2,21 @@ export const getOrCreateFileNode = (graph, filePath) => graph.get(filePath) ?? c
2
2
  const updateImportMaps = (fromImportMaps, toImportMaps) => {
3
3
  for (const id of fromImportMaps.refs)
4
4
  toImportMaps.refs.add(id);
5
- for (const [id, v] of fromImportMaps.imported.entries())
5
+ for (const [id, v] of fromImportMaps.imported)
6
6
  addValues(toImportMaps.imported, id, v);
7
- for (const [id, v] of fromImportMaps.importedAs.entries())
7
+ for (const [id, v] of fromImportMaps.importedAs)
8
8
  addNsValues(toImportMaps.importedAs, id, v);
9
- for (const [id, v] of fromImportMaps.importedNs.entries())
9
+ for (const [id, v] of fromImportMaps.importedNs)
10
10
  addValues(toImportMaps.importedNs, id, v);
11
- for (const [id, v] of fromImportMaps.reExported.entries())
11
+ for (const [id, v] of fromImportMaps.reExported)
12
12
  addValues(toImportMaps.reExported, id, v);
13
- for (const [id, v] of fromImportMaps.reExportedAs.entries())
13
+ for (const [id, v] of fromImportMaps.reExportedAs)
14
14
  addNsValues(toImportMaps.reExportedAs, id, v);
15
- for (const [id, v] of fromImportMaps.reExportedNs.entries())
15
+ for (const [id, v] of fromImportMaps.reExportedNs)
16
16
  addValues(toImportMaps.reExportedNs, id, v);
17
17
  };
18
18
  export const updateImportMap = (file, importMap, graph) => {
19
- for (const [importedFilePath, fileImportMaps] of importMap.entries()) {
19
+ for (const [importedFilePath, fileImportMaps] of importMap) {
20
20
  const importMaps = file.imports.internal.get(importedFilePath);
21
21
  if (!importMaps)
22
22
  file.imports.internal.set(importedFilePath, fileImportMaps);
@@ -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,20 +1,2 @@
1
- import type { ModuleGraph } from '../types/module-graph.js';
2
- import type { MainOptions } from './create-options.js';
3
- type CreateNodeOpts = {
4
- identifier?: string;
5
- hasRef?: boolean;
6
- isEntry?: boolean;
7
- };
8
- type Create = (filePath: string, options?: CreateNodeOpts) => TraceNode;
9
- export type TraceNode = {
10
- filePath: string;
11
- identifier?: string;
12
- hasRef: boolean;
13
- isEntry: boolean;
14
- children: Set<TraceNode>;
15
- };
16
- export declare const printTrace: (node: TraceNode, filePath: string, options: MainOptions, identifier?: string) => void;
17
- export declare const createNode: Create;
18
- export declare const addNodes: (node: TraceNode, id: string, importedSymbols: ModuleGraph, filePaths?: Set<string>) => void;
19
- export declare const createAndPrintTrace: (filePath: string, options: MainOptions, opts?: CreateNodeOpts) => void;
20
- 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,70 +1,45 @@
1
- import picocolors from 'picocolors';
2
- import { toAbsolute, 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 renderTrace = (node, options, level = 0, levels = new Set()) => {
13
- let index = 0;
14
- const size = node.children.size;
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 : '') + (child.isEntry ? IS_ENTRY : '');
22
- const text = `${padding}${picocolors.dim(isLast ? '└─' : '├─')} ${file}${suffix}`;
23
- console.log(text);
24
- if (child.children.size > 0) {
25
- if (!isLast)
26
- levels.add(level);
27
- if (isLast)
28
- levels.delete(level);
29
- renderTrace(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 printTrace = (node, filePath, options, identifier) => {
34
- if (!options.isTrace)
35
- return;
36
- if (options.traceExport && identifier !== options.traceExport)
37
- return;
38
- if (options.traceFile && filePath !== toAbsolute(options.traceFile, options.cwd))
39
- return;
40
- const suffix = (node.isEntry ? IS_ENTRY : '') + (node.children.size === 0 ? HAS_NO_REF : '');
41
- const header = `${toRelative(filePath, options.cwd)}${identifier ? `:${identifier}` : ''}${suffix}`;
42
- console.log(header);
43
- renderTrace(node, options);
44
- console.log();
45
- };
46
- export const createNode = (filePath, { hasRef = false, isEntry = false, identifier } = {}) => ({
47
- filePath,
48
- identifier,
49
- hasRef,
50
- isEntry,
51
- children: new Set(),
52
- });
53
- const addNode = (parent, filePath, { hasRef = false, isEntry = false }) => {
54
- const node = createNode(filePath, { hasRef, isEntry });
55
- parent.children.add(node);
56
- return node;
57
- };
58
- export const addNodes = (node, id, importedSymbols, filePaths) => {
59
- if (!filePaths)
60
- return;
61
- for (const filePath of filePaths) {
62
- addNode(node, filePath, { hasRef: Boolean(importedSymbols.get(filePath)?.traceRefs?.has(id)) });
40
+ if (node.children.length === 0) {
41
+ const leafMarker = isReferenced ? ok(' ✓') : fail(' ✗');
42
+ lines.push(`${dim('└── (no imports found)')}${leafMarker}`);
63
43
  }
64
- };
65
- export const createAndPrintTrace = (filePath, options, opts = {}) => {
66
- if (!options.isTrace)
67
- return;
68
- const traceNode = createNode(filePath, opts);
69
- printTrace(traceNode, filePath, options, opts.identifier);
44
+ return lines.join('\n');
70
45
  };
@@ -6,10 +6,16 @@ import type { ProjectPrincipal } from '../ProjectPrincipal.js';
6
6
  import type { Issues } from '../types/issues.js';
7
7
  import type { ModuleGraph } from '../types/module-graph.js';
8
8
  import type { MainOptions } from './create-options.js';
9
- export type OnUpdate = (options: {
9
+ export type OnFileChange = (options: {
10
10
  issues: Issues;
11
11
  duration?: number;
12
+ mem?: number;
12
13
  }) => void;
14
+ type WatchChange = {
15
+ type: 'added' | 'deleted' | 'modified';
16
+ filePath: string;
17
+ };
18
+ export type WatchHandler = Awaited<ReturnType<typeof getWatchHandler>>;
13
19
  type Watch = {
14
20
  analyzedFiles: Set<string>;
15
21
  analyzeSourceFile: (filePath: string, principal: ProjectPrincipal) => void;
@@ -19,8 +25,18 @@ type Watch = {
19
25
  factory: PrincipalFactory;
20
26
  graph: ModuleGraph;
21
27
  isIgnored: (path: string) => boolean;
22
- onUpdate: OnUpdate;
28
+ onFileChange?: OnFileChange;
23
29
  unreferencedFiles: Set<string>;
30
+ entryPaths: Set<string>;
24
31
  };
25
- export declare const getWatchHandler: (options: MainOptions, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, onUpdate, unreferencedFiles, }: Watch) => Promise<WatchListener<string | Buffer<ArrayBufferLike>>>;
32
+ export declare const getWatchHandler: (options: MainOptions, { analyzedFiles, analyzeSourceFile, chief, collector, analyze, factory, graph, isIgnored, onFileChange, unreferencedFiles, entryPaths, }: Watch) => Promise<{
33
+ listener: WatchListener<string | Buffer<ArrayBufferLike>>;
34
+ handleFileChanges: (changes: WatchChange[]) => Promise<{
35
+ duration: number;
36
+ mem: number;
37
+ }>;
38
+ getEntryPaths: () => Set<string>;
39
+ getGraph: () => ModuleGraph;
40
+ getIssues: () => Issues;
41
+ }>;
26
42
  export {};