knip 5.70.1 → 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 (64) hide show
  1. package/dist/DependencyDeputy.js +2 -2
  2. package/dist/ProjectPrincipal.js +1 -1
  3. package/dist/WorkspaceWorker.js +32 -35
  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/build.js +71 -87
  9. package/dist/graph-explorer/constants.d.ts +2 -0
  10. package/dist/graph-explorer/constants.js +2 -0
  11. package/dist/graph-explorer/explorer.d.ts +11 -0
  12. package/dist/graph-explorer/explorer.js +10 -0
  13. package/dist/graph-explorer/operations/build-trace-tree.d.ts +12 -0
  14. package/dist/graph-explorer/operations/build-trace-tree.js +51 -0
  15. package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
  16. package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
  17. package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
  18. package/dist/graph-explorer/operations/is-referenced.js +89 -0
  19. package/dist/graph-explorer/utils.d.ts +4 -0
  20. package/dist/graph-explorer/utils.js +28 -0
  21. package/dist/graph-explorer/visitors.d.ts +12 -0
  22. package/dist/graph-explorer/visitors.js +30 -0
  23. package/dist/graph-explorer/walk-down.d.ts +4 -0
  24. package/dist/graph-explorer/walk-down.js +119 -0
  25. package/dist/index.js +2 -98
  26. package/dist/plugins/angular/index.js +3 -3
  27. package/dist/plugins/astro/index.js +0 -2
  28. package/dist/plugins/next/index.js +4 -3
  29. package/dist/plugins/next/resolveFromAST.d.ts +1 -0
  30. package/dist/plugins/next/resolveFromAST.js +42 -1
  31. package/dist/plugins/vite/helpers.js +1 -1
  32. package/dist/reporters/codeclimate.js +3 -7
  33. package/dist/reporters/util/util.d.ts +2 -1
  34. package/dist/reporters/util/util.js +1 -0
  35. package/dist/reporters/watch.js +1 -1
  36. package/dist/run.d.ts +25 -0
  37. package/dist/run.js +107 -0
  38. package/dist/types/issues.d.ts +4 -4
  39. package/dist/types/module-graph.d.ts +14 -12
  40. package/dist/typescript/ast-helpers.d.ts +4 -0
  41. package/dist/typescript/ast-helpers.js +48 -0
  42. package/dist/typescript/get-imports-and-exports.js +18 -3
  43. package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
  44. package/dist/typescript/visitors/dynamic-imports/jsDocType.js +7 -5
  45. package/dist/typescript/visitors/imports/importDeclaration.js +5 -4
  46. package/dist/util/create-options.js +1 -1
  47. package/dist/util/file-entry-cache.js +1 -1
  48. package/dist/util/graph-sequencer.js +1 -1
  49. package/dist/util/input.d.ts +1 -0
  50. package/dist/util/module-graph.js +7 -7
  51. package/dist/util/plugin.d.ts +1 -1
  52. package/dist/util/plugin.js +4 -3
  53. package/dist/util/trace.d.ts +3 -13
  54. package/dist/util/trace.js +10 -41
  55. package/dist/util/watch.d.ts +19 -3
  56. package/dist/util/watch.js +28 -17
  57. package/dist/version.d.ts +1 -1
  58. package/dist/version.js +1 -1
  59. package/package.json +1 -1
  60. package/vendor/bash-parser/index.d.ts +6 -1
  61. package/dist/util/has-strictly-ns-references.d.ts +0 -4
  62. package/dist/util/has-strictly-ns-references.js +0 -103
  63. package/dist/util/is-identifier-referenced.d.ts +0 -9
  64. 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;
@@ -89,15 +89,7 @@ export class WorkspaceWorker {
89
89
  if (project.length === 0)
90
90
  return [];
91
91
  const excludeProductionNegations = project.filter(pattern => !(pattern.startsWith('!') && pattern.endsWith('!')));
92
- const negatedPluginConfigPatterns = this.getPluginConfigPatterns().map(negate);
93
- const negatedPluginProjectFilePatterns = this.getPluginProjectFilePatterns().map(negate);
94
- return [
95
- excludeProductionNegations,
96
- negatedPluginConfigPatterns,
97
- negatedPluginProjectFilePatterns,
98
- projectFilePatterns,
99
- this.negatedWorkspacePatterns,
100
- ].flat();
92
+ return [excludeProductionNegations, projectFilePatterns, this.negatedWorkspacePatterns].flat();
101
93
  }
