diff --git a/.changeset/lazy-turtles-dress.md b/.changeset/lazy-turtles-dress.md new file mode 100644 index 00000000000..c98b1dfce1f --- /dev/null +++ b/.changeset/lazy-turtles-dress.md @@ -0,0 +1,25 @@ +--- +'@graphql-tools/batch-execute': major +'@graphql-tools/delegate': major +'@graphql-tools/links': major +'@graphql-tools/utils': major +'@graphql-tools/wrap': major +--- + +BREAKING CHANGES; + +- Rename `Request` to `ExecutionRequest` +- Drop unnecessary `GraphQLResolveInfo` in `ExecutionRequest` +- Add required `operationType: OperationTypeNode` field in `ExecutionRequest` +- Add `context` in `createRequest` and `createRequestInfo` instead of `delegateToSchema` + +> It doesn't rely on info.operation.operationType to allow the user to call an operation from different root type. +And it doesn't call getOperationAST again and again to get operation type from the document/operation because we have it in Request and ExecutionParams +https://github.com/ardatan/graphql-tools/pull/3166/files#diff-d4824895ea613dcc1f710c3ac82e952fe0ca12391b671f70d9f2d90d5656fdceR38 + +Improvements; +- Memoize `defaultExecutor` for a single `GraphQLSchema` so allow `getBatchingExecutor` to memoize `batchingExecutor` correctly. +- And there is no different `defaultExecutor` is created for `subscription` and other operation types. Only one executor is used. + +> Batch executor is memoized by `executor` reference but `createDefaultExecutor` didn't memoize the default executor so this memoization wasn't working correctly on `batch-execute` side. +https://github.com/ardatan/graphql-tools/blob/remove-info-executor/packages/batch-execute/src/getBatchingExecutor.ts#L9 diff --git a/packages/batch-execute/src/createBatchingExecutor.ts b/packages/batch-execute/src/createBatchingExecutor.ts index 98c5e859cd6..2645230bc8e 100644 --- a/packages/batch-execute/src/createBatchingExecutor.ts +++ b/packages/batch-execute/src/createBatchingExecutor.ts @@ -1,10 +1,8 @@ -import { getOperationAST } from 'graphql'; - import DataLoader from 'dataloader'; import { ValueOrPromise } from 'value-or-promise'; -import { Request, Executor, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, Executor, ExecutionResult } from '@graphql-tools/utils'; import { mergeRequests } from './mergeRequests'; import { splitResult } from './splitResult'; @@ -14,32 +12,30 @@ export function createBatchingExecutor( dataLoaderOptions?: DataLoader.Options, extensionsReducer: ( mergedExtensions: Record, - request: Request + request: ExecutionRequest ) => Record = defaultExtensionsReducer ): Executor { const loader = new DataLoader(createLoadFn(executor, extensionsReducer), dataLoaderOptions); - return (request: Request) => - request.info?.operation.operation === 'subscription' ? executor(request) : loader.load(request); + return (request: ExecutionRequest) => { + return request.operationType === 'subscription' ? executor(request) : loader.load(request); + }; } function createLoadFn( executor: Executor, - extensionsReducer: (mergedExtensions: Record, request: Request) => Record + extensionsReducer: (mergedExtensions: Record, request: ExecutionRequest) => Record ) { - return async (requests: ReadonlyArray): Promise> => { - const execBatches: Array> = []; + return async (requests: ReadonlyArray): Promise> => { + const execBatches: Array> = []; let index = 0; const request = requests[index]; - let currentBatch: Array = [request]; + let currentBatch: Array = [request]; execBatches.push(currentBatch); - const operationType = getOperationAST(request.document, undefined)?.operation; - if (operationType == null) { - throw new Error('Could not identify operation type of document.'); - } + const operationType = request.operationType; while (++index < requests.length) { - const currentOperationType = getOperationAST(requests[index].document, undefined)?.operation; + const currentOperationType = requests[index].operationType; if (operationType == null) { throw new Error('Could not identify operation type of document.'); } @@ -68,7 +64,10 @@ function createLoadFn( }; } -function defaultExtensionsReducer(mergedExtensions: Record, request: Request): Record { +function defaultExtensionsReducer( + mergedExtensions: Record, + request: ExecutionRequest +): Record { const newExtensions = request.extensions; if (newExtensions != null) { Object.assign(mergedExtensions, newExtensions); diff --git a/packages/batch-execute/src/getBatchingExecutor.ts b/packages/batch-execute/src/getBatchingExecutor.ts index e315ee3b1a2..4bfda8d6ec7 100644 --- a/packages/batch-execute/src/getBatchingExecutor.ts +++ b/packages/batch-execute/src/getBatchingExecutor.ts @@ -1,14 +1,16 @@ import DataLoader from 'dataloader'; -import { Request, Executor } from '@graphql-tools/utils'; +import { ExecutionRequest, Executor } from '@graphql-tools/utils'; import { createBatchingExecutor } from './createBatchingExecutor'; import { memoize2of4 } from './memoize'; -export const getBatchingExecutor = memoize2of4(function ( +export const getBatchingExecutor = memoize2of4(function getBatchingExecutor( _context: Record, executor: Executor, dataLoaderOptions?: DataLoader.Options | undefined, - extensionsReducer?: undefined | ((mergedExtensions: Record, request: Request) => Record) + extensionsReducer?: + | undefined + | ((mergedExtensions: Record, request: ExecutionRequest) => Record) ): Executor { return createBatchingExecutor(executor, dataLoaderOptions, extensionsReducer); }); diff --git a/packages/batch-execute/src/mergeRequests.ts b/packages/batch-execute/src/mergeRequests.ts index 6c14b168998..d40f35f3442 100644 --- a/packages/batch-execute/src/mergeRequests.ts +++ b/packages/batch-execute/src/mergeRequests.ts @@ -15,10 +15,9 @@ import { ASTKindToNode, InlineFragmentNode, FieldNode, - OperationTypeNode, } from 'graphql'; -import { Request, Maybe } from '@graphql-tools/utils'; +import { ExecutionRequest } from '@graphql-tools/utils'; import { createPrefix } from './prefix'; @@ -57,24 +56,21 @@ import { createPrefix } from './prefix'; * } */ export function mergeRequests( - requests: Array, - extensionsReducer: (mergedExtensions: Record, request: Request) => Record -): Request { + requests: Array, + extensionsReducer: (mergedExtensions: Record, request: ExecutionRequest) => Record +): ExecutionRequest { const mergedVariables: Record = Object.create(null); const mergedVariableDefinitions: Array = []; const mergedSelections: Array = []; const mergedFragmentDefinitions: Array = []; let mergedExtensions: Record = Object.create(null); - let operation: Maybe; - for (const index in requests) { const request = requests[index]; const prefixedRequests = prefixRequest(createPrefix(index), request); for (const def of prefixedRequests.document.definitions) { if (isOperationDefinition(def)) { - operation = def.operation; mergedSelections.push(...def.selectionSet.selections); if (def.variableDefinitions) { mergedVariableDefinitions.push(...def.variableDefinitions); @@ -88,13 +84,9 @@ export function mergeRequests( mergedExtensions = extensionsReducer(mergedExtensions, request); } - if (operation == null) { - throw new Error('Could not identify operation type. Did the document only include fragment definitions?'); - } - const mergedOperationDefinition: OperationDefinitionNode = { kind: Kind.OPERATION_DEFINITION, - operation, + operation: requests[0].operationType, variableDefinitions: mergedVariableDefinitions, selectionSet: { kind: Kind.SELECTION_SET, @@ -111,10 +103,11 @@ export function mergeRequests( extensions: mergedExtensions, context: requests[0].context, info: requests[0].info, + operationType: requests[0].operationType, }; } -function prefixRequest(prefix: string, request: Request): Request { +function prefixRequest(prefix: string, request: ExecutionRequest): ExecutionRequest { let document = aliasTopLevelFields(prefix, request.document); const executionVariables = request.variables ?? {}; const variableNames = Object.keys(executionVariables); @@ -137,6 +130,7 @@ function prefixRequest(prefix: string, request: Request): Request { return { document, variables: prefixedVariables, + operationType: request.operationType, }; } diff --git a/packages/delegate/src/Transformer.ts b/packages/delegate/src/Transformer.ts index 376cb24015c..6e2e807f1fd 100644 --- a/packages/delegate/src/Transformer.ts +++ b/packages/delegate/src/Transformer.ts @@ -1,4 +1,4 @@ -import { Request, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { DelegationContext, DelegationBinding, Transform } from './types'; @@ -25,9 +25,9 @@ export class Transformer> { this.transformations.push({ transform, context }); } - public transformRequest(originalRequest: Request) { + public transformRequest(originalRequest: ExecutionRequest) { return this.transformations.reduce( - (request: Request, transformation: Transformation) => + (request: ExecutionRequest, transformation: Transformation) => transformation.transform.transformRequest != null ? transformation.transform.transformRequest(request, this.delegationContext, transformation.context) : request, diff --git a/packages/delegate/src/createRequest.ts b/packages/delegate/src/createRequest.ts index 4a298a073e7..e73b0758c4a 100644 --- a/packages/delegate/src/createRequest.ts +++ b/packages/delegate/src/createRequest.ts @@ -16,7 +16,7 @@ import { DocumentNode, } from 'graphql'; -import { Request, serializeInputValue, updateArgument } from '@graphql-tools/utils'; +import { ExecutionRequest, serializeInputValue, updateArgument } from '@graphql-tools/utils'; import { ICreateRequestFromInfo, ICreateRequest } from './types'; export function getDelegatingOperation(parentType: GraphQLObjectType, schema: GraphQLSchema): OperationTypeNode { @@ -37,7 +37,8 @@ export function createRequestFromInfo({ fieldName = info.fieldName, selectionSet, fieldNodes = info.fieldNodes, -}: ICreateRequestFromInfo): Request { + context, +}: ICreateRequestFromInfo): ExecutionRequest { return createRequest({ sourceSchema: info.schema, sourceParentType: info.parentType, @@ -51,6 +52,8 @@ export function createRequestFromInfo({ targetFieldName: fieldName, selectionSet, fieldNodes, + context, + info, }); } @@ -67,7 +70,9 @@ export function createRequest({ targetFieldName, selectionSet, fieldNodes, -}: ICreateRequest): Request { + context, + info, +}: ICreateRequest): ExecutionRequest { let newSelectionSet: SelectionSetNode | undefined; let argumentNodeMap: Record; @@ -176,6 +181,9 @@ export function createRequest({ variables: newVariables, rootValue: targetRootValue, operationName: targetOperationName, + operationType: targetOperation, + context, + info, }; } diff --git a/packages/delegate/src/delegateToSchema.ts b/packages/delegate/src/delegateToSchema.ts index 60ce50c1c03..53938ae1ebf 100644 --- a/packages/delegate/src/delegateToSchema.ts +++ b/packages/delegate/src/delegateToSchema.ts @@ -9,6 +9,7 @@ import { OperationDefinitionNode, DocumentNode, GraphQLOutputType, + ExecutionArgs, } from 'graphql'; import { ValueOrPromise } from 'value-or-promise'; @@ -18,7 +19,7 @@ import { getBatchingExecutor } from '@graphql-tools/batch-execute'; import { mapAsyncIterator, Executor, - Request, + ExecutionRequest, Maybe, AggregateError, isAsyncIterable, @@ -50,6 +51,7 @@ export function delegateToSchema, TArgs = any>( fieldName = info.fieldName, selectionSet, fieldNodes, + context, } = options; const request = createRequestFromInfo({ @@ -60,6 +62,7 @@ export function delegateToSchema, TArgs = any>( fieldNodes, rootValue: rootValue ?? (schema as SubschemaConfig).rootValue, operationName, + context, }); return delegateRequest({ @@ -90,17 +93,9 @@ export function delegateRequest, TArgs = any>( validateRequest(delegationContext, processedRequest.document); } - const { context, info } = delegationContext; - const executor = getExecutor(delegationContext); - return new ValueOrPromise(() => - executor({ - ...processedRequest, - context, - info, - }) - ) + return new ValueOrPromise(() => executor(processedRequest)) .then(originalResult => { if (isAsyncIterable(originalResult)) { // "subscribe" to the subscription result and map the result through the transforms @@ -116,32 +111,23 @@ export function delegateRequest, TArgs = any>( function getDelegationContext({ request, schema, - operation, fieldName, returnType, args, - context, info, transforms = [], transformedSchema, skipTypeMerging = false, }: IDelegateRequestOptions): DelegationContext { + const { operationType: operation, context, operationName, document } = request; let operationDefinition: Maybe; - let targetOperation: Maybe; let targetFieldName: string; - if (operation == null) { - operationDefinition = getOperationAST(request.document, request.operationName); + if (fieldName == null) { + operationDefinition = getOperationAST(document, operationName); if (operationDefinition == null) { throw new Error('Cannot infer main operation from the provided document.'); } - targetOperation = operationDefinition.operation; - } else { - targetOperation = operation; - } - - if (fieldName == null) { - operationDefinition = operationDefinition ?? getOperationAST(request.document, request.operationName); targetFieldName = (operationDefinition?.selectionSet.selections[0] as unknown as FieldDefinitionNode).name.value; } else { targetFieldName = fieldName; @@ -158,13 +144,12 @@ function getDelegationContext({ subschema: schema, subschemaConfig: subschemaOrSubschemaConfig, targetSchema, - operation: targetOperation, + operation, fieldName: targetFieldName, args, context, info, - returnType: - returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, targetOperation, targetFieldName), + returnType: returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, operation, targetFieldName), transforms: subschemaOrSubschemaConfig.transforms != null ? subschemaOrSubschemaConfig.transforms.concat(transforms) @@ -180,15 +165,13 @@ function getDelegationContext({ subschema: schema, subschemaConfig: undefined, targetSchema: subschemaOrSubschemaConfig, - operation: targetOperation, + operation, fieldName: targetFieldName, args, context, info, returnType: - returnType ?? - info?.returnType ?? - getDelegationReturnType(subschemaOrSubschemaConfig, targetOperation, targetFieldName), + returnType ?? info?.returnType ?? getDelegationReturnType(subschemaOrSubschemaConfig, operation, targetFieldName), transforms, transformedSchema: transformedSchema ?? subschemaOrSubschemaConfig, skipTypeMerging, @@ -208,9 +191,9 @@ function validateRequest(delegationContext: DelegationContext, document: Do } function getExecutor(delegationContext: DelegationContext): Executor { - const { subschemaConfig, targetSchema, context, operation } = delegationContext; + const { subschemaConfig, targetSchema, context } = delegationContext; - let executor: Executor = subschemaConfig?.executor || createDefaultExecutor(targetSchema, operation); + let executor: Executor = subschemaConfig?.executor || createDefaultExecutor(targetSchema); if (subschemaConfig?.batch) { const batchingOptions = subschemaConfig?.batchingOptions; @@ -225,26 +208,33 @@ function getExecutor(delegationContext: DelegationContext): return executor; } -function createDefaultExecutor(schema: GraphQLSchema, operation: OperationTypeNode): Executor { - if (operation === 'subscription') { - return (({ document, context, variables, rootValue, operationName }: Request) => - subscribe({ +const defaultExecutorCache = new WeakMap(); + +function createDefaultExecutor(schema: GraphQLSchema): Executor { + let defaultExecutor = defaultExecutorCache.get(schema); + if (!defaultExecutor) { + defaultExecutor = function defaultExecutor({ + document, + context, + variables, + rootValue, + operationName, + operationType, + }: ExecutionRequest) { + const executionArgs: ExecutionArgs = { schema, document, contextValue: context, variableValues: variables, rootValue, operationName, - })) as Executor; + }; + if (operationType === 'subscription') { + return subscribe(executionArgs); + } + return execute(executionArgs); + } as Executor; + defaultExecutorCache.set(schema, defaultExecutor); } - - return (({ document, context, variables, rootValue, operationName }: Request) => - execute({ - schema, - document, - contextValue: context, - variableValues: variables, - rootValue, - operationName, - })) as Executor; + return defaultExecutor; } diff --git a/packages/delegate/src/index.ts b/packages/delegate/src/index.ts index 68f0066911f..cf3f755b8e8 100644 --- a/packages/delegate/src/index.ts +++ b/packages/delegate/src/index.ts @@ -9,4 +9,3 @@ export * from './resolveExternalValue'; export * from './subschemaConfig'; export * from './transforms'; export * from './types'; -export { Executor, AsyncExecutor, SyncExecutor, Request } from '@graphql-tools/utils'; diff --git a/packages/delegate/src/transforms/AddArgumentsAsVariables.ts b/packages/delegate/src/transforms/AddArgumentsAsVariables.ts index dfc77be8397..6326c515e59 100644 --- a/packages/delegate/src/transforms/AddArgumentsAsVariables.ts +++ b/packages/delegate/src/transforms/AddArgumentsAsVariables.ts @@ -10,7 +10,7 @@ import { VariableDefinitionNode, } from 'graphql'; -import { getDefinedRootType, Request, serializeInputValue, updateArgument } from '@graphql-tools/utils'; +import { getDefinedRootType, ExecutionRequest, serializeInputValue, updateArgument } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; @@ -28,10 +28,10 @@ export default class AddArgumentsAsVariables implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const { document, variables } = addVariablesToRootField(delegationContext.targetSchema, originalRequest, this.args); return { @@ -44,7 +44,7 @@ export default class AddArgumentsAsVariables implements Transform { function addVariablesToRootField( targetSchema: GraphQLSchema, - originalRequest: Request, + originalRequest: ExecutionRequest, args: Record ): { document: DocumentNode; diff --git a/packages/delegate/src/transforms/AddSelectionSets.ts b/packages/delegate/src/transforms/AddSelectionSets.ts index 3ffad61e54a..4a5951c59bc 100644 --- a/packages/delegate/src/transforms/AddSelectionSets.ts +++ b/packages/delegate/src/transforms/AddSelectionSets.ts @@ -1,6 +1,6 @@ import { SelectionSetNode, TypeInfo, Kind, FieldNode, SelectionNode, print } from 'graphql'; -import { Maybe, Request } from '@graphql-tools/utils'; +import { Maybe, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; import { memoize2 } from '../memoize'; @@ -21,10 +21,10 @@ export default class AddSelectionSets implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/delegate/src/transforms/AddTypenameToAbstract.ts b/packages/delegate/src/transforms/AddTypenameToAbstract.ts index 0eb25a2416c..f254e17d36a 100644 --- a/packages/delegate/src/transforms/AddTypenameToAbstract.ts +++ b/packages/delegate/src/transforms/AddTypenameToAbstract.ts @@ -10,16 +10,16 @@ import { isAbstractType, } from 'graphql'; -import { Maybe, Request } from '@graphql-tools/utils'; +import { Maybe, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; export default class AddTypenameToAbstract implements Transform { public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const document = addTypenameToAbstract(delegationContext.targetSchema, originalRequest.document); return { ...originalRequest, diff --git a/packages/delegate/src/transforms/ExpandAbstractTypes.ts b/packages/delegate/src/transforms/ExpandAbstractTypes.ts index f320397c209..da26311280b 100644 --- a/packages/delegate/src/transforms/ExpandAbstractTypes.ts +++ b/packages/delegate/src/transforms/ExpandAbstractTypes.ts @@ -15,16 +15,16 @@ import { visitWithTypeInfo, } from 'graphql'; -import { implementsAbstractType, Request } from '@graphql-tools/utils'; +import { implementsAbstractType, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; export default class ExpandAbstractTypes implements Transform { public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const targetSchema = delegationContext.targetSchema; const { possibleTypesMap, interfaceExtensionsMap } = extractPossibleTypes( delegationContext.info.schema, diff --git a/packages/delegate/src/transforms/FilterToSchema.ts b/packages/delegate/src/transforms/FilterToSchema.ts index bb1f6767c5b..5f256405cca 100644 --- a/packages/delegate/src/transforms/FilterToSchema.ts +++ b/packages/delegate/src/transforms/FilterToSchema.ts @@ -21,16 +21,16 @@ import { isInterfaceType, } from 'graphql'; -import { Request, implementsAbstractType, TypeMap, getDefinedRootType } from '@graphql-tools/utils'; +import { ExecutionRequest, implementsAbstractType, TypeMap, getDefinedRootType } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; export default class FilterToSchema implements Transform { public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { return { ...originalRequest, ...filterToSchema(delegationContext.targetSchema, originalRequest.document, originalRequest.variables), diff --git a/packages/delegate/src/transforms/VisitSelectionSets.ts b/packages/delegate/src/transforms/VisitSelectionSets.ts index 0c7acb9efaf..1b131eddcec 100644 --- a/packages/delegate/src/transforms/VisitSelectionSets.ts +++ b/packages/delegate/src/transforms/VisitSelectionSets.ts @@ -13,7 +13,13 @@ import { DefinitionNode, } from 'graphql'; -import { Request, collectFields, GraphQLExecutionContext, Maybe, getDefinedRootType } from '@graphql-tools/utils'; +import { + ExecutionRequest, + collectFields, + GraphQLExecutionContext, + Maybe, + getDefinedRootType, +} from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; @@ -27,10 +33,10 @@ export default class VisitSelectionSets implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const document = visitSelectionSets( originalRequest, delegationContext.info.schema, @@ -45,7 +51,7 @@ export default class VisitSelectionSets implements Transform { } function visitSelectionSets( - request: Request, + request: ExecutionRequest, schema: GraphQLSchema, initialType: GraphQLOutputType, visitor: VisitSelectionSetsVisitor diff --git a/packages/delegate/src/transforms/WrapConcreteTypes.ts b/packages/delegate/src/transforms/WrapConcreteTypes.ts index 4b12e78a900..8a252904293 100644 --- a/packages/delegate/src/transforms/WrapConcreteTypes.ts +++ b/packages/delegate/src/transforms/WrapConcreteTypes.ts @@ -13,7 +13,7 @@ import { FragmentDefinitionNode, } from 'graphql'; -import { getRootTypeNames, Request } from '@graphql-tools/utils'; +import { getRootTypeNames, ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '../types'; @@ -21,10 +21,10 @@ import { Transform, DelegationContext } from '../types'; export default class WrapConcreteTypes implements Transform { public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const document = wrapConcreteTypes( delegationContext.returnType, delegationContext.targetSchema, diff --git a/packages/delegate/src/types.ts b/packages/delegate/src/types.ts index 17c101a03c6..5b0dcaee820 100644 --- a/packages/delegate/src/types.ts +++ b/packages/delegate/src/types.ts @@ -14,7 +14,7 @@ import { import DataLoader from 'dataloader'; -import { Request, ExecutionResult, Executor, TypeMap } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult, Executor, TypeMap } from '@graphql-tools/utils'; import { Subschema } from './Subschema'; import { OBJECT_SUBSCHEMA_SYMBOL, FIELD_SUBSCHEMA_MAP_SYMBOL, UNPATHED_ERRORS_SYMBOL } from './symbols'; @@ -25,10 +25,10 @@ export type SchemaTransform> = ( transformedSchema?: GraphQLSchema ) => GraphQLSchema; export type RequestTransform> = ( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: T -) => Request; +) => ExecutionRequest; export type ResultTransform> = ( originalResult: ExecutionResult, delegationContext: DelegationContext, @@ -56,7 +56,6 @@ export interface DelegationContext> { transforms: Array>; transformedSchema: GraphQLSchema; skipTypeMerging: boolean; - operationName?: string; } export type DelegationBinding> = ( @@ -85,7 +84,7 @@ export interface IDelegateToSchemaOptions, TArgs export interface IDelegateRequestOptions, TArgs = Record> extends IDelegateToSchemaOptions { - request: Request; + request: ExecutionRequest; } export interface ICreateRequestFromInfo { @@ -96,6 +95,7 @@ export interface ICreateRequestFromInfo { fieldName?: string; selectionSet?: SelectionSetNode; fieldNodes?: ReadonlyArray; + context?: any; } export interface ICreateRequest { @@ -111,6 +111,8 @@ export interface ICreateRequest { targetFieldName: string; selectionSet?: SelectionSetNode; fieldNodes?: ReadonlyArray; + context?: any; + info?: GraphQLResolveInfo; } export interface MergedTypeInfo> { @@ -137,7 +139,7 @@ export type CreateProxyingResolverFn> = ( ) => GraphQLFieldResolver; export interface BatchingOptions { - extensionsReducer?: (mergedExtensions: Record, request: Request) => Record; + extensionsReducer?: (mergedExtensions: Record, request: ExecutionRequest) => Record; dataLoaderOptions?: DataLoader.Options; } diff --git a/packages/delegate/tests/batchExecution.test.ts b/packages/delegate/tests/batchExecution.test.ts index 93c82b8a0a0..51972c15444 100644 --- a/packages/delegate/tests/batchExecution.test.ts +++ b/packages/delegate/tests/batchExecution.test.ts @@ -1,9 +1,10 @@ import { graphql, execute, ExecutionResult } from 'graphql'; import { makeExecutableSchema } from '@graphql-tools/schema'; -import { delegateToSchema, SubschemaConfig, Request, SyncExecutor, Executor } from '../src'; +import { delegateToSchema, SubschemaConfig } from '../src'; import { stitchSchemas } from '@graphql-tools/stitch'; import { FilterObjectFields } from '@graphql-tools/wrap'; +import { ExecutionRequest, Executor, SyncExecutor } from '@graphql-tools/utils'; describe('batch execution', () => { it('should batch', async () => { @@ -27,7 +28,7 @@ describe('batch execution', () => { const innerSubschemaConfig: SubschemaConfig = { schema: innerSchema, batch: true, - executor: ((request: Request): ExecutionResult => { + executor: ((request: ExecutionRequest): ExecutionResult => { executions++; return execute(innerSchema, request.document, undefined, request.context, request.variables) as ExecutionResult; }) as SyncExecutor @@ -104,7 +105,7 @@ describe('batch execution', () => { let executions = 0; - const executor = ((request: Request): ExecutionResult => { + const executor = ((request: ExecutionRequest): ExecutionResult => { executions++; return execute(innerSchemaA, request.document, undefined, request.context, request.variables) as ExecutionResult; }) as Executor; diff --git a/packages/links/src/linkToExecutor.ts b/packages/links/src/linkToExecutor.ts index 685cd37612c..854e05bcc5f 100644 --- a/packages/links/src/linkToExecutor.ts +++ b/packages/links/src/linkToExecutor.ts @@ -2,12 +2,12 @@ import { toPromise } from '@apollo/client/core'; import { ApolloLink, execute } from '@apollo/client/link/core'; import { Observable } from '@apollo/client/utilities'; -import { Executor, Request, ExecutionResult, observableToAsyncIterable } from '@graphql-tools/utils'; +import { Executor, ExecutionRequest, ExecutionResult, observableToAsyncIterable } from '@graphql-tools/utils'; export const linkToExecutor = (link: ApolloLink): Executor => - async (request: Request) => { - const { document, variables, extensions, context, info, operationName } = request; + async (params: ExecutionRequest) => { + const { document, variables, extensions, context, operationType, operationName, info } = params; const observable = execute(link, { query: document, variables, @@ -19,7 +19,7 @@ export const linkToExecutor = extensions, operationName, }) as Observable>; - if (info?.operation.operation === 'subscription') { + if (operationType === 'subscription') { return observableToAsyncIterable>(observable)[Symbol.asyncIterator](); } return toPromise(observable); diff --git a/packages/loaders/url/src/index.ts b/packages/loaders/url/src/index.ts index 2af5fe7f9cc..090d72c7141 100644 --- a/packages/loaders/url/src/index.ts +++ b/packages/loaders/url/src/index.ts @@ -11,7 +11,7 @@ import { BaseLoaderOptions, observableToAsyncIterable, isAsyncIterable, - Request, + ExecutionRequest, mapAsyncIterator, withCancel, parseGraphQLSDL, @@ -304,12 +304,12 @@ export class UrlLoader implements Loader { variables, operationName, extensions, - }: Request) => { + operationType, + }: ExecutionRequest) => { const controller = new AbortController(); let method = defaultMethod; if (options?.useGETForQueries) { - const operationAst = getOperationAST(document, operationName); - if (operationAst?.operation === 'query') { + if (operationType === 'query') { method = 'GET'; } else { method = defaultMethod; @@ -472,7 +472,7 @@ export class UrlLoader implements Loader { webSocketImpl ); - return async ({ document, variables, operationName }: Request) => { + return async ({ document, variables, operationName }: ExecutionRequest) => { return observableToAsyncIterable( subscriptionClient.request({ query: document, @@ -619,7 +619,7 @@ export class UrlLoader implements Loader { throw new Error(`No valid operations found: ${params.operationName || ''}`); } if ( - operationAst.operation === 'subscription' || + params.operationType === 'subscription' || isLiveQueryOperationDefinitionNode(operationAst, params.variables as Record) ) { return subscriptionExecutor(params); diff --git a/packages/stitch/tests/errors.test.ts b/packages/stitch/tests/errors.test.ts index b9571d460df..6154b4e16ce 100644 --- a/packages/stitch/tests/errors.test.ts +++ b/packages/stitch/tests/errors.test.ts @@ -1,9 +1,8 @@ import { graphql, GraphQLError, buildSchema } from 'graphql'; -import { Executor } from '@graphql-tools/delegate'; import { makeExecutableSchema } from '@graphql-tools/schema'; import { stitchSchemas } from '@graphql-tools/stitch'; -import { assertSome, ExecutionResult } from '@graphql-tools/utils'; +import { assertSome, ExecutionResult, Executor } from '@graphql-tools/utils'; describe('passes along errors for missing fields on list', () => { test('if non-null', async () => { diff --git a/packages/stitch/tests/fixtures/schemas.ts b/packages/stitch/tests/fixtures/schemas.ts index 9364d9747da..7b3e7555346 100644 --- a/packages/stitch/tests/fixtures/schemas.ts +++ b/packages/stitch/tests/fixtures/schemas.ts @@ -22,10 +22,11 @@ import { ExecutionResult, mapAsyncIterator, isAsyncIterable, + ExecutionRequest, } from '@graphql-tools/utils'; import { makeExecutableSchema } from '@graphql-tools/schema'; -import { Request, SubschemaConfig } from '@graphql-tools/delegate'; +import { SubschemaConfig } from '@graphql-tools/delegate'; export class CustomError extends GraphQLError { constructor(message: string, extensions: Record) { @@ -682,8 +683,8 @@ export const subscriptionSchema: GraphQLSchema = makeExecutableSchema({ }); function makeExecutorFromSchema(schema: GraphQLSchema) { - return async ({ document, variables, context, info }: Request) => { - if (info?.operation.operation === 'subscription') { + return async ({ document, variables, context, operationType }: ExecutionRequest) => { + if (operationType === 'subscription') { const result = subscribe( schema, document, diff --git a/packages/utils/src/Interfaces.ts b/packages/utils/src/Interfaces.ts index 22cc148dc34..5dde9a8d595 100644 --- a/packages/utils/src/Interfaces.ts +++ b/packages/utils/src/Interfaces.ts @@ -48,6 +48,7 @@ import { GraphQLType, Source, DefinitionNode, + OperationTypeNode, } from 'graphql'; // graphql-js < v15 backwards compatible ExecutionResult @@ -58,13 +59,14 @@ export interface ExecutionResult> extends GraphQLExe extensions?: Record; } -export interface Request< +export interface ExecutionRequest< TArgs extends Record = Record, TContext = any, TRootValue = any, TExtensions = Record > { document: DocumentNode; + operationType: OperationTypeNode; variables?: TArgs; extensions?: TExtensions; operationName?: string; diff --git a/packages/utils/src/executor.ts b/packages/utils/src/executor.ts index 45fd4e18747..b6463179c75 100644 --- a/packages/utils/src/executor.ts +++ b/packages/utils/src/executor.ts @@ -1,4 +1,4 @@ -import { ExecutionResult, Request } from './Interfaces'; +import { ExecutionResult, ExecutionRequest } from './Interfaces'; type MaybePromise = Promise | T; type MaybeAsyncIterableIterator = AsyncIterableIterator | T; @@ -10,7 +10,7 @@ export type AsyncExecutor, TBaseExtensions = TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions >( - request: Request + request: ExecutionRequest ) => Promise>>; export type SyncExecutor, TBaseExtensions = Record> = < @@ -20,7 +20,7 @@ export type SyncExecutor, TBaseExtensions = R TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions >( - request: Request + request: ExecutionRequest ) => ExecutionResult; export type Executor, TBaseExtensions = Record> = < @@ -30,5 +30,5 @@ export type Executor, TBaseExtensions = Recor TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions >( - request: Request + request: ExecutionRequest ) => MaybePromise>>; diff --git a/packages/utils/src/visitResult.ts b/packages/utils/src/visitResult.ts index f71725fd41f..dad14ecbc18 100644 --- a/packages/utils/src/visitResult.ts +++ b/packages/utils/src/visitResult.ts @@ -15,7 +15,7 @@ import { TypeNameMetaFieldDef, } from 'graphql'; -import { Request, GraphQLExecutionContext, ExecutionResult } from './Interfaces'; +import { ExecutionRequest, GraphQLExecutionContext, ExecutionResult } from './Interfaces'; import { collectFields } from './collectFields'; import { Maybe } from '@graphql-tools/utils'; @@ -77,7 +77,7 @@ export function visitErrors( } export function visitResult( result: ExecutionResult, - request: Request, + request: ExecutionRequest, schema: GraphQLSchema, resultVisitorMap?: ResultVisitorMap, errorVisitorMap?: ErrorVisitorMap diff --git a/packages/utils/tests/visitResult.test.ts b/packages/utils/tests/visitResult.test.ts index e67ca1a38fd..067e1c38852 100644 --- a/packages/utils/tests/visitResult.test.ts +++ b/packages/utils/tests/visitResult.test.ts @@ -22,6 +22,7 @@ describe('visiting results', () => { const request = { document: parse('{ test { field } }'), variables: {}, + operationType: 'query' as const }; it('should visit without throwing', async () => { @@ -45,7 +46,8 @@ describe('visiting results', () => { it('should visit with a request with introspection fields without throwing', async () => { const introspectionRequest = { document: parse('{ test { field __typename } }'), - variables: {} + variables: {}, + operationType: 'query' as const }; const result = { data: { @@ -226,6 +228,7 @@ describe('visiting nested results', () => { } }`), variables: {}, + operationType: 'query' as const, }; it('should work', async () => { @@ -293,6 +296,7 @@ describe('visiting nested results', () => { } }`), variables: {}, + operationType: 'query' as const, }; it('should work', async () => { @@ -352,6 +356,7 @@ describe('visiting errors', () => { const request = { document: parse('{ test { field } }'), variables: {}, + operationType: 'query' as const, }; it('should allow visiting without an errorVisitor', async () => { diff --git a/packages/wrap/src/introspect.ts b/packages/wrap/src/introspect.ts index 6a11a74e545..b0130db1501 100644 --- a/packages/wrap/src/introspect.ts +++ b/packages/wrap/src/introspect.ts @@ -56,6 +56,7 @@ export function introspectSchema( return new ValueOrPromise(() => executor({ document: parsedIntrospectionQuery, + operationType: 'query', context, }) ) diff --git a/packages/wrap/src/transforms/ExtractField.ts b/packages/wrap/src/transforms/ExtractField.ts index 787372bf7f7..8d5d881118f 100644 --- a/packages/wrap/src/transforms/ExtractField.ts +++ b/packages/wrap/src/transforms/ExtractField.ts @@ -1,6 +1,6 @@ import { visit, Kind, SelectionSetNode, BREAK, FieldNode } from 'graphql'; -import { Request } from '@graphql-tools/utils'; +import { ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '@graphql-tools/delegate'; @@ -14,10 +14,10 @@ export default class ExtractField implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, _delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { let fromSelection: SelectionSetNode | undefined; const ourPathFrom = JSON.stringify(this.from); const ourPathTo = JSON.stringify(this.to); diff --git a/packages/wrap/src/transforms/FilterInputObjectFields.ts b/packages/wrap/src/transforms/FilterInputObjectFields.ts index e5b4158fc2c..01533e42674 100644 --- a/packages/wrap/src/transforms/FilterInputObjectFields.ts +++ b/packages/wrap/src/transforms/FilterInputObjectFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLInputFieldConfig } from 'graphql'; -import { Request, InputFieldFilter } from '@graphql-tools/utils'; +import { ExecutionRequest, InputFieldFilter } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -29,10 +29,10 @@ export default class FilterInputObjectFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/wrap/src/transforms/HoistField.ts b/packages/wrap/src/transforms/HoistField.ts index 299c9fcd45d..c94590c753a 100644 --- a/packages/wrap/src/transforms/HoistField.ts +++ b/packages/wrap/src/transforms/HoistField.ts @@ -9,7 +9,13 @@ import { GraphQLFieldResolver, } from 'graphql'; -import { appendObjectFields, removeObjectFields, Request, ExecutionResult, relocatedError } from '@graphql-tools/utils'; +import { + appendObjectFields, + removeObjectFields, + ExecutionRequest, + ExecutionResult, + relocatedError, +} from '@graphql-tools/utils'; import { Transform, defaultMergedResolver, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -153,10 +159,10 @@ export default class HoistField implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } diff --git a/packages/wrap/src/transforms/MapFields.ts b/packages/wrap/src/transforms/MapFields.ts index 0580fa0f604..1f530da717f 100644 --- a/packages/wrap/src/transforms/MapFields.ts +++ b/packages/wrap/src/transforms/MapFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema } from 'graphql'; -import { Request, FieldNodeMappers, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, FieldNodeMappers, ExecutionResult } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -85,10 +85,10 @@ export default class MapFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this._getTransformer().transformRequest(originalRequest, delegationContext, transformationContext); } diff --git a/packages/wrap/src/transforms/MapLeafValues.ts b/packages/wrap/src/transforms/MapLeafValues.ts index a8d7d6bc23d..fb3ce7945e4 100644 --- a/packages/wrap/src/transforms/MapLeafValues.ts +++ b/packages/wrap/src/transforms/MapLeafValues.ts @@ -14,7 +14,7 @@ import { } from 'graphql'; import { - Request, + ExecutionRequest, ExecutionResult, visitResult, ResultVisitorMap, @@ -27,7 +27,7 @@ import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/de import { LeafValueTransformer } from '../types'; export interface MapLeafValuesTransformationContext { - transformedRequest: Request; + transformedRequest: ExecutionRequest; } export default class MapLeafValues implements Transform { @@ -83,10 +83,10 @@ export default class MapLeafValues implements Transform - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/wrap/src/transforms/RenameInterfaceFields.ts b/packages/wrap/src/transforms/RenameInterfaceFields.ts index 091b98c9c6b..3388cd699f5 100644 --- a/packages/wrap/src/transforms/RenameInterfaceFields.ts +++ b/packages/wrap/src/transforms/RenameInterfaceFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLFieldConfig } from 'graphql'; -import { Request } from '@graphql-tools/utils'; +import { ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -27,10 +27,10 @@ export default class RenameInterfaceFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/wrap/src/transforms/RenameObjectFields.ts b/packages/wrap/src/transforms/RenameObjectFields.ts index c763a82844e..4583e55c4b1 100644 --- a/packages/wrap/src/transforms/RenameObjectFields.ts +++ b/packages/wrap/src/transforms/RenameObjectFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLFieldConfig } from 'graphql'; -import { Request } from '@graphql-tools/utils'; +import { ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -27,10 +27,10 @@ export default class RenameObjectFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/wrap/src/transforms/RenameRootFields.ts b/packages/wrap/src/transforms/RenameRootFields.ts index 6db0d3c39b9..caa437f46a4 100644 --- a/packages/wrap/src/transforms/RenameRootFields.ts +++ b/packages/wrap/src/transforms/RenameRootFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLFieldConfig } from 'graphql'; -import { Request } from '@graphql-tools/utils'; +import { ExecutionRequest } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -34,10 +34,10 @@ export default class RenameRootFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext); } } diff --git a/packages/wrap/src/transforms/RenameRootTypes.ts b/packages/wrap/src/transforms/RenameRootTypes.ts index 3d3f06d5aa0..63b4805da61 100644 --- a/packages/wrap/src/transforms/RenameRootTypes.ts +++ b/packages/wrap/src/transforms/RenameRootTypes.ts @@ -1,6 +1,6 @@ import { visit, GraphQLSchema, NamedTypeNode, Kind } from 'graphql'; -import { Request, ExecutionResult, MapperKind, mapSchema, renameType, visitData } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult, MapperKind, mapSchema, renameType, visitData } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -35,10 +35,10 @@ export default class RenameRootTypes implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, _delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const document = visit(originalRequest.document, { [Kind.NAMED_TYPE]: (node: NamedTypeNode) => { const name = node.name.value; diff --git a/packages/wrap/src/transforms/RenameTypes.ts b/packages/wrap/src/transforms/RenameTypes.ts index 00a207b358e..664789e9ed3 100644 --- a/packages/wrap/src/transforms/RenameTypes.ts +++ b/packages/wrap/src/transforms/RenameTypes.ts @@ -9,7 +9,7 @@ import { } from 'graphql'; import { - Request, + ExecutionRequest, ExecutionResult, MapperKind, RenameTypesOptions, @@ -66,10 +66,10 @@ export default class RenameTypes implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, _delegationContext: DelegationContext, _transformationContext: Record - ): Request { + ): ExecutionRequest { const document = visit(originalRequest.document, { [Kind.NAMED_TYPE]: (node: NamedTypeNode) => { const name = node.name.value; diff --git a/packages/wrap/src/transforms/TransformCompositeFields.ts b/packages/wrap/src/transforms/TransformCompositeFields.ts index 53d2c3945fd..99be7cf41e8 100644 --- a/packages/wrap/src/transforms/TransformCompositeFields.ts +++ b/packages/wrap/src/transforms/TransformCompositeFields.ts @@ -11,7 +11,7 @@ import { FragmentDefinitionNode, } from 'graphql'; -import { Request, MapperKind, mapSchema, visitData, ExecutionResult, Maybe } from '@graphql-tools/utils'; +import { ExecutionRequest, MapperKind, mapSchema, visitData, ExecutionResult, Maybe } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -78,10 +78,10 @@ export default class TransformCompositeFields> im } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, _delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { const document = originalRequest.document; const fragments = Object.create(null); for (const def of document.definitions) { diff --git a/packages/wrap/src/transforms/TransformEnumValues.ts b/packages/wrap/src/transforms/TransformEnumValues.ts index 29a6fba90ce..817aaf928bd 100644 --- a/packages/wrap/src/transforms/TransformEnumValues.ts +++ b/packages/wrap/src/transforms/TransformEnumValues.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLEnumValueConfig, ExecutionResult } from 'graphql'; -import { Request, MapperKind, mapSchema, Maybe } from '@graphql-tools/utils'; +import { ExecutionRequest, MapperKind, mapSchema, Maybe } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -43,10 +43,10 @@ export default class TransformEnumValues implements Transform - ): Request { + ): ExecutionRequest { const variableValues = originalRequest.variables ?? {}; const fragments = Object.create(null); @@ -152,7 +152,7 @@ export default class TransformInputObjectFields implements Transform { mapping: Record>, inputFieldNodeTransformer: InputFieldNodeTransformer | undefined, inputObjectNodeTransformer: InputObjectNodeTransformer | undefined, - request: Request, + request: ExecutionRequest, delegationContext?: DelegationContext ): DocumentNode { const typeInfo = new TypeInfo(this._getTransformedSchema()); diff --git a/packages/wrap/src/transforms/TransformInterfaceFields.ts b/packages/wrap/src/transforms/TransformInterfaceFields.ts index e3a3f1da00d..444c98e0500 100644 --- a/packages/wrap/src/transforms/TransformInterfaceFields.ts +++ b/packages/wrap/src/transforms/TransformInterfaceFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, isInterfaceType, GraphQLFieldConfig } from 'graphql'; -import { Request, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -51,10 +51,10 @@ export default class TransformInterfaceFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this._getTransformer().transformRequest(originalRequest, delegationContext, transformationContext); } diff --git a/packages/wrap/src/transforms/TransformObjectFields.ts b/packages/wrap/src/transforms/TransformObjectFields.ts index 0869c96832c..82364c71291 100644 --- a/packages/wrap/src/transforms/TransformObjectFields.ts +++ b/packages/wrap/src/transforms/TransformObjectFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, isObjectType, GraphQLFieldConfig } from 'graphql'; -import { Request, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -51,10 +51,10 @@ export default class TransformObjectFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this._getTransformer().transformRequest(originalRequest, delegationContext, transformationContext); } diff --git a/packages/wrap/src/transforms/TransformQuery.ts b/packages/wrap/src/transforms/TransformQuery.ts index 6a1690a4b53..3143d523250 100644 --- a/packages/wrap/src/transforms/TransformQuery.ts +++ b/packages/wrap/src/transforms/TransformQuery.ts @@ -1,6 +1,6 @@ import { visit, Kind, SelectionSetNode, FragmentDefinitionNode, GraphQLError } from 'graphql'; -import { Request, ExecutionResult, relocatedError } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult, relocatedError } from '@graphql-tools/utils'; import { Transform, DelegationContext } from '@graphql-tools/delegate'; @@ -47,10 +47,10 @@ export default class TransformQuery implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { const pathLength = this.path.length; let index = 0; const document = visit(originalRequest.document, { diff --git a/packages/wrap/src/transforms/TransformRootFields.ts b/packages/wrap/src/transforms/TransformRootFields.ts index 8521c2a2ea7..abd8b5be9bf 100644 --- a/packages/wrap/src/transforms/TransformRootFields.ts +++ b/packages/wrap/src/transforms/TransformRootFields.ts @@ -1,6 +1,6 @@ import { GraphQLSchema, GraphQLFieldConfig } from 'graphql'; -import { Request, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -59,10 +59,10 @@ export default class TransformRootFields implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this._getTransformer().transformRequest(originalRequest, delegationContext, transformationContext); } diff --git a/packages/wrap/src/transforms/WrapFields.ts b/packages/wrap/src/transforms/WrapFields.ts index e6e4702d423..395fe81549a 100644 --- a/packages/wrap/src/transforms/WrapFields.ts +++ b/packages/wrap/src/transforms/WrapFields.ts @@ -12,7 +12,7 @@ import { } from 'graphql'; import { - Request, + ExecutionRequest, appendObjectFields, selectObjectFields, modifyObjectFields, @@ -159,10 +159,10 @@ export default class WrapFields implements Transform - ): Request { + ): ExecutionRequest { const fieldPath: Array = []; const ourPath = JSON.stringify(this.path); const document = visit(originalRequest.document, { diff --git a/packages/wrap/src/transforms/WrapType.ts b/packages/wrap/src/transforms/WrapType.ts index 8d32d768675..fa9d3725927 100644 --- a/packages/wrap/src/transforms/WrapType.ts +++ b/packages/wrap/src/transforms/WrapType.ts @@ -1,6 +1,6 @@ import { GraphQLSchema } from 'graphql'; -import { Request, ExecutionResult } from '@graphql-tools/utils'; +import { ExecutionRequest, ExecutionResult } from '@graphql-tools/utils'; import { Transform, DelegationContext, SubschemaConfig } from '@graphql-tools/delegate'; @@ -22,10 +22,10 @@ export default class WrapType implements Transform { } public transformRequest( - originalRequest: Request, + originalRequest: ExecutionRequest, delegationContext: DelegationContext, transformationContext: Record - ): Request { + ): ExecutionRequest { return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext as any); } diff --git a/packages/wrap/src/types.ts b/packages/wrap/src/types.ts index 2ff018fd6c9..2e6a7ead9d4 100644 --- a/packages/wrap/src/types.ts +++ b/packages/wrap/src/types.ts @@ -10,7 +10,7 @@ import { GraphQLEnumValueConfig, } from 'graphql'; import { DelegationContext } from '@graphql-tools/delegate'; -import { Request, Maybe } from '@graphql-tools/utils'; +import { ExecutionRequest, Maybe } from '@graphql-tools/utils'; export type InputFieldTransformer = ( typeName: string, @@ -22,14 +22,14 @@ export type InputFieldNodeTransformer = ( typeName: string, fieldName: string, inputFieldNode: ObjectFieldNode, - request: Request, + request: ExecutionRequest, delegationContext?: DelegationContext ) => ObjectFieldNode | Array; export type InputObjectNodeTransformer = ( typeName: string, inputObjectNode: ObjectValueNode, - request: Request, + request: ExecutionRequest, delegationContext?: DelegationContext ) => ObjectValueNode | undefined; diff --git a/packages/wrap/tests/fixtures/schemas.ts b/packages/wrap/tests/fixtures/schemas.ts index 172ea0debf9..d413c9ec9f1 100644 --- a/packages/wrap/tests/fixtures/schemas.ts +++ b/packages/wrap/tests/fixtures/schemas.ts @@ -18,11 +18,12 @@ import { introspectSchema } from '../../src/introspect'; import { IResolvers, ExecutionResult, - mapAsyncIterator, isAsyncIterable, + AsyncExecutor, + ExecutionRequest, } from '@graphql-tools/utils'; import { makeExecutableSchema } from '@graphql-tools/schema'; -import { SubschemaConfig, Request } from '@graphql-tools/delegate'; +import { SubschemaConfig } from '@graphql-tools/delegate'; export class CustomError extends GraphQLError { constructor(message: string, extensions: Record) { @@ -677,9 +678,9 @@ export const subscriptionSchema: GraphQLSchema = makeExecutableSchema({ resolvers: subscriptionResolvers, }); -function makeExecutorFromSchema(schema: GraphQLSchema) { - return async ({ document, variables, context, info }: Request) => { - if (info?.operation.operation === 'subscription') { +function makeExecutorFromSchema(schema: GraphQLSchema): AsyncExecutor { + return async ({ document, variables, context, operationType }: ExecutionRequest) => { + if (operationType === 'subscription') { const result = await subscribe( schema, document, @@ -688,9 +689,9 @@ function makeExecutorFromSchema(schema: GraphQLSchema) { variables, ); if (isAsyncIterable>(result)) { - return mapAsyncIterator, TReturn>(result, (originalResult: ExecutionResult) => JSON.parse(JSON.stringify(originalResult))); + return result; } - return JSON.parse(JSON.stringify(result)); + return result; } return (new ValueOrPromise(() => graphql( schema, @@ -700,7 +701,7 @@ function makeExecutorFromSchema(schema: GraphQLSchema) { variables, )) .then(originalResult => JSON.parse(JSON.stringify(originalResult))) - .resolve()) as Promise> | ExecutionResult; + .resolve()); }; } diff --git a/packages/wrap/tests/requests.test.ts b/packages/wrap/tests/requests.test.ts index 3a87fbb520f..4c66ec613e6 100644 --- a/packages/wrap/tests/requests.test.ts +++ b/packages/wrap/tests/requests.test.ts @@ -50,7 +50,10 @@ describe('requests', () => { `), rootValue: undefined, variables: {}, - operationName: 'test' + operationName: 'test', + operationType: 'query', + context: undefined, + info: undefined, }); expect(expectedRequest).toMatchObject(request); diff --git a/packages/wrap/tests/transformFilterToSchema.test.ts b/packages/wrap/tests/transformFilterToSchema.test.ts index 4a752c0a76f..fb5d2385501 100644 --- a/packages/wrap/tests/transformFilterToSchema.test.ts +++ b/packages/wrap/tests/transformFilterToSchema.test.ts @@ -26,7 +26,8 @@ describe('FilterToSchema', () => { document: query, variables: { id: 'c1', - } + }, + operationType: 'query' as const }, { targetSchema: bookingSchema } as DelegationContext, {}); @@ -60,6 +61,7 @@ describe('FilterToSchema', () => { id: 'c1', limit: 10, }, + operationType: 'query' as const, }, { targetSchema: bookingSchema } as DelegationContext, {}); @@ -92,6 +94,7 @@ describe('FilterToSchema', () => { variables: { id: 'b1', }, + operationType: 'query' as const, }, { targetSchema: bookingSchema } as DelegationContext, {});