install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/graphql-codegen-pattern" ~/.claude/skills/intense-visions-harness-engineering-graphql-codegen-pattern-d095ae && rm -rf "$T"
manifest:
agents/skills/codex/graphql-codegen-pattern/SKILL.mdsource content
GraphQL Code Generator Pattern
Generate type-safe TypeScript code from GraphQL schemas and operations to eliminate manual type maintenance
When to Use
- Starting a new GraphQL project with TypeScript
- Adding type safety to existing GraphQL queries and mutations
- Generating typed React hooks for Apollo Client or urql
- Generating resolver type signatures for the server
- Keeping TypeScript types in sync with schema changes
Instructions
- Install the codegen CLI and core plugins.
npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-resolvers
- Create a
configuration file at the project root. Use the TypeScript config format for type-safe configuration.codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { schema: 'src/schema/**/*.graphql', documents: 'src/**/*.{ts,tsx}', generates: { 'src/__generated__/types.ts': { plugins: ['typescript', 'typescript-operations'], config: { strictScalars: true, scalars: { DateTime: 'string', JSON: 'Record<string, unknown>', }, }, }, 'src/__generated__/resolvers.ts': { plugins: ['typescript', 'typescript-resolvers'], config: { useIndexSignature: true, contextType: '../context#Context', }, }, }, }; export default config;
- Use
for end-to-end type safety. This plugin generates typed document nodes that carry their variables and result types — Apollo Client and urql pick them up automatically.TypedDocumentNode
// codegen generates: // export const GetUserDocument: TypedDocumentNode<GetUserQuery, GetUserQueryVariables> // Usage — variables and data are fully typed with no extra annotations: const { data } = useQuery(GetUserDocument, { variables: { id: '1' } }); // data.user.name is typed as string
- Generate typed React hooks for client-side usage. Add the
ortypescript-react-apollo
plugin to generatetypescript-urql
hooks directly.useGetUserQuery()
// codegen.ts addition 'src/__generated__/hooks.ts': { plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'], config: { withHooks: true, withComponent: false, }, },
- Use
preset to co-locate generated types next to the files that define the operations, instead of one giant generated file.near-operation-file
generates: { 'src/': { preset: 'near-operation-file', presetConfig: { extension: '.generated.ts', baseTypesPath: '__generated__/types.ts' }, plugins: ['typescript-operations', 'typescript-react-apollo'], }, },
- Run codegen in watch mode during development and as a CI check to ensure types are up to date.
{ "scripts": { "codegen": "graphql-codegen", "codegen:watch": "graphql-codegen --watch" } }
-
Enable
to force explicit scalar mappings. Without this, custom scalars default tostrictScalars
, defeating the purpose of code generation.any -
Type your resolvers with the generated
type. This catches mismatches between your schema and resolver implementations at compile time.Resolvers
import { Resolvers } from './__generated__/resolvers'; export const resolvers: Resolvers = { Query: { user: async (_parent, { id }, context) => { // args.id is typed as string, return type is enforced return context.dataSources.users.findById(id); }, }, };
- Add generated files to
or commit them — pick one strategy and enforce it. Committing ensures CI does not need the schema endpoint; ignoring ensures no stale generated code..gitignore
Details
Plugin ecosystem:
typescript (base types from schema), typescript-operations (types from queries/mutations), typescript-resolvers (resolver signatures), typescript-react-apollo / typescript-urql (framework hooks), typed-document-node (framework-agnostic typed documents).
Schema sources: Codegen can read schemas from
.graphql files, a running endpoint, a JSON introspection result, or code-first builders. Prefer .graphql files for CI stability.
Fragment handling: Codegen generates types for fragments and composes them into operation types. Use fragments for shared fields to keep generated types DRY.
Enum handling: By default, codegen generates TypeScript
enum. Set enumsAsTypes: true to generate union string literals instead, which work better with tree-shaking and are simpler to use.
Common mistakes:
- Forgetting to re-run codegen after schema changes (use watch mode or CI check)
- Not mapping custom scalars, resulting in
types leaking throughany - Generating into
or build output (generate intonode_modules
)src/ - Mixing hand-written and generated types for the same schema entity
Source
https://the-guild.dev/graphql/codegen
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.