Repository navigation
feat(vue): put the Vue component contract in the graph — API, template bindings, cross-file types - #3135
Open
yanhongwang1017 wants to merge 1 commit into
Open
feat(vue): put the Vue component contract in the graph — API, template bindings, cross-file types#3135yanhongwang1017 wants to merge 1 commit into
yanhongwang1017 wants to merge 1 commit into
Conversation
…e bindings, cross-file types CodeGraph indexed Vue SFCs as generic source files, but the component contract — what an agent actually needs before building with or refactoring a component — was not in the graph at all. "What props does this component take?", "who handles this emit?", "which parents render it?" could not be answered from the graph: the agent fell back to reading .vue source (or hallucinated an interface), which is exactly the Read-displacement codegraph exists to prevent. This adds the missing semantic layer end to end: Component API extraction (vue-extractor, rewritten): - Script blocks are parsed with @vue/compiler-sfc parse plus a dedicated @babel/parser pass — compileScript strips withDefaults(defineProps<T>()) type arguments, so macro types must be read pre-transform. - props (name, type, required, default, leading JSDoc), emits with payload types, slots, and exposed members land on the component node as metadata.componentApi. defineProps/withDefaults/defineEmits/ defineSlots/defineExpose in both type and runtime form, plus Options API props/emits. - Cross-file types: defineProps<ImportedType>() members are pulled from the declaring file — relative paths, tsconfig paths aliases, extends chains, import-rename (lookup name vs declaration name), and diamond dedup so a base reached through two branches shows up once. Types the extractor cannot follow keep the written text; it never guesses. - Cross-file reads go through validatePathWithinRoot: an import that escapes the root (`../`, an absolute path, a Windows //host/share) or an in-root symlink pointing outside it is skipped, not read. Template wiring as graph edges: - Every @event="handler" on a component tag becomes a references edge from the component to the handler function (metadata.vueEvent / .vueComponent), kebab-case tags included — callers, impact and the component view now see which functions a template drives. - <ChildComp> template usage yields component-reference edges, so who-renders-whom is a graph query, surfaced by explore's dynamic-dispatch section. MCP surface: - New codegraph_component tool, opt-in via CODEGRAPH_MCP_TOOLS=component: the full contract in one call — API, child components it renders, and every parent @event binding attached to it, so changing an emit shows exactly which parent handlers break. It stays off the default face, so the single-tool server instructions are unchanged. Storage and parse infrastructure: - nodes.metadata column with a guarded migration (NULL means "not extracted yet"; fills as files re-index). All three node write paths and rowToNode carry it. - Project-root hint threaded into parse workers (and set for in-process parses) so sibling-file type resolution works off-thread. Tests: new vue-component-api / vue-component-bindings / vue-component-types suites; mcp-tool-allowlist pins the default face to explore and covers the component opt-in.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
New PR — body (paste into GitHub)
Base:
colbymchenry:main← head:yanhongwang1017:vue-component-contractTitle:
feat(vue): put the Vue component contract in the graph — API, template bindings, cross-file typesThis is a fresh take on #1858 (closed with direction from @colbymchenry), rebased onto current
mainand reworked around the three points raised there.What it does. CodeGraph indexes Vue SFCs as generic source files, so the component contract — what an agent needs before building with or refactoring a component — was not in the graph. Questions like "what props does this component take?", "who handles this emit?", "which parents render it?" forced a Read of the .vue source (or a guess). This adds the missing layer:
props(name, type, required, default, leading JSDoc),emits(payload types),slotsandexposedland on the component node asmetadata.componentApi, fordefineProps/withDefaults/defineEmits/defineSlots/defineExpose(type and runtime form) plus Options APIprops/emits.defineProps<ImportedType>()members are pulled from the declaring file: relative imports, tsconfigpathsaliases,extendschains, import-rename, diamond dedup. A type it cannot follow keeps the written text; it never guesses.@event="handler"on a component tag becomes areferencesedge to the handler function (metadata.vueEvent/.vueComponent);<ChildComp>usage yields component-reference edges.codegraph_component— one call returns the contract: API, children, and the parents that bind it. Opt-in viaCODEGRAPH_MCP_TOOLS=component; the default tool surface is unchanged (explore only).nodes.metadatawith a guarded migration (NULL = "not extracted yet"; fills on re-index).The three points from #1858:
lexicalPathWithinRoot(refuses../, absolute paths outside the root, and a Windows//host/sharewith no syscall) andvalidatePathWithinRoot(realpath, so an in-root symlink pointing outside is never read). Without a root hint, cross-file expansion is skipped entirely. Tests cover relative/absolute/UNC escapes and the symlink case.codegraph_componentis not inDEFAULT_MCP_TOOLS; it appears only when the operator lists it inCODEGRAPH_MCP_TOOLS.server-instructions.tsis untouched — no agent-facing guidance to runcodegraph init.package-lock.jsonresolves every package fromregistry.npmjs.org. The two new dependencies are@vue/compiler-sfcand@babel/parser(deliberately notvue-component-meta, which does not surface the per-member docs and written-type fidelity this keeps).Validation.
npm run buildpasses. The Vue suites (API / bindings / types) and the tool-allowlist suite are green (31 tests), including the new path-escape and opt-in tests. Full suite on this branch: 9,878 pass; the only failures are 30installer-targetstests, which reproduce identically on a pristinemaincheckout in the same environment and are not caused by this diff.Known limitations (pinned by tests):
defineSlotstypes expand only same-file; complex TS (utility/generic/conditional types) keeps the written text.Supersedes #1858.