Skip to content

Commit

Permalink
BREAKING - Use native AggregateError if possible. Native AggregateErr…
Browse files Browse the repository at this point in the history
…or doesn't have iterator but errors prop
  • Loading branch information
ardatan committed Jun 17, 2021
1 parent e610927 commit e2a5d60
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 51 deletions.
8 changes: 8 additions & 0 deletions .changeset/mean-news-return.md
Original file line number Diff line number Diff line change
@@ -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
1 change: 0 additions & 1 deletion packages/delegate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
42 changes: 29 additions & 13 deletions packages/delegate/src/delegateToSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -76,7 +81,9 @@ function getDelegationReturnType(
return rootType.getFields()[fieldName].type;
}

export function delegateRequest<TContext = Record<string, any>, TArgs = any>(options: IDelegateRequestOptions<TContext, TArgs>) {
export function delegateRequest<TContext = Record<string, any>, TArgs = any>(
options: IDelegateRequestOptions<TContext, TArgs>
) {
const delegationContext = getDelegationContext(options);

const transformer = new Transformer(delegationContext, options.binding);
Expand All @@ -92,11 +99,15 @@ export function delegateRequest<TContext = Record<string, any>, 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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
};
}
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/delegate/src/resolveExternalValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
3 changes: 1 addition & 2 deletions packages/loaders/apollo-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 3 additions & 4 deletions packages/loaders/apollo-engine/src/index.ts
Original file line number Diff line number Diff line change
@@ -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';

/**
Expand Down Expand Up @@ -66,7 +65,7 @@ export class ApolloEngineLoader implements SchemaLoader<ApolloEngineOptions> {
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);
Expand All @@ -79,7 +78,7 @@ export class ApolloEngineLoader implements SchemaLoader<ApolloEngineOptions> {
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);
Expand Down
5 changes: 2 additions & 3 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -35,7 +35,6 @@
"graphql-scalars": "1.10.0"
},
"dependencies": {
"@ardatan/aggregate-error": "0.0.6",
"tslib": "~2.3.0"
},
"publishConfig": {
Expand Down
20 changes: 20 additions & 0 deletions packages/utils/src/AggregateError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let AggregateErrorImpl = globalThis.AggregateError;

if (typeof AggregateErrorImpl === 'undefined') {
class AggregateErrorClass extends Error implements AggregateError {
errors: Error[];
constructor(maybeErrors: Iterable<any>, 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<any>, message?: string) {
return new AggregateErrorClass(errors, message);
} as AggregateErrorConstructor;
}

export { AggregateErrorImpl as AggregateError };
1 change: 1 addition & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ export * from './isDocumentNode';
export * from './astFromValueUntyped';
export * from './executor';
export * from './withCancel';
export * from './AggregateError';
4 changes: 2 additions & 2 deletions packages/utils/src/validate-documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -90,7 +90,7 @@ export function checkValidationErrors(loadDocumentErrors: ReadonlyArray<LoadDocu
}
}

throw new AggregateError(errors);
throw new AggregateError(errors, 'Validation failed');
}
}

Expand Down
7 changes: 4 additions & 3 deletions packages/utils/tests/validate-documents.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ describe('validateGraphQlDocuments', () => {
try {
checkValidationErrors(result);
expect(true).toBeFalsy();
} catch (errors) {
} catch (aggregateError) {
const { errors } = aggregateError;
expect(Symbol.iterator in errors).toBeTruthy();
const generator = errors[Symbol.iterator]();

Expand Down Expand Up @@ -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();
Expand Down
17 changes: 10 additions & 7 deletions packages/wrap/src/introspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IntrospectionQuery>): 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];
Expand All @@ -34,10 +33,14 @@ export function introspectSchema<TExecutor extends AsyncExecutor | SyncExecutor>
options?: IntrospectionOptions
): TExecutor extends AsyncExecutor ? Promise<GraphQLSchema> : GraphQLSchema {
const parsedIntrospectionQuery: DocumentNode = parse(getIntrospectionQuery(options));
return new ValueOrPromise(() => (executor as Executor)<IntrospectionQuery>({
document: parsedIntrospectionQuery,
context,
})).then(introspection => getSchemaFromIntrospection(introspection)).resolve() as any;
return new ValueOrPromise(() =>
(executor as Executor)<IntrospectionQuery>({
document: parsedIntrospectionQuery,
context,
})
)
.then(introspection => getSchemaFromIntrospection(introspection))
.resolve() as any;
}

// Keep for backwards compatibility. Will be removed on next release.
Expand Down
12 changes: 0 additions & 12 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,6 @@
tslib "^1.10.0"
zen-observable "^0.8.14"

"@ardatan/[email protected]":
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/[email protected]":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit e2a5d60

Please sign in to comment.