[graphql] Add @typespec/graphql emitter#11000
Open
FionaBronwen wants to merge 176 commits into
Open
Conversation
Add CODEOWNERS for graphql pull request reviews --------- Co-authored-by: swatikumar <swatikumar@pinterest.com>
…#5033) ### Description This PR sets up the flow to use the GraphQL emitter by providing an interface for the various options that the GraphQL emitter will use eventually. It also sets up test-hosts to work with these options. The actual schema emitter doesn't really do anything other than emit "Hello World" as it did previously, but the options get pass through as confirmed by the test case. Going forward, we can change the code in schema-emitter.ts to setup it up for GraphQL using `navigateProgram`. We need to add diagnostics in the emitter lib definition, but that can be done in a separate PR. The next PR will have the outer layer of the GraphQL emitter setup to deal with multiple schemas similar to multiple services in the OAI emitter. ### Testing Run the tests and see that they pass. --------- Co-authored-by: swatikumar <swatikumar@pinterest.com>
These are just some basic updates to the metadata in the `@typespec/graphql` `package.json`. This brings it in line with other packages like `@typespec/openapi3`.
The `@compose` decorator is used to indicate that a GraphQL `type` or `interface` implements one or more interfaces. As [defined by the GraphQL spec](https://spec.graphql.org/October2021/#sec-Interfaces), a `type` or `interface` implementing an interface must contain all the properties defined by that interface, and so we require that the TypeSpec model implement the interface's properties as well. There is no restriction on how this is accomplished (via spread, via composition, via manual copying of properties, etc). To reduce confusion, we do not allow a TypeSpec model to define both a `type` and an `interface`. In order to define an `interface`, the model must be decorated with the `@Interface` decorator.
The `@operationFields` decorator is used to specify one or more operations that should be placed onto a GraphQL type as fields with arguments. This is our solution for representing [GraphQL field arguments](https://spec.graphql.org/October2021/#sec-Field-Arguments) in TypeSpec, as TypeSpec does not support arguments on model properties.
Implement `@Interface` and `@compose` decorators
Implement `@operationFields` decorator
Import useStateMap from compiler utils (after merge)
A few updates to make the project buildable again: - `implements` became a reserved keyword in 9a4463b, so we switch to `interfaces` - `expectIdenticalTypes` was renamed to `expectTypeEquals` in 32ca22f - `validateDecoratorTarget` was removed in 32ca22f, as the TypeSpec type system handles this - `SyntaxKind` was moved to `compiler/ast` in 32ca22f - we also bump version of `devDependencies` to match those in other projects
Add main.tsp and remove strict from tspconfig.yml
- Add @pinterest/alloy-graphql and graphql to pnpm-workspace catalog - Convert all dependencies in graphql package to use catalog: protocol - Add oxc: false to vitest config to fix JSX transform compatibility with vitest 4
FionaBronwen
force-pushed
the
feature/graphql
branch
from
July 9, 2026 16:48
4e94683 to
eccd476
Compare
Member
|
/azp run typespec - pr tools |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a new first-party TypeSpec emitter package, @typespec/graphql, that generates GraphQL SDL from TypeSpec programs, including a mutation-engine phase (naming, visibility filtering, input/output splitting) and an Alloy-based render phase. The PR also wires the emitter into the website documentation and the playground.
Changes:
- Add
packages/graphqlimplementing the GraphQL emitter, decorators, validation, mutation engine, and Alloy SDL rendering. - Add extensive unit/integration tests for decorators, mutation engine behavior, and component-level SDL rendering.
- Add docs + playground integration, and register new workspace dependencies (
@pinterest/alloy-graphql,graphql).
Reviewed changes
Copilot reviewed 113 out of 115 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| website/src/content/docs/docs/emitters/graphql/reference/index.mdx | New GraphQL emitter reference landing page. |
| website/src/content/docs/docs/emitters/graphql/reference/emitter.md | Documents CLI/config usage and emitter options. |
| website/src/content/docs/docs/emitters/graphql/reference/data-types.md | Documents exported GraphQL-related TypeSpec types. |
| website/src/content/docs/docs/emitters/graphql/guide.md | New end-to-end usage guide and mapping examples. |
| website/src/content/current-sidebar.ts | Adds GraphQL docs entry to website sidebar. |
| pnpm-workspace.yaml | Adds catalog deps for alloy-graphql and graphql; minReleaseAge exclusion. |
| pnpm-lock.yaml | Locks new dependencies and adds packages/graphql importer. |
| packages/playground-website/tsconfig.json | Adds project reference to packages/graphql. |
| packages/playground-website/src/config.ts | Enables @typespec/graphql in playground libraries list. |
| packages/playground-website/samples/graphql.tsp | Adds a GraphQL sample TypeSpec program. |
| packages/playground-website/samples/build.js | Registers GraphQL sample in playground sample builder. |
| packages/playground-website/package.json | Adds @typespec/graphql dependency for playground. |
| packages/graphql/vitest.config.ts | Vitest config for JSX/alloy plugin + dependency dedupe. |
| packages/graphql/tsconfig.json | TypeScript project config for the new package. |
| packages/graphql/test/test-host.ts | Test harness for compiling/emitting GraphQL and parsing SDL. |
| packages/graphql/test/schema.test.ts | Unit tests for @schema decorator behavior. |
| packages/graphql/test/operation-kind.test.ts | Unit tests for @query/@mutation/@subscription operation kind. |
| packages/graphql/test/operation-fields.test.ts | Tests for @operationFields behavior and conflict diagnostics. |
| packages/graphql/test/mutation-engine/type-graph.test.ts | Tests for TypeGraph construction and navigation compatibility. |
| packages/graphql/test/mutation-engine/scalars.test.ts | Scalar mapping/sanitization + @specifiedBy tests. |
| packages/graphql/test/mutation-engine/print-type.test.ts | Tests GraphQL type string printing (nullability/list handling). |
| packages/graphql/test/mutation-engine/operations.test.ts | Operation naming + return-type nullability propagation tests. |
| packages/graphql/test/mutation-engine/naming-integration.test.ts | Integration tests for naming pipelines across kinds. |
| packages/graphql/test/mutation-engine/enums.test.ts | Enum + enum member mutation behavior tests. |
| packages/graphql/test/mutation-engine/context.test.ts | Tests for input/output context caching and propagation. |
| packages/graphql/test/main.tsp | Sample library schema TypeSpec used for testing/manual runs. |
| packages/graphql/test/lib/type-utils.test.ts | Unit tests for type/name utility helpers. |
| packages/graphql/test/lib/template-composition.test.ts | Unit tests for template-instance naming composition. |
| packages/graphql/test/lib/naming.test.ts | Unit tests for naming pipeline functions. |
| packages/graphql/test/interface.test.ts | Tests for interface markers and @compose validation. |
| packages/graphql/test/emitter.test.ts | E2E-ish tests for full SDL emission for common scenarios. |
| packages/graphql/test/e2e-manual/output/.gitignore | Ignores manual E2E output artifacts. |
| packages/graphql/test/crash-repro.test.ts | Regression tests for previously-crashing patterns (records, generics, unions). |
| packages/graphql/test/components/union-type.test.tsx | Component-level SDL rendering tests for unions. |
| packages/graphql/test/components/test-utils.tsx | Shared component test renderer to SDL string. |
| packages/graphql/test/components/scalar-type.test.tsx | Component-level SDL rendering tests for scalars. |
| packages/graphql/test/components/object-type.test.tsx | Component-level SDL rendering tests for object types. |
| packages/graphql/test/components/interface-type.test.tsx | Component-level SDL rendering tests for interface types. |
| packages/graphql/test/components/input-type.test.tsx | Component-level SDL rendering tests for input objects / @OneOf. |
| packages/graphql/test/components/enum-type.test.tsx | Component-level SDL rendering tests for enums. |
| packages/graphql/src/validate.ts | Adds GraphQL-specific validation hook for schemas/names/empties. |
| packages/graphql/src/type-usage.ts | Tracks type usage (input/output/query/mutation) + reachability. |
| packages/graphql/src/tsp-index.ts | Exposes decorators and validate hook for TypeSpec runtime. |
| packages/graphql/src/mutation-engine/type-graph.ts | Builds a self-contained namespace of mutated types for rendering. |
| packages/graphql/src/mutation-engine/schema-mutator.ts | Walks schema namespace, mutates types, builds TypeGraph, checks collisions. |
| packages/graphql/src/mutation-engine/print-type.ts | Converts mutated types into GraphQL type strings (nullability/list rules). |
| packages/graphql/src/mutation-engine/options.ts | Mutation options carrying GraphQL context, visibility, cache keys. |
| packages/graphql/src/mutation-engine/mutations/scalar.ts | Scalar mutation: mapping, sanitization, builtin collision warnings, @specifiedBy. |
| packages/graphql/src/mutation-engine/mutations/operation.ts | Operation mutation: naming + visibility + nullability propagation. |
| packages/graphql/src/mutation-engine/mutations/model.ts | Model mutation: naming, visibility filtering, record→scalar replacement, decorator arg remutation. |
| packages/graphql/src/mutation-engine/mutations/model-property.ts | Property mutation: naming + nullability/nullable-elements tagging. |
| packages/graphql/src/mutation-engine/mutations/index.ts | Barrel exports for mutation classes. |
| packages/graphql/src/mutation-engine/mutations/enum.ts | Enum mutation with member-edge handling + naming pipeline. |
| packages/graphql/src/mutation-engine/mutations/enum-member.ts | Enum member naming pipeline mutation. |
| packages/graphql/src/mutation-engine/mutations/union.ts | Union mutation: flattening/dedup, scalar wrapper models, input @oneOf conversion. |
| packages/graphql/src/mutation-engine/index.ts | Mutation-engine public entrypoints. |
| packages/graphql/src/mutation-engine/engine.ts | MutationEngine wiring + convenience mutation APIs. |
| packages/graphql/src/lib/visibility.ts | Defines visibility filters for query/mutation/output contexts. |
| packages/graphql/src/lib/utils.ts | Structural equality helpers for conflict detection (ops/models/props). |
| packages/graphql/src/lib/template-composition.ts | Template-instance name composition logic. |
| packages/graphql/src/lib/specified-by.ts | @specifiedBy decorator state + decorator implementation. |
| packages/graphql/src/lib/schema.ts | @schema decorator state + schema list helpers. |
| packages/graphql/src/lib/operation-kind.ts | @query/@mutation/@subscription decorator state + duplicate detection. |
| packages/graphql/src/lib/operation-fields.ts | @operationFields implementation + conflict/duplicate diagnostics. |
| packages/graphql/src/lib/one-of.ts | @oneOf marker decorator implementation/helpers. |
| packages/graphql/src/lib/nullable.ts | @nullable/@nullableElements marker decorators + helpers. |
| packages/graphql/src/lib/naming.ts | GraphQL naming pipelines (sanitize + casing + suffixes). |
| packages/graphql/src/lib/interface.ts | @graphqlInterface and @compose state + validation. |
| packages/graphql/src/lib/input-type.ts | Internal marker for identifying input types during render. |
| packages/graphql/src/lib/graphql-type-name.ts | Maps std scalars to GraphQL builtins and resolves type names. |
| packages/graphql/src/lib.ts | Library definition: diagnostics + emitter option schema. |
| packages/graphql/src/index.ts | Package exports (emitter, lib, decorators, mutation engine). |
| packages/graphql/src/emitter.tsx | Core emitter: schema selection, mutation, SDL render, emit files. |
| packages/graphql/src/context/index.ts | Context barrel exports for renderer. |
| packages/graphql/src/context/graphql-schema-context.tsx | Renderer context for passing TypeGraph into Alloy components. |
| packages/graphql/src/components/types/union-type.tsx | Alloy component for GraphQL unions. |
| packages/graphql/src/components/types/scalar-type.tsx | Alloy component for GraphQL scalars (+ specifiedBy). |
| packages/graphql/src/components/types/object-type.tsx | Alloy component for object types (+ interfaces, operation fields). |
| packages/graphql/src/components/types/interface-type.tsx | Alloy component for interface types. |
| packages/graphql/src/components/types/input-type.tsx | Alloy component for input object types (+ @OneOf). |
| packages/graphql/src/components/types/index.ts | Barrel exports for type components. |
| packages/graphql/src/components/types/enum-type.tsx | Alloy component for enums (+ descriptions/deprecation). |
| packages/graphql/src/components/schema.tsx | Top-level schema composition component (types + root ops). |
| packages/graphql/src/components/fields/operation-field.tsx | Alloy component for operation-as-field rendering incl. args/nullability/lists. |
| packages/graphql/src/components/fields/index.ts | Barrel exports for field components. |
| packages/graphql/src/components/fields/field.tsx | Alloy component for model property fields (input/output). |
| packages/graphql/package.json | New package manifest + scripts + deps/peers. |
| packages/graphql/lib/specified-by.tsp | TypeSpec extern decorator declaration for @specifiedBy. |
| packages/graphql/lib/schema.tsp | TypeSpec extern decorator declaration for @schema + SchemaOptions model. |
| packages/graphql/lib/scalars.tsp | Declares TypeSpec.GraphQL.ID scalar. |
| packages/graphql/lib/operation-kind.tsp | TypeSpec extern decorator declarations for query/mutation/subscription. |
| packages/graphql/lib/operation-fields.tsp | TypeSpec extern decorator declaration for @operationFields. |
| packages/graphql/lib/one-of.tsp | TypeSpec extern decorator declaration for @oneOf. |
| packages/graphql/lib/nullable.tsp | TypeSpec extern decorator declarations for nullability markers. |
| packages/graphql/lib/main.tsp | TypeSpec library entrypoint importing JS + decorator declarations. |
| packages/graphql/lib/interface.tsp | TypeSpec extern decorator declarations for @graphqlInterface and @compose. |
| packages/graphql/CHANGELOG.md | New changelog for initial release. |
| packages/graphql/api-extractor.json | Enables API extractor config for the new package. |
| cspell.yaml | Adds new words and ignores .claude/**. |
| .gitignore | Ignores local Claude settings file. |
| .github/CODEOWNERS | Adds CODEOWNERS entry for packages/graphql. |
| .chronus/changes/feature-graphql-2026-6-9-12-47-10.md | Adds Chronus changelog entry for the new emitter. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
|
You can try these changes here
|
- Remove unnecessary cast and outdated comment in test-utils.tsx (graphql types now match) - Add operation name validation for reserved __ prefix in validate.ts
- Add transitive registration of union variant types in type-graph.ts - Add test to verify variant types are registered when only union is passed
Member
Consolidate scalar mappings into a single unified structure that covers all 25 TypeSpec intrinsic scalars. When std scalars like int64 are used directly without defining a custom scalar, they now map to the closest GraphQL built-in type (e.g., int64 → String) instead of crashing. - Unified SCALAR_MAPPINGS table with graphqlType for all scalars - Filter std/library scalars from emission in schema-mutator - Remove renaming of std scalars in scalar mutation - Add comprehensive unit tests for all scalar mappings Fixes crash: "Unknown GraphQL type Long" when using int64 directly.
When encountering types without a GraphQL equivalent (like numeric literals `42` or string literals `"foo"`), emit a warning diagnostic and fall back to String instead of crashing. Adds `unsupported-type` diagnostic that reports which type kind has no GraphQL equivalent.
Member
|
test1 @typespec-graphql-reviewers/core |
The Azure/typespec-azure CI uses its own pnpm catalog which doesn't include @pinterest/alloy-graphql. Using an explicit version bypasses the catalog lookup and allows the downstream CI to pass.
- Fix CodeQL security alert: use iterative stripping for angle brackets in type names to handle nested cases - Revert to catalog: for @pinterest/alloy-graphql (repo requires it)
The tspd doc tool requires tsconfig.build.json to exist. Adding it and regenerating the reference documentation to satisfy CI validation.
…ors (#105) Convert the internal `@nullable`, `@nullableElements`, `@oneOf`, and `@inputType` marker decorators from hand-written implementations (and the `.decorators`-push hack) to compiler `internal auto dec` declarations. - Adopt tspd `gen-extern-signature` generated readers/setters (isNullable, setNullable, isOneOf, setOneOf, isInputType, setInputType, ...) instead of hand-written state accessors; delete src/lib/{nullable,one-of,input-type}.ts. - Type all decorator implementations with the generated `*Decorator` signatures; `$decorators` uses `satisfies TypeSpecGraphQLDecorators`. - Wire up gen-extern-signature into the build; add generated-defs/ and tspconfig.yaml (auto-decorators experimental feature opt-in). - Remove now-unused GraphQLKeys state entries for the migrated decorators.
Co-authored-by: Timothee Guerin <timothee.guerin@outlook.com>
External contributors cannot be added as codeowners, so falling back to the default catch-all for this package.
timotheeguerin
enabled auto-merge
July 16, 2026 17:31
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.
Summary
This PR introduces
@typespec/graphql, a new emitter that generates GraphQL SDL (Schema Definition Language) from TypeSpec definitions.Features
@query,@mutation, and@subscriptiondecorators@graphqlInterfaceand@composefor GraphQL interface inheritancepatterns
@visibilitydecorators@specifiedBydecorator for custom scalar URL specifications@schemadecorator for multi-schema scenariosArchitecture
The emitter uses a two-phase approach:
@pinterest/alloy-graphqlcomponents to emit the final SDL outputExample
Generates:
Test plan
Notes