Summary
For CommonJS code, graphify resolves the import of a function but not calls through the imported binding. The result is that JavaScript projects get almost no calls edges, while the same analysis on other languages produces one to two orders of magnitude more.
Measurement
Same command on eight well-known repos (graphify <path> --code-only, then cluster-only --no-label). Call sites counted by walking each file's tree-sitter AST for the language's own call node type; call edges counted from graph.json:
| Repo |
Language |
Call sites |
calls edges |
ratio |
| JamesNK/Newtonsoft.Json |
C# |
48,070 |
13,487 |
28% |
| google/gson |
Java |
23,468 |
5,337 |
23% |
| spf13/cobra |
Go |
4,430 |
934 |
21% |
| BurntSushi/ripgrep |
Rust |
17,103 |
3,270 |
19% |
| psf/requests |
Python |
2,687 |
453 |
17% |
| gin-gonic/gin |
Go |
9,414 |
1,346 |
14% |
| pallets/flask |
Python |
3,963 |
386 |
10% |
| expressjs/express |
JavaScript |
11,733 |
63 |
1% |
express's whole graph contains 11 calls and 52 indirect_call edges across 404 nodes and 119 callable nodes.
Concrete case
expressjs/express at current HEAD:
// lib/utils.js:61
exports.normalizeType = function(type){ ... };
// lib/response.js:27
var normalizeType = require('./utils').normalizeType;
// lib/response.js:587
this.set('Content-Type', normalizeType(key).value);
Everything here is literal: a literal require path, a literal property, and a plain identifier call.
In the resulting graph.json, the node lib_utils_normalizetype has exactly two incoming edges:
response.js --imports--> normalizeType()
lib/utils.js --contains--> normalizeType()
There is no calls edge from lib/response.js to normalizeType(), even though the import was resolved correctly — so the resolver clearly knows where the symbol lives.
Expected
A calls edge from the calling function in lib/response.js to normalizeType() in lib/utils.js.
Why it matters
The import edge being present while the call edge is missing means the information needed to resolve the call is already available; only the call-site binding is not being made. Any consumer doing reachability or call-graph work on JavaScript gets a graph that is essentially call-free — a "no path found" result on a JS project currently means very little.
The var x = require('./m').x destructuring form is extremely common in CommonJS, so this is likely not an edge case.
Environment
- graphify
0.9.65 (PyPI graphifyy)
- Python 3.14, Windows 10
expressjs/express default branch, shallow clone 2026-09-22
Summary
For CommonJS code, graphify resolves the import of a function but not calls through the imported binding. The result is that JavaScript projects get almost no
callsedges, while the same analysis on other languages produces one to two orders of magnitude more.Measurement
Same command on eight well-known repos (
graphify <path> --code-only, thencluster-only --no-label). Call sites counted by walking each file's tree-sitter AST for the language's own call node type; call edges counted fromgraph.json:callsedgesexpress's whole graph contains 11
callsand 52indirect_calledges across 404 nodes and 119 callable nodes.Concrete case
expressjs/expressat current HEAD:Everything here is literal: a literal require path, a literal property, and a plain identifier call.
In the resulting
graph.json, the nodelib_utils_normalizetypehas exactly two incoming edges:There is no
callsedge fromlib/response.jstonormalizeType(), even though the import was resolved correctly — so the resolver clearly knows where the symbol lives.Expected
A
callsedge from the calling function inlib/response.jstonormalizeType()inlib/utils.js.Why it matters
The import edge being present while the call edge is missing means the information needed to resolve the call is already available; only the call-site binding is not being made. Any consumer doing reachability or call-graph work on JavaScript gets a graph that is essentially call-free — a "no path found" result on a JS project currently means very little.
The
var x = require('./m').xdestructuring form is extremely common in CommonJS, so this is likely not an edge case.Environment
0.9.65(PyPIgraphifyy)expressjs/expressdefault branch, shallow clone 2026-09-22