feat: add GraphQL SDL importer (graphqlerd.py) (#121) - #131
Conversation
Parses GraphQL SDL (.graphql / .gql) or an introspection JSON dump into an entity type diagram: one node per type, interface, input, enum, union or custom scalar, listing each field with its type and marking @deprecated, with edges for field references, implements and union membership. The parser is stdlib-only. Enums and custom scalars are dimmed rather than unlinked, and --group buckets types by the schema file they came from. Registered in SKILL.md, toolbox.md, cookbook.md, diagram-ir.md, mcp.md, both READMEs and the CHANGELOG, and wired into diagramctl build and the MCP server with .graphql/.gql auto-detection.
parse_sdl emits one entry per "extend" definition, so a schema with both "type Foo" and "extend type Foo" produced two nodes with the same id and diagramctl build failed validation with E-DUP-ID. merge_extends now folds same-name definitions (fields, implements, union members) into the base entry before the graph is built, covering extends that arrive from a different schema file too. The CLI summary line now counts merged types. Also guards the re.match in the implements scan (Optional per the type stubs) and adds regression tests for in-file and cross-file extends.
|
Reviewed end to end and found one real bug, now fixed in ccb3e09 (pushed to this branch):
Everything else checked out: all registration points (SKILL.md, toolbox.md, cookbook.md, diagram-ir.md, mcp.md, both READMEs, CHANGELOG under |
- CHANGELOG: cut 3.4.0 (GraphQL importer Agents365-ai#131, rendered-output pitfalls Agents365-ai#132, 365-skills distribution removed Agents365-ai#133) - SKILL.md metadata.version 3.3.0 -> 3.4.0 - tests: align hardcoded declared version
Fixes #121.
Adds
graphqlerd.py, a GraphQL SDL importer that emits the skill's autolayout graph JSON, following the shapeprotoimports.pyestablished in #128.What it does
One node per
type,interface,input,enum,unionor customscalar, each listing its fields with types and marking@deprecated. Edges for field references (labelled with the field name),implements, and union membership.Two input modes. SDL from a
.graphql/.gqlfile or a directory, and an introspection JSON dump.The parser is stdlib-only, no
graphql-core. It handles descriptions, comments, field arguments with defaults, list and non-null wrappers, directives andextend. Anything it does not recognise is skipped rather than guessed at, so the worst case is a missing field and never a wrong edge.Two choices the issue left open:
--groupbuckets types by the source schema file. GraphQL has no package concept, so there was nothing native to group on. A schema split acrossbilling.graphqlandcatalog.graphqlis how SDL is namespaced in practice, and it invents no convention the maintainer did not ask for.The five builtin scalars never become nodes. An introspection dump always lists them, so without that filter every introspection run gained five orphan nodes.
Registration
SKILL.mdrouting row and description,toolbox.md(row, entry, count 41 → 42),cookbook.mdprompt,diagram-ir.mdauto-detect list,mcp.mdbuild row,CHANGELOG.md, and both READMEs (15 → 16 extractors). Wired intodiagramctl.py buildwith.graphql/.gqlauto-detection and into the MCP server's--fromenum.Directory detection is ordered after the existing language and
.protomarkers, matching the reasoning already in that function: a schema file is often one part of a project whose own markers describe it better.Testing
188 on
main, so 28 are new:tests/test_graphqlerd.pycovers the parser, the graph, the introspection path and the CLI, plus one importer smoke test intests/test_scripts.pynext to the protobuf one.Six sabotage runs, so no new test passes vacuously:
Two of those started out passing under sabotage, which is how the builtin-scalar leak above was found and how the comment decoy got moved to the start of its line where the definition scan would actually reach it.
End to end,
diagramctl.py buildon a two-file schema directory produces a.drawiothatvalidate.pyreports with 0 errors.Not verified
CI runs Python 3.11 and this machine only has 3.14, so the suite was not run on 3.11. The script is plain stdlib with no version-sensitive syntax, but I did not execute it there.