Repository navigation
package.json dependencies produce two unlinked nodes with the same label #4569
Description
Summary
For each entry under dependencies / devDependencies / peerDependencies, extractors/json_config.py emits two nodes with the same label:
- the generic key node
<stem>_dependencies_react, created bywalk_objectand reached throughdependencies --contains--> - the external ref node
ref_react, created by the dependency branch and reached throughpackage.json --imports-->
No edge connects them. Source files that import the package (import React from "react") resolve to ref_react, so the manifest's own entry for the dependency is cut off from the code that uses it.
Reproduction (graphifyy 0.9.84; json_config.py is identical in 0.9.92)
package.json:
{
"name": "demo",
"dependencies": {
"react": "^19.0.0"
}
}from pathlib import Path
from graphify.extractors.json_config import extract_json
r = extract_json(Path("package.json"))Nodes (stem shortened):
<stem>_package_json 'package.json' code
<stem>_package_name 'name' code
<stem>_package_dependencies 'dependencies' code
<stem>_package_dependencies_react 'react' code <- key node
ref_react 'react' concept <- ref node
Edges:
<stem>_package_json -contains-> <stem>_package_name
<stem>_package_json -contains-> <stem>_package_dependencies
<stem>_package_dependencies -contains-> <stem>_package_dependencies_react
<stem>_package_json -imports-> ref_react
Neither react node has an edge to the other.
Impact on a real graph
On a small Vite + React project, community detection put the two react nodes (and the two react-dom nodes) in different communities: the key nodes went to "package manifest" and the ref nodes to "SPA entry" with main.tsx. Each @types/* devDependency also got a near-isolated key node, so suggest_questions lists them as weakly connected ("possible documentation gaps"). Cross-community bridge scores for devDependencies / index.html are inflated by the split.
Cause
The #1764 fix (comment at the parent_key in _DEP_KEYS branch) moved the imports edge source from key_nid to file_nid, to avoid the self-referential-looking react --imports--> react. That edge was the only link between the key node and the ref node, so they are now disconnected.
Suggested fix
Link the two nodes again, with a relation that does not read as a self-import:
dep_nid = _make_id("ref", key)
if dep_nid:
add_node(dep_nid, key, line, file_type="concept")
add_edge(file_nid, dep_nid, "imports", line, context="import")
add_edge(key_nid, dep_nid, "declares", line) # reconnect the manifest entryThe node ids still differ, so the J-4 namespacing and the #1764 self-loop concern both hold. An alternative is to skip creating the key node for pairs under a _DEP_KEYS parent, so that ref_* is the only node per dependency, but that drops the version-range location.
Activity
github-actions commentedon Oct 19, 2026
Thanks for opening this issue, @BiSide. A maintainer will take a look soon.
If you would like to discuss it in real time, come say hi on our Discord server. For longer-form questions and ideas there is also GitHub Discussions.
To help us triage, please make sure the report includes what you expected, what actually happened, and the steps (and a small sample) to reproduce it.
fix(json_config): link a package.json dependency's manifest entry to …
test(json_config): a package.json dependency's manifest entry is link…