knip 6.24.0 → 6.25.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.
- package/dist/ConfigurationChief.d.ts +13 -1
- package/dist/ConfigurationChief.js +3 -0
- package/dist/ProjectPrincipal.d.ts +2 -0
- package/dist/ProjectPrincipal.js +4 -1
- package/dist/binaries/bash-parser.js +55 -83
- package/dist/binaries/index.js +3 -0
- package/dist/compilers/index.d.ts +29 -5
- package/dist/constants.d.ts +5 -1
- package/dist/constants.js +5 -0
- package/dist/graph/analyze.js +37 -2
- package/dist/graph/build.js +9 -0
- package/dist/graph-explorer/explorer.d.ts +1 -0
- package/dist/graph-explorer/explorer.js +2 -0
- package/dist/graph-explorer/operations/find-all-cycles.d.ts +3 -0
- package/dist/graph-explorer/operations/find-all-cycles.js +43 -0
- package/dist/graph-explorer/operations/find-cycles.js +3 -9
- package/dist/graph-explorer/utils.d.ts +10 -1
- package/dist/graph-explorer/utils.js +53 -0
- package/dist/plugins/bun/index.js +28 -14
- package/dist/plugins/eve/index.d.ts +3 -0
- package/dist/plugins/eve/index.js +22 -0
- package/dist/plugins/execa/visitors/execa.js +10 -18
- package/dist/plugins/fumadocs/index.d.ts +3 -0
- package/dist/plugins/fumadocs/index.js +18 -0
- package/dist/plugins/graphql-codegen/index.js +9 -7
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/jest/index.js +13 -3
- package/dist/plugins/next/index.js +23 -10
- package/dist/plugins/node/index.js +4 -1
- package/dist/plugins/pnpm/index.js +21 -1
- package/dist/plugins/pnpm/types.d.ts +6 -0
- package/dist/plugins/pnpm/types.js +1 -0
- package/dist/plugins/prettier/index.js +19 -3
- package/dist/plugins/prettier/types.d.ts +6 -1
- package/dist/plugins/rspack/index.js +5 -0
- package/dist/plugins/serverless-framework/index.js +12 -1
- package/dist/plugins/serverless-framework/types.d.ts +5 -2
- package/dist/plugins/storybook/index.js +7 -0
- package/dist/plugins/typedoc/index.js +9 -3
- package/dist/plugins/typedoc/types.d.ts +2 -0
- package/dist/plugins/vite/visitors/importMetaGlob.js +1 -8
- package/dist/plugins/webpack/visitors/requireContext.js +2 -13
- package/dist/plugins/yarn/index.js +13 -4
- package/dist/plugins/yarn/types.d.ts +10 -0
- package/dist/plugins/yarn/types.js +1 -0
- package/dist/plugins/zx/visitors/zx.js +4 -4
- package/dist/reporters/cycles.d.ts +3 -0
- package/dist/reporters/cycles.js +79 -0
- package/dist/reporters/index.d.ts +1 -0
- package/dist/reporters/index.js +2 -0
- package/dist/reporters/json.d.ts +3 -0
- package/dist/reporters/json.js +2 -1
- package/dist/reporters/util/util.d.ts +3 -1
- package/dist/reporters/util/util.js +5 -1
- package/dist/schema/configuration.d.ts +40 -6
- package/dist/schema/configuration.js +6 -0
- package/dist/schema/plugins.d.ts +10 -0
- package/dist/schema/plugins.js +2 -0
- package/dist/types/PluginNames.d.ts +2 -2
- package/dist/types/PluginNames.js +2 -0
- package/dist/types/config.d.ts +9 -0
- package/dist/types/issues.d.ts +3 -0
- package/dist/types/module-graph.d.ts +7 -0
- package/dist/types/package-json.d.ts +4 -1
- package/dist/typescript/ast-nodes.d.ts +3 -1
- package/dist/typescript/ast-nodes.js +9 -1
- package/dist/typescript/get-imports-and-exports.js +10 -0
- package/dist/typescript/glob-imports.d.ts +3 -0
- package/dist/typescript/glob-imports.js +49 -0
- package/dist/typescript/resolve-module-names.d.ts +2 -0
- package/dist/typescript/resolve-module-names.js +35 -1
- package/dist/typescript/visitors/calls.js +4 -6
- package/dist/typescript/visitors/imports.js +8 -8
- package/dist/typescript/visitors/script-visitors.js +4 -4
- package/dist/typescript/visitors/walk.js +2 -3
- package/dist/util/cli-arguments.d.ts +2 -1
- package/dist/util/cli-arguments.js +4 -2
- package/dist/util/create-options.d.ts +32 -5
- package/dist/util/create-options.js +4 -1
- package/dist/util/get-included-issue-types.d.ts +1 -0
- package/dist/util/get-included-issue-types.js +4 -2
- package/dist/util/issue-initializers.js +1 -1
- package/dist/util/load-tsconfig.js +17 -4
- package/dist/util/module-graph.js +1 -0
- package/dist/util/modules.js +25 -4
- package/dist/util/scripts.d.ts +7 -0
- package/dist/util/scripts.js +75 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/schema.json +40 -1
|
@@ -207,6 +207,11 @@ export declare class ConfigurationChief {
|
|
|
207
207
|
entry?: string | string[] | undefined;
|
|
208
208
|
project?: string | string[] | undefined;
|
|
209
209
|
} | undefined;
|
|
210
|
+
eve?: string | boolean | string[] | {
|
|
211
|
+
config?: string | string[] | undefined;
|
|
212
|
+
entry?: string | string[] | undefined;
|
|
213
|
+
project?: string | string[] | undefined;
|
|
214
|
+
} | undefined;
|
|
210
215
|
execa?: string | boolean | string[] | {
|
|
211
216
|
config?: string | string[] | undefined;
|
|
212
217
|
entry?: string | string[] | undefined;
|
|
@@ -227,6 +232,11 @@ export declare class ConfigurationChief {
|
|
|
227
232
|
entry?: string | string[] | undefined;
|
|
228
233
|
project?: string | string[] | undefined;
|
|
229
234
|
} | undefined;
|
|
235
|
+
fumadocs?: string | boolean | string[] | {
|
|
236
|
+
config?: string | string[] | undefined;
|
|
237
|
+
entry?: string | string[] | undefined;
|
|
238
|
+
project?: string | string[] | undefined;
|
|
239
|
+
} | undefined;
|
|
230
240
|
gatsby?: string | boolean | string[] | {
|
|
231
241
|
config?: string | string[] | undefined;
|
|
232
242
|
entry?: string | string[] | undefined;
|
|
@@ -852,7 +862,7 @@ export declare class ConfigurationChief {
|
|
|
852
862
|
ignoreMembers?: (string | RegExp)[] | undefined;
|
|
853
863
|
ignoreUnresolved?: (string | RegExp)[] | undefined;
|
|
854
864
|
ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
|
|
855
|
-
ignoreIssues?: Record<string, ("binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
865
|
+
ignoreIssues?: Record<string, ("binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
856
866
|
includeEntryExports?: boolean | undefined;
|
|
857
867
|
};
|
|
858
868
|
getIgnores(workspaceName: string): {
|
|
@@ -899,10 +909,12 @@ export declare class ConfigurationChief {
|
|
|
899
909
|
drizzle?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
900
910
|
eleventy?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
901
911
|
eslint?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
912
|
+
eve?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
902
913
|
execa?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
903
914
|
expo?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
904
915
|
"expressive-code"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
905
916
|
fast?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
917
|
+
fumadocs?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
906
918
|
gatsby?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
907
919
|
"github-action"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
908
920
|
"github-actions"?: (boolean | import("./types/config.ts").EnsuredPluginConfiguration) | undefined;
|
|
@@ -34,6 +34,7 @@ const defaultConfig = {
|
|
|
34
34
|
ignoreBinaries: [],
|
|
35
35
|
ignoreDependencies: [],
|
|
36
36
|
ignoreFiles: [],
|
|
37
|
+
cycles: {},
|
|
37
38
|
ignoreIssues: {},
|
|
38
39
|
ignoreMembers: [],
|
|
39
40
|
ignoreUnresolved: [],
|
|
@@ -103,6 +104,7 @@ export class ConfigurationChief {
|
|
|
103
104
|
const ignoreMembers = rawConfig.ignoreMembers ?? [];
|
|
104
105
|
const ignoreUnresolved = rawConfig.ignoreUnresolved ?? [];
|
|
105
106
|
const ignoreExportsUsedInFile = rawConfig.ignoreExportsUsedInFile ?? false;
|
|
107
|
+
const cycles = rawConfig.cycles ?? {};
|
|
106
108
|
const ignoreIssues = rawConfig.ignoreIssues ?? {};
|
|
107
109
|
const ignoreWorkspaces = rawConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
|
|
108
110
|
const isIncludeEntryExports = rawConfig.includeEntryExports ?? this.isIncludeEntryExports;
|
|
@@ -116,6 +118,7 @@ export class ConfigurationChief {
|
|
|
116
118
|
return {
|
|
117
119
|
ignore,
|
|
118
120
|
ignoreFiles,
|
|
121
|
+
cycles,
|
|
119
122
|
ignoreBinaries,
|
|
120
123
|
ignoreDependencies,
|
|
121
124
|
ignoreMembers,
|
|
@@ -4,6 +4,7 @@ import type { AsyncCompilers, SyncCompilers } from './compilers/types.ts';
|
|
|
4
4
|
import type { GetImportsAndExportsOptions, IgnoreExportsUsedInFile, PluginVisitorContext, PluginVisitorObject } from './types/config.ts';
|
|
5
5
|
import type { FileNode, ModuleGraph } from './types/module-graph.ts';
|
|
6
6
|
import type { Paths } from './types/project.ts';
|
|
7
|
+
import type { ResolveGlobPattern } from './typescript/resolve-module-names.ts';
|
|
7
8
|
import { SourceFileManager } from './typescript/SourceFileManager.ts';
|
|
8
9
|
import type { MainOptions } from './util/create-options.ts';
|
|
9
10
|
import type { ToSourceFilePath, WorkspaceManifestHandler } from './util/to-source-path.ts';
|
|
@@ -27,6 +28,7 @@ export declare class ProjectPrincipal {
|
|
|
27
28
|
private findWorkspaceManifestImports;
|
|
28
29
|
fileManager: SourceFileManager;
|
|
29
30
|
private resolveModule;
|
|
31
|
+
resolveGlobPattern: ResolveGlobPattern;
|
|
30
32
|
resolvedFiles: Set<string>;
|
|
31
33
|
deletedFiles: Set<string>;
|
|
32
34
|
private onPathAdded;
|
package/dist/ProjectPrincipal.js
CHANGED
|
@@ -6,7 +6,7 @@ import { DEFAULT_EXTENSIONS } from './constants.js';
|
|
|
6
6
|
import { _getImportsAndExports } from './typescript/get-imports-and-exports.js';
|
|
7
7
|
import { createBunShellVisitor } from './typescript/visitors/script-visitors.js';
|
|
8
8
|
import { buildVisitor } from './typescript/visitors/walk.js';
|
|
9
|
-
import { createCustomModuleResolver } from './typescript/resolve-module-names.js';
|
|
9
|
+
import { createCustomModuleResolver, createGlobAliasResolver } from './typescript/resolve-module-names.js';
|
|
10
10
|
import { SourceFileManager } from './typescript/SourceFileManager.js';
|
|
11
11
|
import { compact } from './util/array.js';
|
|
12
12
|
import { timerify } from './util/Performance.js';
|
|
@@ -21,6 +21,7 @@ export class ProjectPrincipal {
|
|
|
21
21
|
sourceText: '',
|
|
22
22
|
addScript: () => { },
|
|
23
23
|
addImport: () => { },
|
|
24
|
+
addImportGlob: () => { },
|
|
24
25
|
markExportRegistered: () => { },
|
|
25
26
|
};
|
|
26
27
|
pluginVisitorObjects = [];
|
|
@@ -37,6 +38,7 @@ export class ProjectPrincipal {
|
|
|
37
38
|
findWorkspaceManifestImports;
|
|
38
39
|
fileManager;
|
|
39
40
|
resolveModule = () => undefined;
|
|
41
|
+
resolveGlobPattern = pattern => [pattern];
|
|
40
42
|
resolvedFiles = new Set();
|
|
41
43
|
deletedFiles = new Set();
|
|
42
44
|
onPathAdded;
|
|
@@ -90,6 +92,7 @@ export class ProjectPrincipal {
|
|
|
90
92
|
const scopedPaths = this.paths.size > 0 ? Array.from(this.paths, ([scope, paths]) => ({ scope, paths })) : undefined;
|
|
91
93
|
const scopedRootDirs = this.rootDirs.size > 0 ? Array.from(this.rootDirs, ([scope, rootDirs]) => ({ scope, rootDirs })) : undefined;
|
|
92
94
|
this.resolveModule = createCustomModuleResolver({ scopedPaths, scopedRootDirs }, customCompilerExtensions, this.toSourceFilePath, this.findWorkspaceManifestImports, this.tsConfigFile);
|
|
95
|
+
this.resolveGlobPattern = createGlobAliasResolver(scopedPaths);
|
|
93
96
|
}
|
|
94
97
|
readFile(filePath) {
|
|
95
98
|
return this.fileManager.readFile(filePath);
|
|
@@ -5,6 +5,7 @@ import { toBinary, toDeferResolve } from '../util/input.js';
|
|
|
5
5
|
import { extractBinary, isValidBinary } from '../util/modules.js';
|
|
6
6
|
import { relative } from '../util/path.js';
|
|
7
7
|
import { truncate } from '../util/string.js';
|
|
8
|
+
import { walkCommands } from '../util/scripts.js';
|
|
8
9
|
import { resolve as fallbackResolve } from './fallback.js';
|
|
9
10
|
import KnownResolvers from './resolvers/index.js';
|
|
10
11
|
import { resolve as resolverFromPlugins } from './plugins.js';
|
|
@@ -46,93 +47,64 @@ export const getDependenciesFromScript = (script, options) => {
|
|
|
46
47
|
const processScript = (s) => {
|
|
47
48
|
collectFunctionNames(s.commands);
|
|
48
49
|
const pending = [];
|
|
49
|
-
const mainDeps =
|
|
50
|
+
const mainDeps = [];
|
|
51
|
+
for (const statement of s.commands) {
|
|
52
|
+
for (const command of walkCommands(statement.command))
|
|
53
|
+
mainDeps.push(...processCommand(command, pending));
|
|
54
|
+
}
|
|
50
55
|
const expansionDeps = pending.flatMap(inner => processScript(inner));
|
|
51
56
|
return [...mainDeps, ...expansionDeps];
|
|
52
57
|
};
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (binary in KnownResolvers) {
|
|
83
|
-
const resolver = KnownResolvers[binary];
|
|
84
|
-
return resolver(binary, args, { ...options, fromArgs });
|
|
85
|
-
}
|
|
86
|
-
if (pluginArgsMap.has(binary)) {
|
|
87
|
-
return [...resolverFromPlugins(binary, args, { ...options, fromArgs }), ...fromNodeOptions];
|
|
88
|
-
}
|
|
89
|
-
if (spawningBinaries.includes(binary)) {
|
|
90
|
-
const rest = node.suffix
|
|
91
|
-
.filter(w => w.text !== '--')
|
|
92
|
-
.map(w => w.text)
|
|
93
|
-
.join(' ');
|
|
94
|
-
return [toBinary(binary), ...getDependenciesFromScript(rest, options)];
|
|
95
|
-
}
|
|
96
|
-
if (binary in Plugins) {
|
|
97
|
-
const inputs = fallbackResolve(binary, args, { ...options, fromArgs });
|
|
98
|
-
if (options.knownBinsOnly)
|
|
99
|
-
for (const input of inputs)
|
|
100
|
-
input.optional = true;
|
|
101
|
-
return [...inputs, ...fromNodeOptions];
|
|
102
|
-
}
|
|
103
|
-
if (options.knownBinsOnly && !text?.startsWith('.'))
|
|
104
|
-
return [];
|
|
105
|
-
return [...fallbackResolve(binary, args, { ...options, fromArgs }), ...fromNodeOptions];
|
|
106
|
-
}
|
|
107
|
-
case 'AndOr':
|
|
108
|
-
case 'Pipeline':
|
|
109
|
-
return node.commands.flatMap(n => getDependenciesFromNode(n, pending));
|
|
110
|
-
case 'If':
|
|
111
|
-
return [
|
|
112
|
-
...getDependenciesFromStatements(node.clause.commands, pending),
|
|
113
|
-
...getDependenciesFromStatements(node.then.commands, pending),
|
|
114
|
-
...(node.else ? getDependenciesFromNode(node.else, pending) : []),
|
|
115
|
-
];
|
|
116
|
-
case 'While':
|
|
117
|
-
return [
|
|
118
|
-
...getDependenciesFromStatements(node.clause.commands, pending),
|
|
119
|
-
...getDependenciesFromStatements(node.body.commands, pending),
|
|
120
|
-
];
|
|
121
|
-
case 'For':
|
|
122
|
-
case 'Select':
|
|
123
|
-
case 'Subshell':
|
|
124
|
-
case 'BraceGroup':
|
|
125
|
-
return getDependenciesFromStatements(node.body.commands, pending);
|
|
126
|
-
case 'CompoundList':
|
|
127
|
-
return getDependenciesFromStatements(node.commands, pending);
|
|
128
|
-
case 'Function':
|
|
129
|
-
case 'Coproc':
|
|
130
|
-
return getDependenciesFromNode(node.body, pending);
|
|
131
|
-
case 'Statement':
|
|
132
|
-
return getDependenciesFromNode(node.command, pending);
|
|
133
|
-
default:
|
|
134
|
-
return [];
|
|
58
|
+
const processCommand = (node, pending) => {
|
|
59
|
+
const text = node.name?.value;
|
|
60
|
+
const binary = text ? extractBinary(text) : text;
|
|
61
|
+
if (node.name)
|
|
62
|
+
collectExpansionScripts(node.name, pending);
|
|
63
|
+
for (const prefix of node.prefix)
|
|
64
|
+
if (prefix.value)
|
|
65
|
+
collectExpansionScripts(prefix.value, pending);
|
|
66
|
+
for (const suffix of node.suffix)
|
|
67
|
+
collectExpansionScripts(suffix, pending);
|
|
68
|
+
if (!binary || binary === '.' || binary === 'source' || binary === '[')
|
|
69
|
+
return [];
|
|
70
|
+
if (binary.startsWith('-') || binary.startsWith('..'))
|
|
71
|
+
return [];
|
|
72
|
+
if (definedFunctions.has(binary))
|
|
73
|
+
return [];
|
|
74
|
+
const args = node.suffix.map(w => w.value);
|
|
75
|
+
if (['!', 'test'].includes(binary))
|
|
76
|
+
return fromArgs(args);
|
|
77
|
+
const fromNodeOptions = node.prefix
|
|
78
|
+
.filter(a => a.name === 'NODE_OPTIONS' && a.value)
|
|
79
|
+
.map(a => a.value.value)
|
|
80
|
+
.map(arg => parseNodeArgs(arg.split(' ')))
|
|
81
|
+
.filter(args => args.require)
|
|
82
|
+
.flatMap(arg => arg.require)
|
|
83
|
+
.map(id => toDeferResolve(id));
|
|
84
|
+
if (binary in KnownResolvers) {
|
|
85
|
+
const resolver = KnownResolvers[binary];
|
|
86
|
+
return resolver(binary, args, { ...options, fromArgs });
|
|
135
87
|
}
|
|
88
|
+
if (pluginArgsMap.has(binary)) {
|
|
89
|
+
return [...resolverFromPlugins(binary, args, { ...options, fromArgs }), ...fromNodeOptions];
|
|
90
|
+
}
|
|
91
|
+
if (spawningBinaries.includes(binary)) {
|
|
92
|
+
const rest = node.suffix
|
|
93
|
+
.filter(w => w.text !== '--')
|
|
94
|
+
.map(w => w.text)
|
|
95
|
+
.join(' ');
|
|
96
|
+
return [toBinary(binary), ...getDependenciesFromScript(rest, options)];
|
|
97
|
+
}
|
|
98
|
+
if (binary in Plugins) {
|
|
99
|
+
const inputs = fallbackResolve(binary, args, { ...options, fromArgs });
|
|
100
|
+
if (options.knownBinsOnly)
|
|
101
|
+
for (const input of inputs)
|
|
102
|
+
input.optional = true;
|
|
103
|
+
return [...inputs, ...fromNodeOptions];
|
|
104
|
+
}
|
|
105
|
+
if (options.knownBinsOnly && !text?.startsWith('.'))
|
|
106
|
+
return [];
|
|
107
|
+
return [...fallbackResolve(binary, args, { ...options, fromArgs }), ...fromNodeOptions];
|
|
136
108
|
};
|
|
137
109
|
try {
|
|
138
110
|
const parsed = parse(script);
|
package/dist/binaries/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SCRIPT_INTERPOLATION } from '../constants.js';
|
|
1
2
|
import { fromBinary, isBinary, isDependency } from '../util/input.js';
|
|
2
3
|
import { timerify } from '../util/Performance.js';
|
|
3
4
|
import { getDependenciesFromScript } from './bash-parser.js';
|
|
@@ -8,6 +9,8 @@ const getInputsFromScripts = (npmScripts, options) => {
|
|
|
8
9
|
for (const input of results) {
|
|
9
10
|
if (!input.specifier)
|
|
10
11
|
continue;
|
|
12
|
+
if (input.specifier.includes(SCRIPT_INTERPOLATION))
|
|
13
|
+
continue;
|
|
11
14
|
if (isDependency(input) && input.specifier.startsWith('http'))
|
|
12
15
|
continue;
|
|
13
16
|
if (isBinary(input) && !/^\b/.test(fromBinary(input)))
|
|
@@ -153,6 +153,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
153
153
|
entry?: string | string[] | undefined;
|
|
154
154
|
project?: string | string[] | undefined;
|
|
155
155
|
} | undefined;
|
|
156
|
+
eve?: string | boolean | string[] | {
|
|
157
|
+
config?: string | string[] | undefined;
|
|
158
|
+
entry?: string | string[] | undefined;
|
|
159
|
+
project?: string | string[] | undefined;
|
|
160
|
+
} | undefined;
|
|
156
161
|
execa?: string | boolean | string[] | {
|
|
157
162
|
config?: string | string[] | undefined;
|
|
158
163
|
entry?: string | string[] | undefined;
|
|
@@ -173,6 +178,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
173
178
|
entry?: string | string[] | undefined;
|
|
174
179
|
project?: string | string[] | undefined;
|
|
175
180
|
} | undefined;
|
|
181
|
+
fumadocs?: string | boolean | string[] | {
|
|
182
|
+
config?: string | string[] | undefined;
|
|
183
|
+
entry?: string | string[] | undefined;
|
|
184
|
+
project?: string | string[] | undefined;
|
|
185
|
+
} | undefined;
|
|
176
186
|
gatsby?: string | boolean | string[] | {
|
|
177
187
|
config?: string | string[] | undefined;
|
|
178
188
|
entry?: string | string[] | undefined;
|
|
@@ -789,7 +799,7 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
789
799
|
project?: string | string[] | undefined;
|
|
790
800
|
} | undefined;
|
|
791
801
|
$schema?: string | undefined;
|
|
792
|
-
rules?: Partial<Record<"binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved", "error" | "off" | "warn">> | undefined;
|
|
802
|
+
rules?: Partial<Record<"binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved", "error" | "off" | "warn">> | undefined;
|
|
793
803
|
entry?: string | string[] | undefined;
|
|
794
804
|
project?: string | string[] | undefined;
|
|
795
805
|
paths?: Record<string, string[]> | undefined;
|
|
@@ -800,15 +810,19 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
800
810
|
ignoreMembers?: (string | RegExp)[] | undefined;
|
|
801
811
|
ignoreUnresolved?: (string | RegExp)[] | undefined;
|
|
802
812
|
ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
|
|
803
|
-
ignoreIssues?: Record<string, ("binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
813
|
+
ignoreIssues?: Record<string, ("binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
814
|
+
cycles?: {
|
|
815
|
+
allow?: string[][] | undefined;
|
|
816
|
+
dynamicImports?: boolean | undefined;
|
|
817
|
+
} | undefined;
|
|
804
818
|
ignoreWorkspaces?: string[] | undefined;
|
|
805
819
|
includeEntryExports?: boolean | undefined;
|
|
806
820
|
compilers?: Record<string, true | CompilerAsync | CompilerSync> | undefined;
|
|
807
821
|
tags?: string[] | undefined;
|
|
808
822
|
treatConfigHintsAsErrors?: boolean | undefined;
|
|
809
823
|
treatTagHintsAsErrors?: boolean | undefined;
|
|
810
|
-
include?: ("binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
811
|
-
exclude?: ("binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
824
|
+
include?: ("binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
825
|
+
exclude?: ("binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[] | undefined;
|
|
812
826
|
workspaces?: Record<string, {
|
|
813
827
|
angular?: string | boolean | string[] | {
|
|
814
828
|
config?: string | string[] | undefined;
|
|
@@ -960,6 +974,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
960
974
|
entry?: string | string[] | undefined;
|
|
961
975
|
project?: string | string[] | undefined;
|
|
962
976
|
} | undefined;
|
|
977
|
+
eve?: string | boolean | string[] | {
|
|
978
|
+
config?: string | string[] | undefined;
|
|
979
|
+
entry?: string | string[] | undefined;
|
|
980
|
+
project?: string | string[] | undefined;
|
|
981
|
+
} | undefined;
|
|
963
982
|
execa?: string | boolean | string[] | {
|
|
964
983
|
config?: string | string[] | undefined;
|
|
965
984
|
entry?: string | string[] | undefined;
|
|
@@ -980,6 +999,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
980
999
|
entry?: string | string[] | undefined;
|
|
981
1000
|
project?: string | string[] | undefined;
|
|
982
1001
|
} | undefined;
|
|
1002
|
+
fumadocs?: string | boolean | string[] | {
|
|
1003
|
+
config?: string | string[] | undefined;
|
|
1004
|
+
entry?: string | string[] | undefined;
|
|
1005
|
+
project?: string | string[] | undefined;
|
|
1006
|
+
} | undefined;
|
|
983
1007
|
gatsby?: string | boolean | string[] | {
|
|
984
1008
|
config?: string | string[] | undefined;
|
|
985
1009
|
entry?: string | string[] | undefined;
|
|
@@ -1605,7 +1629,7 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
|
|
|
1605
1629
|
ignoreMembers?: (string | RegExp)[] | undefined;
|
|
1606
1630
|
ignoreUnresolved?: (string | RegExp)[] | undefined;
|
|
1607
1631
|
ignoreExportsUsedInFile?: boolean | Record<string, boolean | undefined> | undefined;
|
|
1608
|
-
ignoreIssues?: Record<string, ("binaries" | "catalog" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
1632
|
+
ignoreIssues?: Record<string, ("binaries" | "catalog" | "cycles" | "dependencies" | "devDependencies" | "duplicates" | "enumMembers" | "exports" | "files" | "namespaceMembers" | "nsExports" | "nsTypes" | "optionalPeerDependencies" | "types" | "unlisted" | "unresolved")[]> | undefined;
|
|
1609
1633
|
includeEntryExports?: boolean | undefined;
|
|
1610
1634
|
}> | undefined;
|
|
1611
1635
|
syncCompilers: Record<string, true | CompilerSync>;
|
package/dist/constants.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const IGNORED_DEPENDENCIES: Set<string>;
|
|
|
16
16
|
export declare const IGNORED_RUNTIME_DEPENDENCIES: Set<string>;
|
|
17
17
|
export declare const FOREIGN_FILE_EXTENSIONS: Set<string>;
|
|
18
18
|
export declare const IGNORE_DEFINITELY_TYPED: Set<string>;
|
|
19
|
-
export declare const ISSUE_TYPES: readonly ['files', 'dependencies', 'devDependencies', 'optionalPeerDependencies', 'unlisted', 'binaries', 'unresolved', 'exports', 'nsExports', 'types', 'nsTypes', 'enumMembers', 'namespaceMembers', 'duplicates', 'catalog'];
|
|
19
|
+
export declare const ISSUE_TYPES: readonly ['files', 'dependencies', 'devDependencies', 'optionalPeerDependencies', 'unlisted', 'binaries', 'unresolved', 'exports', 'nsExports', 'types', 'nsTypes', 'enumMembers', 'namespaceMembers', 'duplicates', 'catalog', 'cycles'];
|
|
20
20
|
export declare const ISSUE_TYPE_TITLE: {
|
|
21
21
|
readonly files: 'Unused files';
|
|
22
22
|
readonly dependencies: 'Unused dependencies';
|
|
@@ -33,6 +33,7 @@ export declare const ISSUE_TYPE_TITLE: {
|
|
|
33
33
|
readonly namespaceMembers: 'Unused exported namespace members';
|
|
34
34
|
readonly duplicates: 'Duplicate exports';
|
|
35
35
|
readonly catalog: 'Unused catalog entries';
|
|
36
|
+
readonly cycles: 'Circular dependencies';
|
|
36
37
|
};
|
|
37
38
|
export declare const SYMBOL_TYPE: {
|
|
38
39
|
readonly CLASS: 'class';
|
|
@@ -53,6 +54,7 @@ export declare const FIX_FLAGS: {
|
|
|
53
54
|
};
|
|
54
55
|
export declare const SIDE_EFFECTS = "__side-effects";
|
|
55
56
|
export declare const OPAQUE = "__opaque";
|
|
57
|
+
export declare const SCRIPT_INTERPOLATION = "$__knip__";
|
|
56
58
|
export declare const IMPORT_FLAGS: {
|
|
57
59
|
readonly NONE: 0;
|
|
58
60
|
readonly RE_EXPORT: number;
|
|
@@ -62,4 +64,6 @@ export declare const IMPORT_FLAGS: {
|
|
|
62
64
|
readonly OPTIONAL: number;
|
|
63
65
|
readonly SIDE_EFFECTS: number;
|
|
64
66
|
readonly OPAQUE: number;
|
|
67
|
+
readonly AUGMENT: number;
|
|
68
|
+
readonly DYNAMIC: number;
|
|
65
69
|
};
|
package/dist/constants.js
CHANGED
|
@@ -186,6 +186,7 @@ export const ISSUE_TYPES = [
|
|
|
186
186
|
'namespaceMembers',
|
|
187
187
|
'duplicates',
|
|
188
188
|
'catalog',
|
|
189
|
+
'cycles',
|
|
189
190
|
];
|
|
190
191
|
export const ISSUE_TYPE_TITLE = {
|
|
191
192
|
files: 'Unused files',
|
|
@@ -203,6 +204,7 @@ export const ISSUE_TYPE_TITLE = {
|
|
|
203
204
|
namespaceMembers: 'Unused exported namespace members',
|
|
204
205
|
duplicates: 'Duplicate exports',
|
|
205
206
|
catalog: 'Unused catalog entries',
|
|
207
|
+
cycles: 'Circular dependencies',
|
|
206
208
|
};
|
|
207
209
|
export const SYMBOL_TYPE = {
|
|
208
210
|
CLASS: 'class',
|
|
@@ -223,6 +225,7 @@ export const FIX_FLAGS = {
|
|
|
223
225
|
};
|
|
224
226
|
export const SIDE_EFFECTS = '__side-effects';
|
|
225
227
|
export const OPAQUE = '__opaque';
|
|
228
|
+
export const SCRIPT_INTERPOLATION = '$__knip__';
|
|
226
229
|
export const IMPORT_FLAGS = {
|
|
227
230
|
NONE: 0,
|
|
228
231
|
RE_EXPORT: 1 << 0,
|
|
@@ -232,4 +235,6 @@ export const IMPORT_FLAGS = {
|
|
|
232
235
|
OPTIONAL: 1 << 4,
|
|
233
236
|
SIDE_EFFECTS: 1 << 5,
|
|
234
237
|
OPAQUE: 1 << 6,
|
|
238
|
+
AUGMENT: 1 << 7,
|
|
239
|
+
DYNAMIC: 1 << 8,
|
|
235
240
|
};
|
package/dist/graph/analyze.js
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import { createGraphExplorer } from '../graph-explorer/explorer.js';
|
|
2
|
-
import { getIssueType, hasStrictlyEnumReferences } from '../graph-explorer/utils.js';
|
|
2
|
+
import { getIgnoredCycleImportFlags, getIssueType, getRuntimeImport, hasStrictlyEnumReferences, } from '../graph-explorer/utils.js';
|
|
3
3
|
import traceReporter from '../reporters/trace.js';
|
|
4
4
|
import { shouldCountRefs } from '../typescript/ast-nodes.js';
|
|
5
5
|
import { getPackageNameFromModuleSpecifier } from '../util/modules.js';
|
|
6
|
-
import {
|
|
6
|
+
import { relative } from '../util/path.js';
|
|
7
|
+
import { perfObserver, timerify } from '../util/Performance.js';
|
|
7
8
|
import { findMatch } from '../util/regex.js';
|
|
8
9
|
import { getShouldIgnoreHandler, getShouldIgnoreTagHandler, isAlwaysIgnored } from '../util/tag.js';
|
|
9
10
|
import { INTERNAL_TAG } from '../constants.js';
|
|
11
|
+
const toCyclePathKey = (path) => {
|
|
12
|
+
const length = path.length > 1 && path[0] === path[path.length - 1] ? path.length - 1 : path.length;
|
|
13
|
+
return path.slice(0, length).join('\0');
|
|
14
|
+
};
|
|
15
|
+
const getAllowedCyclePaths = (cycles) => {
|
|
16
|
+
if (!cycles.allow?.length)
|
|
17
|
+
return;
|
|
18
|
+
const paths = new Set();
|
|
19
|
+
for (const path of cycles.allow)
|
|
20
|
+
if (path.length > 0)
|
|
21
|
+
paths.add(toCyclePathKey(path));
|
|
22
|
+
return paths;
|
|
23
|
+
};
|
|
24
|
+
const isAllowedCycle = (symbols, paths) => paths?.has(toCyclePathKey(symbols.map(s => s.symbol))) ?? false;
|
|
10
25
|
export const analyze = async ({ analyzedFiles, counselor, chief, collector, deputy, entryPaths, graph, streamer, unreferencedFiles, options, }) => {
|
|
11
26
|
const shouldIgnore = getShouldIgnoreHandler(options.isProduction);
|
|
12
27
|
const shouldIgnoreTags = getShouldIgnoreTagHandler(options.tags);
|
|
@@ -210,6 +225,26 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
|
|
|
210
225
|
}
|
|
211
226
|
}
|
|
212
227
|
}
|
|
228
|
+
if (options.isReportCycles) {
|
|
229
|
+
const cyclesConfig = chief.config.cycles;
|
|
230
|
+
const allowedCyclePaths = getAllowedCyclePaths(cyclesConfig);
|
|
231
|
+
const ignoredFlags = getIgnoredCycleImportFlags(cyclesConfig.dynamicImports ?? false);
|
|
232
|
+
for (const cycle of timerify(explorer.findAllCycles, 'findAllCycles')(ignoredFlags)) {
|
|
233
|
+
const filePath = cycle[0];
|
|
234
|
+
const ws = chief.findWorkspaceByFilePath(filePath);
|
|
235
|
+
if (!ws)
|
|
236
|
+
continue;
|
|
237
|
+
const symbols = cycle.slice(0, -1).map((file, index) => {
|
|
238
|
+
const node = graph.get(file);
|
|
239
|
+
const edge = node && getRuntimeImport(node, cycle[index + 1], ignoredFlags);
|
|
240
|
+
return edge ? { symbol: relative(options.cwd, file), ...edge } : { symbol: relative(options.cwd, file) };
|
|
241
|
+
});
|
|
242
|
+
if (isAllowedCycle(symbols, allowedCyclePaths))
|
|
243
|
+
continue;
|
|
244
|
+
const symbol = symbols.map(s => s.symbol).join(' → ');
|
|
245
|
+
collector.addIssue({ type: 'cycles', filePath, workspace: ws.name, symbol, symbols, fixes: [] });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
213
248
|
const unusedFiles = options.isReportFiles
|
|
214
249
|
? [...unreferencedFiles].filter(filePath => !analyzedFiles.has(filePath))
|
|
215
250
|
: [];
|
package/dist/graph/build.js
CHANGED
|
@@ -10,6 +10,7 @@ import { tryRealpath } from '../util/fs.js';
|
|
|
10
10
|
import { createManifest } from '../util/package-json.js';
|
|
11
11
|
import { _glob, _syncGlob, negate, prependDirToPattern as prependDir } from '../util/glob.js';
|
|
12
12
|
import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
|
|
13
|
+
import { resolveImportGlobs } from '../typescript/glob-imports.js';
|
|
13
14
|
import { loadTSConfig } from '../util/load-tsconfig.js';
|
|
14
15
|
import { createFileNode, updateImportMap } from '../util/module-graph.js';
|
|
15
16
|
import { getPackageNameFromModuleSpecifier, isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
|
|
@@ -382,6 +383,13 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
382
383
|
pp.addEntryPath(specifierFilePath, { skipExportsAnalysis: true });
|
|
383
384
|
}
|
|
384
385
|
}
|
|
386
|
+
if (file.importGlobs.length > 0) {
|
|
387
|
+
const globbed = resolveImportGlobs(file.importGlobs, filePath, pp.resolveGlobPattern, workspace.dir);
|
|
388
|
+
for (const importedFilePath of globbed) {
|
|
389
|
+
if (!isGitIgnored(importedFilePath))
|
|
390
|
+
pp.addEntryPath(importedFilePath, { skipExportsAnalysis: true });
|
|
391
|
+
}
|
|
392
|
+
}
|
|
385
393
|
file.imports.unresolved = unresolvedImports;
|
|
386
394
|
const pluginRefs = externalRefsFromInputs?.get(filePath);
|
|
387
395
|
if (pluginRefs)
|
|
@@ -393,6 +401,7 @@ export async function build({ chief, collector, counselor, deputy, principal, is
|
|
|
393
401
|
node.exports = file.exports;
|
|
394
402
|
node.duplicates = file.duplicates;
|
|
395
403
|
node.scripts = file.scripts;
|
|
404
|
+
node.importGlobs = file.importGlobs;
|
|
396
405
|
updateImportMap(node, file.imports.internal, graph);
|
|
397
406
|
node.internalImportCache = file.imports.internal;
|
|
398
407
|
}
|
|
@@ -13,6 +13,7 @@ export declare const createGraphExplorer: (graph: ModuleGraph, entryPaths: Set<s
|
|
|
13
13
|
resolveDefinition: (filePath: string, identifier: string) => import("./operations/resolve-definition.ts").DefinitionResult | null;
|
|
14
14
|
getUsage: (filePath: string, identifier: string) => import("./operations/get-usage.ts").UsageResult;
|
|
15
15
|
findCycles: (filePath: string, maxDepth?: number) => import("../session/types.ts").Cycle[];
|
|
16
|
+
findAllCycles: (ignoredFlags?: number) => import("../session/types.ts").Cycle[];
|
|
16
17
|
getContention: (filePath: string) => Map<string, import("../session/types.ts").ContentionDetails>;
|
|
17
18
|
invalidateCache: () => void;
|
|
18
19
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { invalidateCache as invalidateCacheInternal } from './cache.js';
|
|
2
2
|
import { buildExportsTree } from './operations/build-exports-tree.js';
|
|
3
|
+
import { findAllCycles } from './operations/find-all-cycles.js';
|
|
3
4
|
import { findCycles } from './operations/find-cycles.js';
|
|
4
5
|
import { getContention } from './operations/get-contention.js';
|
|
5
6
|
import { getDependencyUsage } from './operations/get-dependency-usage.js';
|
|
@@ -16,6 +17,7 @@ export const createGraphExplorer = (graph, entryPaths) => {
|
|
|
16
17
|
resolveDefinition: (filePath, identifier) => resolveDefinition(graph, filePath, identifier),
|
|
17
18
|
getUsage: (filePath, identifier) => getUsage(graph, entryPaths, filePath, identifier),
|
|
18
19
|
findCycles: (filePath, maxDepth) => findCycles(graph, filePath, maxDepth),
|
|
20
|
+
findAllCycles: (ignoredFlags) => findAllCycles(graph, ignoredFlags),
|
|
19
21
|
getContention: (filePath) => getContention(graph, filePath),
|
|
20
22
|
invalidateCache: () => invalidateCacheInternal(graph),
|
|
21
23
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getRuntimeSuccessors } from '../utils.js';
|
|
2
|
+
const UNVISITED = undefined;
|
|
3
|
+
const ON_STACK = 1;
|
|
4
|
+
const DONE = 2;
|
|
5
|
+
export const findAllCycles = (graph, ignoredFlags) => {
|
|
6
|
+
const cycles = [];
|
|
7
|
+
const state = new Map();
|
|
8
|
+
for (const root of graph.keys()) {
|
|
9
|
+
if (state.get(root) !== UNVISITED)
|
|
10
|
+
continue;
|
|
11
|
+
const path = [];
|
|
12
|
+
const indexOnPath = new Map();
|
|
13
|
+
const successorsStack = [];
|
|
14
|
+
const push = (filePath) => {
|
|
15
|
+
state.set(filePath, ON_STACK);
|
|
16
|
+
indexOnPath.set(filePath, path.length);
|
|
17
|
+
path.push(filePath);
|
|
18
|
+
const node = graph.get(filePath);
|
|
19
|
+
successorsStack.push((node ? getRuntimeSuccessors(node, ignoredFlags) : new Set()).values());
|
|
20
|
+
};
|
|
21
|
+
push(root);
|
|
22
|
+
while (path.length > 0) {
|
|
23
|
+
const current = path[path.length - 1];
|
|
24
|
+
const next = successorsStack[successorsStack.length - 1].next();
|
|
25
|
+
if (next.done) {
|
|
26
|
+
state.set(current, DONE);
|
|
27
|
+
indexOnPath.delete(current);
|
|
28
|
+
path.pop();
|
|
29
|
+
successorsStack.pop();
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const successor = next.value;
|
|
33
|
+
const successorState = state.get(successor);
|
|
34
|
+
if (successorState === ON_STACK) {
|
|
35
|
+
cycles.push([...path.slice(indexOnPath.get(successor)), successor]);
|
|
36
|
+
}
|
|
37
|
+
else if (successorState === UNVISITED) {
|
|
38
|
+
push(successor);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return cycles;
|
|
43
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getRuntimeSuccessors } from '../utils.js';
|
|
1
2
|
export const findCycles = (graph, filePath, maxDepth = 16) => {
|
|
2
3
|
const cycles = [];
|
|
3
4
|
const visited = new Set();
|
|
@@ -7,16 +8,9 @@ export const findCycles = (graph, filePath, maxDepth = 16) => {
|
|
|
7
8
|
if (path.length > maxDepth)
|
|
8
9
|
return;
|
|
9
10
|
const node = graph.get(currentPath);
|
|
10
|
-
if (!node
|
|
11
|
+
if (!node)
|
|
11
12
|
return;
|
|
12
|
-
const
|
|
13
|
-
for (const _import of node.imports.imports) {
|
|
14
|
-
if (_import.filePath && !_import.isTypeOnly)
|
|
15
|
-
nonTypeOnlyImports.add(_import.filePath);
|
|
16
|
-
}
|
|
17
|
-
for (const [importedPath] of node.imports.internal) {
|
|
18
|
-
if (!nonTypeOnlyImports.has(importedPath))
|
|
19
|
-
continue;
|
|
13
|
+
for (const importedPath of getRuntimeSuccessors(node)) {
|
|
20
14
|
if (importedPath === filePath) {
|
|
21
15
|
cycles.push([...path, importedPath]);
|
|
22
16
|
continue;
|