diff --git a/.changeset/mean-news-return.md b/.changeset/mean-news-return.md new file mode 100644 index 00000000000..57f962b5bf1 --- /dev/null +++ b/.changeset/mean-news-return.md @@ -0,0 +1,8 @@ +--- +'@graphql-tools/delegate': major +'@graphql-tools/apollo-engine-loader': major +'@graphql-tools/utils': major +'@graphql-tools/wrap': major +--- + +BREAKING - Use native AggregateError if possible. Native AggregateError doesn't have iterator but errors prop diff --git a/packages/delegate/package.json b/packages/delegate/package.json index b9dcaa0a76a..663562b2253 100644 --- a/packages/delegate/package.json +++ b/packages/delegate/package.json @@ -35,7 +35,6 @@ "@graphql-tools/batch-execute": "^7.1.2", "@graphql-tools/schema": "^7.1.5", "@graphql-tools/utils": "^7.7.1", - "@ardatan/aggregate-error": "0.0.6", "dataloader": "2.0.0", "tslib": "~2.3.0", "value-or-promise": "1.0.10" diff --git a/packages/delegate/src/delegateToSchema.ts b/packages/delegate/src/delegateToSchema.ts index a120ae46db1..412af94a454 100644 --- a/packages/delegate/src/delegateToSchema.ts +++ b/packages/delegate/src/delegateToSchema.ts @@ -14,11 +14,16 @@ import { import { ValueOrPromise } from 'value-or-promise'; -import AggregateError from '@ardatan/aggregate-error'; - import { getBatchingExecutor } from '@graphql-tools/batch-execute'; -import { mapAsyncIterator, ExecutionResult, Executor, ExecutionParams, Subscriber } from '@graphql-tools/utils'; +import { + mapAsyncIterator, + ExecutionResult, + Executor, + ExecutionParams, + Subscriber, + AggregateError, +} from '@graphql-tools/utils'; import { IDelegateToSchemaOptions, IDelegateRequestOptions, StitchingInfo, DelegationContext } from './types'; @@ -76,7 +81,9 @@ function getDelegationReturnType( return rootType.getFields()[fieldName].type; } -export function delegateRequest, TArgs = any>(options: IDelegateRequestOptions) { +export function delegateRequest, TArgs = any>( + options: IDelegateRequestOptions +) { const delegationContext = getDelegationContext(options); const transformer = new Transformer(delegationContext, options.binding); @@ -92,11 +99,15 @@ export function delegateRequest, TArgs = any>(opt if (operation === 'query' || operation === 'mutation') { const executor = getExecutor(delegationContext); - return new ValueOrPromise(() => executor({ - ...processedRequest, - context, - info, - })).then(originalResult => transformer.transformResult(originalResult)).resolve(); + return new ValueOrPromise(() => + executor({ + ...processedRequest, + context, + info, + }) + ) + .then(originalResult => transformer.transformResult(originalResult)) + .resolve(); } const subscriber = getSubscriber(delegationContext); @@ -149,7 +160,7 @@ function getDelegationContext({ if (fieldName == null) { operationDefinition = operationDefinition ?? getOperationAST(request.document, undefined); - targetFieldName = ((operationDefinition.selectionSet.selections[0] as unknown) as FieldDefinitionNode).name.value; + targetFieldName = (operationDefinition.selectionSet.selections[0] as unknown as FieldDefinitionNode).name.value; } else { targetFieldName = fieldName; } @@ -170,12 +181,14 @@ function getDelegationContext({ context, info, rootValue: rootValue ?? subschemaOrSubschemaConfig?.rootValue ?? info?.rootValue ?? emptyObject, - returnType: returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, targetOperation, targetFieldName), + returnType: + returnType ?? info?.returnType ?? getDelegationReturnType(targetSchema, targetOperation, targetFieldName), transforms: subschemaOrSubschemaConfig.transforms != null ? subschemaOrSubschemaConfig.transforms.concat(transforms) : transforms, - transformedSchema: transformedSchema ?? (subschemaOrSubschemaConfig as Subschema)?.transformedSchema ?? targetSchema, + transformedSchema: + transformedSchema ?? (subschemaOrSubschemaConfig as Subschema)?.transformedSchema ?? targetSchema, skipTypeMerging, }; } @@ -190,7 +203,10 @@ function getDelegationContext({ context, info, rootValue: rootValue ?? info?.rootValue ?? emptyObject, - returnType: returnType ?? info?.returnType ?? getDelegationReturnType(subschemaOrSubschemaConfig, targetOperation, targetFieldName), + returnType: + returnType ?? + info?.returnType ?? + getDelegationReturnType(subschemaOrSubschemaConfig, targetOperation, targetFieldName), transforms, transformedSchema: transformedSchema ?? subschemaOrSubschemaConfig, skipTypeMerging, diff --git a/packages/delegate/src/resolveExternalValue.ts b/packages/delegate/src/resolveExternalValue.ts index 73495d174ce..15590aeb371 100644 --- a/packages/delegate/src/resolveExternalValue.ts +++ b/packages/delegate/src/resolveExternalValue.ts @@ -13,7 +13,7 @@ import { locatedError, } from 'graphql'; -import AggregateError from '@ardatan/aggregate-error'; +import { AggregateError } from '@graphql-tools/utils'; import { StitchingInfo, SubschemaConfig } from './types'; import { annotateExternalObject, isExternalObject } from './externalObjects'; diff --git a/packages/delegate/src/transforms/CheckResultAndHandleErrors.ts b/packages/delegate/src/transforms/CheckResultAndHandleErrors.ts index 264541de177..ff2218ee2ce 100644 --- a/packages/delegate/src/transforms/CheckResultAndHandleErrors.ts +++ b/packages/delegate/src/transforms/CheckResultAndHandleErrors.ts @@ -7,9 +7,7 @@ import { locatedError, } from 'graphql'; -import AggregateError from '@ardatan/aggregate-error'; - -import { getResponseKeyFromInfo, ExecutionResult, relocatedError } from '@graphql-tools/utils'; +import { AggregateError, getResponseKeyFromInfo, ExecutionResult, relocatedError } from '@graphql-tools/utils'; import { SubschemaConfig, Transform, DelegationContext } from '../types'; import { resolveExternalValue } from '../resolveExternalValue'; diff --git a/packages/loaders/apollo-engine/package.json b/packages/loaders/apollo-engine/package.json index 4e99982fe17..3382d69b11d 100644 --- a/packages/loaders/apollo-engine/package.json +++ b/packages/loaders/apollo-engine/package.json @@ -30,8 +30,7 @@ "graphql": "^14.0.0 || ^15.0.0" }, "dependencies": { - "@ardatan/aggregate-error": "0.0.6", - "@graphql-tools/utils": "^7.0.0", + "@graphql-tools/utils": "^7.10.0", "cross-fetch": "3.1.4", "tslib": "~2.3.0", "sync-fetch": "0.3.0" diff --git a/packages/loaders/apollo-engine/src/index.ts b/packages/loaders/apollo-engine/src/index.ts index 3015ce125b1..2c1c4b47ba5 100644 --- a/packages/loaders/apollo-engine/src/index.ts +++ b/packages/loaders/apollo-engine/src/index.ts @@ -1,6 +1,5 @@ -import { SchemaLoader, Source, SingleFileOptions, parseGraphQLSDL } from '@graphql-tools/utils'; +import { SchemaLoader, Source, SingleFileOptions, parseGraphQLSDL, AggregateError } from '@graphql-tools/utils'; import { fetch } from 'cross-fetch'; -import AggregateError from '@ardatan/aggregate-error'; import syncFetch from 'sync-fetch'; /** @@ -66,7 +65,7 @@ export class ApolloEngineLoader implements SchemaLoader { const { data, errors } = await response.json(); if (errors) { - throw new AggregateError(errors); + throw new AggregateError(errors, 'Introspection from Apollo Engine failed'); } return parseGraphQLSDL(pointer, data.service.schema.document, options); @@ -79,7 +78,7 @@ export class ApolloEngineLoader implements SchemaLoader { const { data, errors } = response.json(); if (errors) { - throw new AggregateError(errors); + throw new AggregateError(errors, 'Introspection from Apollo Engine failed'); } return parseGraphQLSDL(pointer, data.service.schema.document, options); diff --git a/packages/utils/package.json b/packages/utils/package.json index eea7a9e3136..52c2341c81c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,8 +11,8 @@ "license": "MIT", "sideEffects": false, "main": "dist/index.js", - "module": "dist/index.mjs", - "exports": { + "module": "dist/index.mjs", + "exports": { ".": { "require": "./dist/index.js", "import": "./dist/index.mjs" @@ -35,7 +35,6 @@ "graphql-scalars": "1.10.0" }, "dependencies": { - "@ardatan/aggregate-error": "0.0.6", "tslib": "~2.3.0" }, "publishConfig": { diff --git a/packages/utils/src/AggregateError.ts b/packages/utils/src/AggregateError.ts new file mode 100644 index 00000000000..1300c199ade --- /dev/null +++ b/packages/utils/src/AggregateError.ts @@ -0,0 +1,20 @@ +let AggregateErrorImpl = globalThis.AggregateError; + +if (typeof AggregateErrorImpl === 'undefined') { + class AggregateErrorClass extends Error implements AggregateError { + errors: Error[]; + constructor(maybeErrors: Iterable, message = '') { + super(message); + this.name = 'AggregateError'; + Error.captureStackTrace(this, AggregateErrorClass); + this.errors = [...maybeErrors].map(maybeError => + maybeError instanceof Error ? maybeError : new Error(maybeError) + ); + } + } + AggregateErrorImpl = function (errors: Iterable, message?: string) { + return new AggregateErrorClass(errors, message); + } as AggregateErrorConstructor; +} + +export { AggregateErrorImpl as AggregateError }; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index c7028aba3ad..4d08ad7b403 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -46,3 +46,4 @@ export * from './isDocumentNode'; export * from './astFromValueUntyped'; export * from './executor'; export * from './withCancel'; +export * from './AggregateError'; diff --git a/packages/utils/src/validate-documents.ts b/packages/utils/src/validate-documents.ts index b2d429c8266..ebb3b2160ec 100644 --- a/packages/utils/src/validate-documents.ts +++ b/packages/utils/src/validate-documents.ts @@ -9,7 +9,7 @@ import { ASTVisitor, } from 'graphql'; import { Source } from './loaders'; -import AggregateError from '@ardatan/aggregate-error'; +import { AggregateError } from './AggregateError'; export type ValidationRule = (context: ValidationContext) => ASTVisitor; @@ -90,7 +90,7 @@ export function checkValidationErrors(loadDocumentErrors: ReadonlyArray { try { checkValidationErrors(result); expect(true).toBeFalsy(); - } catch (errors) { + } catch (aggregateError) { + const { errors } = aggregateError; expect(Symbol.iterator in errors).toBeTruthy(); const generator = errors[Symbol.iterator](); @@ -112,8 +113,8 @@ describe('checkValidationErrors', () => { let errors; try { checkValidationErrors(loadDocumentErrors as any); - } catch (_errors) { - errors = _errors; + } catch (aggregateError) { + errors = aggregateError.errors; } expect(Symbol.iterator in errors).toBeTruthy(); diff --git a/packages/wrap/src/introspect.ts b/packages/wrap/src/introspect.ts index 08ef51fdf9c..34e91c3f8cf 100644 --- a/packages/wrap/src/introspect.ts +++ b/packages/wrap/src/introspect.ts @@ -10,15 +10,14 @@ import { import { ValueOrPromise } from 'value-or-promise'; -import { AsyncExecutor, Executor, SyncExecutor, ExecutionResult } from '@graphql-tools/utils'; -import AggregateError from '@ardatan/aggregate-error'; +import { AsyncExecutor, Executor, SyncExecutor, ExecutionResult, AggregateError } from '@graphql-tools/utils'; function getSchemaFromIntrospection(introspectionResult: ExecutionResult): GraphQLSchema { if (introspectionResult?.data?.__schema) { return buildClientSchema(introspectionResult.data); } else if (introspectionResult?.errors?.length) { if (introspectionResult.errors.length > 1) { - const combinedError = new AggregateError(introspectionResult.errors); + const combinedError = new AggregateError(introspectionResult.errors, 'Could not obtain introspection result'); throw combinedError; } const error = introspectionResult.errors[0]; @@ -34,10 +33,14 @@ export function introspectSchema options?: IntrospectionOptions ): TExecutor extends AsyncExecutor ? Promise : GraphQLSchema { const parsedIntrospectionQuery: DocumentNode = parse(getIntrospectionQuery(options)); - return new ValueOrPromise(() => (executor as Executor)({ - document: parsedIntrospectionQuery, - context, - })).then(introspection => getSchemaFromIntrospection(introspection)).resolve() as any; + return new ValueOrPromise(() => + (executor as Executor)({ + document: parsedIntrospectionQuery, + context, + }) + ) + .then(introspection => getSchemaFromIntrospection(introspection)) + .resolve() as any; } // Keep for backwards compatibility. Will be removed on next release. diff --git a/yarn.lock b/yarn.lock index 74e476793cd..2dc7cea0628 100644 --- a/yarn.lock +++ b/yarn.lock @@ -144,13 +144,6 @@ tslib "^1.10.0" zen-observable "^0.8.14" -"@ardatan/aggregate-error@0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz#fe6924771ea40fc98dc7a7045c2e872dc8527609" - integrity sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ== - dependencies: - tslib "~2.0.1" - "@babel/code-frame@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -12714,11 +12707,6 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@~2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== -tslib@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" - integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== - tslib@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"