TypeScript Resolvers
Package name | Weekly Downloads | Version | License | Updated |
---|---|---|---|---|
@graphql-codegen/typescript-resolvers | Dec 27th, 2022 |
Installation
yarn add -D @graphql-codegen/typescript-resolvers
Usage Requirements
In order to use this GraphQL Codegen plugin, please make sure that you have GraphQL operations (query
/ mutation
/ subscription
and fragment
) set as documents: …
in your codegen.yml
.
Without loading your GraphQL operations (query
, mutation
, subscription
and fragment
), you won't see any change in the generated output.
Watch Episode #26 of graphql.wtf
for a quick introduction to this plugin and its features:
This plugin generates TypeScript signature for resolve
functions of your GraphQL API.
You can use this plugin to generate simple resolvers signature based on your GraphQL types, or you can change its behavior be providing custom model types (mappers).
You can find a blog post explaining the usage of this plugin here: https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen
Config API Reference
useIndexSignature
type: boolean
default: false
Adds an index signature to any generates resolver.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
useIndexSignature: true
},
},
},
};
export default config;
noSchemaStitching
type: boolean
default: true
Disables/Enables Schema Stitching support.
By default, the resolver signature does not include the support for schema-stitching.
Set to false
to enable that.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
noSchemaStitching: false
},
},
},
};
export default config;
wrapFieldDefinitions
type: boolean
default: true
Set to true
in order to wrap field definitions with FieldWrapper
.
This is useful to allow return types such as Promises and functions. Needed for
compatibility with federation: true
when
customResolveInfo
type: string
default: graphql#GraphQLResolveInfo
You can provide your custom GraphQLResolveInfo instead of the default one from graphql-js
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolveInfo: './my-types#MyResolveInfo'
},
},
},
};
export default config;
customResolverFn
type: string
default: (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => Promise<TResult> | TResult
You can provide your custom ResolveFn instead the default. It has to be a type that uses the generics <TResult, TParent, TContext, TArgs>
Usage Examples
Custom Signature
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolverFn: './my-types#MyResolveFn'
},
},
},
};
export default config;
With Graphile
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolverFn: './my-types#MyResolveFn'
},
},
},
};
export default config;
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
"path/to/file.ts": {
"plugins": [
{
"add": {
"content": "import { GraphileHelpers } from 'graphile-utils/node8plus/fieldHelpers';"
}
},
"typescript",
"typescript-resolvers"
],
"config": {
"customResolverFn": "(\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo & { graphile: GraphileHelpers<TParent> }\n) => Promise<TResult> | TResult;\n"
}
}
}
};
export default config;
directiveResolverMappings
type: Record
Map the usage of a directive into using a specific resolver.
allowParentTypeOverride
type: boolean
Allow you to override the ParentType
generic in each resolver, by avoid enforcing the base type of the generated generic type.
This will generate ParentType = Type
instead of ParentType extends Type = Type
in each resolver.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
allowParentTypeOverride: true
},
},
},
};
export default config;
optionalInfoArgument
type: boolean
Sets info
argument of resolver function to be optional field. Useful for testing.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
optionalInfoArgument: true
},
},
},
};
export default config;
makeResolverTypeCallable
type: boolean
Set to true
in order to allow the Resolver type to be callable
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
makeResolverTypeCallable: true
},
},
},
};
export default config;
addUnderscoreToArgsType
type: boolean
Adds _
to generated Args
types in order to avoid duplicate identifiers.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
addUnderscoreToArgsType: true
},
},
},
};
export default config;
contextType
type: string
Use this configuration to set a custom type for your context
, and it will
affect all the resolvers, without the need to override it using generics each time.
If you wish to use an external type and import it from another file, you can use add
plugin
and add the required import
statement, or you can use a module#type
syntax.
Usage Examples
Custom Context Type
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
contextType: 'MyContext'
},
},
},
};
export default config;
Custom Context Type
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
contextType: './my-types#MyContext'
},
},
},
};
export default config;
fieldContextTypes
type: Array_1
Use this to set a custom type for a specific field context
.
It will only affect the targeted resolvers.
You can either use Field.Path#ContextTypeName
or Field.Path#ExternalFileName#ContextTypeName
Usage Examples
Custom Field Context Types
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
fieldContextTypes: ['MyType.foo#CustomContextType', 'MyType.bar#./my-file#ContextTypeOne']
},
},
},
};
export default config;
rootValueType
type: string
Use this configuration to set a custom type for the rootValue
, and it will
affect resolvers of all root types (Query, Mutation and Subscription), without the need to override it using generics each time.
If you wish to use an external type and import it from another file, you can use add
plugin
and add the required import
statement, or you can use both module#type
or module#namespace#type
syntax.
Usage Examples
Custom RootValue Type
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
rootValueType: 'MyRootValue'
},
},
},
};
export default config;
Custom RootValue Type
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
rootValueType: './my-types#MyRootValue'
},
},
},
};
export default config;
directiveContextTypes
type: Array_1
Use this to set a custom type for a specific field context
decorated by a directive.
It will only affect the targeted resolvers.
You can either use Field.Path#ContextTypeName
or Field.Path#ExternalFileName#ContextTypeName
ContextTypeName should by a generic Type that take the context or field context type as only type parameter.
Usage Examples
Directive Context Extender
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
directiveContextTypes: ['myCustomDirectiveName#./my-file#CustomContextExtender']
},
},
},
};
export default config;
mapperTypeSuffix
type: string
Adds a suffix to the imported names to prevent name clashes.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
mapperTypeSuffix: 'Model'
},
},
},
};
export default config;
mappers
type: object
Replaces a GraphQL type usage with a custom type, allowing you to return custom object from
your resolvers.
You can use both module#type
and module#namespace#type
syntax.
Usage Examples
Custom Context Type
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
mappers: {
User: './my-models#UserDbObject',
Book: './my-models#Collections',
}
},
},
},
};
export default config;
defaultMapper
type: string
Allow you to set the default mapper when it's not being override by mappers
or generics.
You can specify a type name, or specify a string in module#type
or module#namespace#type
format.
The default value of mappers is the TypeScript type generated by typescript
package.
Usage Examples
Replace with any
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
defaultMapper: 'any',
},
},
},
};
export default config;
Custom Base Object
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
defaultMapper: './my-file#BaseObject',
},
},
},
};
export default config;
Wrap default types with Partial
You can also specify a custom wrapper for the original type, without overriding the original generated types, use {T}
to specify the identifier. (for flow, use $Shape<{T}>
)
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
defaultMapper: 'Partial<{T}>',
},
},
},
};
export default config;
Allow deep partial with utility-types
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
plugins: ['typescript', 'typescript-resolver', { add: { content: "import { DeepPartial } from 'utility-types';" } }],
config: {
defaultMapper: 'DeepPartial<{T}>',
},
},
},
};
export default config;
avoidOptionals
type: AvoidOptionalsConfig | boolean
default: false
This will cause the generator to avoid using optionals (?
),
so all field resolvers must be implemented in order to avoid compilation errors.
Usage Examples
Override all definition types
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
plugins: ['typescript', 'typescript-resolver'],
config: {
avoidOptionals: true
},
},
},
};
export default config;
Override only specific definition types
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
plugins: ['typescript', 'typescript-resolver'],
config: {
avoidOptionals: {
field: true,
inputValue: true,
object: true,
defaultValue: true,
}
},
},
},
};
export default config;
showUnusedMappers
type: boolean
default: true
Warns about unused mappers.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
plugins: ['typescript', 'typescript-resolver'],
config: {
showUnusedMappers: true,
},
},
},
};
export default config;
enumValues
type: EnumValuesMap
Overrides the default value of enum values declared in your GraphQL schema, supported
in this plugin because of the need for integration with typescript
package.
See documentation under typescript
plugin for more information and examples.
resolverTypeWrapperSignature
type: string
default: Promise<T> | T
Allow you to override resolverTypeWrapper
definition.
federation
type: boolean
default: false
Supports Apollo Federation
enumPrefix
type: boolean
default: true
Allow you to disable prefixing for generated enums, works in combination with typesPrefix
.
Usage Examples
Disable enum prefixes
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
plugins: ['typescript', 'typescript-resolver'],
config: {
typesPrefix: 'I',
enumPrefix: false
},
},
},
};
export default config;
optionalResolveType
type: boolean
default: false
Sets the __resolveType
field as optional field.
immutableTypes
type: boolean
default: false
Generates immutable types by adding readonly
to properties and uses ReadonlyArray
.
namespacedImportName
type: string
default: ''
Prefixes all GraphQL related generated types with that value, as namespaces import. You can use this feature to allow separation of plugins to different files.
resolverTypeSuffix
type: string
default: Resolvers
Suffix we add to each generated type resolver.
allResolversTypeName
type: string
default: Resolvers
The type name to use when exporting all resolvers signature as unified type.
internalResolversPrefix
type: string
default: '__'
Defines the prefix value used for __resolveType
and __isTypeOf
resolvers.
If you are using mercurius-js
, please set this field to empty string for better compatibility.
onlyResolveTypeForInterfaces
type: boolean
default: false
Turning this flag to true
will generate resolver signature that has only resolveType
for interfaces, forcing developers to write inherited type resolvers in the type itself.
strictScalars
type: boolean
default: false
Makes scalars strict.
If scalars are found in the schema that are not defined in scalars
an error will be thrown during codegen.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
strictScalars: true,
},
},
},
};
export default config;
defaultScalarType
type: string
default: any
Allows you to override the type that unknown scalars will have.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
defaultScalarType: 'unknown'
},
},
},
};
export default config;
scalars
type: ScalarsMap_1
Extends or overrides the built-in scalars and custom GraphQL scalars to a custom type.
namingConvention
type: NamingConvention_1
default: change-case-all#pascalCase
Allow you to override the naming convention of the output.
You can either override all namings, or specify an object with specific custom naming convention per output.
The format of the converter must be a valid module#method
.
Allowed values for specific output are: typeNames
, enumValues
.
You can also use "keep" to keep all GraphQL names as-is.
Additionally, you can set transformUnderscore
to true
if you want to override the default behavior,
which is to preserve underscores.
Available case functions in change-case-all
are camelCase
, capitalCase
, constantCase
, dotCase
, headerCase
, noCase
, paramCase
, pascalCase
, pathCase
, sentenceCase
, snakeCase
, lowerCase
, localeLowerCase
, lowerCaseFirst
, spongeCase
, titleCase
, upperCase
, localeUpperCase
and upperCaseFirst
See more
typesPrefix
typesSuffix
skipTypename
type: boolean
default: false
Does not add __typename
to the generated types, unless it was specified in the selection set.
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
skipTypename: true
},
},
},
};
export default config;
nonOptionalTypename
type: boolean
default: false
Automatically adds __typename
field to the generated types, even when they are not specified
in the selection set, and makes it non-optional
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
nonOptionalTypename: true
},
},
},
};
export default config;
useTypeImports
type: boolean
default: false
Will use import type {}
rather than import {}
when importing only types. This gives
compatibility with TypeScript's "importsNotUsedAsValues": "error" option
Usage Examples
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
// ...
generates: {
'path/to/file': {
// plugins...
config: {
useTypeImports: true
},
},
},
};
export default config;
dedupeFragments
type: boolean
default: false
Removes fragment duplicates for reducing data transfer. It is done by removing sub-fragments imports from fragment definition Instead - all of them are imported to the Operation node.
inlineFragmentTypes
type: string
default: inline
Whether fragment types should be inlined into other operations. "inline" is the default behavior and will perform deep inlining fragment types within operation type definitions. "combine" is the previous behavior that uses fragment type references without inlining the types (and might cause issues with deeply nested fragment that uses list types).
emitLegacyCommonJSImports
type: boolean
default: true
Emit legacy common js imports.
Default it will be true
this way it ensure that generated code works with non-compliant bundlers.
Usage Example
Quick Start with typescript-resolvers
You can find a blog post we wrote about using and customizing this plugin here
Run graphql-codegen
as usual, with this new plugin:
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'schema.json',
generates: {
'./src/resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
Import the types from the generated file and use in the resolver:
import { Resolvers } from './resolvers-types'
export const resolvers: Resolvers = {
Query: {
myQuery: (root, args, context) => {}
}
}
This will make the resolver fully typed and compatible with typescript compiler, including the handler's arguments and return value.
Generated resolvers can be passed directly into graphql-tools makeExecutableSchema
function.
Integration with Apollo-Server
By default apollo-server
will not work with generated resolvers signature.
If you are using Apollo Server with TypeScript, note that you need to set useIndexSignature: true
in your config, in order to add a compatible index signature (more info).
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
generates: {
'./resolvers-types.ts': {
config: {
useIndexSignature: true
},
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
If you wish to have an easy start, and have the ability to use resolvers chaining without models types, you can also add to your config defaultMapper: Partial<{T}>
. This will allow you to return partial types in your resolvers.
Use Your Model Types (mappers
)
If you wish to use your custom model types, codegen allow you to use mappers
feature to map GraphQL types to your custom model types. You can find an article explaining how to use mappers
here.
Here's the basic example of using it:
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'./resolvers-types.ts': {
config: {
contextType: 'models#MyContextType',
mappers: {
User: './models#UserModel',
Profile: './models#UserProfile'
}
},
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
Enum Resolvers
Apollo-Server and schemas built with graphql-tools
supports creating resolvers for GraphQL enum
s.
This is helpful because you can have internal values that are different from the public enum values, and you can use the internal values in your resolvers.
Codegen allows you to specify either mappers
or enumValues
to map enums in your resolvers, and if you are using it for enums, you'll get a resolver signature for the enum resolvers as well.
Usage Example
With the following schema:
type Query {
favoriteColor: Color!
}
enum Color {
RED
BLUE
}
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'./resolvers-types.ts': {
config: {
enumValues: {
Color: './enums#ColorsCode'
}
},
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
export enum ColorsCode {
MY_RED = '#FF0000',
MY_BLUE = '#0000FF'
}
import { Resolvers } from './resolvers-types'
import { ColorsCode } from './enums'
const resolvers: Resolvers = {
Color: {
RED: ColorsCode.MY_RED,
BLUE: ColorsCode.MY_BLUE
},
Query: {
favoriteColor: () => ColorsCode.MY_RED // Now you cn return this, and it will be mapped to your actual GraphQL enum
}
}
You can also define the same with explicit enum values:
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'./resolvers-types.ts': {
config: {
enumValues: {
Color: {
RED: '#FF0000',
BLUE: '#0000FF'
}
}
},
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
Or, with mappers
:
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'./resolvers-types.ts': {
config: {
mappers: {
Color: './enums#ColorsCode'
}
},
plugins: ['typescript', 'typescript-resolvers']
}
}
}
export default config
Defined shared mappers across configurations
In some case, you might want to share some common mappers
between many output file configurations.
To do so, you can leverage the YAML references features as follow:
import type { CodegenConfig } from '@graphql-codegen/cli'
const sharedMappers = {
ID: 'IDType'
}
const config: CodegenConfig = {
schema: 'schema.graphql',
documents: 'src/*.ts',
generates: {
'resolvers-types-1.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
mappers: {
...sharedMappers,
String: 'StringType'
}
}
},
'resolvers-types-2.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
mappers: {
...sharedMappers,
String: 'StringType'
}
}
}
}
}
export default config
The above configuration will provide the ID type mapping to both resolvers-types-1.ts
and resolvers-types-2.ts
files.
The complete example is available here: codegen-repros/reusable-mappers
You can also achieve a similar reusable mappers configuration by providing a TypeScript or JavaScript file configuration.