Currently GraphQL v17 is in alpha, this guide is based on the alpha release and is subject to change.
Breaking changes
Default values
GraphQL schemas allow default values for input fields and arguments. Historically, GraphQL.js did not rigorously validate or coerce these defaults during schema construction, leading to potential runtime errors or inconsistencies. For example:
- A default value of “5” (string) for an Int-type argument would pass schema validation but fail at runtime.
- Internal serialization methods like astFromValue could produce invalid ASTs if inputs were not properly coerced.
With the new changes default values will be validated and coerced during schema construction.
input ExampleInput {
value: Int = "invalid" # Now triggers a validation error
}
This goes hand-in-hand with the deprecation of astFromValue
in favor of valueToLiteral
or default: { value: <externalValue> }
.
// Before (deprecated)
const defaultValue = astFromValue(internalValue, type);
// After
const defaultValue = valueToLiteral(externalValue, type);
If you want to continue using the old behavior, you can use defaultValue
in your schema definitions. The new
behavior will be exposed as default: { literal: <literal> }
.
GraphQLError constructor arguments
The GraphQLError
constructor now only accepts a message and options object as arguments. Previously, it also accepted positional arguments.
- new GraphQLError('message', 'source', 'positions', 'path', 'originalError', 'extensions');
+ new GraphQLError('message', { source, positions, path, originalError, extensions });
createSourceEventStream
arguments
The createSourceEventStream
function now only accepts an object as an argument. Previously, it also accepted positional arguments.
- createSourceEventStream(schema, document, rootValue, contextValue, variableValues, operationName);
+ createSourceEventStream({ schema, document, rootValue, contextValue, variableValues, operationName });
execute
will error for incremental delivery
The execute
function will now throw an error if it sees a @defer
or @stream
directive. Use experimentalExecuteIncrementally
instead.
If you know you are dealing with incremental delivery requests, you can replace the import.
- import { execute } from 'graphql';
+ import { experimentalExecuteIncrementally as execute } from 'graphql';
Remove incremental delivery support from subscribe
In case you have fragments that you use with defer/stream
that end up in a subscription,
use the if
argument of the directive to disable it in your subscription operation
subscribe
return type
The subscribe
function can now also return a non-Promise value, previously this was only a Promise.
This shouldn’t change a lot as await value
will still work as expected. This could lead to
some typing inconsistencies though.
Remove singleResult
from incremental results
You can remove branches that check for singleResult
in your code, as it is no longer used.
Node support
Dropped support for Node 14 (subject to change)
Removed TokenKindEnum
, KindEnum
and DirectiveLocationEnum
types
We have removed the TokenKindEnum
, KindEnum
and DirectiveLocationEnum
types,
use Kind
, TokenKind
and DirectiveLocation
instead. https://github.com/graphql/graphql-js/pull/3579
Removed graphql/subscription
module
use graphql/execution
instead for subscriptions, all execution related exports have been
unified there.
Removed GraphQLInterfaceTypeNormalizedConfig
export
Use ReturnType<GraphQLInterfaceType['toConfig']>
if you really need this
Empty AST collections will be undefined
Empty AST collections will be presented by undefined
rather than an empty array.
Info.variableValues
The shape of Info.variableValues
has changed to be an object containing
sources
and coerced
as keys.
A Source contains the signature
and provided value
pre-coercion for the
variable. A signature
is an object containing the name
, input-type
and
defaultValue
for the variable.
Stream directive can’t be on multiple instances of the same field
The @stream
directive can’t be on multiple instances of the same field,
this won’t pass validate
anymore.
See https://github.com/graphql/graphql-js/pull/4342
Stream initialCount becomes non-nullable
The initialCount
argument of the @stream
directive is now non-nullable.
See https://github.com/graphql/graphql-js/pull/4322
GraphQLSchemas converted to configuration may no longer be assumed valid
The assumeValid
config property exported by the GraphQLSchema.toConfig()
method now passes through the original
flag passed on creation of the GraphQLSchema
.
Previously, the assumeValid
property would be to true
if validation had been run, potentially concealing the original intent.
See https://github.com/graphql/graphql-js/pull/4244 and https://github.com/graphql/graphql-js/issues/3448
coerceInputValue
returns undefined
on error
coerceInputValue
now aborts early when an error occurs, to optimize execution speed on the happy path.
Use the validateInputValue
helper to retrieve the actual errors.
Removals
- Removed deprecated
getOperationType
function, usegetRootType
on theGraphQLSchema
instance instead - Removed deprecated
getVisitFn
function, usegetEnterLeaveForKind
instead - Removed deprecated
printError
andformatError
utilities, you can usetoString
ortoJSON
on the error as a replacement - Removed deprecated
assertValidName
andisValidNameError
utilities, useassertName
instead - Removed deprecated
assertValidExecutionArguments
function, useassertValidSchema
instead - Removed deprecated
getFieldDefFn
fromTypeInfo
- Removed deprecated
TypeInfo
fromvalidate
https://github.com/graphql/graphql-js/pull/4187
Deprecations
- Deprecated
astFromValue
usevalueToLiteral
instead, when leveragingvalueToLiteral
ensure that you are working with externally provided values i.e. the SDL provided defaultValue to a variable. - Deprecated
valueFromAST
usecoerceInputLiteral
instead - Deprecated
findBreakingChanges()
andfindDangerousChanges()
. UsefindSchemaChanges()
instead, which can also be used to find safe changes. - Deprecated
serialize
.parseValue
, andparseLiteral
properties on scalar type configuration. UsecoerceOutputValue
,coerceInputValue
, andcoerceInputLiteral
instead.
Experimental Features
Experimental Support for Incremental Delivery
- Spec PR / RFC
- enabled only when using
experimentalExecuteIncrementally()
, use of a schema or operation with@defer
/@stream
directives withinexecute()
will now throw. - enable early execution with the new
enableEarlyExecution
configuration option forexperimentalExecuteIncrementally()
.
Experimental Support for Fragment Arguments
- Spec PR
- enable with the new
experimentalFragmentArguments
configuration option forparse()
. - new experimental
Kind.FRAGMENT_ARGUMENT
for visiting - new experimental
TypeInfo
methods and options for handling fragment arguments. - coerce AST via new function
coerceInputLiteral()
with experimental fragment variables argument (as opposed to deprecatedvalueFromAST()
function).
Features
- Added
hideSuggestions
option toexecute
/validate
/subscribe
/… to hide schema-suggestions in error messages - Added
abortSignal
option tographql()
,execute()
, andsubscribe()
allows cancellation of these methods; theabortSignal
can also be passed to field resolvers to cancel asynchronous work that they initiate. extensions
supportsymbol
keys, in addition to the normal string keys.- Added ability for resolver functions to return async iterables.
- Added
perEventExecutor
execution option to allows specifying a custom executor for subscription source stream events, which can be useful for preparing a per event execution context argument. - Added
validateInputValue
andvalidateInputLiteral
helpers to validate input values and literals, respectively. - Added
replaceVariableValues
helper to replace variables within complex scalars uses as inputs. Internally, this allows variables embedded within complex scalars to finally use the correct default values. - Added new
printDirective
helper.