Skip to content

Commit fc4d2e7

Browse files
committed
Add GraphQL emitter documentation to website
- Add guide.md with usage documentation for the GraphQL emitter - Generate reference docs using tspd doc tool - Add GraphQL to sidebar under Emitters section with preview badge - Add regen-docs script and tspd dev dependency to graphql package
1 parent fd06dd3 commit fc4d2e7

8 files changed

Lines changed: 686 additions & 1 deletion

File tree

packages/graphql/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"test": "vitest run",
4444
"test:watch": "vitest -w",
4545
"lint": "eslint . --max-warnings=0",
46-
"lint:fix": "eslint . --fix"
46+
"lint:fix": "eslint . --fix",
47+
"regen-docs": "tspd doc . --enable-experimental --output-dir ../../website/src/content/docs/docs/emitters/graphql/reference"
4748
},
4849
"files": [
4950
"lib/*.tsp",
@@ -64,6 +65,7 @@
6465
"@typespec/emitter-framework": "workspace:~",
6566
"@typespec/http": "workspace:~",
6667
"@typespec/mutator-framework": "workspace:~",
68+
"@typespec/tspd": "workspace:~",
6769
"rimraf": "~6.0.1",
6870
"source-map-support": "~0.5.21",
6971
"typescript": "~5.8.2",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

website/src/content/current-sidebar.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ const sidebar: SidebarItem[] = [
177177
["emitters/protobuf/guide"],
178178
"preview",
179179
),
180+
createLibraryReferenceStructure(
181+
"emitters/graphql",
182+
"GraphQL",
183+
false,
184+
["emitters/graphql/guide"],
185+
"preview",
186+
),
180187
{
181188
label: "Clients",
182189
items: [
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
---
2+
title: Guide
3+
---
4+
5+
The GraphQL emitter (`@typespec/graphql`) generates GraphQL Schema Definition Language (SDL) from TypeSpec sources. The generated schemas can be used with any GraphQL server implementation.
6+
7+
## Fundamental Concepts
8+
9+
The GraphQL emitter transforms TypeSpec models, operations, and enums into their GraphQL equivalents. To generate a valid GraphQL schema, your TypeSpec must follow certain conventions.
10+
11+
### Schemas
12+
13+
A GraphQL schema is defined by applying the [`@schema`](../reference/decorators#@TypeSpec.GraphQL.schema) decorator to a TypeSpec namespace. All types and operations within the namespace will be emitted to a single GraphQL schema file.
14+
15+
```typespec
16+
import "@typespec/graphql";
17+
18+
using GraphQL;
19+
20+
@schema
21+
namespace MyService {
22+
// Types and operations go here
23+
}
24+
```
25+
26+
You can optionally specify a name for the schema, which will be used in the output filename:
27+
28+
```typespec
29+
@schema(#{ name: "petstore" })
30+
namespace PetStore {
31+
// ...
32+
}
33+
```
34+
35+
This will generate a file named `petstore.graphql`.
36+
37+
### Object Types
38+
39+
TypeSpec models are transformed into GraphQL object types. For example:
40+
41+
```typespec
42+
model Pet {
43+
id: string;
44+
name: string;
45+
age: int32;
46+
}
47+
```
48+
49+
Becomes:
50+
51+
```graphql
52+
type Pet {
53+
id: String!
54+
name: String!
55+
age: Int!
56+
}
57+
```
58+
59+
Note that all fields are non-nullable (`!`) by default in GraphQL. See [Nullability](#nullability) for how to make fields nullable.
60+
61+
### Operations
62+
63+
GraphQL supports three operation types: queries, mutations, and subscriptions. Use the corresponding decorators to specify the operation kind:
64+
65+
```typespec
66+
@query op getPet(id: string): Pet;
67+
@query op listPets(): Pet[];
68+
69+
@mutation op createPet(name: string, age: int32): Pet;
70+
@mutation op deletePet(id: string): boolean;
71+
72+
@subscription op onPetCreated(): Pet;
73+
```
74+
75+
This generates:
76+
77+
```graphql
78+
type Query {
79+
getPet(id: String!): Pet!
80+
listPets: [Pet!]!
81+
}
82+
83+
type Mutation {
84+
createPet(name: String!, age: Int!): Pet!
85+
deletePet(id: String!): Boolean!
86+
}
87+
88+
type Subscription {
89+
onPetCreated: Pet!
90+
}
91+
```
92+
93+
### Input Types
94+
95+
When a model is used as an operation parameter (mutation input), the emitter automatically generates a corresponding GraphQL input type with an `Input` suffix:
96+
97+
```typespec
98+
model Pet {
99+
name: string;
100+
age: int32;
101+
}
102+
103+
@mutation op createPet(input: Pet): Pet;
104+
```
105+
106+
Generates:
107+
108+
```graphql
109+
input PetInput {
110+
name: String!
111+
age: Int!
112+
}
113+
114+
type Mutation {
115+
createPet(input: PetInput!): Pet!
116+
}
117+
```
118+
119+
### Enums
120+
121+
TypeSpec enums map to GraphQL enums with member names converted to `CONSTANT_CASE`:
122+
123+
```typespec
124+
enum PetStatus {
125+
Available,
126+
Pending,
127+
Sold,
128+
}
129+
```
130+
131+
Becomes:
132+
133+
```graphql
134+
enum PetStatus {
135+
AVAILABLE
136+
PENDING
137+
SOLD
138+
}
139+
```
140+
141+
### Nullability
142+
143+
By default, all GraphQL types are non-nullable. To make a field or return type nullable, use TypeSpec's union with `null`:
144+
145+
```typespec
146+
model Pet {
147+
id: string;
148+
nickname: string | null; // Nullable field
149+
}
150+
151+
@query op findPet(id: string): Pet | null; // Nullable return
152+
```
153+
154+
Generates:
155+
156+
```graphql
157+
type Pet {
158+
id: String!
159+
nickname: String # No ! means nullable
160+
}
161+
162+
type Query {
163+
findPet(id: String!): Pet # Nullable return
164+
}
165+
```
166+
167+
For nullable array elements, the emitter handles `Array<T | null>` patterns:
168+
169+
```typespec
170+
model SearchResult {
171+
pets: (Pet | null)[]; # Array with nullable elements
172+
}
173+
```
174+
175+
Generates:
176+
177+
```graphql
178+
type SearchResult {
179+
pets: [Pet]! # Non-null array, nullable elements
180+
}
181+
```
182+
183+
### Interfaces
184+
185+
GraphQL interfaces allow you to define a common set of fields that multiple types can implement. Use the [`@interface`](../reference/decorators#@TypeSpec.GraphQL.interface) decorator:
186+
187+
```typespec
188+
@`interface`(#{ interfaceOnly: true })
189+
model Node {
190+
id: string;
191+
}
192+
193+
@compose(Node)
194+
model Pet {
195+
...Node;
196+
name: string;
197+
}
198+
```
199+
200+
Generates:
201+
202+
```graphql
203+
interface Node {
204+
id: String!
205+
}
206+
207+
type Pet implements Node {
208+
id: String!
209+
name: String!
210+
}
211+
```
212+
213+
The `interfaceOnly` option prevents the model from also being emitted as an object type (useful for abstract interfaces like `Node`).
214+
215+
## Type Mappings
216+
217+
| TypeSpec Type | GraphQL Type |
218+
|--------------|--------------|
219+
| `string` | `String` |
220+
| `boolean` | `Boolean` |
221+
| `int32` | `Int` |
222+
| `float32`, `float64` | `Float` |
223+
| `GraphQL.ID` | `ID` |
224+
| `T[]` | `[T!]!` |
225+
| `T \| null` | `T` (nullable) |
226+
227+
## Example Configuration
228+
229+
To use the GraphQL emitter, add it to your `tspconfig.yaml`:
230+
231+
```yaml
232+
emit:
233+
- "@typespec/graphql"
234+
```
235+
236+
The emitter will generate `.graphql` files in your output directory.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: "Data types"
3+
description: "Data types exported by @typespec/graphql"
4+
---
5+
6+
## TypeSpec.GraphQL
7+
8+
### `ID` {#TypeSpec.GraphQL.ID}
9+
10+
Represents a GraphQL ID scalar — a unique identifier serialized as a string.
11+
12+
```typespec
13+
scalar TypeSpec.GraphQL.ID
14+
```
15+
16+
#### Examples
17+
18+
```typespec
19+
model User {
20+
id: GraphQL.ID;
21+
name: string;
22+
}
23+
```
24+
25+
## TypeSpec.GraphQL.Schema
26+
27+
### `SchemaOptions` {#TypeSpec.GraphQL.Schema.SchemaOptions}
28+
29+
Options for configuring a GraphQL schema.
30+
31+
```typespec
32+
model TypeSpec.GraphQL.Schema.SchemaOptions
33+
```
34+
35+
#### Properties
36+
37+
| Name | Type | Description |
38+
| ----- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
39+
| name? | `string` | The name of the GraphQL schema. Used in the output filename when emitting<br />multiple schemas (e.g., `{name}.graphql`). Defaults to `"schema"`. |

0 commit comments

Comments
 (0)