Skip to content

refactor(types): single source for GraphQL type mapping (type-mapping convergence ③) - #144

Merged
allmonday merged 1 commit into
masterfrom
refactor/type-mapping-single-source
Sep 4, 2026
Merged

refactor(types): single source for GraphQL type mapping (type-mapping convergence ③)#144
allmonday merged 1 commit into
masterfrom
refactor/type-mapping-single-source

Conversation

@allmonday

Copy link
Copy Markdown
Collaborator

Summary

Lands the type-mapping convergence plan from the full-project orthogonality review (mindmap node #13 / 收敛路线③): the Python → GraphQL type mapping had 4 parallel implementations and 3 scalar tables, and they had already drifted apart.

Measured before this PR — the same annotation fed to two exits:

Python type compose describe JSON-RPC rpc.describe
datetime DateTime (registered scalar) datetime (class-name fallback — never a valid scalar)
dict rejected (UnsupportedTypeError) JSON (a scalar no schema ever defined)
UUID UUID UUIDby luck: the class-name fallback happened to match

Changes

Piece What
SCALAR_TYPE_MAP → module-level The 8-entry table in type_converter becomes THE single table; compose_type_mapper imports it instead of maintaining an identical copy. The specs/001 R2 fork (SQLModel-free compose) is preserved — the fork covers behavior, not data.
type_ref_to_sdl public compose_schema exports the TypeRef renderer; the compose MCP server's verbatim copy (_type_ref_to_str) is deleted.
introspector._type_to_sdl_name → thin shell Delegates to ComposeTypeMapper + type_ref_to_sdl. Its private 4-entry table, class-name fallback, and invented JSON scalar are gone. dict keeps the descriptive JSON name (describe is informational; compose rejects dict outright). A fresh mapper per call — a shared instance leaked registrations across describes (test isolation caught it: id reuse after GC made behavior order-dependent).
federation._type_expr untouched By design: it renders lossless Python expressions for the machine contract, not GraphQL SDL, and has no scalar table of its own.

Behavior change

describe_service signatures now carry nullability markers consistent with the compose schema: intInt!, datetimeDateTime!, Optional[list[T]][T!] (was the falsely-non-null [T!]!). Lenient fallbacks (bare list, general unions) keep the former conventions so describe never crashes.

12 existing assertions updated to the corrected semantics; 5 regression tests added (single-sourcing identity, datetime/UUID/dict fixes, public renderer).

Verification

Full suite 1677 passed / 0 failed; ruff check src/ clean.

🤖 Generated with Claude Code

…13 plan)

The Python → GraphQL type mapping had 4 parallel implementations and 3
scalar tables (full-project orthogonality review, pattern 1):

- SCALAR_TYPE_MAP is now a module-level constant in type_converter and
  the ONLY table; compose_type_mapper imports it (the specs/001 R2 fork
  keeps its SQLModel-free behavior — the fork covers behavior, not data)
- compose_schema.type_ref_to_sdl is the public single TypeRef renderer;
  the compose MCP server's verbatim copy (_type_ref_to_str) is deleted
- introspector._type_to_sdl_name is a thin shell over
  ComposeTypeMapper + type_ref_to_sdl: its private 4-entry table
  described datetime as "datetime" (class-name fallback — never a
  registered scalar) and invented a "JSON" scalar no schema defined;
  UUID matched only by luck. A FRESH mapper per call — the shared
  instance leaked registrations across describes (test isolation
  proven). Lenient fallbacks (bare list, general unions) keep the
  former conventions; dict keeps its descriptive "JSON" name since
  compose rejects dict outright
- federation._type_expr untouched by design: it renders lossless
  Python expressions for the machine contract, not GraphQL SDL, and
  has no scalar table of its own

Behavior change: describe signatures now carry nullability markers
consistent with the compose schema (int → "Int!", datetime → "DateTime!",
Optional[list[T]] → "[T!]!" instead of the falsely-non-null "[T!]!").
12 assertions updated to the corrected semantics; 5 regression tests
added (single-sourcing + the datetime/UUID/dict fixes).

Co-Authored-By: Claude <noreply@anthropic.com>
@allmonday
allmonday merged commit d474242 into master Sep 4, 2026
5 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