102
94
  getPluginProjectFilePatterns(patterns = []) {
103
95
  for (const [pluginName, plugin] of PluginEntries) {
@@ -175,18 +167,10 @@ export class WorkspaceWorker {
175
167
  const createGetInputsFromScripts = (containingFilePath) => (scripts, options) => _getInputsFromScripts(scripts, { ...baseOptions, ...options, containingFilePath });
176
168
  const inputs = [];
177
169
  const remainingPlugins = new Set(this.enabledPlugins);
178
- const addInput = (input, containingFilePath = input.containingFilePath) => {
179
- if (isConfig(input)) {
180
- handleConfigInput(input.pluginName, { ...input, containingFilePath });
181
- }
182
- else {
183
- inputs.push({ ...input, containingFilePath });
184
- }
185
- };
186
170
  const configFilesMap = this.configFilesMap;
187
171
  const configFiles = this.configFilesMap.get(wsName);
188
172
  const seen = new Map();
189
- const handleConfigInput = (pluginName, input) => {
173
+ const storeConfigFilePath = (pluginName, input) => {
190
174
  const configFilePath = this.getReferencedInternalFilePath(input);
191
175
  if (configFilePath) {
192
176
  const workspace = this.findWorkspaceByFilePath(configFilePath);
@@ -202,20 +186,26 @@ export class WorkspaceWorker {
202
186
  };
203
187
  for (const input of [...inputsFromManifest, ...productionInputsFromManifest]) {
204
188
  if (isConfig(input)) {
205
- handleConfigInput(input.pluginName, { ...input, containingFilePath });
189
+ storeConfigFilePath(input.pluginName, { ...input, containingFilePath });
206
190
  }
207
- else {
208
- if (!isProduction)
209
- addInput(input, containingFilePath);
210
- else if (isProduction && (input.production || hasProductionInput(input)))
211
- addInput(input, containingFilePath);
191
+ else if (!isProduction || (isProduction && (input.production || hasProductionInput(input)))) {
192
+ inputs.push({ ...input, containingFilePath });
212
193
  }
213
194
  }
214
195
  const runPlugin = async (pluginName, patterns) => {
215
196
  const plugin = Plugins[pluginName];
216
197
  const config = this.getConfigForPlugin(pluginName);
217
198
  if (!config)
218
- return;
199
+ return [];
200
+ const inputs = [];
201
+ const addInput = (input, containingFilePath = input.containingFilePath) => {
202
+ if (isConfig(input)) {
203
+ storeConfigFilePath(input.pluginName, { ...input, containingFilePath });
204
+ }
205
+ else {
206
+ inputs.push(Object.assign(input, { containingFilePath }));
207
+ }
208
+ };
219
209
  const label = 'config file';
220
210
  const configFilePaths = await _glob({ patterns, cwd: rootCwd, dir: cwd, gitignore: false, label });
221
211
  const options = {
@@ -229,7 +219,7 @@ export class WorkspaceWorker {
229
219
  if (config.entry) {
230
220
  const toInput = isProduction && plugin.production && plugin.production.length > 0 ? toProductionEntry : toEntry;
231
221
  for (const id of config.entry)
232
- addInput(toInput(id));
222
+ inputs.push(toInput(id));
233
223
  }
234
224
  else if ((!plugin.resolveConfig && !plugin.resolveFromAST) ||
235
225
  (configFilePaths.filter(path => basename(path) !== 'package.json').length === 0 &&
@@ -237,10 +227,10 @@ export class WorkspaceWorker {
237
227
  this.configFilesMap.get(wsName)?.get(pluginName)?.size === 0))) {
238
228
  if (plugin.entry)
239
229
  for (const id of plugin.entry)
240
- addInput(toEntry(id));
230
+ inputs.push(toEntry(id));
241
231
  if (plugin.production)
242
232
  for (const id of plugin.production)
243
- addInput(toProductionEntry(id));
233
+ inputs.push(toProductionEntry(id));
244
234
  }
245
235
  for (const configFilePath of configFilePaths) {
246
236
  const isManifest = basename(configFilePath) === 'package.json';
@@ -295,8 +285,8 @@ export class WorkspaceWorker {
295
285
  }
296
286
  }
297
287
  if (!isManifest) {
298
- addInput(toEntry(configFilePath));
299
- addInput(toConfig(pluginName, configFilePath));
288
+ inputs.push(toEntry(configFilePath));
289
+ storeConfigFilePath(pluginName, toConfig(pluginName, configFilePath));
300
290
  cache.configFile = toEntry(configFilePath);
301
291
  if (fd?.changed && fd.meta && !seen.get(key)?.has(configFilePath)) {
302
292
  fd.meta.data = cache;
@@ -311,26 +301,33 @@ export class WorkspaceWorker {
311
301
  for (const id of dependencies)
312
302
  addInput(id, containingFilePath);
313
303
  }
304
+ if (inputs.some(input => input.specifier.startsWith('!')))
305
+ for (const input of inputs)
306
+ input.group = pluginName;
307
+ return inputs;
314
308
  };
315
309
  const enabledPluginTitles = this.enabledPlugins.map(name => Plugins[name].title);
316
310
  debugLogObject(this.name, 'Enabled plugins', enabledPluginTitles);
317
311
  for (const pluginName of this.enabledPlugins) {
318
312
  const patterns = [...this.getConfigurationFilePatterns(pluginName), ...(configFiles?.get(pluginName) ?? [])];
319
313
  configFiles?.delete(pluginName);
320
- await runPlugin(pluginName, compact(patterns));
314
+ for (const input of await runPlugin(pluginName, compact(patterns)))
315
+ inputs.push(input);
321
316
  remainingPlugins.delete(pluginName);
322
317
  }
323
318
  {
324
319
  const configFiles = this.configFilesMap.get(wsName);
325
320
  if (configFiles) {
326
321
  do {
327
- for (const [pluginName, dependencies] of configFiles.entries()) {
322
+ for (const [pluginName, dependencies] of configFiles) {
328
323
  configFiles.delete(pluginName);
329
- if (this.enabledPlugins.includes(pluginName))
330
- await runPlugin(pluginName, Array.from(dependencies));
324
+ if (this.enabledPlugins.includes(pluginName)) {
325
+ for (const input of await runPlugin(pluginName, Array.from(dependencies)))
326
+ inputs.push(input);
327
+ }
331
328
  else
332
329
  for (const id of dependencies)
333
- addInput(toEntry(id));
330
+ inputs.push(toEntry(id));
334
331
  }
335
332
  } while (remainingPlugins.size > 0 && configFiles.size > 0);
336
333
  }
@@ -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
  };
@@ -106,33 +106,34 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
106
106
  for (const id of inputsFromPlugins)
107
107
  inputs.add(Object.assign(id, { skipExportsAnalysis: !id.allowIncludeExports }));
108
108
  enabledPluginsStore.set(name, worker.enabledPlugins);
109
- const entryPatterns = new Set();
110
- const entryPatternsSkipExports = new Set();
111
- const productionPatterns = new Set();
112
- const productionPatternsSkipExports = new Set();
109
+ const DEFAULT_GROUP = 'default';
110
+ const createPatternMap = () => new Map([[DEFAULT_GROUP, new Set()]]);
111
+ const groups = new Set([DEFAULT_GROUP]);
112
+ const entryPatterns = createPatternMap();
113
+ const entryPatternsSkipExports = createPatternMap();
114
+ const productionPatterns = createPatternMap();
115
+ const productionPatternsSkipExports = createPatternMap();
113
116
  const projectFilePatterns = new Set();
117
+ const addPattern = (map, input, pattern) => {
118
+ if (input.group && !map.has(input.group))
119
+ map.set(input.group, new Set());
120
+ map.get(input.group ?? DEFAULT_GROUP).add(pattern);
121
+ };
122
+ const toWorkspaceRelative = (path) => (isAbsolute(path) ? relative(dir, path) : path);
114
123
  for (const input of inputs) {
124
+ if (input.group)
125
+ groups.add(input.group);
115
126
  const specifier = input.specifier;
116
127
  if (isEntry(input)) {
117
- const relativePath = isAbsolute(specifier) ? relative(dir, specifier) : specifier;
118
- if (!input.skipExportsAnalysis) {
119
- entryPatterns.add(relativePath);
120
- }
121
- else {
122
- entryPatternsSkipExports.add(relativePath);
123
- }
128
+ const targetMap = input.skipExportsAnalysis ? entryPatternsSkipExports : entryPatterns;
129
+ addPattern(targetMap, input, toWorkspaceRelative(specifier));
124
130
  }
125
131
  else if (isProductionEntry(input)) {
126
- const relativePath = isAbsolute(specifier) ? relative(dir, specifier) : specifier;
127
- if (!input.skipExportsAnalysis) {
128
- productionPatterns.add(relativePath);
129
- }
130
- else {
131
- productionPatternsSkipExports.add(relativePath);
132
- }
132
+ const targetMap = input.skipExportsAnalysis ? productionPatternsSkipExports : productionPatterns;
133
+ addPattern(targetMap, input, toWorkspaceRelative(specifier));
133
134
  }
134
135
  else if (isProject(input)) {
135
- projectFilePatterns.add(isAbsolute(specifier) ? relative(dir, specifier) : specifier);
136
+ projectFilePatterns.add(toWorkspaceRelative(specifier));
136
137
  }
137
138
  else if (isAlias(input)) {
138
139
  principal.addPaths({ [input.specifier]: input.prefixes }, input.dir ?? dir);
@@ -150,11 +151,11 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
150
151
  const resolvedFilePath = getReferencedInternalFilePath(input, ws);
151
152
  if (resolvedFilePath) {
152
153
  if (isDeferResolveProductionEntry(input)) {
153
- productionPatternsSkipExports.add(resolvedFilePath);
154
+ addPattern(productionPatternsSkipExports, input, resolvedFilePath);
154
155
  }
155
156
  else if (isDeferResolveEntry(input)) {
156
157
  if (!options.isProduction || !input.optional)
157
- entryPatternsSkipExports.add(resolvedFilePath);
158
+ addPattern(entryPatternsSkipExports, input, resolvedFilePath);
158
159
  }
159
160
  else {
160
161
  principal.addEntryPath(resolvedFilePath, { skipExportsAnalysis: true });
@@ -162,82 +163,63 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
162
163
  }
163
164
  }
164
165
  }
166
+ const negatedEntryPatterns = [];
165
167
  if (options.isProduction) {
166
- const negatedEntryPatterns = [...entryPatterns, ...entryPatternsSkipExports].map(negate);
167
- {
168
- const label = 'entry paths';
169
- const patterns = worker.getProductionEntryFilePatterns(negatedEntryPatterns);
170
- const workspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, gitignore: false, label });
171
- principal.addEntryPaths(workspaceEntryPaths);
168
+ for (const map of [entryPatterns, entryPatternsSkipExports]) {
169
+ for (const patterns of map.values())
170
+ for (const pattern of patterns)
171
+ negatedEntryPatterns.push(negate(pattern));
172
172
  }
173
- {
174
- const label = 'production entry paths from plugins (ignore exports)';
175
- const patterns = Array.from(productionPatternsSkipExports);
176
- const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
177
- principal.addEntryPaths(pluginWorkspaceEntryPaths, { skipExportsAnalysis: true });
173
+ }
174
+ {
175
+ const patterns = options.isProduction
176
+ ? worker.getProductionEntryFilePatterns(negatedEntryPatterns)
177
+ : worker.getEntryFilePatterns();
178
+ const entryPaths = await _glob({ ...sharedGlobOptions, patterns, gitignore: false, label: 'entry paths' });
179
+ if (!options.isProduction) {
180
+ const hints = worker.getConfigurationHints('entry', patterns, entryPaths, principal.entryPaths);
181
+ for (const hint of hints)
182
+ collector.addConfigurationHint(hint);
178
183
  }
184
+ principal.addEntryPaths(entryPaths);
185
+ }
186
+ for (const group of groups) {
179
187
  {
180
- const label = 'production entry paths from plugins';
181
- const patterns = Array.from(productionPatterns);
188
+ const patterns = worker.getPluginEntryFilePatterns([
189
+ ...((!options.isProduction && entryPatterns.get(group)) || []),
190
+ ...((!options.isProduction && group === DEFAULT_GROUP && worker.getPluginConfigPatterns()) || []),
191
+ ...(productionPatterns.get(group) ?? []),
192
+ ]);
193
+ const label = `entry paths from plugins${group !== DEFAULT_GROUP ? ` - ${group}` : ''}`;
182
194
  const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
183
195
  principal.addEntryPaths(pluginWorkspaceEntryPaths);
184
196
  }
185
197
  {
186
- const label = 'project paths';
187
- const patterns = worker.getProductionProjectFilePatterns(negatedEntryPatterns);
188
- const workspaceProjectPaths = await _glob({ ...sharedGlobOptions, patterns, label });
189
- for (const projectPath of workspaceProjectPaths)
190
- principal.addProjectPath(projectPath);
191
- }
192
- }
193
- else {
194
- {
195
- const label = 'entry paths from plugins (ignore exports)';
196
198
  const patterns = worker.getPluginEntryFilePatterns([
197
- ...entryPatternsSkipExports,
198
- ...productionPatternsSkipExports,
199
+ ...((!options.isProduction && entryPatternsSkipExports.get(group)) || []),
200
+ ...(productionPatternsSkipExports.get(group) ?? []),
199
201
  ]);
202
+ const label = `entry paths from plugins (ignore exports)${group !== DEFAULT_GROUP ? ` - ${group}` : ''}`;
200
203
  const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
201
204
  principal.addEntryPaths(pluginWorkspaceEntryPaths, { skipExportsAnalysis: true });
202
205
  }
203
- {
204
- const label = 'entry paths from plugins';
205
- const patterns = worker.getPluginEntryFilePatterns([...entryPatterns, ...productionPatterns]);
206
- const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
207
- principal.addEntryPaths(pluginWorkspaceEntryPaths);
208
- }
209
- {
210
- const label = 'entry paths';
211
- const patterns = worker.getEntryFilePatterns();
212
- const entryPaths = await _glob({ ...sharedGlobOptions, patterns, gitignore: false, label });
213
- const hints = worker.getConfigurationHints('entry', patterns, entryPaths, principal.entryPaths);
214
- for (const hint of hints)
215
- collector.addConfigurationHint(hint);
216
- principal.addEntryPaths(entryPaths);
217
- }
218
- {
219
- const label = 'project paths from plugins';
220
- const patterns = worker.getPluginProjectFilePatterns();
221
- const pluginWorkspaceProjectPaths = await _glob({ ...sharedGlobOptions, patterns, label });
222
- for (const projectPath of pluginWorkspaceProjectPaths)
223
- principal.addProjectPath(projectPath);
224
- }
225
- {
226
- const label = 'plugin configuration paths (ignore exports)';
227
- const patterns = worker.getPluginConfigPatterns();
228
- const configurationEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
229
- principal.addEntryPaths(configurationEntryPaths, { skipExportsAnalysis: true });
230
- }
231
- {
232
- const label = 'project paths';
233
- const patterns = worker.getProjectFilePatterns([...productionPatternsSkipExports, ...projectFilePatterns]);
234
- const projectPaths = await _glob({ ...sharedGlobOptions, patterns, label });
206
+ }
207
+ {
208
+ const patterns = options.isProduction
209
+ ? worker.getProductionProjectFilePatterns(negatedEntryPatterns)
210
+ : worker.getProjectFilePatterns([
211
+ ...(productionPatternsSkipExports.get(DEFAULT_GROUP) ?? []),
212
+ ...projectFilePatterns,
213
+ ...worker.getPluginProjectFilePatterns(),
214
+ ]);
215
+ const projectPaths = await _glob({ ...sharedGlobOptions, patterns, label: 'project paths' });
216
+ if (!options.isProduction) {
235
217
  const hints = worker.getConfigurationHints('project', config.project, projectPaths, principal.projectPaths);
236
218
  for (const hint of hints)
237
219
  collector.addConfigurationHint(hint);
238
- for (const projectPath of projectPaths)
239
- principal.addProjectPath(projectPath);
240
220
  }
221
+ for (const projectPath of projectPaths)
222
+ principal.addProjectPath(projectPath);
241
223
  }
242
224
  if (options.configFilePath) {
243
225
  factory.getPrincipals().at(0)?.addEntryPath(options.configFilePath, { skipExportsAnalysis: true });
@@ -294,13 +276,15 @@ export async function build({ chief, collector, counselor, deputy, factory, isGi
294
276
  if (!isIgnored)
295
277
  principal.addEntryPath(filePath, { skipExportsAnalysis: true });
296
278
  }
297
- for (const [_import, specifierFilePath] of file.imports.imports) {
298
- const packageName = getPackageNameFromModuleSpecifier(_import.specifier);
299
- if (packageName && isInternalWorkspace(packageName)) {
300
- file.imports.external.add({ ..._import, specifier: packageName });
301
- const principal = getPrincipalByFilePath(specifierFilePath);
302
- if (principal && !isGitIgnored(specifierFilePath)) {
303
- principal.addNonEntryPath(specifierFilePath);
279
+ for (const _import of file.imports.imports) {
280
+ if (_import.filePath) {
281
+ const packageName = getPackageNameFromModuleSpecifier(_import.specifier);
282
+ if (packageName && isInternalWorkspace(packageName)) {
283
+ file.imports.external.add({ ..._import, specifier: packageName });
284
+ const principal = getPrincipalByFilePath(_import.filePath);
285
+ if (principal && !isGitIgnored(_import.filePath)) {
286
+ principal.addNonEntryPath(_import.filePath);
287
+ }
304
288
  }
305
289
  }
306
290
  }
@@ -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[];