Skip to content

Commit

Permalink
get defer/stream from graphql-js (#4796)
Browse files Browse the repository at this point in the history
* get defer/stream from graphql-js

* prettier

* use agnostic root type getter

* use createGraphQLError

* fix issue with v15 and v16 cause of obj vs enum

* Fix tests

* Remove unused subscribe

* Fix TS

* Fix ESM

* ESM fix

* move collect fields to utils

* chore(dependencies): updated changesets for modified dependencies

* run prettier

* make default execute incremental

* chore(dependencies): updated changesets for modified dependencies

* ..

* chore(dependencies): updated changesets for modified dependencies

* Sync

* Use ValueOrPromise

* chore(dependencies): updated changesets for modified dependencies

* Fix

* chore(dependencies): updated changesets for modified dependencies

* Go

* Go

* stop

Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Nov 1, 2022
1 parent 691966b commit 80836fa
Show file tree
Hide file tree
Showing 52 changed files with 4,675 additions and 526 deletions.
6 changes: 6 additions & 0 deletions .changeset/@graphql-tools_executor-4796-dependencies.md
@@ -0,0 +1,6 @@
---
'@graphql-tools/executor': patch
---
dependencies updates:
- Added dependency [`@repeaterjs/repeater@3.0.4` ↗︎](https://www.npmjs.com/package/@repeaterjs/repeater/v/3.0.4) (to `dependencies`)
- Added dependency [`value-or-promise@1.0.1` ↗︎](https://www.npmjs.com/package/value-or-promise/v/1.0.1) (to `dependencies`)
5 changes: 5 additions & 0 deletions .changeset/chatty-worms-pull.md
@@ -0,0 +1,5 @@
---
'@graphql-tools/utils': minor
---

add `@defer` directive
5 changes: 5 additions & 0 deletions .changeset/quick-clocks-beam.md
@@ -0,0 +1,5 @@
---
'@graphql-tools/executor': patch
---

get defer stream from graphql-js
5 changes: 5 additions & 0 deletions .changeset/spotty-maps-approve.md
@@ -0,0 +1,5 @@
---
'@graphql-tools/utils': minor
---

export collect field helpers
5 changes: 5 additions & 0 deletions .changeset/spotty-suns-bake.md
@@ -0,0 +1,5 @@
---
'@graphql-tools/utils': minor
---

add `@stream` directive
7 changes: 7 additions & 0 deletions .changeset/warm-bags-camp.md
@@ -0,0 +1,7 @@
---
'@graphql-tools/utils': major
'@graphql-tools/delegate': patch
'@graphql-tools/stitch': patch
---

update `collectFields` to support collecting deffered values
8 changes: 7 additions & 1 deletion packages/batch-delegate/tests/basic.example.test.ts
@@ -1,4 +1,4 @@
import { execute } from '@graphql-tools/executor';
import { execute, isIncrementalResult } from '@graphql-tools/executor';
import { OperationTypeNode, parse } from 'graphql';

import { makeExecutableSchema } from '@graphql-tools/schema';
Expand Down Expand Up @@ -89,6 +89,9 @@ describe('batch delegation within basic stitching example', () => {
const result = await execute({ schema: stitchedSchema, document: parse(query) });

expect(numCalls).toEqual(1);

if (isIncrementalResult(result)) throw Error('result is incremental');

expect(result.errors).toBeUndefined();
const chirps: any = result.data!['trendingChirps'];
expect(chirps[0].chirpedAtUser.email).not.toBe(null);
Expand Down Expand Up @@ -182,6 +185,9 @@ describe('batch delegation within basic stitching example', () => {

const result = await execute({ schema: stitchedSchema, document: parse(query) });
expect(numCalls).toEqual(1);

if (isIncrementalResult(result)) throw Error('result is incremental');

expect(result.data).toEqual({
users: [
{
Expand Down
3 changes: 2 additions & 1 deletion packages/batch-delegate/tests/withTransforms.test.ts
@@ -1,4 +1,4 @@
import { execute } from '@graphql-tools/executor';
import { execute, isIncrementalResult } from '@graphql-tools/executor';
import { GraphQLList, GraphQLObjectType, Kind, OperationTypeNode, parse } from 'graphql';

import { makeExecutableSchema } from '@graphql-tools/schema';
Expand Down Expand Up @@ -121,6 +121,7 @@ describe('works with complex transforms', () => {
`;

const result = await execute({ schema: stitchedSchema, document: parse(query) });
if (isIncrementalResult(result)) throw Error('result is incremental');

expect(result.errors).toBeUndefined();
expect(result.data).toEqual({
Expand Down
4 changes: 2 additions & 2 deletions packages/batch-execute/tests/batchExecute.test.ts
Expand Up @@ -2,7 +2,7 @@ import { parse, print, OperationDefinitionNode, validate } from 'graphql';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { createBatchingExecutor } from '@graphql-tools/batch-execute';
import { ExecutionResult, Executor } from '@graphql-tools/utils';
import { execute } from '@graphql-tools/executor';
import { normalizedExecutor } from '@graphql-tools/executor';

describe('batch execution', () => {
let executorCalls = 0;
Expand Down Expand Up @@ -41,7 +41,7 @@ describe('batch execution', () => {
if (errors.length > 0) {
return { errors };
}
return execute({
return normalizedExecutor({
schema,
document,
variableValues: executorVariables,
Expand Down
11 changes: 3 additions & 8 deletions packages/delegate/src/delegateToSchema.ts
Expand Up @@ -36,7 +36,7 @@ import { Subschema } from './Subschema.js';
import { createRequest, getDelegatingOperation } from './createRequest.js';
import { Transformer } from './Transformer.js';
import { applySchemaTransforms } from './applySchemaTransforms.js';
import { ExecutionArgs, execute, subscribe } from '@graphql-tools/executor';
import { normalizedExecutor } from '@graphql-tools/executor';

export function delegateToSchema<
TContext extends Record<string, any> = Record<string, any>,
Expand Down Expand Up @@ -219,18 +219,13 @@ function getExecutor<TContext extends Record<string, any>>(

export const createDefaultExecutor = memoize1(function createDefaultExecutor(schema: GraphQLSchema): Executor {
return function defaultExecutor(request: ExecutionRequest) {
const executionArgs: ExecutionArgs = {
return normalizedExecutor({
schema,
document: request.document,
rootValue: request.rootValue,
contextValue: request.context,
variableValues: request.variables,
operationName: request.operationName,
};
const operationType = request.operationType || getOperationASTFromRequest(request).operation;
if (operationType === 'subscription') {
return subscribe(executionArgs);
}
return execute(executionArgs);
});
};
});
12 changes: 2 additions & 10 deletions packages/delegate/src/mergeFields.ts
Expand Up @@ -92,17 +92,9 @@ async function executeDelegationStage(
source = error;
}
if (source instanceof Error || source == null) {
const fieldNodeResponseKeyMap = collectFields(
schema,
EMPTY_OBJECT,
EMPTY_OBJECT,
type,
selectionSet,
new Map(),
new Set()
);
const { fields } = collectFields(schema, EMPTY_OBJECT, EMPTY_OBJECT, type, selectionSet);
const nullResult = {};
for (const [responseKey, fieldNodes] of fieldNodeResponseKeyMap) {
for (const [responseKey, fieldNodes] of fields) {
const combinedPath = [...path, responseKey];
if (source instanceof GraphQLError) {
nullResult[responseKey] = relocatedError(source, combinedPath);
Expand Down
4 changes: 3 additions & 1 deletion packages/executor/package.json
Expand Up @@ -52,8 +52,10 @@
"definition": "dist/typings/index.d.ts"
},
"dependencies": {
"@repeaterjs/repeater": "3.0.4",
"@graphql-tools/utils": "8.13.1",
"@graphql-typed-document-node/core": "3.1.1"
"@graphql-typed-document-node/core": "3.1.1",
"value-or-promise": "1.0.1"
},
"devDependencies": {
"graphql": "^16.6.0",
Expand Down
22 changes: 22 additions & 0 deletions packages/executor/src/__testUtils__/expectEqualPromisesOrValues.ts
@@ -0,0 +1,22 @@
import { isPromise, MaybePromise } from '@graphql-tools/utils';
import { expectJSON } from './expectJSON.js';

export function expectMatchingValues<T>(values: ReadonlyArray<T>): T {
const [firstValue, ...remainingValues] = values;
for (const value of remainingValues) {
expectJSON(value).toDeepEqual(firstValue);
}
return firstValue;
}

export function expectEqualPromisesOrValues<T>(items: ReadonlyArray<MaybePromise<T>>): MaybePromise<T> {
const [firstItem, ...remainingItems] = items;
if (isPromise(firstItem)) {
if (remainingItems.every(isPromise)) {
return Promise.all(items).then(expectMatchingValues);
}
} else if (remainingItems.every(item => !isPromise(item))) {
return expectMatchingValues(items);
}
throw new Error('Cannot compare promises and values');
}
22 changes: 22 additions & 0 deletions packages/executor/src/__testUtils__/expectPromise.ts
@@ -0,0 +1,22 @@
import { isPromise } from '@graphql-tools/utils';

export function expectPromise(maybePromise: unknown) {
expect(isPromise(maybePromise)).toBeTruthy();

return {
toResolve() {
return maybePromise;
},
async toRejectWith(message: string) {
let caughtError: Error | undefined;
try {
await maybePromise;
} catch (error) {
caughtError = error as Error;
}

expect(caughtError).toBeInstanceOf(Error);
expect(caughtError).toHaveProperty('message', message);
},
};
}

0 comments on commit 80836fa

Please sign in to comment.