knip 5.46.3 → 5.46.5
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 +1 -1
- package/dist/ConfigurationChief.js +14 -6
- package/dist/PrincipalFactory.js +3 -5
- package/dist/WorkspaceWorker.js +2 -1
- package/dist/compilers/compilers.d.ts +1 -1
- package/dist/compilers/compilers.js +3 -3
- package/dist/compilers/vue.js +2 -2
- package/dist/util/create-workspace-graph.d.ts +1 -1
- package/dist/util/create-workspace-graph.js +2 -2
- package/dist/util/graph-sequencer.d.ts +9 -0
- package/dist/util/graph-sequencer.js +94 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
|
@@ -38,7 +38,7 @@ export declare class ConfigurationChief {
|
|
|
38
38
|
availableWorkspaceNames: string[];
|
|
39
39
|
availableWorkspacePkgNames: Set<string>;
|
|
40
40
|
availableWorkspaceDirs: string[];
|
|
41
|
-
workspaceGraph: WorkspaceGraph
|
|
41
|
+
workspaceGraph: WorkspaceGraph;
|
|
42
42
|
includedWorkspaces: Workspace[];
|
|
43
43
|
resolvedConfigFilePath?: string;
|
|
44
44
|
rawConfig?: any;
|
|
@@ -4,13 +4,14 @@ import { partitionCompilers } from './compilers/index.js';
|
|
|
4
4
|
import { DEFAULT_EXTENSIONS, KNIP_CONFIG_LOCATIONS, ROOT_WORKSPACE_NAME } from './constants.js';
|
|
5
5
|
import { knipConfigurationSchema } from './schema/configuration.js';
|
|
6
6
|
import { pluginNames } from './types/PluginNames.js';
|
|
7
|
-
import { arrayify, compact } from './util/array.js';
|
|
7
|
+
import { arrayify, compact, partition } from './util/array.js';
|
|
8
8
|
import parsedArgValues from './util/cli-arguments.js';
|
|
9
9
|
import { createWorkspaceGraph } from './util/create-workspace-graph.js';
|
|
10
10
|
import { ConfigurationError } from './util/errors.js';
|
|
11
11
|
import { findFile, isDirectory, isFile, loadJSON } from './util/fs.js';
|
|
12
12
|
import { getIncludedIssueTypes } from './util/get-included-issue-types.js';
|
|
13
13
|
import { _dirGlob } from './util/glob.js';
|
|
14
|
+
import { graphSequencer } from './util/graph-sequencer.js';
|
|
14
15
|
import { defaultRules } from './util/issue-initializers.js';
|
|
15
16
|
import { _load } from './util/loader.js';
|
|
16
17
|
import mapWorkspaces from './util/map-workspaces.js';
|
|
@@ -63,7 +64,7 @@ export class ConfigurationChief {
|
|
|
63
64
|
availableWorkspaceNames = [];
|
|
64
65
|
availableWorkspacePkgNames = new Set();
|
|
65
66
|
availableWorkspaceDirs = [];
|
|
66
|
-
workspaceGraph;
|
|
67
|
+
workspaceGraph = new Map();
|
|
67
68
|
includedWorkspaces = [];
|
|
68
69
|
resolvedConfigFilePath;
|
|
69
70
|
rawConfig;
|
|
@@ -205,7 +206,12 @@ export class ConfigurationChief {
|
|
|
205
206
|
!picomatch.isMatch(name, this.ignoredWorkspacePatterns)));
|
|
206
207
|
}
|
|
207
208
|
getAvailableWorkspaceNames(names) {
|
|
208
|
-
|
|
209
|
+
const availableWorkspaceNames = [];
|
|
210
|
+
for (const name of names) {
|
|
211
|
+
if (!picomatch.isMatch(name, this.ignoredWorkspacePatterns))
|
|
212
|
+
availableWorkspaceNames.push(name);
|
|
213
|
+
}
|
|
214
|
+
return availableWorkspaceNames;
|
|
209
215
|
}
|
|
210
216
|
getIncludedWorkspaces() {
|
|
211
217
|
if (this.workspace) {
|
|
@@ -237,9 +243,9 @@ export class ConfigurationChief {
|
|
|
237
243
|
const workspaceDirsWithDependents = new Set(initialWorkspaces);
|
|
238
244
|
const addDependents = (dir) => {
|
|
239
245
|
seen.add(dir);
|
|
240
|
-
|
|
246
|
+
const dirs = graph.get(dir);
|
|
247
|
+
if (!dirs || dirs.size === 0)
|
|
241
248
|
return;
|
|
242
|
-
const dirs = graph[dir];
|
|
243
249
|
if (initialWorkspaces.some(dir => dirs.has(dir)))
|
|
244
250
|
workspaceDirsWithDependents.add(dir);
|
|
245
251
|
for (const dir of dirs)
|
|
@@ -281,7 +287,9 @@ export class ConfigurationChief {
|
|
|
281
287
|
return this.workspacePackages.get(name)?.manifest;
|
|
282
288
|
}
|
|
283
289
|
getWorkspaces() {
|
|
284
|
-
|
|
290
|
+
const sorted = graphSequencer(this.workspaceGraph, this.includedWorkspaces.map(workspace => workspace.dir));
|
|
291
|
+
const [root, rest] = partition(sorted.chunks.flat(), dir => dir === this.cwd);
|
|
292
|
+
return [...root, ...rest.reverse()].map(dir => this.includedWorkspaces.find(w => w.dir === dir));
|
|
285
293
|
}
|
|
286
294
|
getDescendentWorkspaces(name) {
|
|
287
295
|
return this.availableWorkspaceNames
|
package/dist/PrincipalFactory.js
CHANGED
|
@@ -22,16 +22,14 @@ export class PrincipalFactory {
|
|
|
22
22
|
options.compilerOptions = mergePaths(cwd, compilerOptions, paths);
|
|
23
23
|
if (isFile && compilerOptions.module !== ts.ModuleKind.CommonJS)
|
|
24
24
|
compilerOptions.moduleResolution ??= ts.ModuleResolutionKind.Bundler;
|
|
25
|
-
const principal = this.findReusablePrincipal(
|
|
25
|
+
const principal = this.findReusablePrincipal(compilerOptions);
|
|
26
26
|
if (!isIsolateWorkspaces && principal) {
|
|
27
27
|
this.linkPrincipal(principal, cwd, compilerOptions, pkgName, compilers);
|
|
28
28
|
return principal.principal;
|
|
29
29
|
}
|
|
30
30
|
return this.addNewPrincipal(options);
|
|
31
31
|
}
|
|
32
|
-
findReusablePrincipal(
|
|
33
|
-
if (compilerOptions.rootDir && cwd !== compilerOptions.rootDir)
|
|
34
|
-
return;
|
|
32
|
+
findReusablePrincipal(compilerOptions) {
|
|
35
33
|
const workspacePaths = compilerOptions?.paths ? Object.keys(compilerOptions.paths) : [];
|
|
36
34
|
const principal = Array.from(this.principals).find(principal => {
|
|
37
35
|
if (compilerOptions.pathsBasePath && principal.principal.compilerOptions.pathsBasePath)
|
|
@@ -63,7 +61,7 @@ export class PrincipalFactory {
|
|
|
63
61
|
return principal;
|
|
64
62
|
}
|
|
65
63
|
getPrincipals() {
|
|
66
|
-
return Array.from(this.principals, p => p.principal)
|
|
64
|
+
return Array.from(this.principals, p => p.principal);
|
|
67
65
|
}
|
|
68
66
|
getPrincipalByPackageName(packageName) {
|
|
69
67
|
return Array.from(this.principals).find(principal => principal.pkgNames.has(packageName))?.principal;
|
package/dist/WorkspaceWorker.js
CHANGED
|
@@ -123,7 +123,8 @@ export class WorkspaceWorker {
|
|
|
123
123
|
return patterns;
|
|
124
124
|
}
|
|
125
125
|
getPluginEntryFilePatterns(patterns) {
|
|
126
|
-
|
|
126
|
+
const negateWorkspaces = patterns.some(pattern => pattern.startsWith('**/')) ? this.negatedWorkspacePatterns : [];
|
|
127
|
+
return [patterns, negateWorkspaces, this.ignoredWorkspacePatterns.map(negate)].flat();
|
|
127
128
|
}
|
|
128
129
|
getProductionEntryFilePatterns(negatedTestFilePatterns) {
|
|
129
130
|
const entry = this.config.entry.filter(hasProductionSuffix);
|
|
@@ -2,4 +2,4 @@ import type { SyncCompilerFn } from './types.js';
|
|
|
2
2
|
export declare const fencedCodeBlockMatcher: RegExp;
|
|
3
3
|
export declare const importMatcher: RegExp;
|
|
4
4
|
export declare const importsWithinScripts: SyncCompilerFn;
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const scriptBodies: SyncCompilerFn;
|
|
@@ -11,11 +11,11 @@ export const importsWithinScripts = (text) => {
|
|
|
11
11
|
}
|
|
12
12
|
return scripts.join(';\n');
|
|
13
13
|
};
|
|
14
|
-
const
|
|
15
|
-
export const
|
|
14
|
+
const scriptBodyExtractor = /<script\b[^>]*>(?<body>[\s\S]*?)<\/script>/gm;
|
|
15
|
+
export const scriptBodies = (text) => {
|
|
16
16
|
const scripts = [];
|
|
17
17
|
let scriptMatch;
|
|
18
|
-
while ((scriptMatch =
|
|
18
|
+
while ((scriptMatch = scriptBodyExtractor.exec(text))) {
|
|
19
19
|
if (scriptMatch.groups?.body)
|
|
20
20
|
scripts.push(scriptMatch.groups.body);
|
|
21
21
|
}
|
package/dist/compilers/vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { scriptBodies } from './compilers.js';
|
|
2
2
|
const condition = (hasDependency) => hasDependency('vue') || hasDependency('nuxt');
|
|
3
|
-
const compiler =
|
|
3
|
+
const compiler = scriptBodies;
|
|
4
4
|
export default { condition, compiler };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { WorkspacePackage } from '../types/package-json.js';
|
|
2
|
-
export type WorkspaceGraph =
|
|
2
|
+
export type WorkspaceGraph = Map<string, Set<string>>;
|
|
3
3
|
export declare function createWorkspaceGraph(cwd: string, wsNames: string[], wsPkgNames: Set<string>, wsPackages: Map<string, WorkspacePackage>): WorkspaceGraph;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join } from './path.js';
|
|
2
2
|
const types = ['peerDependencies', 'devDependencies', 'optionalDependencies', 'dependencies'];
|
|
3
3
|
export function createWorkspaceGraph(cwd, wsNames, wsPkgNames, wsPackages) {
|
|
4
|
-
const graph =
|
|
4
|
+
const graph = new Map();
|
|
5
5
|
const packages = Array.from(wsPackages.values());
|
|
6
6
|
const getWorkspaceDirs = (pkg) => {
|
|
7
7
|
const dirs = new Set();
|
|
@@ -21,7 +21,7 @@ export function createWorkspaceGraph(cwd, wsNames, wsPkgNames, wsPackages) {
|
|
|
21
21
|
for (const name of wsNames) {
|
|
22
22
|
const pkg = wsPackages.get(name);
|
|
23
23
|
if (pkg)
|
|
24
|
-
graph
|
|
24
|
+
graph.set(join(cwd, name), getWorkspaceDirs(pkg));
|
|
25
25
|
}
|
|
26
26
|
return graph;
|
|
27
27
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export function graphSequencer(graph, includedNodes = [...graph.keys()]) {
|
|
2
|
+
const reverseGraph = new Map();
|
|
3
|
+
for (const key of graph.keys()) {
|
|
4
|
+
reverseGraph.set(key, []);
|
|
5
|
+
}
|
|
6
|
+
const nodes = new Set(includedNodes);
|
|
7
|
+
const visited = new Set();
|
|
8
|
+
const outDegree = new Map();
|
|
9
|
+
for (const [from, edges] of graph.entries()) {
|
|
10
|
+
outDegree.set(from, 0);
|
|
11
|
+
for (const to of edges) {
|
|
12
|
+
if (nodes.has(from) && nodes.has(to)) {
|
|
13
|
+
changeOutDegree(from, 1);
|
|
14
|
+
reverseGraph.get(to).push(from);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (!nodes.has(from)) {
|
|
18
|
+
visited.add(from);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const chunks = [];
|
|
22
|
+
const cycles = [];
|
|
23
|
+
let safe = true;
|
|
24
|
+
while (nodes.size) {
|
|
25
|
+
const chunk = [];
|
|
26
|
+
let minDegree = Number.MAX_SAFE_INTEGER;
|
|
27
|
+
for (const node of nodes) {
|
|
28
|
+
const degree = outDegree.get(node);
|
|
29
|
+
if (degree === 0) {
|
|
30
|
+
chunk.push(node);
|
|
31
|
+
}
|
|
32
|
+
minDegree = Math.min(minDegree, degree);
|
|
33
|
+
}
|
|
34
|
+
if (minDegree === 0) {
|
|
35
|
+
chunk.forEach(removeNode);
|
|
36
|
+
chunks.push(chunk);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const cycleNodes = [];
|
|
40
|
+
for (const node of nodes) {
|
|
41
|
+
const cycle = findCycle(node);
|
|
42
|
+
if (cycle.length) {
|
|
43
|
+
cycles.push(cycle);
|
|
44
|
+
cycle.forEach(removeNode);
|
|
45
|
+
cycleNodes.push(...cycle);
|
|
46
|
+
if (cycle.length > 1) {
|
|
47
|
+
safe = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
chunks.push(cycleNodes);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { safe, chunks, cycles };
|
|
55
|
+
function changeOutDegree(node, value) {
|
|
56
|
+
const degree = outDegree.get(node) ?? 0;
|
|
57
|
+
outDegree.set(node, degree + value);
|
|
58
|
+
}
|
|
59
|
+
function removeNode(node) {
|
|
60
|
+
for (const from of reverseGraph.get(node)) {
|
|
61
|
+
changeOutDegree(from, -1);
|
|
62
|
+
}
|
|
63
|
+
visited.add(node);
|
|
64
|
+
nodes.delete(node);
|
|
65
|
+
}
|
|
66
|
+
function findCycle(startNode) {
|
|
67
|
+
const queue = [[startNode, [startNode]]];
|
|
68
|
+
const cycleVisited = new Set();
|
|
69
|
+
const cycles = [];
|
|
70
|
+
while (queue.length) {
|
|
71
|
+
const [id, cycle] = queue.shift();
|
|
72
|
+
const nodes = graph.get(id);
|
|
73
|
+
if (!nodes)
|
|
74
|
+
continue;
|
|
75
|
+
for (const to of nodes) {
|
|
76
|
+
if (to === startNode) {
|
|
77
|
+
cycleVisited.add(to);
|
|
78
|
+
cycles.push([...cycle]);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (visited.has(to) || cycleVisited.has(to)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
cycleVisited.add(to);
|
|
85
|
+
queue.push([to, [...cycle, to]]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!cycles.length) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
cycles.sort((a, b) => b.length - a.length);
|
|
92
|
+
return cycles[0];
|
|
93
|
+
}
|
|
94
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "5.46.
|
|
1
|
+
export declare const version = "5.46.5";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '5.46.
|
|
1
|
+
export const version = '5.46.5';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "5.46.
|
|
3
|
+
"version": "5.46.5",
|
|
4
4
|
"description": "Find and fix unused files, dependencies and exports in your TypeScript and JavaScript projects",
|
|
5
5
|
"homepage": "https://knip.dev",
|
|
6
6
|
"repository": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@nodelib/fs.walk": "3.0.1",
|
|
63
63
|
"@snyk/github-codeowners": "1.1.0",
|
|
64
64
|
"easy-table": "1.2.0",
|
|
65
|
-
"enhanced-resolve": "^5.18.
|
|
65
|
+
"enhanced-resolve": "^5.18.1",
|
|
66
66
|
"fast-glob": "^3.3.3",
|
|
67
67
|
"jiti": "^2.4.2",
|
|
68
68
|
"js-yaml": "^4.1.0",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@jest/types": "^29.6.3",
|
|
85
85
|
"@release-it/bumper": "^7.0.2",
|
|
86
|
-
"@types/bun": "1.2.
|
|
86
|
+
"@types/bun": "1.2.8",
|
|
87
87
|
"@types/js-yaml": "^4.0.9",
|
|
88
88
|
"@types/minimist": "^1.2.5",
|
|
89
89
|
"@types/picomatch": "3.0.1",
|