Skip to content

Commit e10dbf8

Browse files
committed
compat with v16
1 parent 7223b52 commit e10dbf8

File tree

13 files changed

+96
-66
lines changed

13 files changed

+96
-66
lines changed

packages/core/src/orchestrator.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
OnExecuteDoneHookResultOnNextHook,
2323
OnExecuteDoneHookResultOnEndHook,
2424
ExecuteFunction,
25-
AsyncIterableIteratorOrValue,
25+
AsyncGeneratorOrValue,
2626
isAsyncIterable,
2727
} from '@envelop/types';
2828
import {
@@ -282,7 +282,7 @@ export function createEnvelopOrchestrator<PluginsContext = any>(plugins: Plugin[
282282
let subscribeFn = subscribe as SubscribeFunction;
283283

284284
const afterCalls: SubscribeResultHook[] = [];
285-
let context = args.contextValue || {};
285+
let context: object = (args.contextValue as any) || {};
286286

287287
for (const onSubscribe of beforeCallbacks.subscribe) {
288288
const after = await onSubscribe({
@@ -357,10 +357,11 @@ export function createEnvelopOrchestrator<PluginsContext = any>(plugins: Plugin[
357357
? makeExecute(async args => {
358358
const onResolversHandlers: OnResolverCalledHook[] = [];
359359
let executeFn = execute as ExecuteFunction;
360-
let result: AsyncIterableIteratorOrValue<ExecutionResult>;
360+
let result: AsyncGeneratorOrValue<ExecutionResult>;
361361

362362
const afterCalls: OnExecuteDoneHook[] = [];
363-
let context = args.contextValue || {};
363+
// @ts-expect-error contextValue is now of type unknown
364+
let context: object = args.contextValue || {};
364365

365366
for (const onExecute of beforeCallbacks.execute) {
366367
let stopCalled = false;
@@ -435,7 +436,7 @@ export function createEnvelopOrchestrator<PluginsContext = any>(plugins: Plugin[
435436
}
436437

437438
if (onNextHandler.length && isAsyncIterable(result)) {
438-
result = mapAsyncIterator(result, async result => {
439+
result = mapAsyncIterator(result as AsyncGenerator<ExecutionResult, void, void>, async result => {
439440
for (const onNext of onNextHandler) {
440441
await onNext({ result, setResult: newResult => (result = newResult) });
441442
}

packages/core/src/traced-orchestrator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug
8888
typeResolver,
8989
}
9090
: argsOrSchema;
91-
91+
// @ts-expect-error GraphQL.js types contextValue as unknown
9292
const done = createTracer('execute', args.contextValue || {});
9393

9494
try {
@@ -97,6 +97,7 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug
9797

9898
if (!isAsyncIterable(result)) {
9999
result.extensions = result.extensions || {};
100+
// @ts-expect-error GraphQL.js types contextValue as unknown
100101
result.extensions.envelopTracing = args.contextValue._envelopTracing;
101102
} else {
102103
// eslint-disable-next-line no-console
@@ -135,6 +136,7 @@ export function traceOrchestrator<TInitialContext extends ArbitraryObject, TPlug
135136
subscribeFieldResolver,
136137
}
137138
: argsOrSchema;
139+
// @ts-expect-error GraphQL.js types contextValue as unknown
138140
const done = createTracer('subscribe', args.contextValue || {});
139141

140142
try {

packages/core/src/utils.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
ExecutionArgs,
1212
} from 'graphql';
1313
import {
14-
AsyncIterableIteratorOrValue,
14+
AsyncGeneratorOrValue,
1515
ExecuteFunction,
1616
PolymorphicExecuteArguments,
1717
PolymorphicSubscribeArguments,
@@ -73,15 +73,15 @@ function getSubscribeArgs(args: PolymorphicSubscribeArguments): SubscriptionArgs
7373
* Utility function for making a subscribe function that handles polymorphic arguments.
7474
*/
7575
export const makeSubscribe = (
76-
subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncIterableIterator<ExecutionResult> | ExecutionResult>
76+
subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncGeneratorOrValue<ExecutionResult>>
7777
): SubscribeFunction =>
78-
((...polyArgs: PolymorphicSubscribeArguments): PromiseOrValue<AsyncIterableIterator<ExecutionResult> | ExecutionResult> =>
78+
((...polyArgs: PolymorphicSubscribeArguments): PromiseOrValue<AsyncGeneratorOrValue<ExecutionResult>> =>
7979
subscribeFn(getSubscribeArgs(polyArgs))) as SubscribeFunction;
8080

8181
export async function* mapAsyncIterator<TInput, TOutput = TInput>(
82-
asyncIterable: AsyncIterableIterator<TInput>,
82+
asyncIterable: AsyncGenerator<TInput, void, void> | AsyncIterable<TInput>,
8383
map: (input: TInput) => Promise<TOutput> | TOutput
84-
): AsyncIterableIterator<TOutput> {
84+
): AsyncGenerator<TOutput, void, void> {
8585
for await (const value of asyncIterable) {
8686
yield map(value);
8787
}
@@ -106,15 +106,15 @@ function getExecuteArgs(args: PolymorphicExecuteArguments): ExecutionArgs {
106106
* Utility function for making a execute function that handles polymorphic arguments.
107107
*/
108108
export const makeExecute = (
109-
executeFn: (args: ExecutionArgs) => PromiseOrValue<AsyncIterableIteratorOrValue<ExecutionResult>>
109+
executeFn: (args: ExecutionArgs) => PromiseOrValue<AsyncGeneratorOrValue<ExecutionResult>>
110110
): ExecuteFunction =>
111-
((...polyArgs: PolymorphicExecuteArguments): PromiseOrValue<AsyncIterableIteratorOrValue<ExecutionResult>> =>
111+
((...polyArgs: PolymorphicExecuteArguments): PromiseOrValue<AsyncGeneratorOrValue<ExecutionResult>> =>
112112
executeFn(getExecuteArgs(polyArgs))) as ExecuteFunction;
113113

114114
export async function* finalAsyncIterator<TInput>(
115-
asyncIterable: AsyncIterableIterator<TInput>,
115+
asyncIterable: AsyncGenerator<TInput, void, void>,
116116
onFinal: () => void
117-
): AsyncIterableIterator<TInput> {
117+
): AsyncGenerator<TInput, void, void> {
118118
try {
119119
yield* asyncIterable;
120120
} finally {

packages/plugins/execute-subscription-event/src/subscribe.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { createSourceEventStream } from 'graphql';
2-
3-
import { ExecuteFunction, makeSubscribe, SubscribeFunction } from '@envelop/core';
2+
import { ExecuteFunction, makeSubscribe, mapAsyncIterator, SubscribeFunction } from '@envelop/core';
43
import { isAsyncIterable } from '@envelop/types';
5-
import mapAsyncIterator from 'graphql/subscription/mapAsyncIterator';
64

75
/**
86
* This is a almost identical port from graphql-js subscribe.
@@ -33,7 +31,7 @@ export const subscribe = (execute: ExecuteFunction): SubscribeFunction =>
3331
// the GraphQL specification. The `execute` function provides the
3432
// "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
3533
// "ExecuteQuery" algorithm, for which `execute` is also used.
36-
const mapSourceToResponse = async (payload: object) =>
34+
const mapSourceToResponse = async (payload: unknown) =>
3735
execute({
3836
schema,
3937
document,

packages/plugins/extended-validation/test/one-of.spec.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,37 @@ import {
55
GraphQLString,
66
GraphQLID,
77
GraphQLInt,
8-
GraphQLNonNull,
98
GraphQLSchema,
109
GraphQLBoolean,
11-
GraphQLList,
10+
GraphQLNonNull as _GraphQLNonNull,
11+
GraphQLList as _GraphQLList,
12+
GraphQLNullableType,
13+
GraphQLType,
1214
} from 'graphql';
1315
import { assertSingleExecutionValue, createTestkit } from '@envelop/testing';
1416
import { useExtendedValidation, ONE_OF_DIRECTIVE_SDL, OneOfInputObjectsRule } from '../src';
1517

18+
// GraphQL.js 16 introduced requiring new constructor calls for creating GraphQLNonNull
19+
function GraphQLNonNull<T extends GraphQLNullableType>(type: T): _GraphQLNonNull<T> {
20+
try {
21+
// @ts-ignore
22+
return _GraphQLNonNull(type);
23+
} catch (_) {
24+
// @ts-ignore
25+
return new _GraphQLNonNull(type);
26+
}
27+
}
28+
// GraphQL.js 16 introduced requiring new constructor calls for creating GraphQLList
29+
function GraphQLList<T extends GraphQLType>(type: T): _GraphQLList<T> {
30+
try {
31+
// @ts-ignore
32+
return _GraphQLList(type);
33+
} catch (_) {
34+
// @ts-ignore
35+
return new _GraphQLList(type);
36+
}
37+
}
38+
1639
describe('oneOf', () => {
1740
const astSchema = buildSchema(/* GraphQL */ `
1841
${ONE_OF_DIRECTIVE_SDL}

packages/plugins/fragment-arguments/src/extended-parser.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2-
import { Parser } from 'graphql/language/parser';
3-
import { Lexer } from 'graphql/language/lexer';
4-
import { TokenKind, Kind, Source, DocumentNode, TokenKindEnum, Token } from 'graphql';
2+
import { ParseOptions, Parser } from 'graphql/language/parser';
3+
import type { Lexer } from 'graphql/language/lexer';
4+
import { TokenKind, Kind, Token, Location } from 'graphql';
55

6-
declare module 'graphql/language/parser' {
7-
export class Parser {
8-
constructor(source: string | Source, options?: ParseOptions);
9-
_lexer: Lexer;
10-
expectOptionalKeyword(word: string): boolean;
11-
expectToken(token: TokenKindEnum): void;
12-
peek(token: TokenKindEnum): boolean;
13-
parseFragmentName(): string;
14-
parseArguments(flag: boolean): any;
15-
parseDirectives(flag: boolean): any;
16-
loc(start: Token): any;
17-
parseNamedType(): any;
18-
parseSelectionSet(): any;
19-
expectKeyword(keyword: string): void;
20-
parseVariableDefinitions(): void;
21-
parseDocument(): DocumentNode;
6+
export class FragmentArgumentCompatibleParser extends Parser {
7+
// see https://github.com/graphql/graphql-js/pull/3248
8+
getLexer(): Lexer {
9+
return (this as any)._lexer as Lexer;
10+
}
11+
12+
// see https://github.com/graphql/graphql-js/pull/3248
13+
getOptions(): ParseOptions {
14+
return (this as any)._options as ParseOptions;
15+
}
16+
17+
// for backwards-compat with v15, this api was removed in v16 in favor of the this.node API.
18+
loc(startToken: Token): Location | undefined {
19+
if (this.getOptions()?.noLocation !== true) {
20+
const lexer = this.getLexer();
21+
return new Location(startToken, lexer.lastToken, lexer.source);
22+
}
23+
return undefined;
2224
}
23-
}
2425

25-
export class FragmentArgumentCompatibleParser extends Parser {
2626
parseFragment() {
27-
const start = this._lexer.token;
27+
const start = this.getLexer().token;
2828
this.expectToken(TokenKind.SPREAD);
2929
const hasTypeCondition = this.expectOptionalKeyword('on');
3030

@@ -59,7 +59,7 @@ export class FragmentArgumentCompatibleParser extends Parser {
5959
}
6060

6161
parseFragmentDefinition() {
62-
const start = this._lexer.token;
62+
const start = this.getLexer().token;
6363
this.expectKeyword('fragment');
6464
const name = this.parseFragmentName();
6565

packages/plugins/prometheus/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export function extractDeprecatedFields(node: ASTNode, typeInfo: TypeInfo): Depr
114114
Field: () => {
115115
const field = typeInfo.getFieldDef();
116116

117-
if (field && field.isDeprecated) {
117+
if (field && (field.deprecationReason != null || (field as any).isDeprecated)) {
118118
found.push({
119119
fieldName: field.name,
120120
typeName: typeInfo.getParentType()!.name || '',

packages/plugins/prometheus/test/prom.spec.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ import { PrometheusTracingPluginConfig, usePrometheus, createHistogram, createCo
22
import { makeExecutableSchema } from '@graphql-tools/schema';
33
import { assertSingleExecutionValue, createTestkit } from '@envelop/testing';
44
import { Registry, Histogram, Counter } from 'prom-client';
5-
import { print } from 'graphql';
5+
import { ASTNode, print as graphQLPrint } from 'graphql';
66
import { useExtendContext } from '@envelop/core';
77

8+
// Graphql.js 16 and 15 produce different results
9+
// Graphql.js 16 output has not trailing \n
10+
// In order to produce the same output we remove any trailing white-space
11+
const print = (ast: ASTNode) => graphQLPrint(ast).replace(/^\s+|\s+$/g, '');
12+
813
describe('Prom Metrics plugin', () => {
914
const schema = makeExecutableSchema({
1015
typeDefs: /* GraphQL */ `
@@ -167,7 +172,7 @@ describe('Prom Metrics plugin', () => {
167172
expect(result.errors).toBeUndefined();
168173
expect(await metricCount('graphql_envelop_error_result')).toBe(0);
169174
expect(await metricCount('test_parse', 'count')).toBe(1);
170-
expect(await metricString('test_parse')).toContain(`test_parse_count{opText=\"{\\n regularField\\n}\\n\"} 1`);
175+
expect(await metricString('test_parse')).toContain(`test_parse_count{opText=\"{\\n regularField\\n}\"} 1`);
171176
});
172177
});
173178

@@ -199,7 +204,7 @@ describe('Prom Metrics plugin', () => {
199204
expect(result.errors).toBeUndefined();
200205
expect(await metricCount('graphql_envelop_error_result')).toBe(0);
201206
expect(await metricCount('test_validate', 'count')).toBe(1);
202-
expect(await metricString('test_validate')).toContain(`test_validate_count{opText=\"{\\n regularField\\n}\\n\"} 1`);
207+
expect(await metricString('test_validate')).toContain(`test_validate_count{opText=\"{\\n regularField\\n}\"} 1`);
203208
});
204209

205210
it('should register to onValidate event when needed', () => {
@@ -271,7 +276,7 @@ describe('Prom Metrics plugin', () => {
271276
expect(result.errors).toBeUndefined();
272277
expect(await metricCount('graphql_envelop_error_result')).toBe(0);
273278
expect(await metricCount('test_context', 'count')).toBe(1);
274-
expect(await metricString('test_context')).toContain(`test_context_count{opText=\"{\\n regularField\\n}\\n\"} 1`);
279+
expect(await metricString('test_context')).toContain(`test_context_count{opText=\"{\\n regularField\\n}\"} 1`);
275280
});
276281

277282
it('Should trace contextBuilding timing', async () => {
@@ -320,7 +325,7 @@ describe('Prom Metrics plugin', () => {
320325
expect(result.errors).toBeUndefined();
321326
expect(await metricCount('graphql_envelop_error_result')).toBe(0);
322327
expect(await metricCount('test_execute', 'count')).toBe(1);
323-
expect(await metricString('test_execute')).toContain(`test_execute_count{opText=\"{\\n regularField\\n}\\n\"} 1`);
328+
expect(await metricString('test_execute')).toContain(`test_execute_count{opText=\"{\\n regularField\\n}\"} 1`);
324329
});
325330

326331
it('Should trace error during execute with a single error', async () => {
@@ -398,9 +403,7 @@ describe('Prom Metrics plugin', () => {
398403

399404
expect(result.errors?.length).toBe(1);
400405
expect(await metricCount('test_error')).toBe(1);
401-
expect(await metricString('test_error')).toContain(
402-
`test_error{opText=\"{\\n errorField\\n}\\n\",errorMessage=\"error\"} 1`
403-
);
406+
expect(await metricString('test_error')).toContain(`test_error{opText=\"{\\n errorField\\n}\",errorMessage=\"error\"} 1`);
404407
});
405408

406409
it('Should not trace parse errors when not needed', async () => {

packages/plugins/resource-limitations/src/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const ResourceLimitationValidationRule =
9595
);
9696
} else if ('first' in argumentValues === true && 'last' in argumentValues === false) {
9797
// eslint-disable-next-line dot-notation
98-
if (argumentValues['first'] < 1 || argumentValues['first'] > 100) {
98+
if ((argumentValues['first'] as number) < 1 || (argumentValues['first'] as number) > 100) {
9999
context.reportError(
100100
new GraphQLError(
101101
buildInvalidPaginationRangeErrorMessage({
@@ -107,11 +107,11 @@ export const ResourceLimitationValidationRule =
107107
);
108108
} else {
109109
// eslint-disable-next-line dot-notation
110-
nodeCost = argumentValues['first'];
110+
nodeCost = argumentValues['first'] as number;
111111
}
112112
} else if ('last' in argumentValues === true && 'false' in argumentValues === false) {
113113
// eslint-disable-next-line dot-notation
114-
if (argumentValues['last'] < 1 || argumentValues['last'] > 100) {
114+
if ((argumentValues['last'] as number) < 1 || (argumentValues['last'] as number) > 100) {
115115
context.reportError(
116116
new GraphQLError(
117117
buildInvalidPaginationRangeErrorMessage({
@@ -123,7 +123,7 @@ export const ResourceLimitationValidationRule =
123123
);
124124
} else {
125125
// eslint-disable-next-line dot-notation
126-
nodeCost = argumentValues['last'];
126+
nodeCost = argumentValues['last'] as number;
127127
}
128128
} else {
129129
context.reportError(

packages/plugins/response-cache/src/plugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ function applyResponseCacheLogic(schema: GraphQLSchema, idFieldNames: Array<stri
266266
...fieldConfig,
267267
resolve(src, args, context, info) {
268268
const result = (fieldConfig.resolve ?? defaultFieldResolver)(src, args, context, info);
269-
runWith(result, (id: string) => {
269+
// result must be of type string
270+
runWith(result, id => {
270271
if (contextSymbol in context) {
271272
const ctx: Context = context[contextSymbol];
272273
if (ctx.ignoredTypesMap.has(typename)) {
@@ -276,6 +277,7 @@ function applyResponseCacheLogic(schema: GraphQLSchema, idFieldNames: Array<stri
276277
ctx.skip = true;
277278
return;
278279
}
280+
// @ts-expect-error TODO: investigate what to do if id is something unexpected
279281
ctx.identifier.set(`${typename}:${id}`, { typename, id });
280282
ctx.types.add(typename);
281283
if (typename in ctx.ttlPerType) {

0 commit comments

Comments
 (0)