Skip to content

Commit 8fe0243

Browse files
authored
chore: upgrade to graphql 16 (#137)
Graphql 16 Brings internal breaking api changes. BREAKING CHANGE: A minimum of Graphql 16 is now required
1 parent e713e47 commit 8fe0243

File tree

8 files changed

+91
-95
lines changed

8 files changed

+91
-95
lines changed

lib/messages/complete.ts

+8-10
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,19 @@ export const complete: MessageHandler<CompleteMessage> = async ({ server, event,
1616
if (!subscription) {
1717
return
1818
}
19-
const execContext = buildExecutionContext(
20-
server.schema,
21-
parse(subscription.subscription.query),
22-
undefined,
23-
await buildContext({ server, connectionInitPayload: subscription.connectionInitPayload, connectionId: subscription.connectionId }),
24-
subscription.subscription.variables,
25-
subscription.subscription.operationName,
26-
undefined,
27-
)
19+
const execContext = buildExecutionContext({
20+
schema: server.schema,
21+
document: parse(subscription.subscription.query),
22+
contextValue: await buildContext({ server, connectionInitPayload: subscription.connectionInitPayload, connectionId: subscription.connectionId }),
23+
variableValues: subscription.subscription.variables,
24+
operationName: subscription.subscription.operationName,
25+
})
2826

2927
if (isArray(execContext)) {
3028
throw new AggregateError(execContext)
3129
}
3230

33-
const { field, root, args, context, info } = getResolverAndArgs({ server, execContext })
31+
const { field, root, args, context, info } = getResolverAndArgs({ execContext })
3432

3533
const onComplete = (field?.subscribe as SubscribePseudoIterable<PubSubEvent>)?.onComplete
3634
server.log('messages:complete:onComplete', { onComplete: !!onComplete })

lib/messages/disconnect.ts

+8-10
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,19 @@ export const disconnect: MessageHandler<null> = async ({ server, event }) => {
2424
const deletions = topicSubscriptions.map(async (sub) => {
2525
const queryContext = await buildContext({ server, connectionInitPayload: sub.connectionInitPayload, connectionId })
2626

27-
const execContext = buildExecutionContext(
28-
server.schema,
29-
parse(sub.subscription.query),
30-
undefined,
31-
queryContext,
32-
sub.subscription.variables,
33-
sub.subscription.operationName,
34-
undefined,
35-
)
27+
const execContext = buildExecutionContext({
28+
schema: server.schema,
29+
document: parse(sub.subscription.query),
30+
contextValue: queryContext,
31+
variableValues: sub.subscription.variables,
32+
operationName: sub.subscription.operationName,
33+
})
3634

3735
if (isArray(execContext)) {
3836
throw new AggregateError(execContext)
3937
}
4038

41-
const { field, root, args, context, info } = getResolverAndArgs({ server, execContext })
39+
const { field, root, args, context, info } = getResolverAndArgs({ execContext })
4240

4341
const onComplete = (field?.subscribe as SubscribePseudoIterable<PubSubEvent>)?.onComplete
4442
server.log('messages:disconnect:onComplete', { onComplete: !!onComplete })

lib/messages/subscribe.ts

+13-17
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,13 @@ const setupSubscription: MessageHandler<SubscribeMessage> = async ({ server, eve
4949

5050
const contextValue = await buildContext({ server, connectionInitPayload: connection.payload, connectionId })
5151

52-
const execContext = buildExecutionContext(
53-
server.schema,
54-
parse(message.payload.query),
55-
undefined,
52+
const execContext = buildExecutionContext({
53+
schema: server.schema,
54+
document: parse(message.payload.query),
5655
contextValue,
57-
message.payload.variables,
58-
message.payload.operationName,
59-
undefined,
60-
)
56+
variableValues: message.payload.variables,
57+
operationName: message.payload.operationName,
58+
})
6159

6260
if (isArray(execContext)) {
6361
return postToConnection(server)({
@@ -80,7 +78,7 @@ const setupSubscription: MessageHandler<SubscribeMessage> = async ({ server, eve
8078
return
8179
}
8280

83-
const { field, root, args, context, info } = getResolverAndArgs({ server, execContext })
81+
const { field, root, args, context, info } = getResolverAndArgs({ execContext })
8482
if (!field) {
8583
throw new Error('No field')
8684
}
@@ -160,15 +158,13 @@ const validateMessage = (server: ServerClosure) => (message: SubscribeMessage) =
160158
async function executeQuery(server: ServerClosure, message: SubscribeMessage, contextValue: any, event: APIGatewayWebSocketEvent) {
161159
server.log('executeQuery', { connectionId: event.requestContext.connectionId, query: message.payload.query })
162160

163-
const result = await execute(
164-
server.schema,
165-
parse(message.payload.query),
166-
undefined,
161+
const result = await execute({
162+
schema: server.schema,
163+
document: parse(message.payload.query),
167164
contextValue,
168-
message.payload.variables,
169-
message.payload.operationName,
170-
undefined,
171-
)
165+
variableValues: message.payload.variables,
166+
operationName: message.payload.operationName,
167+
})
172168

173169
await postToConnection(server)({
174170
...event.requestContext,

lib/pubsub/complete.ts

+8-10
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@ export const complete = (serverPromise: Promise<ServerClosure> | ServerClosure):
2525
})
2626
await server.models.subscription.delete({ id: sub.id })
2727

28-
const execContext = buildExecutionContext(
29-
server.schema,
30-
parse(sub.subscription.query),
31-
undefined,
32-
await buildContext({ server, connectionInitPayload: sub.connectionInitPayload, connectionId: sub.connectionId }),
33-
sub.subscription.variables,
34-
sub.subscription.operationName,
35-
undefined,
36-
)
28+
const execContext = buildExecutionContext({
29+
schema: server.schema,
30+
document: parse(sub.subscription.query),
31+
contextValue: await buildContext({ server, connectionInitPayload: sub.connectionInitPayload, connectionId: sub.connectionId }),
32+
variableValues: sub.subscription.variables,
33+
operationName: sub.subscription.operationName,
34+
})
3735

3836
if (isArray(execContext)) {
3937
throw new AggregateError(execContext)
4038
}
4139

42-
const { field, root, args, context, info } = getResolverAndArgs({ server, execContext })
40+
const { field, root, args, context, info } = getResolverAndArgs({ execContext })
4341

4442
const onComplete = (field?.subscribe as SubscribePseudoIterable<PubSubEvent>)?.onComplete
4543
server.log('pubsub:complete:onComplete', { onComplete: !!onComplete })

lib/pubsub/publish.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ export const publish = (serverPromise: Promise<ServerClosure> | ServerClosure):
1212
server.log('pubsub:publish', { subscriptions: subscriptions.map(({ connectionId, filter, subscription }) => ({ connectionId, filter, subscription }) ) })
1313

1414
const iters = subscriptions.map(async (sub) => {
15-
const payload = await execute(
16-
server.schema,
17-
parse(sub.subscription.query),
18-
event,
19-
await buildContext({ server, connectionInitPayload: sub.connectionInitPayload, connectionId: sub.connectionId }),
20-
sub.subscription.variables,
21-
sub.subscription.operationName,
22-
undefined,
23-
)
15+
const payload = await execute({
16+
schema: server.schema,
17+
document: parse(sub.subscription.query),
18+
rootValue: event,
19+
contextValue: await buildContext({ server, connectionInitPayload: sub.connectionInitPayload, connectionId: sub.connectionId }),
20+
variableValues: sub.subscription.variables,
21+
operationName: sub.subscription.operationName,
22+
})
2423

2524
const message: NextMessage = {
2625
id: sub.subscriptionId,

lib/utils/getResolverAndArgs.ts

+35-28
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import { getOperationRootType } from 'graphql'
1+
import { GraphQLError } from 'graphql'
22
import {
33
buildResolveInfo,
4-
collectFields,
54
ExecutionContext,
65
getFieldDef,
76
} from 'graphql/execution/execute'
7+
import { collectFields } from 'graphql/execution/collectFields'
88
import { getArgumentValues } from 'graphql/execution/values'
99
import { addPath } from 'graphql/jsutils/Path'
10-
import { ServerClosure } from '../types'
1110

1211
interface ResolverAndArgs {
1312
field: ReturnType<typeof getFieldDef>
@@ -17,44 +16,52 @@ interface ResolverAndArgs {
1716
info: ReturnType<typeof buildResolveInfo>
1817
}
1918

20-
export const getResolverAndArgs = ({ server, execContext }: { server: ServerClosure, execContext: ExecutionContext }): ResolverAndArgs => {
21-
// Taken from graphql-js - https://github.com/graphql/graphql-js/blob/main/src/subscription/subscribe.ts#L189
22-
const type = getOperationRootType(server.schema, execContext.operation)
23-
const fields = collectFields(
24-
execContext,
25-
type,
26-
execContext.operation.selectionSet,
27-
Object.create(null),
28-
Object.create(null),
19+
export const getResolverAndArgs = ({ execContext }: { execContext: ExecutionContext }): ResolverAndArgs => {
20+
// Taken from graphql-js executeSubscription - https://github.com/graphql/graphql-js/blob/main/src/execution/subscribe.ts#L187
21+
const { schema, fragments, operation, variableValues, contextValue } = execContext
22+
23+
const rootType = schema.getSubscriptionType()
24+
if (rootType == null) {
25+
throw new GraphQLError(
26+
'Schema is not configured to execute subscription operation.',
27+
operation,
28+
)
29+
}
30+
31+
const rootFields = collectFields(
32+
schema,
33+
fragments,
34+
variableValues,
35+
rootType,
36+
operation.selectionSet,
2937
)
30-
const responseNames = Object.keys(fields)
31-
const responseName = responseNames[0]
32-
const fieldNodes = fields[responseName]
33-
const fieldNode = fieldNodes[0]
34-
const fieldName = fieldNode.name.value
35-
const field = getFieldDef(server.schema, type, fieldName)
36-
const path = addPath(undefined, responseName, type.name)
37-
38-
if (!field) {
39-
throw new Error('invalid schema, unknown field definition')
38+
const [responseName, fieldNodes] = [...rootFields.entries()][0]
39+
const fieldDef = getFieldDef(schema, rootType, fieldNodes[0])
40+
41+
if (!fieldDef) {
42+
const fieldName = fieldNodes[0].name.value
43+
throw new GraphQLError(
44+
`The subscription field "${fieldName}" is not defined.`,
45+
fieldNodes,
46+
)
4047
}
4148

49+
const path = addPath(undefined, responseName, rootType.name)
4250
const info = buildResolveInfo(
4351
execContext,
44-
field,
52+
fieldDef,
4553
fieldNodes,
46-
type,
54+
rootType,
4755
path,
4856
)
4957

50-
const args = getArgumentValues(field, fieldNode, execContext.variableValues)
51-
const context = execContext.contextValue
58+
const args = getArgumentValues(fieldDef, fieldNodes[0], variableValues)
5259

5360
return {
54-
field,
61+
field: fieldDef,
5562
root: null,
5663
args,
57-
context,
64+
context: contextValue,
5865
info,
5966
}
6067
}

package-lock.json

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
},
4040
"peerDependencies": {
4141
"aws-sdk": ">= 2.844.0",
42-
"graphql": ">= 14.0.0 < 16"
42+
"graphql": ">= 16.0.0"
4343
},
4444
"devDependencies": {
4545
"@architect/functions": "^4.0.0",
@@ -64,7 +64,7 @@
6464
"esbuild-register": "^3.0.0",
6565
"eslint": "^7.29.0",
6666
"eslint-plugin-mocha-no-only": "^1.1.1",
67-
"graphql": "^15.0.0",
67+
"graphql": "^16.0.1",
6868
"graphql-ws": "^5.3.0",
6969
"inside-out-async": "^1.0.0",
7070
"mocha": "^9.1.2",

0 commit comments

Comments
 (0)