Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .changeset/ten-ads-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
'@envelop/core': minor
'@envelop/apollo-server-errors': minor
'@envelop/apollo-tracing': minor
'@envelop/auth0': minor
'@envelop/dataloader': minor
'@envelop/depth-limit': minor
'@envelop/disable-introspection': minor
'@envelop/execute-subscription-event': minor
'@envelop/extended-validation': minor
'@envelop/filter-operation-type': minor
'@envelop/fragment-arguments': minor
'@envelop/generic-auth': minor
'@envelop/graphql-jit': minor
'@envelop/graphql-middleware': minor
'@envelop/graphql-modules': minor
'@envelop/live-query': minor
'@envelop/newrelic': minor
'@envelop/opentelemetry': minor
'@envelop/operation-field-permissions': minor
'@envelop/parser-cache': minor
'@envelop/persisted-operations': minor
'@envelop/preload-assets': minor
'@envelop/prometheus': minor
'@envelop/rate-limiter': minor
'@envelop/resource-limitations': minor
'@envelop/response-cache': minor
'@envelop/sentry': minor
'@envelop/statsd': minor
'@envelop/validation-cache': minor
'@envelop/testing': minor
'@envelop/types': minor
---

add support for GraphQL.js 16
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
graphql_version:
# - 14
- 15
# - 16.0.0-rc.1
- 16.0.0-rc.7
steps:
- name: Checkout Master
uses: actions/checkout@v2
Expand Down Expand Up @@ -67,7 +67,7 @@ jobs:
graphql_version:
# - 14
- 15
# - 16.0.0-rc.1
- 16.0.0-rc.7
steps:
- name: Checkout Master
uses: actions/checkout@v2
Expand Down
12 changes: 11 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.formatOnSave": true,
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/node_modules": true,
"test-lib": true,
"lib": true,
"coverage": true,
"npm": true,
"**/dist": true
}
}
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
12 changes: 7 additions & 5 deletions packages/core/src/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
OnContextErrorHandler,
SubscribeErrorHook,
DefaultContext,
Maybe,
} from '@envelop/types';
import {
DocumentNode,
Expand All @@ -40,7 +41,6 @@ import {
validate,
ValidationRule,
} from 'graphql';
import { Maybe } from 'graphql/jsutils/Maybe';
import { prepareTracedSchema, resolversHooksSymbol } from './traced-schema';
import { errorAsyncIterator, finalAsyncIterator, makeExecute, makeSubscribe, mapAsyncIterator } from './utils';

Expand Down Expand Up @@ -307,7 +307,7 @@ export function createEnvelopOrchestrator<PluginsContext extends DefaultContext>
const afterCalls: SubscribeResultHook<PluginsContext>[] = [];
const subscribeErrorHandlers: SubscribeErrorHook[] = [];

let context = args.contextValue || {};
let context = (args.contextValue as {}) || {};

for (const onSubscribe of beforeCallbacks.subscribe) {
const after = await onSubscribe({
Expand Down Expand Up @@ -338,9 +338,11 @@ export function createEnvelopOrchestrator<PluginsContext extends DefaultContext>
context[resolversHooksSymbol] = onResolversHandlers;
}

let result = await subscribeFn({
let result: AsyncIterableIteratorOrValue<ExecutionResult> = await subscribeFn({
...args,
contextValue: context,
// Casted for GraphQL.js 15 compatibility
// Can be removed once we drop support for GraphQL.js 15
});

const onNextHandler: OnSubscribeResultResultOnNextHook<PluginsContext>[] = [];
Expand Down Expand Up @@ -399,7 +401,7 @@ export function createEnvelopOrchestrator<PluginsContext extends DefaultContext>
});
}

return result;
return result as AsyncIterableIterator<ExecutionResult>;
});

const customExecute = beforeCallbacks.execute.length
Expand All @@ -409,7 +411,7 @@ export function createEnvelopOrchestrator<PluginsContext extends DefaultContext>
let result: AsyncIterableIteratorOrValue<ExecutionResult>;

const afterCalls: OnExecuteDoneHook<PluginsContext>[] = [];
let context = args.contextValue || {};
let context = (args.contextValue as {}) || {};

