Skip to content

TS/JS: make barrel re-export bindings queryable nodes#250

Merged
zzet merged 1 commit into
mainfrom
feat/ts-barrel-reexport-nodes
Jul 4, 2026
Merged

TS/JS: make barrel re-export bindings queryable nodes#250
zzet merged 1 commit into
mainfrom
feat/ts-barrel-reexport-nodes

Conversation

@zzet

@zzet zzet commented Jul 4, 2026

Copy link
Copy Markdown
Owner

A JS/TS barrel (export { X } from './mod', optionally aliased) is the public API a consumer imports — but the extractor recorded re-exports only as file-level edges and minted no node for the forwarded binding, so querying the façade path an agent actually knows (src/middleware.ts::persist) returned a silent zero.

The extractor now mints a node at the barrel site under the exported (post-alias) name for each named value specifier within the cap, marked with a reexport flag plus a node→canonical forward edge resolved through the existing import machinery. find_usages on a re-export node returns its own direct refs (consumer imports binding to it) merged with the canonical declaration's usages by walking the forward edge, so the façade answers with the full usage set. Aliased re-exports mint under the alias; type-only re-exports stay reference edges and mint no value node; call resolution treats the node as a transparent forwarder.

A JS/TS barrel forwards another module's surface with
`export { X } from './mod'` (optionally `export { X as Y }`), and that is
the public API a consumer imports. Until now the extractor recorded a
re-export only as a file-level edge and minted no node for the forwarded
binding, so `find_usages("src/middleware.ts::persist")` resolved nothing —
querying the façade an agent actually imports returned a silent zero.

For each named value specifier within the cap the extractor now mints a
node at the barrel site under the exported (post-alias) name, following the
standard `<file>::<name>` id scheme, marked with a reexport flag and a
node->canonical re-export edge that resolves through the same import
machinery as the file-level edge. Aliased re-exports mint under the alias
name; type-only re-exports stay reference edges and mint no value node.

find_usages on a re-export node returns its own direct refs — consumer
imports that bind to it — merged with the canonical declaration's usages by
walking the forward edge, so the façade answers with the full usage set.
Call resolution treats a re-export node as a transparent forwarder and
skips it as a candidate, so a call still binds to the real declaration and
the canonical node's usages remain a superset of before.

Claude-Session: https://claude.ai/code/session_01SXwzimUB1ZVcBaGsC9qfZ5
@zzet zzet merged commit 5f64c80 into main Jul 4, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant