From f96492c096c373f2287cffc3328258245a020b82 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sat, 22 Feb 2025 00:19:49 +0100 Subject: [PATCH] Rename to @experimental_disableErrorPropagation --- src/execution/__tests__/onerror-test.ts | 93 ------------------------- src/execution/execute.ts | 10 +-- src/type/directives.ts | 50 ++----------- 3 files changed, 11 insertions(+), 142 deletions(-) delete mode 100644 src/execution/__tests__/onerror-test.ts diff --git a/src/execution/__tests__/onerror-test.ts b/src/execution/__tests__/onerror-test.ts deleted file mode 100644 index ae1db3cfda..0000000000 --- a/src/execution/__tests__/onerror-test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, it } from 'mocha'; - -import { expectJSON } from '../../__testUtils__/expectJSON.js'; - -import type { PromiseOrValue } from '../../jsutils/PromiseOrValue.js'; - -import { parse } from '../../language/parser.js'; - -import { buildSchema } from '../../utilities/buildASTSchema.js'; - -import { execute } from '../execute.js'; -import type { ExecutionResult } from '../types.js'; - -const syncError = new Error('bar'); - -const throwingData = { - foo() { - throw syncError; - }, -}; - -const schema = buildSchema(` - type Query { - foo : Int! - } - - enum _ErrorAction { PROPAGATE, NULL } - directive @onError(action: _ErrorAction) on QUERY | MUTATION | SUBSCRIPTION -`); - -function executeQuery( - query: string, - rootValue: unknown, -): PromiseOrValue { - return execute({ schema, document: parse(query), rootValue }); -} - -describe('Execute: handles errors', () => { - it('with `@onError(action: NULL) returns null', async () => { - const query = ` - query getFoo @onError(action: NULL) { - foo - } - `; - const result = await executeQuery(query, throwingData); - expectJSON(result).toDeepEqual({ - data: { foo: null }, - errors: [ - { - message: 'bar', - path: ['foo'], - locations: [{ line: 3, column: 9 }], - }, - ], - }); - }); - it('with `@onError(action: PROPAGATE) propagates the error', async () => { - const query = ` - query getFoo @onError(action: PROPAGATE) { - foo - } - `; - const result = await executeQuery(query, throwingData); - expectJSON(result).toDeepEqual({ - data: null, - errors: [ - { - message: 'bar', - path: ['foo'], - locations: [{ line: 3, column: 9 }], - }, - ], - }); - }); - it('by default propagates the error', async () => { - const query = ` - query getFoo { - foo - } - `; - const result = await executeQuery(query, throwingData); - expectJSON(result).toDeepEqual({ - data: null, - errors: [ - { - message: 'bar', - path: ['foo'], - locations: [{ line: 3, column: 9 }], - }, - ], - }); - }); -}); diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 9d043512f3..71cbdb6b42 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -45,8 +45,7 @@ import { isObjectType, } from '../type/definition.js'; import { - ErrorAction, - GraphQLOnErrorDirective, + GraphQLDisableErrorPropagationDirective, GraphQLStreamDirective, } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; @@ -320,9 +319,12 @@ export function executeQueryOrMutationOrSubscriptionEvent( } function errorPropagation(operation: OperationDefinitionNode): boolean { - const value = getDirectiveValues(GraphQLOnErrorDirective, operation); + const directiveNode = operation.directives?.find( + (directive) => + directive.name.value === GraphQLDisableErrorPropagationDirective.name, + ); - return value?.action !== ErrorAction.NULL; + return directiveNode === undefined; } export function experimentalExecuteQueryOrMutationOrSubscriptionEvent( diff --git a/src/type/directives.ts b/src/type/directives.ts index 0a03172d69..96f5b6b65a 100644 --- a/src/type/directives.ts +++ b/src/type/directives.ts @@ -9,7 +9,6 @@ import { toObjMapWithSymbols } from '../jsutils/toObjMap.js'; import type { DirectiveDefinitionNode } from '../language/ast.js'; import { DirectiveLocation } from '../language/directiveLocation.js'; -import { Kind } from '../language/kinds.js'; import { assertName } from './assertName.js'; import type { @@ -17,11 +16,7 @@ import type { GraphQLFieldNormalizedConfigArgumentMap, GraphQLSchemaElement, } from './definition.js'; -import { - GraphQLArgument, - GraphQLEnumType, - GraphQLNonNull, -} from './definition.js'; +import { GraphQLArgument, GraphQLNonNull } from './definition.js'; import { GraphQLBoolean, GraphQLInt, GraphQLString } from './scalars.js'; /** @@ -282,51 +277,16 @@ export const GraphQLOneOfDirective: GraphQLDirective = new GraphQLDirective({ }); /** - * Possible error handling actions. + * Disables error propagation (experimental). */ -export const ErrorAction = { - PROPAGATE: 'PROPAGATE' as const, - NULL: 'NULL' as const, -} as const; - -// eslint-disable-next-line @typescript-eslint/no-redeclare -export type ErrorAction = (typeof ErrorAction)[keyof typeof ErrorAction]; - -export const _ErrorAction = new GraphQLEnumType({ - name: '_ErrorAction', - description: 'Possible error handling actions.', - values: { - PROPAGATE: { - value: ErrorAction.PROPAGATE, - description: - 'Non-nullable positions that error cause the error to propagate to the nearest nullable ancestor position. The error is added to the "errors" list.', - }, - NULL: { - value: ErrorAction.NULL, - description: - 'Positions that error are replaced with a `null` and an error is added to the "errors" list.', - }, - }, -}); - -/** - * Controls how the executor handles errors. - */ -export const GraphQLOnErrorDirective = new GraphQLDirective({ - name: 'onError', - description: 'Controls how the executor handles errors.', +export const GraphQLDisableErrorPropagationDirective = new GraphQLDirective({ + name: 'experimental_disableErrorPropagation', + description: 'Disables error propagation.', locations: [ DirectiveLocation.QUERY, DirectiveLocation.MUTATION, DirectiveLocation.SUBSCRIPTION, ], - args: { - action: { - type: new GraphQLNonNull(_ErrorAction), - description: 'The action to execute when a field error is encountered.', - default: { literal: { kind: Kind.ENUM, value: 'PROPAGATE' } }, - }, - }, }); /**