Skip to content

Add Alloy infrastructure, context system, and field components#77

Open
FionaBronwen wants to merge 5 commits into
fionabronwen/graphql-statemap-to-decoratorsfrom
fionabronwen/graphql-alloy-foundation-v2
Open

Add Alloy infrastructure, context system, and field components#77
FionaBronwen wants to merge 5 commits into
fionabronwen/graphql-statemap-to-decoratorsfrom
fionabronwen/graphql-alloy-foundation-v2

Conversation

@FionaBronwen
Copy link
Copy Markdown

@FionaBronwen FionaBronwen commented Apr 12, 2026

Summary

Adds the Alloy component infrastructure for the GraphQL emitter:

  • Alloy JSX dependencies (@alloy-js/core, @alloy-js/graphql)
  • TspContext integration from @typespec/emitter-framework for program/typekit access
  • GraphQLSchemaContext with a TypeGraph interface — the mutation pipeline's output contract
  • Field and OperationField components for rendering GraphQL fields
  • GraphQLTypeExpression component for resolving TypeSpec types to GraphQL type strings (handles scalars, models, enums, unions, arrays, nullability)

The schema context holds a TypeGraph ({ readonly globalNamespace: Namespace }) — a self-contained namespace of mutated types. Downstream components walk the namespace directly rather than consuming pre-classified arrays or side-channel maps.

Key design decisions

  • TypeGraph as the context contract — the mutation pipeline produces a flat namespace of mutated types. Components query the namespace for what they need rather than depending on pre-sorted buckets.

Test plan

  • Field components will be tested end-to-end in the next PR when the Alloy emitter is wired up

@FionaBronwen FionaBronwen changed the base branch from fionabronwen/graphql-nullable-tracking to feature/graphql April 14, 2026 16:12
@FionaBronwen FionaBronwen force-pushed the fionabronwen/graphql-alloy-foundation-v2 branch 8 times, most recently from 8f1da87 to 8b51ca4 Compare April 14, 2026 21:04
@FionaBronwen FionaBronwen marked this pull request as ready for review April 14, 2026 21:14
@FionaBronwen FionaBronwen changed the base branch from feature/graphql to fionabronwen/graphql-statemap-to-decorators April 21, 2026 16:00
@FionaBronwen FionaBronwen force-pushed the fionabronwen/graphql-alloy-foundation-v2 branch from 8b51ca4 to 8f411e1 Compare April 21, 2026 16:24
Introduce the foundation for the component-based GraphQL emitter:

- Build/config: Add @alloy-js/core, @alloy-js/graphql dependencies,
  configure JSX transpilation (tsconfig, vitest)
- Context system: GraphQLSchemaContext with ClassifiedTypes,
  ModelVariants, and ScalarVariant interfaces
- Field components: Field, OperationField, and GraphQLTypeExpression
  for rendering model properties and operations as GraphQL SDL
- Type resolution: GraphQLTypeExpression handles scalars, models,
  enums, unions, arrays, and nullability using an isInput prop to
  distinguish input vs output context
- Scalar mappings: Add getGraphQLBuiltinName() for built-in scalar
  identity checks
@FionaBronwen FionaBronwen force-pushed the fionabronwen/graphql-alloy-foundation-v2 branch from 8f411e1 to 5f26c25 Compare April 28, 2026 15:28
The ModelVariants lookup structure was originally designed to help
components decide when to append "Input" suffix to model names.
However, the mutation engine now fully handles this:
- Input models are mutated with the "Input" suffix already applied
- Property type references are rewired to point to the correct variants

This commit removes the unused ModelVariants interface and the lookup
logic from GraphQLTypeExpression, simplifying the component to just
use the model's name directly.

Also adds unionMembers to context (needed for union rendering).
Remove unused utility functions that were superseded by the mutation engine:
- getTemplatedModelName (mutation engine handles template naming)
- getSingleNameWithNamespace (never used in production)
- isArray, isRecordType, isScalarOrEnumArray, isUnionArray (use compiler's isArrayModelType)
- unwrapModel, unwrapType (never imported)
- isTrueModel (never imported)

Also removes the corresponding test for getSingleNameWithNamespace.
Comment thread packages/graphql/src/context/graphql-schema-context.tsx Outdated
Comment thread packages/graphql/src/context/graphql-schema-context.tsx Outdated
Comment thread packages/graphql/src/context/graphql-schema-context.tsx Outdated
Remove ClassifiedTypes, ScalarVariant, unionMembers, and
scalarSpecifications from GraphQLSchemaContextValue. The context now
holds a single TypeGraph — a self-contained namespace of mutated types
that downstream components can walk directly.

Classification (input/output/interface) and scalar metadata are derived
from the TypeGraph at render time rather than pre-computed into parallel
arrays and side-channel maps.
Per the GraphQL spec, 'nullability directly determines whether a field
is required'. Optional fields (?) should be nullable in both input and
output contexts.

The previous logic made optional input fields non-null, which:
1. Violated the GraphQL specification
2. Caused crashes on circular references (e.g., Author.friend?: Author
   became AuthorInput.friend: AuthorInput!, an invalid non-null cycle)
FionaBronwen added a commit that referenced this pull request Jun 3, 2026
After the TypeGraph refactor in PR #77, ScalarVariant was removed from the
context module. Move it to schema-mutator.ts where it belongs since it's
part of the MutatedSchema interface.
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.

2 participants