for (const onExecute of beforeCallbacks.execute) {
let stopCalled = false;
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/traced-orchestrator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DocumentNode, ExecutionArgs, GraphQLFieldResolver, GraphQLSchema, GraphQLTypeResolver, SubscriptionArgs } from 'graphql';
import { Maybe } from 'graphql/jsutils/Maybe';
import { ArbitraryObject, isAsyncIterable } from '@envelop/types';
import { ArbitraryObject, isAsyncIterable, Maybe } from '@envelop/types';
import { EnvelopOrchestrator } from './orchestrator';

const HR_TO_NS = 1e9;
Expand Down Expand Up @@ -88,7 +87,8 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug
typeResolver,
}
: argsOrSchema;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore GraphQL.js types contextValue as unknown
const done = createTracer('execute', args.contextValue || {});

try {
Expand All @@ -97,6 +97,8 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug

if (!isAsyncIterable(result)) {
result.extensions = result.extensions || {};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore GraphQL.js types contextValue as unknown
result.extensions.envelopTracing = args.contextValue._envelopTracing;
} else {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -135,6 +137,8 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug
subscribeFieldResolver,
}
: argsOrSchema;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore GraphQL.js types contextValue as unknown
const done = createTracer('subscribe', args.contextValue || {});

try {
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import {
PolymorphicExecuteArguments,
PolymorphicSubscribeArguments,
SubscribeFunction,
PromiseOrValue,
} from '@envelop/types';
import { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue';

export const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');

Expand Down Expand Up @@ -73,13 +73,13 @@ function getSubscribeArgs(args: PolymorphicSubscribeArguments): SubscriptionArgs
* Utility function for making a subscribe function that handles polymorphic arguments.
*/
export const makeSubscribe = (
subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncIterableIterator<ExecutionResult> | ExecutionResult>
subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncIterableIterator<ExecutionResult>>
): SubscribeFunction =>
((...polyArgs: PolymorphicSubscribeArguments): PromiseOrValue<AsyncIterableIterator<ExecutionResult> | ExecutionResult> =>
((...polyArgs: PolymorphicSubscribeArguments): PromiseOrValue<AsyncIterableIterator<ExecutionResult>> =>
subscribeFn(getSubscribeArgs(polyArgs))) as SubscribeFunction;

export async function* mapAsyncIterator<TInput, TOutput = TInput>(
asyncIterable: AsyncIterableIterator<TInput>,
asyncIterable: AsyncIterable<TInput>,
map: (input: TInput) => Promise<TOutput> | TOutput
): AsyncIterableIterator<TOutput> {
for await (const value of asyncIterable) {
Expand Down Expand Up @@ -109,10 +109,10 @@ export const makeExecute = (
executeFn: (args: ExecutionArgs) => PromiseOrValue<AsyncIterableIteratorOrValue<ExecutionResult>>
): ExecuteFunction =>
((...polyArgs: PolymorphicExecuteArguments): PromiseOrValue<AsyncIterableIteratorOrValue<ExecutionResult>> =>
executeFn(getExecuteArgs(polyArgs))) as ExecuteFunction;
executeFn(getExecuteArgs(polyArgs))) as unknown as ExecuteFunction;

export async function* finalAsyncIterator<TInput>(
asyncIterable: AsyncIterableIterator<TInput>,
asyncIterable: AsyncIterable<TInput>,
onFinal: () => void
): AsyncIterableIterator<TInput> {
try {
Expand All @@ -123,7 +123,7 @@ export async function* finalAsyncIterator<TInput>(
}

export async function* errorAsyncIterator<TInput>(
asyncIterable: AsyncIterableIterator<TInput>,
asyncIterable: AsyncIterable<TInput>,
onError: (err: unknown) => void
): AsyncIterableIterator<TInput> {
try {
Expand Down
15 changes: 10 additions & 5 deletions packages/plugins/apollo-federation/test/federation.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ApolloGateway, LocalGraphQLDataSource } from '@apollo/gateway';
import { assertSingleExecutionValue, createTestkit } from '@envelop/testing';
import { execute } from 'graphql';
import { execute, versionInfo } from 'graphql';
import { useApolloFederation } from '../src';
import * as accounts from './fixtures/accounts';
import * as products from './fixtures/products';
import * as reviews from './fixtures/reviews';

describe('useApolloFederation', () => {
if (versionInfo.major > 15) {
it('dummy', () => {});
return;
}
const query = /* GraphQL */ `
# A query that the gateway resolves by calling all three services
query GetCurrentUserReviews {
Expand All @@ -23,6 +23,11 @@ describe('useApolloFederation', () => {
}
`;

const { ApolloGateway, LocalGraphQLDataSource }: typeof import('@apollo/gateway') = require('@apollo/gateway');
const accounts: typeof import('./fixtures/accounts') = require('./fixtures/accounts');
const products: typeof import('./fixtures/products') = require('./fixtures/products');
const reviews: typeof import('./fixtures/reviews') = require('./fixtures/reviews');

const gateway = new ApolloGateway({
localServiceList: [
{ name: 'accounts', typeDefs: accounts.typeDefs },
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/apollo-server-errors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
4 changes: 4 additions & 0 deletions packages/plugins/apollo-server-errors/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const makeHandleResult =
if (result.errors && result.errors.length > 0) {
setResult({
...result,
// Upstream issue in apollo with GraphQL.js 16
// Type 'ApolloError[]' is not assignable to type 'readonly GraphQLError[]'. Property '[Symbol.toStringTag]' is missing in type 'ApolloError' but required in type 'GraphQLError'.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
errors: formatApolloErrors(result.errors, {
debug: options.debug,
formatter: options.formatter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { envelop, useSchema } from '@envelop/core';
import { useApolloServerErrors } from '../src';
import { assertSingleExecutionValue } from '@envelop/testing';

// Fix compat by mocking broken function
// we can remove this once apollo fixed legacy usages of execute(schema, ...args)
// aka when https://github.com/apollographql/apollo-server/pull/5662 or rather https://github.com/apollographql/apollo-server/pull/5664 has been released
jest.mock('../../../../node_modules/apollo-server-core/dist/utils/schemaHash', () => ({
generateSchemaHash: () => 'noop',
}));

describe('useApolloServerErrors', () => {
const executeBoth = async (schema: GraphQLSchema, query: string, debug: boolean) => {
const apolloServer = new ApolloServerBase({ schema, debug });
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/apollo-tracing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
14 changes: 8 additions & 6 deletions packages/plugins/apollo-tracing/test/use-apollo-tracing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ describe('useApolloTracing', () => {
expect(result.errors).toBeUndefined();
expect(result.data).toBeDefined();
expect(result.extensions?.tracing).toBeDefined();
expect(result.extensions?.tracing.duration).toBeGreaterThan(1000000000);
expect(result.extensions?.tracing.execution.resolvers[0].duration).toBeGreaterThan(990000000);
expect(result.extensions?.tracing.execution.resolvers[0].path).toEqual(['foo']);
expect(result.extensions?.tracing.execution.resolvers[0].parentType).toBe('Query');
expect(result.extensions?.tracing.execution.resolvers[0].fieldName).toBe('foo');
expect(result.extensions?.tracing.execution.resolvers[0].returnType).toBe('String');
// If you wonder why, we do this all for v16 compat which changed types of extensions to unknown
const tracing: any = result.extensions?.tracing;
expect(tracing.duration).toBeGreaterThan(1000000000);
expect(tracing.execution.resolvers[0].duration).toBeGreaterThan(990000000);
expect(tracing.execution.resolvers[0].path).toEqual(['foo']);
expect(tracing.execution.resolvers[0].parentType).toBe('Query');
expect(tracing.execution.resolvers[0].fieldName).toBe('foo');
expect(tracing.execution.resolvers[0].returnType).toBe('String');
});
});
2 changes: 1 addition & 1 deletion packages/plugins/auth0/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/dataloader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"peerDependencies": {
"dataloader": "^2.0.0",
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/depth-limit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/disable-introspection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/execute-subscription-event/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"typescript": "4.4.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
6 changes: 4 additions & 2 deletions packages/plugins/execute-subscription-event/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SubscriptionArgs, execute } from 'graphql';
import { Plugin } from '@envelop/types';
import { Plugin, PromiseOrValue } from '@envelop/types';
import { makeExecute, DefaultContext } from '@envelop/core';
import { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue';
import { subscribe } from './subscribe';

export type ContextFactoryOptions = {
Expand Down Expand Up @@ -30,6 +29,9 @@ export const useExtendContextValuePerExecuteSubscriptionEvent = <TContextValue =
try {
return await execute({
...executionArgs,
// GraphQL.js 16 changed the type of contextValue to unknown
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
contextValue: { ...executionArgs.contextValue, ...context?.contextPartial },
});
} finally {
Expand Down
Loading