pnpm-viz 1.0.2 → 1.0.4

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.
@@ -25,14 +25,31 @@ export async function startServer(projectPath, port = 3000) {
25
25
  }
26
26
  return;
27
27
  }
28
+ // Helper to check if file exists
29
+ const fileExists = (p) => fs.existsSync(p) && fs.lstatSync(p).isFile();
28
30
  // Static File Serving
29
- let filePath = path.join(WEB_ROOT, req.url === '/' ? 'index.html' : req.url || 'index.html');
30
- // Security check to prevent directory traversal
31
+ let requestUrl = req.url === '/' ? '/index.html' : req.url || '/index.html';
32
+ // Remove query params
33
+ requestUrl = requestUrl.split('?')[0];
34
+ // Map /assets requests correctly if needed, but Vite puts them in assets/
35
+ // If request is like /assets/main.js, it should map to dist/web/assets/main.js
36
+ let filePath = path.join(WEB_ROOT, requestUrl);
37
+ // Security check
31
38
  if (!filePath.startsWith(WEB_ROOT)) {
32
39
  res.writeHead(403);
33
40
  res.end('Forbidden');
34
41
  return;
35
42
  }
43
+ // If file doesn't exist, try index.html (SPA Fallback)
44
+ if (!fileExists(filePath)) {
45
+ // If it looks like an asset request (has extension), might be 404
46
+ if (path.extname(filePath)) {
47
+ res.writeHead(404);
48
+ res.end('Not Found');
49
+ return;
50
+ }
51
+ filePath = path.join(WEB_ROOT, 'index.html');
52
+ }
36
53
  const extname = path.extname(filePath);
37
54
  let contentType = 'text/html';
38
55
  switch (extname) {
@@ -54,27 +71,14 @@ export async function startServer(projectPath, port = 3000) {
54
71
  case '.svg':
55
72
  contentType = 'image/svg+xml';
56
73
  break;
74
+ case '.ico':
75
+ contentType = 'image/x-icon';
76
+ break;
57
77
  }
58
78
  fs.readFile(filePath, (error, content) => {
59
79
  if (error) {
60
- if (error.code === 'ENOENT') {
61
- // SPA Fallback necessary? React Router? Not using router yet.
62
- // basic fallback
63
- fs.readFile(path.join(WEB_ROOT, 'index.html'), (err, content) => {
64
- if (err) {
65
- res.writeHead(404);
66
- res.end('Not Found');
67
- }
68
- else {
69
- res.writeHead(200, { 'Content-Type': 'text/html' });
70
- res.end(content, 'utf-8');
71
- }
72
- });
73
- }
74
- else {
75
- res.writeHead(500);
76
- res.end('Server Error: ' + error.code);
77
- }
80
+ res.writeHead(500);
81
+ res.end('Server Error: ' + error.code);
78
82
  }
79
83
  else {
80
84
  res.writeHead(200, { 'Content-Type': contentType });
@@ -112,6 +112,24 @@ export class LockfileParser {
112
112
  }
113
113
  }
114
114
  }
115
+ // Post-processing: Ensure all edge targets exist as nodes
116
+ // This prevents Cytoscape from crashing
117
+ const existingNodeIds = new Set(Object.keys(graph.nodes));
118
+ for (const edge of graph.edges) {
119
+ if (!existingNodeIds.has(edge.target)) {
120
+ // Determine if we can resolve it to an existing node with a similar name?
121
+ // For now, create a placeholder node
122
+ graph.nodes[edge.target] = {
123
+ id: edge.target,
124
+ name: edge.target, // Fallback name
125
+ version: 'unknown',
126
+ path: 'virtual:' + edge.target,
127
+ dependencies: [],
128
+ isDev: false
129
+ };
130
+ existingNodeIds.add(edge.target);
131
+ }
132
+ }
115
133
  return graph;
116
134
  }
117
135
  processDeps(deps, parentId, graph, type) {