pkg-scaffold 3.2.0 → 3.3.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.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * ============================================================================
3
+ * Circular Dependency Detector for pkg-scaffold v3.3.0
4
+ *
5
+ * Copyright (C) 2026 DreamLongYT
6
+ * Licensed under the Apache License, Version 2.0.
7
+ * "The original code was from the lovely DreamLong"
8
+ * ============================================================================
9
+ * Implements a high-performance Tarjan-based or DFS-based algorithm to
10
+ * detect circular dependencies in the codebase graph.
11
+ * Addresses Knip Issue #1734.
12
+ */
13
+
14
+ export class CircularDetector {
15
+ constructor(context) {
16
+ this.context = context;
17
+ this.cycles = [];
18
+ }
19
+
20
+ /**
21
+ * Detects cycles in the provided dependency graph
22
+ * @param {Map} graph - The codebase dependency graph
23
+ * @returns {Array} List of detected cycles
24
+ */
25
+ detectCycles(graph) {
26
+ this.cycles = [];
27
+ const visited = new Set();
28
+ const stack = new Set();
29
+ const path = [];
30
+
31
+ for (const filePath of graph.keys()) {
32
+ if (!visited.has(filePath)) {
33
+ this.dfs(filePath, graph, visited, stack, path);
34
+ }
35
+ }
36
+
37
+ return this.cycles;
38
+ }
39
+
40
+ dfs(node, graph, visited, stack, path) {
41
+ visited.add(node);
42
+ stack.add(node);
43
+ path.push(node);
44
+
45
+ const edges = graph.get(node)?.outgoingEdges || [];
46
+ for (const neighbor of edges) {
47
+ if (stack.has(neighbor)) {
48
+ // Cycle detected
49
+ const cycleStartIndex = path.indexOf(neighbor);
50
+ const cycle = path.slice(cycleStartIndex);
51
+ this.cycles.push(cycle);
52
+ } else if (!visited.has(neighbor)) {
53
+ this.dfs(neighbor, graph, visited, stack, path);
54
+ }
55
+ }
56
+
57
+ stack.delete(node);
58
+ path.pop();
59
+ }
60
+
61
+ /**
62
+ * Formats cycles for reporting
63
+ */
64
+ formatCycles() {
65
+ return this.cycles.map(cycle => {
66
+ return cycle.join(' -> ') + ' -> ' + cycle[0];
67
+ });
68
+ }
69
+ }
70
+
71
+ export default CircularDetector;
@@ -25,15 +25,25 @@ export class PathMapper {
25
25
  const rawText = await fs.readFile(configPath, 'utf8');
26
26
 
27
27
  // Strip inline single-line and block comments before parsing
28
- const jsonCleanText = rawText.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
28
+ // Improved regex to handle more edge cases in tsconfig comments
29
+ const jsonCleanText = rawText
30
+ .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1')
31
+ .replace(/,(\s*[\]}])/g, '$1'); // Remove trailing commas
32
+
29
33
  const tsconfig = JSON.parse(jsonCleanText);
30
34
 
31
35
  if (!tsconfig.compilerOptions) return;
32
36
 
33
37
  const opts = tsconfig.compilerOptions;
38
+
39
+ // v6 Path Resolution Fix (Knip Issue #1794)
40
+ // Ensure baseUrl is correctly resolved relative to the tsconfig file location
41
+ const configDir = path.dirname(configPath);
34
42
  if (opts.baseUrl) {
35
43
  this.baseUrl = opts.baseUrl;
36
- this.absoluteBaseUrl = path.resolve(this.context.cwd, this.baseUrl);
44
+ this.absoluteBaseUrl = path.resolve(configDir, this.baseUrl);
45
+ } else {
46
+ this.absoluteBaseUrl = configDir;
37
47
  }
38
48
 
39
49
  if (opts.paths) {
@@ -21,6 +21,16 @@ export class WorkspaceGraph {
21
21
  const pnpmWorkspacePath = path.join(this.context.cwd, 'pnpm-workspace.yaml');
22
22
 
23
23
  let workspaceGlobs = [];
24
+ this.hoistedDependencies = new Set();
25
+
26
+ // Load hoisted dependencies from root package.json (Knip Issue #1792 fix)
27
+ try {
28
+ const rootPkg = JSON.parse(await fs.readFile(rootPackageJsonPath, 'utf8'));
29
+ const deps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
30
+ Object.keys(deps).forEach(d => this.hoistedDependencies.add(d));
31
+ } catch (e) {
32
+ // No root package.json or unreadable
33
+ }
24
34
 
25
35
  // Protocol A: Check for pnpm workspace configurations
26
36
  try {