knip 5.70.2 → 5.71.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 (57) hide show
  1. package/dist/DependencyDeputy.js +2 -2
  2. package/dist/ProjectPrincipal.js +1 -1
  3. package/dist/WorkspaceWorker.js +1 -1
  4. package/dist/binaries/bash-parser.js +14 -1
  5. package/dist/compilers/index.js +1 -1
  6. package/dist/constants.js +1 -0
  7. package/dist/graph/analyze.js +21 -16
  8. package/dist/graph-explorer/constants.d.ts +2 -0
  9. package/dist/graph-explorer/constants.js +2 -0
  10. package/dist/graph-explorer/explorer.d.ts +11 -0
  11. package/dist/graph-explorer/explorer.js +10 -0
  12. package/dist/graph-explorer/operations/build-trace-tree.d.ts +12 -0
  13. package/dist/graph-explorer/operations/build-trace-tree.js +51 -0
  14. package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
  15. package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
  16. package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
  17. package/dist/graph-explorer/operations/is-referenced.js +89 -0
  18. package/dist/graph-explorer/utils.d.ts +4 -0
  19. package/dist/graph-explorer/utils.js +28 -0
  20. package/dist/graph-explorer/visitors.d.ts +12 -0
  21. package/dist/graph-explorer/visitors.js +30 -0
  22. package/dist/graph-explorer/walk-down.d.ts +4 -0
  23. package/dist/graph-explorer/walk-down.js +119 -0
  24. package/dist/index.js +2 -98
  25. package/dist/plugins/angular/index.js +3 -3
  26. package/dist/plugins/next/index.js +4 -3
  27. package/dist/plugins/next/resolveFromAST.d.ts +1 -0
  28. package/dist/plugins/next/resolveFromAST.js +42 -1
  29. package/dist/plugins/vite/helpers.js +1 -1
  30. package/dist/reporters/codeclimate.js +3 -7
  31. package/dist/reporters/util/util.d.ts +2 -1
  32. package/dist/reporters/util/util.js +1 -0
  33. package/dist/reporters/watch.js +1 -1
  34. package/dist/run.d.ts +25 -0
  35. package/dist/run.js +107 -0
  36. package/dist/types/issues.d.ts +4 -4
  37. package/dist/types/module-graph.d.ts +9 -10
  38. package/dist/typescript/ast-helpers.d.ts +4 -0
  39. package/dist/typescript/ast-helpers.js +48 -0
  40. package/dist/typescript/get-imports-and-exports.js +4 -1
  41. package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
  42. package/dist/util/create-options.js +1 -1
  43. package/dist/util/file-entry-cache.js +1 -1
  44. package/dist/util/graph-sequencer.js +1 -1
  45. package/dist/util/module-graph.js +7 -7
  46. package/dist/util/trace.d.ts +3 -13
  47. package/dist/util/trace.js +10 -41
  48. package/dist/util/watch.d.ts +19 -3
  49. package/dist/util/watch.js +28 -17
  50. package/dist/version.d.ts +1 -1
  51. package/dist/version.js +1 -1
  52. package/package.json +1 -1
  53. package/vendor/bash-parser/index.d.ts +6 -1
  54. package/dist/util/has-strictly-ns-references.d.ts +0 -4
  55. package/dist/util/has-strictly-ns-references.js +0 -103
  56. package/dist/util/is-identifier-referenced.d.ts +0 -9
  57. package/dist/util/is-identifier-referenced.js +0 -145
