Skip to content

fix(export): honor --functions for json and graphson formats - #2141

Merged
carlos-alm merged 9 commits into
mainfrom
fix/export-functions-json-graphson
Jul 20, 2026
Merged

fix(export): honor --functions for json and graphson formats#2141
carlos-alm merged 9 commits into
mainfrom
fix/export-functions-json-graphson

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

codegraph export -f json --functions and -f graphson --functions silently ignored the --functions flag, always returning file-level output (json) or a fixed mixed-kind shape (graphson) — the only two of the six export formats that didn't branch on opts.fileLevel, unlike dot/mermaid/graphml/neo4j which already did.

Found during

Dogfooding v3.16.0 — see #2136

Test plan

  • npx vitest run tests/graph/export.test.ts — 35/35 passing (added 3 new cases covering fileLevel vs functions for both formats)
  • npx vitest run tests/integration/exports.test.ts tests/unit/index-exports.test.ts — 26/26 passing
  • Manually verified codegraph export -f json --functions and -f graphson --functions now produce distinct, correctly-scoped output against a real build

exportJSON and exportGraphSON ignored opts.fileLevel entirely, always
returning file-level (json) or a fixed all-kinds (graphson) shape
regardless of --functions. dot/mermaid/graphml/neo4j already branched
on fileLevel correctly.

Closes #2136

Impact: 2 functions changed, 2 affected
@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a longstanding bug where --functions (fileLevel: false) was silently ignored by exportJSON and exportGraphSON — the only two of six export formats that didn't branch on opts.fileLevel. Both functions now follow the same pattern as exportDOT, exportMermaid, exportGraphML, and exportNeo4jCSV.

  • exportJSON: adds a fileLevel branch; the default path is unchanged, and the new function-level path mirrors loadFunctionLevelEdges semantics (nodes as numeric IDs in edges, scoped to calls relationships).
  • exportGraphSON: adds a fileLevel branch; the default file-level path now returns only file vertices connected by file-file edges (replacing the previous mixed-kind dump), and the new function-level path surfaces per-function/class vertices with their calls edges.
  • Tests: three new test cases cover the new fileLevel: false paths, and three existing GraphSON tests are updated to pass { fileLevel: false } explicitly to match the corrected default behaviour.

Confidence Score: 5/5

Safe to merge — the fix is a straightforward application of the branching pattern already proven across four other exporters, and all 35 export tests pass.

The change adds a missing code path rather than touching existing behaviour. The new function-level branches use the same shared loaders and paginateResult plumbing as every other exporter, and the updated tests explicitly guard the corrected defaults.

No files require special attention.

Important Files Changed

Filename Overview
src/features/export.ts Adds fileLevel branching to exportJSON and exportGraphSON, mirroring the pattern already used by the other four exporters. Logic is correct; minor inconsistencies in limit forwarding and duplicated nodeMap building are style items.
tests/graph/export.test.ts Adds three new test cases (two for JSON, one for GraphSON) covering the fileLevel: false path, and updates three existing GraphSON tests to explicitly pass { fileLevel: false } to match the now-correct default behaviour.

Reviews (7): Last reviewed commit: "fix(export): align exportGraphSON functi..." | Re-trigger Greptile

Comment on lines +268 to +272
const data = exportJSON(db, { fileLevel: false });
expect(data.nodes.every((n) => n.kind !== 'file')).toBe(true);
expect(data.nodes.some((n) => n.name === 'doWork')).toBe(true);
expect(data.edges.some((e) => e.source === fn && e.target === fn2)).toBe(true);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing db.close() in the first new JSON test leaves an open in-memory database handle. Every surrounding test does close its db; this one should too.

Suggested change
const data = exportJSON(db, { fileLevel: false });
expect(data.nodes.every((n) => n.kind !== 'file')).toBe(true);
expect(data.nodes.some((n) => n.name === 'doWork')).toBe(true);
expect(data.edges.some((e) => e.source === fn && e.target === fn2)).toBe(true);
});
const data = exportJSON(db, { fileLevel: false });
expect(data.nodes.every((n) => n.kind !== 'file')).toBe(true);
expect(data.nodes.some((n) => n.name === 'doWork')).toBe(true);
expect(data.edges.some((e) => e.source === fn && e.target === fn2)).toBe(true);
db.close();
});

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added the missing db.close() to this test to match its sibling tests.

…s from v3.16.0 session

- benchmark scripts are .ts, not .js; note npm run benchmark alias and
  git fetch --tags requirement for correct version labeling
- warn against running registry prune --ttl 0 against the real global
  registry; recommend CODEGRAPH_REGISTRY_PATH isolation instead
- warn about update-graph.sh hook contamination risk from scratch files
  with tracked extensions
- recommend copying .codegraphrc.json aside before editing it in place
  and testing config-driven commands from a different cwd than the target
- recommend full edge-set diffs (not just counts) for incremental rebuild
  verification — this is what caught #2138 in the v3.16.0 session
@github-actions

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

2 functions changed2 callers affected across 2 files

  • exportJSON in src/features/export.ts:330 (2 transitive callers)
  • exportGraphSON in src/features/export.ts:430 (2 transitive callers)

@carlos-alm

Copy link
Copy Markdown
Contributor Author

Addressed Greptile's review feedback:

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

carlos-alm and others added 2 commits July 20, 2026 11:07
…mats

The function-level (--functions) branch retained pre-existing behavior
that queried all non-file nodes independently of edges (including
isolated nodes with no calls) and included every edge kind (inherits,
implements, imports, etc.), not just calls. dot/mermaid/graphml/neo4j
all already use loadFunctionLevelEdges for this scope. Now graphson
does too, so all five function-level exporters agree on scope: calls
edges only, nodes limited to those participating in at least one call.

Impact: 1 functions changed, 2 affected
@carlos-alm

Copy link
Copy Markdown
Contributor Author

Follow-up fix pushed (2348999): the exportGraphSON function-level (--functions) branch — which Greptile's summary above accurately described as retaining the original per-node-kind SQL (all edge kinds, including isolated nodes) rather than using loadFunctionLevelEdges — has been updated to use loadFunctionLevelEdges, matching exportJSON/DOT/Mermaid/GraphML/Neo4j. Now all five function-level exporters agree: calls-only edges, and only nodes that participate in at least one call (no implements/inherits/imports edges, no isolated nodes). Added a regression test asserting this scope. Not re-triggering Greptile since this refinement was independently identified outside of Greptile's own review (which already scored this PR 5/5 / safe to merge).

@carlos-alm
carlos-alm merged commit 1687729 into main Jul 20, 2026
12 checks passed
@carlos-alm
carlos-alm deleted the fix/export-functions-json-graphson branch July 20, 2026 23:37
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant