Skip to content

Commit 916d023

Browse files
ikusakov2ikusakoveddeee888
authored
Documentation for migrating from Apollo Tooling to GraphQL Codegen (dotansimha#10612)
* docs * fixed docs * added more docs * better comments * Run prettier --------- Co-authored-by: Igor Kusakov <[email protected]> Co-authored-by: Eddy Nguyen <[email protected]> Co-authored-by: Eddy Nguyen <[email protected]>
1 parent cb2d3e7 commit 916d023

2 files changed

Lines changed: 304 additions & 0 deletions

File tree

website/src/pages/docs/migration/_meta.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export default {
44
'from-0-13': 'v0.13 -> v0.17',
55
'from-4-0': 'v4.0 -> v5.0',
66
'operations-and-client-preset-from-5-0': 'typescript-operations and client-preset v5.0 -> v6.0',
7+
'apollo-tooling': 'Apollo Tooling -> GraphQL Code Generator',
78
};
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
---
2+
description: Migrating from Apollo Tooling (apollo client:codegen) to GraphQL Code Generator. What has changed? How to migrate? What configuration options replace Apollo Tooling's behaviour?
3+
---
4+
5+
import { Callout, Tabs } from '@theguild/components'
6+
7+
# Migrating from Apollo Tooling to GraphQL Code Generator
8+
9+
[Apollo Tooling](https://github.com/apollographql/apollo-tooling) (the `apollo` CLI, specifically `apollo client:codegen`) is a code generation tool that generates TypeScript types from GraphQL operations for use with Apollo Client.
10+
11+
This guide explains how to replace it with [GraphQL Code Generator](https://the-guild.dev/graphql/codegen), which is actively maintained, more flexible, and supports a broader range of use cases.
12+
13+
<Callout>
14+
This setup is available in the next major version of `graphql-code-generator` and `graphql-code-generator-community`.
15+
</Callout>
16+
17+
## Installation
18+
19+
Remove Apollo Tooling and install GraphQL Code Generator:
20+
21+
<Tabs items={['Before', 'After']}>
22+
<Tabs.Tab>
23+
```sh npm2yarn
24+
npm uninstall apollo
25+
```
26+
</Tabs.Tab>
27+
28+
<Tabs.Tab>
29+
```sh npm2yarn
30+
npm i -D @graphql-codegen/cli @graphql-codegen/typescript-operations @graphql-codegen/near-operation-file-preset
31+
```
32+
</Tabs.Tab>
33+
</Tabs>
34+
35+
### Required packages
36+
37+
| Package | Description |
38+
| --------------------------------------------- | ------------------------------------------------------------------ |
39+
| `@graphql-codegen/cli` | Core CLI that runs the code generator |
40+
| `@graphql-codegen/typescript-operations` | Plugin that generates TypeScript types for GraphQL operations |
41+
| `@graphql-codegen/near-operation-file-preset` | Preset that places generated files next to their source operations |
42+
43+
```json filename="package.json"
44+
{
45+
"devDependencies": {
46+
...
47+
"@graphql-codegen/cli": "...",
48+
"@graphql-codegen/typescript-operations": "...",
49+
"@graphql-codegen/near-operation-file-preset": "..."
50+
...
51+
}
52+
}
53+
```
54+
55+
## Configuration
56+
57+
Apollo Tooling is configured via `apollo.config.js` (or `apollo.config.ts`) and invoked with `apollo client:codegen`. GraphQL Code Generator uses a `codegen.ts` file and is invoked with `graphql-codegen`.
58+
59+
<Tabs items={['Before', 'After']}>
60+
<Tabs.Tab>
61+
```js filename="apollo.config.js"
62+
module.exports = {
63+
client: {
64+
service: {
65+
name: 'my-service',
66+
localSchemaFile: './schema.graphql',
67+
},
68+
includes: ['./src/**/*.tsx', './src/**/*.ts'],
69+
},
70+
}
71+
```
72+
73+
```sh
74+
apollo client:codegen --target=typescript --outputFlat src/__generated__/types.ts
75+
```
76+
77+
</Tabs.Tab>
78+
79+
<Tabs.Tab>
80+
```ts filename="codegen.ts"
81+
import type { CodegenConfig } from '@graphql-codegen/cli'
82+
83+
const config: CodegenConfig = {
84+
schema: './schema.graphql',
85+
documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'],
86+
generates: {
87+
'./src/': {
88+
preset: 'near-operation-file',
89+
presetConfig: {
90+
extension: '.ts',
91+
folder: '**generated**',
92+
filePerOperation: true,
93+
inGeneratesOnly: true,
94+
},
95+
plugins: ['typescript-operations'],
96+
},
97+
},
98+
}
99+
100+
export default config
101+
```
102+
103+
```sh
104+
graphql-codegen
105+
```
106+
107+
</Tabs.Tab>
108+
</Tabs>
109+
110+
Add a script to your `package.json` to run the code generator:
111+
112+
```json filename="package.json"
113+
{
114+
"scripts": {
115+
"codegen": "graphql-codegen"
116+
}
117+
}
118+
```
119+
120+
## Per-file generation with `near-operation-file`
121+
122+
Apollo Tooling's default behaviour is to generate one TypeScript file per graphql operation, placed in a `__generated__` folder next to the source.
123+
For example, given `src/Component.ts` containing a query `GetUser`, Apollo Tooling produces `src/__generated__/GetUser.ts`.
124+
125+
GraphQL Code Generator replicates this with the [`near-operation-file` preset](https://the-guild.dev/graphql/codegen/plugins/presets/near-operation-file-preset).
126+
127+
```ts filename="codegen.ts"
128+
import type { CodegenConfig } from '@graphql-codegen/cli'
129+
130+
const config: CodegenConfig = {
131+
schema: './schema.graphql',
132+
documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'],
133+
generates: {
134+
'./src/': {
135+
preset: 'near-operation-file',
136+
presetConfig: {
137+
extension: '.ts', // Extension for generated files
138+
folder: '__generated__', // Generated files go into __generated__/ subfolder
139+
filePerOperation: true, // Generate type files per-operation (not per-component)
140+
inGeneratesOnly: true // Only generate files defined in `generates` scan paths (don't generate for all `documents`)
141+
},
142+
plugins: ['typescript-operations']
143+
}
144+
}
145+
}
146+
147+
export default config
148+
```
149+
150+
With this configuration, `src/Component.ts``src/__generated__/Component.ts`, matching Apollo Tooling's output structure exactly.
151+
152+
## Type naming conventions
153+
154+
Apollo Tooling generates type names using **only field names**, omitting the GraphQL object type name:
155+
156+
```ts
157+
// Apollo Tooling output
158+
export type GetUserQuery_user = { ... };
159+
export type GetUserQuery_user_address = { ... };
160+
```
161+
162+
To achieve similar naming with GraphQL Codegen use the `extractAllFieldsToTypesCompact: true` configuration option:
163+
164+
```ts filename="codegen.ts"
165+
const config: CodegenConfig = {
166+
schema: './schema.graphql',
167+
documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'],
168+
generates: {
169+
'./src/': {
170+
preset: 'near-operation-file',
171+
presetConfig: {
172+
extension: '.ts',
173+
folder: '__generated__',
174+
filePerOperation: true,
175+
inGeneratesOnly: true
176+
},
177+
plugins: ['typescript-operations'],
178+
config: {
179+
extractAllFieldsToTypesCompact: true
180+
}
181+
}
182+
}
183+
}
184+
```
185+
186+
## Enum types
187+
188+
Apollo Tooling generates enums as native TypeScript `enum` declarations and references them directly by name (without any namespace prefix):
189+
190+
```ts
191+
// Apollo Tooling output
192+
export enum UserManagerRoleType {
193+
ROLE_TYPE_1 = 'ROLE_TYPE_1',
194+
ROLE_TYPE_2 = 'ROLE_TYPE_2',
195+
ROLE_TYPE_3 = 'ROLE_TYPE_3'
196+
}
197+
198+
export type GetUserQuery_user_manager = {
199+
roleType: UserManagerRoleType
200+
}
201+
```
202+
203+
GraphQL Code Generator generates string literal union types by default. To produce native `enum` declarations matching Apollo Tooling's output, set `enumType: 'native'`:
204+
205+
```ts filename="codegen.ts"
206+
const config: CodegenConfig = {
207+
schema: './schema.graphql',
208+
documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'],
209+
generates: {
210+
'./src/': {
211+
preset: 'near-operation-file',
212+
presetConfig: {
213+
extension: '.ts',
214+
folder: '__generated__',
215+
filePerOperation: true,
216+
inGeneratesOnly: true
217+
},
218+
plugins: ['typescript-operations'],
219+
config: {
220+
extractAllFieldsToTypesCompact: true,
221+
enumType: 'native'
222+
}
223+
}
224+
}
225+
}
226+
```
227+
228+
<Callout type="warning">
229+
Native TypeScript `enum` declarations incur a runtime cost (they compile to JavaScript objects). If you only need
230+
type-level checking, consider using the default `string-literal` enum type instead:
231+
232+
```ts
233+
type UserManagerRoleType = 'ROLE_TYPE_1' | 'ROLE_TYPE_2' | 'ROLE_TYPE_3'
234+
```
235+
236+
See the [typescript-operations configuration reference](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-operations#enumtype) for all available enum type options.
237+
238+
</Callout>
239+
240+
## Recommended configuration
241+
242+
Below is a configuration that produces output closely matching Apollo Tooling's behaviour, including per-file generation, enum output, and type naming:
243+
244+
```ts filename="codegen.ts"
245+
import type { CodegenConfig } from '@graphql-codegen/cli'
246+
247+
const config: CodegenConfig = {
248+
schema: './schema.graphql',
249+
documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'],
250+
generates: {
251+
'./src/': {
252+
preset: 'near-operation-file',
253+
presetConfig: {
254+
extension: '.ts',
255+
folder: '__generated__',
256+
// Generate type files per-operation (not per-component)
257+
filePerOperation: true,
258+
// Only generate files defined in `generates` scan paths (don't generate for all `documents`)
259+
inGeneratesOnly: true
260+
},
261+
plugins: ['typescript-operations'],
262+
config: {
263+
// Keep original naming as-is (no camelCase conversion)
264+
namingConvention: 'keep',
265+
// Extract nested field types to named types (matches Apollo Tooling naming)
266+
extractAllFieldsToTypesCompact: true,
267+
// Print each field on its own line for readability
268+
printFieldsOnNewLines: true,
269+
// Use native TypeScript enums (matches Apollo Tooling enum output)
270+
enumType: 'native',
271+
// Always include __typename in result types
272+
nonOptionalTypename: true,
273+
// Don't add __typename to root query/mutation/subscription types
274+
skipTypeNameForRoot: true,
275+
// Don't add 'Query'/'Mutation'/'Subscription' suffixes to operation result types
276+
omitOperationSuffix: true,
277+
// Don't add 'Fragment' suffix to fragment result types
278+
fragmentSuffix: ''
279+
}
280+
}
281+
}
282+
}
283+
284+
export default config
285+
```
286+
287+
## Manual changes
288+
289+
The setup above closely mimics Apollo Tooling but isn’t an exact match. The following items may require manual fixes:
290+
291+
1. Nested field types naming. In very rare cases, the names generated by GraphQL Codegen don’t match Apollo Tooling’s. Update these cases manually.
292+
293+
2. Enum file location. Occasionally, GraphQL Codegen places enums in a different file. If an enum is missing, check nearby generated files and adjust your imports accordingly.
294+
295+
3. Occasional mismatch between `Type | null` and `Type | null | undefined`.
296+
297+
4. Occasional `is possibly null` and `has any type` typecheck bugs.
298+
299+
## Further reading
300+
301+
- [GraphQL Code Generator configuration reference](https://the-guild.dev/graphql/codegen/docs/config-reference/codegen-config)
302+
- [typescript-operations plugin documentation](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-operations)
303+
- [near-operation-file preset documentation](https://the-guild.dev/graphql/codegen/plugins/presets/near-operation-file-preset)

0 commit comments

Comments
 (0)