@@ -174,7 +174,7 @@ export class DependencyDeputy {
174
174
  const dependencyIssues = [];
175
175
  const devDependencyIssues = [];
176
176
  const optionalPeerDependencyIssues = [];
177
- for (const [workspace, { manifestPath: filePath, manifestStr }] of this._manifests.entries()) {
177
+ for (const [workspace, { manifestPath: filePath, manifestStr }] of this._manifests) {
178
178
  const referencedDependencies = this.referencedDependencies.get(workspace);
179
179
  const hasTypesIncluded = this.getHasTypesIncluded(workspace);
180
180
  const peeker = new PackagePeeker(manifestStr);
@@ -342,7 +342,7 @@ export class DependencyDeputy {
342
342
  }
343
343
  getConfigurationHints() {
344
344
  const configurationHints = new Set();
345
- for (const [workspaceName, manifest] of this._manifests.entries()) {
345
+ for (const [workspaceName, manifest] of this._manifests) {
346
346
  for (const identifier of manifest.unusedIgnoreDependencies) {
347
347
  configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
348
348
  }
@@ -217,7 +217,7 @@ export class ProjectPrincipal {
217
217
  return externalRefs.length > 0;
218
218
  }
219
219
  reconcileCache(graph) {
220
- for (const [filePath, file] of graph.entries()) {
220
+ for (const [filePath, file] of graph) {
221
221
  const fd = this.cache.getFileDescriptor(filePath);
222
222
  if (!fd?.meta)
223
223
  continue;
@@ -319,7 +319,7 @@ export class WorkspaceWorker {
319
319
  const configFiles = this.configFilesMap.get(wsName);
320
320
  if (configFiles) {
321
321
  do {
322
- for (const [pluginName, dependencies] of configFiles.entries()) {
322
+ for (const [pluginName, dependencies] of configFiles) {
323
323
  configFiles.delete(pluginName);
324
324
  if (this.enabledPlugins.includes(pluginName)) {
325
325
  for (const input of await runPlugin(pluginName, Array.from(dependencies)))
@@ -25,6 +25,12 @@ export const getDependenciesFromScript = (script, options) => {
25
25
  knownBinsOnly: false,
26
26
  });
27
27
  };
28
+ const definedFunctions = new Set();
29
+ const collectFunctionNames = (nodes) => {
30
+ for (const node of nodes)
31
+ if (node.type === 'Function')
32
+ definedFunctions.add(node.name.text);
33
+ };
28
34
  const getDependenciesFromNodes = (nodes) => nodes.flatMap(node => {
29
35
  switch (node.type) {
30
36
  case 'Command': {
@@ -41,6 +47,8 @@ export const getDependenciesFromScript = (script, options) => {
41
47
  return [];
42
48
  if (binary.startsWith('-') || binary.startsWith('"') || binary.startsWith('..'))
43
49
  return [];
50
+ if (definedFunctions.has(binary))
51
+ return [];
44
52
  const args = node.suffix?.map(arg => arg.text) ?? [];
45
53
  if (['!', 'test'].includes(binary))
46
54
  return fromArgs(args);
@@ -82,13 +90,18 @@ export const getDependenciesFromScript = (script, options) => {
82
90
  return getDependenciesFromNodes(node.commands);
83
91
  case 'Function':
84
92
  return getDependenciesFromNodes(node.body.commands);
93
+ case 'Subshell':
94
+ return getDependenciesFromNodes(node.list.commands);
85
95
  default:
86
96
  return [];
87
97
  }
88
98
  });
89
99
  try {
90
100
  const parsed = parse(script);
91
- return parsed?.commands ? getDependenciesFromNodes(parsed.commands) : [];
101
+ if (!parsed?.commands)
102
+ return [];
103
+ collectFunctionNames(parsed.commands);
104
+ return getDependenciesFromNodes(parsed.commands);
92
105
  }
93
106
  catch (error) {
94
107
  const msg = `Warning: failed to parse and ignoring script in ${relative(options.cwd, options.containingFilePath)} (${truncate(script, 30)})`;
@@ -38,7 +38,7 @@ const compilers = new Map([
38
38
  ]);
39
39
  export const getIncludedCompilers = (syncCompilers, asyncCompilers, dependencies) => {
40
40
  const hasDependency = (packageName) => dependencies.has(packageName);
41
- for (const [extension, { condition, compiler }] of compilers.entries()) {
41
+ for (const [extension, { condition, compiler }] of compilers) {
42
42
  if (extension === '.mdx' && AstroMDX.condition(hasDependency)) {
43
43
  syncCompilers.set(extension, AstroMDX.compiler);
44
44
  }
package/dist/constants.js CHANGED
@@ -89,6 +89,7 @@ export const IGNORED_GLOBAL_BINARIES = new Set([
89
89
  'rmdir',
90
90
  'rsync',
91
91
  'scp',
92
+ 'sed',
92
93
  'seq',
93
94
  'set',
94
95
  'sh',
@@ -1,13 +1,13 @@
1
- import { getType, hasStrictlyEnumReferences, hasStrictlyNsReferences } from '../util/has-strictly-ns-references.js';
2
- import { getIsIdentifierReferencedHandler } from '../util/is-identifier-referenced.js';
1
+ import { createGraphExplorer } from '../graph-explorer/explorer.js';
2
+ import { getIssueType, hasStrictlyEnumReferences } from '../graph-explorer/utils.js';
3
3
  import { getPackageNameFromModuleSpecifier } from '../util/modules.js';
4
4
  import { findMatch } from '../util/regex.js';
5
5
  import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.js';
6
- import { createAndPrintTrace, printTrace } from '../util/trace.js';
6
+ import { printTraceNode } from '../util/trace.js';
7
7
  export const analyze = async ({ analyzedFiles, counselor, chief, collector, deputy, entryPaths, factory, graph, streamer, unreferencedFiles, options, }) => {
8
8
  const shouldIgnore = getShouldIgnoreHandler(options.isProduction);
9
9
  const shouldIgnoreTags = getShouldIgnoreTagHandler(options.tags);
10
- const isIdentifierReferenced = getIsIdentifierReferencedHandler(graph, entryPaths, options.isTrace);
10
+ const explorer = createGraphExplorer(graph, entryPaths);
11
11
  const ignoreExportsUsedInFile = chief.config.ignoreExportsUsedInFile;
12
12
  const isExportedItemReferenced = (exportedItem) => exportedItem.refs[1] ||
13
13
  (exportedItem.refs[0] > 0 &&
@@ -17,7 +17,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
17
17
  const analyzeGraph = async () => {
18
18
  if (options.isReportValues || options.isReportTypes) {
19
19
  streamer.cast('Connecting the dots');
20
- for (const [filePath, file] of graph.entries()) {
20
+ for (const [filePath, file] of graph) {
21
21
  const exportItems = file.exports;
22
22
  if (!exportItems || exportItems.size === 0)
23
23
  continue;
@@ -27,16 +27,17 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
27
27
  const principal = factory.getPrincipalByPackageName(workspace.pkgName);
28
28
  const isEntry = entryPaths.has(filePath);
29
29
  if (!isIncludeEntryExports && isEntry) {
30
- createAndPrintTrace(filePath, options, { isEntry });
31
30
  continue;
32
31
  }
33
32
  const importsForExport = file.imported;
34
- for (const [identifier, exportedItem] of exportItems.entries()) {
33
+ for (const [identifier, exportedItem] of exportItems) {
35
34
  if (shouldIgnore(exportedItem.jsDocTags))
36
35
  continue;
37
36
  const isIgnored = shouldIgnoreTags(exportedItem.jsDocTags);
38
37
  if (importsForExport) {
39
- const { isReferenced, reExportingEntryFile, traceNode } = isIdentifierReferenced(filePath, identifier, isIncludeEntryExports);
38
+ const [isReferenced, reExportingEntryFile] = explorer.isReferenced(filePath, identifier, {
39
+ includeEntryExports: isIncludeEntryExports,
40
+ });
40
41
  if ((isReferenced || exportedItem.refs[1]) && isIgnored) {
41
42
  for (const tagName of exportedItem.jsDocTags) {
42
43
  if (options.tags[1].includes(tagName.replace(/^@/, ''))) {
@@ -48,15 +49,12 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
48
49
  continue;
49
50
  if (reExportingEntryFile) {
50
51
  if (!isIncludeEntryExports) {
51
- createAndPrintTrace(filePath, options, { identifier, isEntry, hasRef: isReferenced });
52
52
  continue;
53
53
  }
54
54
  const reExportedItem = graph.get(reExportingEntryFile)?.exports.get(identifier);
55
55
  if (reExportedItem && shouldIgnore(reExportedItem.jsDocTags))
56
56
  continue;
57
57
  }
58
- if (traceNode)
59
- printTrace(traceNode, filePath, options, identifier);
60
58
  if (isReferenced) {
61
59
  if (options.includedIssueTypes.enumMembers && exportedItem.type === 'enum') {
62
60
  if (!options.includedIssueTypes.nsTypes && importsForExport.refs.has(identifier))
@@ -70,9 +68,11 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
70
68
  continue;
71
69
  if (member.refs[0] === 0) {
72
70
  const id = `${identifier}.${member.identifier}`;
73
- const { isReferenced } = isIdentifierReferenced(filePath, id, true);
71
+ const [isMemberReferenced] = explorer.isReferenced(filePath, id, {
72
+ includeEntryExports: true,
73
+ });
74
74
  const isIgnored = shouldIgnoreTags(member.jsDocTags);
75
- if (!isReferenced) {
75
+ if (!isMemberReferenced) {
76
76
  if (isIgnored)
77
77
  continue;
78
78
  collector.addIssue({
@@ -125,7 +125,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
125
125
  continue;
126
126
  }
127
127
  }
128
- const [hasStrictlyNsRefs, namespace] = hasStrictlyNsReferences(graph, importsForExport, identifier);
128
+ const [hasStrictlyNsRefs, namespace] = explorer.hasStrictlyNsReferences(filePath, identifier);
129
129
  const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
130
130
  if (hasStrictlyNsRefs &&
131
131
  ((!options.includedIssueTypes.nsTypes && isType) || !(options.includedIssueTypes.nsExports || isType)))
@@ -135,7 +135,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
135
135
  continue;
136
136
  if (!options.isSkipLibs && principal?.hasExternalReferences(filePath, exportedItem))
137
137
  continue;
138
- const type = getType(hasStrictlyNsRefs, isType);
138
+ const type = getIssueType(hasStrictlyNsRefs, isType);
139
139
  collector.addIssue({
140
140
  type,
141
141
  filePath,
@@ -153,7 +153,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
153
153
  }
154
154
  }
155
155
  }
156
- for (const [filePath, file] of graph.entries()) {
156
+ for (const [filePath, file] of graph) {
157
157
  const ws = chief.findWorkspaceByFilePath(filePath);
158
158
  if (ws) {
159
159
  if (file.duplicates && options.includedIssueTypes.duplicates) {
@@ -227,5 +227,10 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
227
227
  collector.addConfigurationHint(hint);
228
228
  };
229
229
  await analyzeGraph();
230
+ if (options.isTrace) {
231
+ const nodes = explorer.buildExportsTree({ filePath: options.traceFile, identifier: options.traceExport });
232
+ for (const node of nodes)
233
+ printTraceNode(node, options);
234
+ }
230
235
  return analyzeGraph;
231
236
  };
@@ -0,0 +1,2 @@
1
+ export declare const CONTINUE = "continue";
2
+ export declare const STOP = "stop";
@@ -0,0 +1,2 @@
1
+ export const CONTINUE = 'continue';
2
+ export const STOP = 'stop';
@@ -0,0 +1,11 @@
1
+ import type { ModuleGraph } from '../types/module-graph.js';
2
+ export declare const createGraphExplorer: (graph: ModuleGraph, entryPaths: Set<string>) => {
3
+ isReferenced: (filePath: string, identifier: string, options: {
4
+ includeEntryExports: boolean;
5
+ }) => [boolean, string | undefined];
6
+ hasStrictlyNsReferences: (filePath: string, identifier: string) => [boolean, (string | undefined)?];
7
+ buildExportsTree: (options: {
8
+ filePath?: string;
9
+ identifier?: string;
10
+ }) => import("./operations/build-trace-tree.js").TreeNode[];
11
+ };
@@ -0,0 +1,10 @@
1
+ import { buildExportsTree } from './operations/build-trace-tree.js';
2
+ import { hasStrictlyNsReferences } from './operations/has-strictly-ns-references.js';
3
+ import { isReferenced } from './operations/is-referenced.js';
4
+ export const createGraphExplorer = (graph, entryPaths) => {
5
+ return {
6
+ isReferenced: (filePath, identifier, options) => isReferenced(graph, entryPaths, filePath, identifier, options),
7
+ hasStrictlyNsReferences: (filePath, identifier) => hasStrictlyNsReferences(graph, graph.get(filePath)?.imported, identifier),
8
+ buildExportsTree: (options) => buildExportsTree(graph, entryPaths, options),
9
+ };
10
+ };
@@ -0,0 +1,12 @@
1
+ import type { Identifier, ModuleGraph } from '../../types/module-graph.js';
2
+ export interface TreeNode {
3
+ filePath: string;
4
+ identifier: string;
5
+ hasRef: boolean;
6
+ isEntry: boolean;
7
+ children: TreeNode[];
8
+ }
9
+ export declare const buildExportsTree: (graph: ModuleGraph, entryPaths: Set<string>, options: {
10
+ filePath?: string;
11
+ identifier?: Identifier;
12
+ }) => TreeNode[];
@@ -0,0 +1,51 @@
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
+ };
@@ -0,0 +1,2 @@
1
+ import type { ImportMaps, ModuleGraph } from '../../types/module-graph.js';
2
+ export declare const hasStrictlyNsReferences: (graph: ModuleGraph, importsForExport: ImportMaps | undefined, identifier: string) => [boolean, string?];
@@ -0,0 +1,98 @@
1
+ import { forEachAliasReExport, forEachNamespaceReExport, forEachPassThroughReExport, getStarReExportSources, } from '../visitors.js';
2
+ export const hasStrictlyNsReferences = (graph, importsForExport, identifier) => {
3
+ if (!importsForExport)
4
+ return [false];
5
+ let foundNamespace;
6
+ const aliasByIdentifier = new Map();
7
+ const namespaceReExports = new Map();
8
+ const namespaceEdges = [];
9
+ const directById = new Map();
10
+ forEachPassThroughReExport(importsForExport, (id, sources) => {
11
+ directById.set(id, sources);
12
+ });
13
+ forEachAliasReExport(importsForExport, (id, alias, sources) => {
14
+ let arr = aliasByIdentifier.get(id);
15
+ if (!arr) {
16
+ arr = [];
17
+ aliasByIdentifier.set(id, arr);
18
+ }
19
+ arr.push({ alias, sources });
20
+ });
21
+ forEachNamespaceReExport(importsForExport, (namespace, sources) => {
22
+ namespaceEdges.push({ namespace, sources });
23
+ let arr = namespaceReExports.get(namespace);
24
+ if (!arr) {
25
+ arr = [];
26
+ namespaceReExports.set(namespace, arr);
27
+ }
28
+ arr.push(sources);
29
+ });
30
+ const starSources = getStarReExportSources(importsForExport);
31
+ const followReExports = (sources, nextId, propagateNamespace = true) => {
32
+ for (const filePath of sources) {
33
+ const file = graph.get(filePath);
34
+ if (!file?.imported)
35
+ continue;
36
+ const result = hasStrictlyNsReferences(graph, file.imported, nextId);
37
+ if (result[0] === false)
38
+ return result;
39
+ if (propagateNamespace && result[1])
40
+ foundNamespace = result[1];
41
+ }
42
+ return undefined;
43
+ };
44
+ for (const ns of importsForExport.importedNs.keys()) {
45
+ const hasNsRef = importsForExport.refs.has(ns);
46
+ if (!hasNsRef)
47
+ return [false, ns];
48
+ for (const ref of importsForExport.refs) {
49
+ if (ref.startsWith(`${ns}.`))
50
+ return [false, ns];
51
+ }
52
+ const nsReExports = namespaceReExports.get(ns);
53
+ if (nsReExports) {
54
+ for (const sources of nsReExports) {
55
+ const result = followReExports(sources, identifier, false);
56
+ if (result)
57
+ return result;
58
+ }
59
+ }
60
+ const nsAliases = aliasByIdentifier.get(ns);
61
+ if (nsAliases) {
62
+ for (const { sources } of nsAliases) {
63
+ const result = followReExports(sources, identifier, false);
64
+ if (result)
65
+ return result;
66
+ }
67
+ }
68
+ foundNamespace = ns;
69
+ }
70
+ const directSources = directById.get(identifier);
71
+ if (directSources) {
72
+ const result = followReExports(directSources, identifier, true);
73
+ if (result)
74
+ return result;
75
+ }
76
+ if (starSources) {
77
+ const result = followReExports(starSources, identifier, true);
78
+ if (result)
79
+ return result;
80
+ }
81
+ const [id, ...rest] = identifier.split('.');
82
+ const aliasEntries = aliasByIdentifier.get(id);
83
+ if (aliasEntries) {
84
+ for (const { alias, sources } of aliasEntries) {
85
+ const result = followReExports(sources, [alias, ...rest].join('.'), true);
86
+ if (result)
87
+ return result;
88
+ }
89
+ }
90
+ for (const { namespace: ns, sources } of namespaceEdges) {
91
+ const result = followReExports(sources, `${ns}.${identifier}`, true);
92
+ if (result)
93
+ return result;
94
+ }
95
+ if (foundNamespace)
96
+ return [true, foundNamespace];
97
+ return [false];
98
+ };
@@ -0,0 +1,4 @@
1
+ import type { Identifier, ModuleGraph } from '../../types/module-graph.js';
2
+ export declare const isReferenced: (graph: ModuleGraph, entryPaths: Set<string>, filePath: string, id: Identifier, options: {
3
+ includeEntryExports: boolean;
4
+ }) => [boolean, string | undefined];
@@ -0,0 +1,89 @@
1
+ import { OPAQUE } from '../../constants.js';
2
+ import { getAliasReExportMap, getNamespaceReExportSources, getPassThroughReExportSources, getStarReExportSources, } from '../visitors.js';
3
+ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
4
+ const seen = new Set();
5
+ const check = (currentPath, currentId) => {
6
+ const isEntryFile = entryPaths.has(currentPath);
7
+ let reExportingEntryFile = isEntryFile ? currentPath : undefined;
8
+ if (isEntryFile && !options.includeEntryExports)
9
+ return [false, reExportingEntryFile];
10
+ if (seen.has(currentPath))
11
+ return [false, reExportingEntryFile];
12
+ seen.add(currentPath);
13
+ const restIds = currentId.split('.');
14
+ const identifier = restIds.shift();
15
+ const file = graph.get(currentPath)?.imported;
16
+ if (!identifier || !file) {
17
+ return [false, reExportingEntryFile];
18
+ }
19
+ const directSources = getPassThroughReExportSources(file, identifier);
20
+ const starSources = getStarReExportSources(file);
21
+ const followSources = (sources, nextId) => {
22
+ for (const byFilePath of sources) {
23
+ if (seen.has(byFilePath))
24
+ continue;
25
+ const result = check(byFilePath, nextId);
26
+ if (result[1])
27
+ reExportingEntryFile = result[1];
28
+ if (result[0])
29
+ return true;
30
+ }
31
+ return false;
32
+ };
33
+ if (file.imported.get(OPAQUE) ||
34
+ ((identifier === currentId || (identifier !== currentId && file.refs.has(currentId))) &&
35
+ (file.imported.has(identifier) || file.importedAs.has(identifier)))) {
36
+ return [true, reExportingEntryFile];
37
+ }
38
+ for (const [exportId, aliases] of file.importedAs) {
39
+ if (identifier === exportId) {
40
+ for (const alias of aliases.keys()) {
41
+ const aliasedRef = [alias, ...restIds].join('.');
42
+ if (file.refs.has(aliasedRef)) {
43
+ return [true, reExportingEntryFile];
44
+ }
45
+ }
46
+ }
47
+ }
48
+ for (const namespace of file.importedNs.keys()) {
49
+ if (file.refs.has(`${namespace}.${currentId}`)) {
50
+ return [true, reExportingEntryFile];
51
+ }
52
+ const nsAliasMap = getAliasReExportMap(file, namespace);
53
+ if (nsAliasMap) {
54
+ for (const [alias, sources] of nsAliasMap) {
55
+ if (followSources(sources, `${alias}.${currentId}`))
56
+ return [true, reExportingEntryFile];
57
+ }
58
+ }
59
+ const nsReExportSources = getNamespaceReExportSources(file, namespace);
60
+ if (nsReExportSources) {
61
+ if (followSources(nsReExportSources, `${namespace}.${currentId}`))
62
+ return [true, reExportingEntryFile];
63
+ }
64
+ }
65
+ const aliasMap = getAliasReExportMap(file, identifier);
66
+ if (aliasMap) {
67
+ for (const [alias, sources] of aliasMap) {
68
+ const ref = [alias, ...restIds].join('.');
69
+ if (followSources(sources, ref))
70
+ return [true, reExportingEntryFile];
71
+ }
72
+ }
73
+ if (directSources) {
74
+ if (followSources(directSources, currentId))
75
+ return [true, reExportingEntryFile];
76
+ }
77
+ else if (starSources) {
78
+ if (followSources(starSources, currentId))
79
+ return [true, reExportingEntryFile];
80
+ }
81
+ for (const [namespace, sources] of file.reExportedNs) {
82
+ if (followSources(sources, `${namespace}.${currentId}`)) {
83
+ return [true, reExportingEntryFile];
84
+ }
85
+ }
86
+ return [false, reExportingEntryFile];
87
+ };
88
+ return check(filePath, id);
89
+ };
@@ -0,0 +1,4 @@
1
+ import type { ImportMaps, ModuleGraph } from '../types/module-graph.js';
2
+ export declare const hasNamespaceMemberReference: (graph: ModuleGraph, importingFile: string, importedFile: string, namespace: string, member: string) => boolean | null;
3
+ export declare const hasStrictlyEnumReferences: (importsForExport: ImportMaps | undefined, identifier: string) => boolean;
4
+ export declare const getIssueType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
@@ -0,0 +1,28 @@
1
+ import { OPAQUE } from '../constants.js';
2
+ export const hasNamespaceMemberReference = (graph, importingFile, importedFile, namespace, member) => {
3
+ const importerNode = graph.get(importingFile);
4
+ if (!importerNode)
5
+ return null;
6
+ const importMap = importerNode.imports.internal.get(importedFile);
7
+ if (!importMap)
8
+ return null;
9
+ if (importMap.imported.get(OPAQUE))
10
+ return true;
11
+ if (importMap.refs.size === 0)
12
+ return false;
13
+ const refKey = member ? `${namespace}.${member}` : namespace;
14
+ return refKey ? importMap.refs.has(refKey) : null;
15
+ };
16
+ export const hasStrictlyEnumReferences = (importsForExport, identifier) => {
17
+ if (!importsForExport || !importsForExport.refs.has(identifier))
18
+ return false;
19
+ for (const ref of importsForExport.refs)
20
+ if (ref.startsWith(`${identifier}.`))
21
+ return false;
22
+ return true;
23
+ };
24
+ export const getIssueType = (hasOnlyNsReference, isType) => {
25
+ if (hasOnlyNsReference)
26
+ return isType ? 'nsTypes' : 'nsExports';
27
+ return isType ? 'types' : 'exports';
28
+ };
@@ -0,0 +1,12 @@
1
+ import type { ImportMaps } from '../types/module-graph.js';
2
+ type PassThroughReExportCallback = (identifier: string, sources: Set<string>) => boolean | void;
3
+ type AliasReExportCallback = (identifier: string, alias: string, sources: Set<string>) => boolean | void;
4
+ type NamespaceReExportCallback = (namespace: string, sources: Set<string>) => boolean | void;
5
+ export declare const forEachPassThroughReExport: (importMaps: ImportMaps, callback: PassThroughReExportCallback) => boolean;
6
+ export declare const forEachAliasReExport: (importMaps: ImportMaps, callback: AliasReExportCallback) => boolean;
7
+ export declare const forEachNamespaceReExport: (importMaps: ImportMaps, callback: NamespaceReExportCallback) => boolean;
8
+ export declare const getStarReExportSources: (importMaps: ImportMaps) => Set<string> | undefined;
9
+ export declare const getPassThroughReExportSources: (importMaps: ImportMaps, identifier: string) => Set<string> | undefined;
10
+ export declare const getAliasReExportMap: (importMaps: ImportMaps, identifier: string) => Map<string, Set<string>> | undefined;
11
+ export declare const getNamespaceReExportSources: (importMaps: ImportMaps, namespace: string) => Set<string> | undefined;
12
+ export {};
@@ -0,0 +1,30 @@
1
+ import { IMPORT_STAR } from '../constants.js';
2
+ export const forEachPassThroughReExport = (importMaps, callback) => {
3
+ for (const [identifier, sources] of importMaps.reExported) {
4
+ if (identifier === IMPORT_STAR)
5
+ continue;
6
+ if (callback(identifier, sources ?? new Set()) === false)
7
+ return false;
8
+ }
9
+ return true;
10
+ };
11
+ export const forEachAliasReExport = (importMaps, callback) => {
12
+ for (const [identifier, aliasMap] of importMaps.reExportedAs) {
13
+ for (const [alias, sources] of aliasMap) {
14
+ if (callback(identifier, alias, sources ?? new Set()) === false)
15
+ return false;
16
+ }
17
+ }
18
+ return true;
19
+ };
20
+ export const forEachNamespaceReExport = (importMaps, callback) => {
21
+ for (const [namespace, sources] of importMaps.reExportedNs) {
22
+ if (callback(namespace, sources ?? new Set()) === false)
23
+ return false;
24
+ }
25
+ return true;
26
+ };
27
+ export const getStarReExportSources = (importMaps) => importMaps.reExported.get(IMPORT_STAR);
28
+ export const getPassThroughReExportSources = (importMaps, identifier) => importMaps.reExported.get(identifier);
29
+ export const getAliasReExportMap = (importMaps, identifier) => importMaps.reExportedAs.get(identifier);
30
+ export const getNamespaceReExportSources = (importMaps, namespace) => importMaps.reExportedNs.get(namespace);
@@ -0,0 +1,4 @@
1
+ import type { ModuleGraph } from '../types/module-graph.js';
2
+ type Visitor = (sourceFile: string, identifier: string, importingFile: string, identifierPath: string, isEntry: boolean, isReExport: boolean) => 'continue' | 'stop' | undefined;
3
+ export declare const walkDown: (graph: ModuleGraph, filePath: string, identifier: string, visitor: Visitor, entryPaths: Set<string>, visited?: Set<string>) => boolean;
4
+ export {};